购买
下载掌阅APP,畅读海量书库
立即打开
畅读海量书库
扫码下载掌阅APP

第5章
图像预处理

获得了相机采集的图像之后,图像质量往往会与预想的有所差异,如出现形状失真、亮度低、图像噪声大等问题,因此需要对图像进行即时校正和图像增强等预处理,方便后续的检测和识别。图像预处理是非常关键的一个环节,输出的图像质量关系到识别的准确率和速度。本章将深入介绍图像预处理的几种常用算法。

本章主要涉及的知识点如下。

●图像的仿射变换与梯形校正:讨论如何解决图像形状失真的问题。

●感兴趣区域(Region of Interest,ROI):学习如何将图像处理的范围缩小到关键的ROI。

●图像增强:讨论如何增强图像质量、增加对比度、处理失焦图像。

●图像平滑与去噪:用软件的算法消除图像噪声,主要方法有均值滤波、中值滤波和高斯滤波。

●光照不均匀:探讨解决光照不均匀问题的方法。

注意

本章内容不涉及三维图像校正,这部分内容将在第13章详细介绍。

5.1 图像的变换与校正

由于相机拍摄的时候可能存在角度偏差,因此实际获得的画面可能会与想象中有所差异。例如,采集连续目标时,可能每幅图中目标区域的位置和角度都不一样;又或者目标对象是一块矩形区域,而在采集到的图像中,这一块可能变成了梯形或扭曲的四边形。

因此,接下来要做的第一件事,就是把这块区域进行一些调整,使之恢复成原本的矩形区域。本节就以解决图像形状失真问题为目的,介绍Halcon中的图像二维变换方法。

5.1.1 二维图像的平移、旋转和缩放

为了校正图像在拍摄中的失真问题,可以对图像进行一些简单的几何变换,如平移、缩放和旋转等,这些是图形学中的基本几何变换。

一个点 p 0 的位置可以用3个坐标表示( x p y p z p ),这3个坐标也可以看成一个3D向量。

1. 图像的平移

如果将这个点移动( x t y t )个向量,相当于在 p 坐标的左边乘以一个平移矩阵 T 。设平移后的点为 p t ,如公式(5.1)所示。

2. 图像的旋转

如果将这个点在二维平面上绕坐标原点旋转角度 γ ,相当于在 p 0 坐标的左边乘以一个旋转矩阵 R 。设旋转后的点为 p r ,如公式(5.2)所示。

注意

如果是绕x轴和y轴旋转,将涉及关于三维坐标系变换的知识,该部分内容将在第13章详细介绍。

3. 图像的缩放

假设这个点在二维平面上,沿 x 轴方向放大 s x 倍,沿 y 轴方向放大 s y 倍,那么变化后的该点的坐标记为 p s ,如公式(5.3)所示。

注意

平移、缩放和旋转都需要有一个参考点,围绕该点进行仿射变换操作。

5.1.2 图像的仿射变换

把平移、旋转和缩放结合起来,可以在Halcon中使用仿射变换的相关算子。一个仿射变换矩阵包括平移向量和旋转向量。

1. 仿射变换矩阵

在仿射变换前,先确定仿射变换矩阵,步骤如下。

(1)使用hom_mat2d_identity (HomMat2DIdentity)创建一个空的仿射变换矩阵。

(2)指定变换的参数,这里可以指定平移、缩放、旋转参数,举例如下。

●设置平移矩阵,向 x 轴正方向平移30个像素,向 y 轴正方向平移30个像素:hom_mat2d_translate (HomMat2DIdentity, 30, 30, HomMat2DTranslate)。

●设置旋转矩阵,以点( P x , P y )为参考点,旋转角度phi:hom_mat2d_rotate (HomMat2DIdentity,rad(phi), Px,Py, HomMat2DRotate)。

●设置缩放矩阵,以点( P x , P y )为参考点,放大2倍:hom_mat2d_scale (HomMat2DRotate, 2, 2,Px, Py, HomMat2DScale)。

2. 应用仿射变换矩阵

仿射变换矩阵可以应用于像素点(Pixel)、二维点(Point)、图像(Image)、区域(Region)及XLD轮廓等对象。下面分别举例。

(1)应用于像素点:使用affine_trans_pixel算子。

(2)应用于二维点:使用affine_trans_point_2d算子。

(3)应用于图像:使用affine_trans_image算子。

