本帖最后由 holybang 于 2025-10-7 11:29 编辑
2025年10月7日更新
最初发的图,因为是基于C++的算法库自己跑出来的,没有第一时间分享halcon的实现。现在跟大家分享halcon代码如下
- * 1. 读取彩色图片
- read_image (Image, '输入图片路径')
- * 2. 简单降噪一下并转换为HSV颜色空间并提取H通道
- gauss_filter (Image, ImageGaussed, 5)
- decompose3(ImageGaussed, ImageR, ImageG, ImageB)
- trans_from_rgb (ImageR, ImageG, ImageB, ImageH, ImageS, ImageV, 'hsv')
- * 3. 对H通道进行局部自适应拉伸,增强局部对比度
- convert_image_type(ImageH, ImageH_real, 'real')
- gen_image_proto (ImageH_real, ImageP3, 3)
- gen_image_proto (ImageH_real, ImageScale, 255.0/6.0)
- mean_image (ImageH_real, ImageMean, 31, 31)
- sub_image (ImageMean, ImageP3, ImageH_LB, 1, 0)
- sub_image(ImageH_real, ImageH_LB, ImageH1, 1, 0)
- mult_image(ImageH1, ImageScale, ImageEnhanced, 1.0, 0)
- threshold(ImageEnhanced, RegionBZ, -100000, 0)
- overpaint_region (ImageEnhanced, RegionBZ, 0, 'fill')
- threshold(ImageEnhanced, Region255, 255, 100000)
- overpaint_region(ImageEnhanced, Region255, 255, 'fill')
- * 4. 获得增强对比度之后的H通道的频谱图
- fft_generic (ImageEnhanced, HFFT, 'to_freq', -1, 'none', 'dc_center', 'complex')
- power_ln (HFFT, HFFT_ln)
- * 5. 将频谱图最大最小归一化到0-255
- get_image_size(Image, Width, Height)
- gen_rectangle1(ImageEntireReg, 0, 0, Width, Height)
- min_max_gray(ImageEntireReg, HFFT_ln, 0, Min, Max, Range)
- scale_image_range(HFFT_ln, HFFT_ln_scaled, Min, Max)
- convert_image_type (HFFT_ln_scaled, HFFT_ln_8u, 'byte')
- * 6. 对频谱图简单降噪一下
- gauss_filter (HFFT_ln_8u, GaussFiltered, 3)
- * 7. 自适应阈值处理,得到频谱局部极值点的region,因为图中要增强的网格特征是一种重复纹理,所以频谱图上一定会表现为距离相等的一些极值点
- local_threshold(GaussFiltered, img_thresh, 'adapted_std_deviation', 'light', ['mask_size', 'scale'], [61, 0.35])
- * 8. 对频谱极值点区域进行形态学膨胀
- dilation_circle (img_thresh, Dilated, 2.5)
- * 9. 保留面积<100的区域,期望丢弃频谱图中面积比较大的区域,因为网格纹理对应的频谱极值点一定都会比较小
- connection (Dilated, ConnectedRegions)
- select_shape (ConnectedRegions, SmallRegions, 'area', 'and', 0, 100)
- * 10. 将区域转换成real类型的蒙版图像,因为后续要将区域作为频域滤波器使用,所以也得做最大最小归一化
- region_to_bin(SmallRegions, ImageMaskFiltered, 255, 0, Width, Height)
- convert_image_type(ImageMaskFiltered, ImageMaskFiltered, 'real')
- min_max_gray(ImageEntireReg, ImageMaskFiltered, 0, Min, Max, Range)
- scale_image(ImageMaskFiltered, ImageMaskFiltered, 1.0/Max, 0)
- * 11. 应用自定义蒙版图像作为滤波器
- convol_fft (HFFT, ImageMaskFiltered, ImageComplex)
- ****** 为了可视化ImageComplex ******
- power_ln (ImageComplex, ImageComplex_ln)
- connection(SmallRegions, ConnectedSmallRegions)
- union1 (SmallRegions, RegionUnion)
- min_max_gray(RegionUnion, ImageComplex_ln, 0, Min, Max, Range)
- scale_image_range(ImageComplex_ln, ImageComplex_ln_scaled, Min, Max)
- convert_image_type (ImageComplex_ln_scaled, ImageComplex_ln_scaled_8u, 'byte')
- ****** 为了可视化ImageComplex ******
- * 12. 逆傅里叶变换得到增强网格后的H通道
- fft_generic(ImageComplex, ImageResult, 'from_freq', 1, 'none', 'dc_center', 'real')
- * 保存结果
- min_max_gray(ImageEntireReg, ImageResult, 0, Min, Max, Range)
- scale_image(ImageResult, ImageResult, 255.0/(Max-Min), -255.0*Min/(Max-Min))
- convert_image_type(ImageResult, ImageResult, 'byte')
- write_image(ImageResult, 'png', 0, 'result.png')
复制代码
halcon结果
这是以上halcon代码保存下来的result.png的效果,和最初的C++的效果基本一致,我略有改进所以结果还更好了一点。
总体思路是:
1. 由于是彩色图片,总是先观察哪个通道的图能够以最小的噪声凸显最明显的纹理(对应代码中的ImageH)
色度通道
2. 由于原图亮度和对比度都不均匀,所以尝试了使用局部自适应拉伸来增强色度通道的对比度,如下图所示(对应代码中的ImageEnhanced)
3. 由于2的结果ImageEnhanced依旧不够好,所以考虑使用纹理增强中常见的频域方法,这个图片中重复的小方格纹理特征对应到频谱图上就是一系列距离相等的亮点(如下图所示,对应代码中的HFFT_ln),因此接下来就是设法保留频谱图上的这些间距相等的小亮点,去掉其他频率的能量
4. 对ImageEnhanced进行傅里叶变换,得到频谱图HFFT,通过归一化和一些基础的图像处理套路,得到小亮点的区域,如下图(对应代码中的SmallRegions)
5. 基于这些小亮点区域,对频谱图进行卷积之后,得到(对应的代码中的ImageComplex_ln_scaled_8u)
6. 最后,将步骤5得到的频谱图转换回到空域,即可得到最终结果(对应代码中的ImageResult)
有问题欢迎交流
以下是最初发的帖子内容
色度通道
色度通道频域图
色度通道频域滤波结果
频域处理后
色度通道重建最终结果
以上类似效果可以吗?
|