(4)应用于区域:使用affine_trans_region算子。

(5)应用于XLD轮廓:使用affine_trans_contour_xld算子。

5.1.3 投影变换

上文介绍的仿射变换其实是投影变换的一个特殊例子,其特殊性在于变换后图像的形状仍然维持原状。投影变换包括的情况很多,有可能变换前后图像的形状发生了很大的改变,如对边不再平行,或者发生了透视畸变等,这时可以使用投影变换使其恢复原状。其步骤与仿射变换类似,首先计算投影变换矩阵,然后计算投影变换参数,最后将投影变换矩阵映射到对象上。

要计算投影变换矩阵,应找出投影区域的特征点的位置及其投影后的位置,通过hom_vector_to_proj_hom_mat2d算子进行换算,就可以根据已知的投影对应的点的值计算投影变换矩阵。然后使用projective_trans_image对图像进行投射变换,就能得到投影后的图像了。下面用一个实例进行介绍。

5.1.4 实例:透视形变图像校正

透视形变图像校正步骤如下。

(1)读取图像,并对图像进行简单的处理,分割出目标形变区域。

(2)获取形变区域的轮廓,并计算出顶点坐标信息。

(3)利用上一步得出的坐标信息,计算投影变换矩阵。

(4)进行投影变换。

透视形变图像校正结果如图5.1所示。

图5.1 透视形变图像校正结果

实现代码参考如下:

*关闭当前显示窗口,清空屏幕
dev_close_window ()
*读取测试图像
read_image (Image_display, 'data/display.jpg')
*将图像转化为灰度图像
rgb1_to_gray (Image_display, GrayImage)
*获取图像的尺寸
get_image_size(Image_display,imageWidth, imageHeight)
*新建显示窗口,适应图像尺寸
dev_open_window (0, 0, imageWidth, imageHeight, 'black', WindowHandle1)
dev_display (GrayImage)
*初始化角点坐标
XCoordCorners := []
YCoordCorners := []
*阈值处理,提取较暗的区域
threshold(GrayImage,DarkRegion,0, 80)
*分离不相连的区域
connection (DarkRegion, ConnectedRegions)
*选择面积最大的暗色区域,即屏幕区域
select_shape_std (ConnectedRegions, displayRegion, 'max_area', 70)
*裁剪屏幕区域
reduce_domain (GrayImage, displayRegion, displayImage)
*创建边缘轮廓
gen_contour_region_xld (displayRegion, Contours, 'border')
*将轮廓分割为边
segment_contours_xld (Contours, ContoursSplit, 'lines', 5, 4, 2)
*获取边的数量
count_obj (ContoursSplit, Number)
*存储每条边的起点位置
for index:=1 to Number by 1
   select_obj(ContoursSplit, ObjectCurrent, index)
   *拟合每条边
   fit_line_contour_xld (ObjectCurrent, 'tukey', -1, 0, 5, 2, RowBegin,
ColBegin, RowEnd, ColEnd, Nr, Nc, Dist)
   *存储每条边的顶点x坐标
   tuple_concat (XCoordCorners, RowBegin, XCoordCorners)
   *存储每条边的顶点y坐标
   tuple_concat (YCoordCorners, ColBegin, YCoordCorners)
endfor

* 投影变换,为4个特征点与校正后的坐标建立关联
XOff:= 100
YOff:= 100*imageHeight/imageWidth
hom_vector_to_proj_hom_mat2d (XCoordCorners, YCoordCorners, [1,1,1,1],
[YOff,YOff,imageHeight-YOff,imageHeight-YOff], [XOff,imageWidth-XOff,imageWidth-
XOff,XOff], [1,1,1,1], 'normalized_dlt', HomMat2D)
*投影变换
projective_trans_image (Image_display, Image_rectified, HomMat2D, 'bilinear',
'false', 'false')
*显示校正结果
dev_display (Image_rectified)

上述代码中用了较多篇幅来提取显示器区域的4个角的特征点,并以这几个特征点为依据提取了显示器的边界。提取特征点的方法将在第9章详细讲述,如果读者觉得这部分理解有困难,也可以直接指定目标区域的顶点坐标,以及投影后的矩形顶点坐标,然后通过使用程序换算二者的对应关系得到投影矩阵,进而得到校正后的目标形状。

5.2 感兴趣区域(ROI)

ROI是Halcon中的一个很重要的概念,为了减少计算量,只关注待检测物体或该物体周围的一片区域即可,ROI就是图像处理所关注的区域。

5.2.1 ROI的意义

创建ROI主要是出于以下两个方面的原因。

(1)因为将要处理的图像缩减到了ROI区域,需要处理的像素数减少了,对于ROI外的像素可以不处理,因此可以加快图像处理的速度。如果原图是1920像素×1280像素,那么对整幅图像进行处理的计算量是非常大的,而需要关注的区域可能只是图像中的某一部分,因此将这部分区域裁剪出来进行处理,可以减少计算量,提高效率。

(2)由于ROI可以作为形状模板,因此在模板匹配时,ROI即为匹配搜索的参考图像。

5.2.2 创建ROI

在采集到原始图像后,即可选择关注的区域作为ROI。ROI可以是任何形状,常规的有矩形、圆形、椭圆,可以是自定义的或者是通过图像处理得出的特定区域。此时,选择的区域还不能称为ROI,它还只是形状或者说是像素范围。如果要将这部分区域变成独立的图像,还需要将其从原图上裁剪出来。

ROI的范围明确后,在Halcon中可以通过reduce_domain算子将其截取出来成为单独的一幅图片。

这里以5.1.4节的图5.1为例,介绍ROI的生成过程,如图5.2所示。

图5.2 ROI的生成过程

这里在原图上使用矩形ROI绘制工具指定了一个矩形的4个顶点。使用gen_rectangle1算子生成矩形ROI_0的形状,然后通过reduce_domain从原图中截取出矩形覆盖的这一部分的图像,即为ROI,命名为ImageReduced。在窗口中显示ImageReduced的内容,即为所关注的ROI图像。实现代码参考如下:

dev_close_window ()
*读取测试图像
read_image (Image_display, 'data/display')
*获取图像的尺寸
get_image_size(Image_display,imageWidth, imageHeight)
*新建显示窗口,适应图像尺寸
dev_open_window (0, 0, imageWidth, imageHeight, 'black', WindowHandle)
dev_display (Image_display)
*选择ROI,指定矩形顶点坐标
gen_rectangle1 (ROI_0, 52, 46, 456, 574)
*从原图中分割出ROI
reduce_domain (Image_display, ROI_0, reducedImage)
*在新窗口中显示分割后的ROI图像
dev_open_window (0, 400, imageWidth, imageHeight, 'black', WindowHandle1)
dev_display (reducedImage)

5.3 图像增强

图像增强主要是为了突出图像中的细节,为后续的特征识别或者检测做准备。图像增强可以有多种方式,本节介绍直方图均衡、增强对比度、处理失焦图像这3种方式。

5.3.1 直方图均衡

直方图均衡就是从图像的灰度图入手,建立一个0~255灰度值的直方图,统计每个灰度值在直方图中出现的次数,将灰度图中对应点的灰度值记录在直方图中。接着对该直方图进行均衡化操作,使像素的灰度值分布得更加均匀,从而增强图像的亮度。在Halcon中可以使用equ_histo_image算子进行直方图均衡,举例如下:

*读取图像,如果是彩色图像,需要转化为单通道黑白图像
read_image (board, 'data/boardEqu')
rgb1_to_gray (board, GrayImage)

equ_histo_image (GrayImage, ImageEquHisto)
*显示直方图
gray_histo (board, board, AbsoluteHisto1, RelativeHisto1)
gray_histo (ImageEquHisto, ImageEquHisto, AbsoluteHisto2, RelativeHisto2)
dev_open_window (0, 0, 512, 512, 'black', WindowHandle)
dev_set_color ('red')
gen_region_histo (Histo1, AbsoluteHisto1, 255, 5, 1)
dev_set_color ('green')
gen_region_histo (Histo2, AbsoluteHisto2, 255, 450, 1)

在这个例子中,使用了equ_histo_image算子对图像的灰度直方图进行了均衡。图5.3所示为直方图均衡结果。图5.3(a)为原始图像,图5.3(b)为均衡后的图像,可见亮度有明显提升。

图5.3 直方图均衡结果(1)

图5.4(a)为原始图像的灰度直方图,图5.4(b)为均衡后的灰度直方图。通过均衡直方图,能增加图像的亮度。

图5.4 直方图均衡结果(2)

5.3.2 增强对比度

除了可以使用均衡直方图增加亮度外,还可以增强图像的对比度,对图像的边缘和细节进行增强,使其更加明显。在Halcon图像处理中,可以使用emphasize算子实现这一操作。代码举例如下:

read_image (text, 'data/text')
emphasize (text, ImageEmphasize, 10, 10, 1.5)
dev_display(ImageEmphasize)

在这个例子中,使用了emphasize算子对图像的对比度进行了增强。图5.5所示为增强对比度的结果。图5.5(a)为原始图像,图5.5(b)为增强对比度后的图像,可见对比度有明显提升。

图5.5 使用emphasize算子增强图像的对比度

除了使用emphasize算子外,还可以使用scale_image_max算子进行图像对比度增强,使其明暗变化更加明显。代码举例如下:

read_image (text, 'data/text')
scale_image_max (text, ImageScaleMax)
dev_display(ImageScaleMax)

在这个例子中,使用了scale_image_max对图像的对比度进行了增强。图5.6所示为增强对比度的结果。图5.6(a)为原始图像,图5.6(b)为使用scale_image_max算子增强对比度后的图像,可见对比度有明显提升。

图5.6 使用scale_image_max算子增强图像的对比度

5.3.3 处理失焦图像

一些对焦不准的图像可能存在模糊不清的问题,这时需要考虑锐化操作。锐化的算子有很多,常见的如Sobel算子、Canny算子、Laplace算子等,这些将在第10章具体介绍。本小节介绍一种常用的冲击滤波器,其也可以进行边缘的增强,原理是在图像的边缘形成一些冲击,以对边缘进行增强。Halcon中使用shock_filter算子实现这一功能。代码举例如下:

read_image (test, 'data/defocusComponnet')
shock_filter (test, SharpenedImage, 0.5, 20, 'canny', 2.5)
dev_display(SharpenedImage)

shock_filter算子的第5个参数是canny,也可以选择laplace,分别对应两种不同的边缘检测算子。锐化效果如图5.7所示。

图5.7 锐化效果

由图5.7可以看出,模糊的边缘变得清晰,但边缘仍有毛刺等不平滑现象,可以进一步调节锐化参数,直至得到比较理想的效果。

5.4 图像平滑与去噪

有时拍摄的图像中会存在很多杂点和噪声,对于比较均匀的噪声,可以考虑用软件的算法进行消除。例如,可以用图像平滑的方法进行去噪,主要的方法有均值滤波、中值滤波、高斯滤波等。

5.4.1 均值滤波

均值滤波的原理就是将像素灰度值与其邻域内的像素灰度值相加取平均值。该滤波器区域就如同一个小的“窗口”,在图像上从左上角开始滑动,将该“窗口”内的像素灰度值相加并取平均值,然后将该灰度值赋值给“窗口”中的每一个像素。在Halcon中使用mean_image算子进行均值滤波,代码举例如下:

read_image (ImageNoise, 'data/marker')
mean_image (ImageNoise, ImageMean, 9,9)
dev_display(ImageMean) 

在这个例子中,mean_imag算子的第一个参数ImageNoise是输入的带噪声的图像;第二个参数ImageMean是输出的均值滤波后的图像;9是卷积核的尺寸,即“窗口”中包含的像素的横纵坐标方向的尺寸。注意,这里滤波器的“窗口”尺寸一般都是奇数像素尺寸的正方形,如3、5、7、9、11、15等,因为奇数可以保证中心像素处于滤波器正中间。该尺寸默认取9。均值滤波效果如图5.8所示。

图5.8 均值滤波效果

图5.8(a)为输入的带噪声的图像,图5.8(b)为均值滤波后的图像。可见,该方法能有效地消除一些高斯噪声,但也容易导致图像变得模糊。因此,对一些图像边界或是需要准确分割的区域,需要考虑使用边界处理的算法或者其他更好的方法。

5.4.2 中值滤波

中值滤波的原理与均值滤波相似,不同的是,它以像素为中心,取一个指定形状的邻域作为滤波器,该形状可以是正方形,也可以是圆形。然后将该区域内的像素灰度值进行排序,以排序结果的中间值作为灰度计算结果赋值给该区域内的像素。在Halcon中使用median_image算子进行均值滤波,代码举例如下:

read_image (ImageNoise, 'data/marker')
median_image (ImageNoise, ImageMedian, 'circle', 3, 'continued')
dev_display(ImageMedian)

在这个例子中,median_image算子的参数解释如下。

第1个参数ImageNoise是输入的带噪声的图像。

第2个参数ImageMedian是输出的中值滤波后的图像。

第3个参数是邻域的形状,这里选择circle,也可以选择square。

第4个参数是卷积核的尺寸,这里选择3,表示圆形的半径是3个像素。注意,如果第3个参数选择square,那么这里选择3,表示正方形的边长是2×3+1,即7。

第5个参数表示边界的处理方式,因为边界处往往无法移动滤波“窗口”,因此需要对像素做一些补充。这里选择continued,表示延伸边界像素。也可以选择cyclic,表示循环延伸边界像素。中值滤波效果如图5.9所示。

图5.9 中值滤波效果

由图5.9可知,该方法对于去除一些孤立的噪声点非常有效,也能够保留大部分边缘信息。但是在使用时也要注意滤波器的尺寸的选择,如果选得太大,也容易造成图像的模糊。

5.4.3 高斯滤波

高斯滤波与前两种方法不同的是,它利用的滤波器不是简单地求均值或者排序,而是调用一个二维离散的高斯函数。高斯滤波适用于去除高斯噪声。在Halcon中使用gauss_filter算子进行高斯滤波,代码举例如下:

read_image (ImageNoise, 'data/marker')
gauss_filter (ImageNoise, ImageGauss, 5)
dev_display(ImageGauss)

在这个例子中,gauss_filter算子的参数如下。

第1个参数ImageNoise是输入的带高斯噪声的图像。

第2个参数ImageGauss是输出的高斯滤波后的图像。

第3个参数是滤波器的尺寸,尺寸值越大,平滑效果就越明显。可以根据实际效果调节该参数,一般取3、5、7、9、11。高斯滤波效果如图5.10所示。

图5.10 高斯滤波效果

图5.10(a)为带高斯噪声的图像,图5.10(b)为应用了高斯滤波器后的图像。与前两种方法相比,高斯滤波能够保留更多的边缘和细节,图像更为清晰,平滑的效果也更加柔和。

5.5 光照不均匀

光照不均匀是采集图像时常见的一个问题,由于拍摄环境的光线变化导致图像受光不均匀,这将增加识别图像的难度。可以首先考虑改变硬件环境以避免这一情况,如增加遮光罩、增加光源,或者改变打光方式。硬件上的调整能显著地改善图像质量,为软件提供高质量的图像输入。但是如果条件有限,不便于改变硬件环境或重新采集图像,也可以通过软件算法改善这一情况。

改善光照的方式有很多,本节列举一种,即采用通道分离的方式对彩色图像进行光线均衡化处理。其步骤如下。

(1)输入光照不均匀的彩色图像。这里强调彩色图像,是因为黑白图像是单通道,不适用于这种方法,可以直接通过直方图均衡的方式对图像进行增强。

(2)分离出RGB通道。使用decompose3算子将图像分离成红绿蓝3个通道,并将每个通道单独存成一幅图像。

(3)对每个颜色通道的图像进行直方图均衡,使其色彩过渡更加平滑。

(4)将平滑后的3个通道的图像重新组合成三通道的彩色图像。这里使用compose3算子将三通道图像重新组合。

完成上述步骤的图像效果如图5.11所示。

图5.11 光照不均匀的图像处理效果

下面是实现这一过程的代码:

read_image (test, 'data/label')
decompose3(test, image1, image2, image3)
mean_image (image1, Mean1, 9, 9)
emphasize (Mean1, em1, 5, 5, 1.5)
illuminate (em1, ImageI1, 20, 20, 0.55)
equ_histo_image (image2, ImageEquHisto2)
equ_histo_image (image3, ImageEquHisto3)
compose3 (ImageI1, ImageEquHisto2, ImageEquHisto3, MultiChannelImage)
dev_display(MultiChannelImage)

由图5.11可以看出,图像光线不均匀的情况有所改善,阴影部分的文字也显露出来了,但是仍然存在局部较大,边缘不清晰等情况。因此,还应当结合前文介绍的去噪和平滑等方法,进一步增强图像质量。 8FEmXgelRnnlah49A64jHp1ZLQZFzNvzci/D3Dpsv4y1sNx7/JEY5UKJZosS4Yc0

点击中间区域
呼出菜单
上一章
目录
下一章
×