使用Halcon变换与校正图像
文章目录
- 使用Halcon变换与校正图像
- 1. 二维图像的平移、旋转和缩放
- 1.图像的平移
- 2.图像的旋转
- 3.图像的缩放
- 2. 图像的仿射变换
- 3. 投影变换
- 4 实例:透视形变图像校正
由于相机拍摄的时候可能存在角度偏差,因此实际获得的画面可能会与想象中有所差异。例如采集连续目标时,可能每幅图中目标区域的位置和角度都不一样;又或者目标对象是一块矩形区域,而在采集到的图像中,这一块可能变成了梯形或扭曲的四边形。
因此,接下来要做的第一件事,就是把这块区域进行一些调整,使之恢复成原本的矩形区域。
本节就以解决图像形状失真问题为目的,介绍Halcon中的图像二维变换方法。
1. 二维图像的平移、旋转和缩放
为了校正图像在拍摄中的失真问题,可以对图像进行一些简单的几何变换,如平移、缩放和旋
转等,这些是图形学中的基本几何变换。
一个点P。的位置可以用3个坐标表示(xp,Pp2,),这3个坐标也可以看成一个3D向量。
1.图像的平移
如果将这个点移动(x,y)个向量,相当于在p坐标的左边乘以一个平移矩阵T。设平移后的
点为p,如公式所示。
2.图像的旋转
如果将这个点在二维平面上绕坐标原点旋转角度y,相当于在p坐标的左边乘以一个旋转矩阵
R。设旋转后的点为pr,如公式所示。
3.图像的缩放
假设这个点在二维平面上,沿x轴方向放大s倍,沿y轴方向放大s倍,那么变化后的该点
的坐标记为p,如公式所示。
2. 图像的仿射变换
把平移、旋转和缩放结合起来,可以在Halcon中使用仿射变换的相关算子。一个仿射变换矩阵包括平移向量和旋转向量。
1.仿射变换矩阵
在仿射变换前,先确定仿射变换矩阵,步骤如下。
(1)使用hom_mat2d_identity(HomMat2DIdentity)创建一个空的仿射变换矩阵。
(2)指定变换的参数,这里可以指定平移、缩放、旋转参数,举例如下。
设置平移矩阵,向x轴正方向平移30个像素,向y轴正方向平移30个像素:hom_mat2d
translate (HomMat2DIdentity, 30, 30, HomMat2DTranslate).
设置旋转矩阵,以点(P2,P,)为参考点,旋转角度phi:hom mat2d rotate (HomMat2DIdentity
rad(phi),Px,Py, HomMat2DRotate)。
设置缩放矩阵,以点(PP,)为参考点,放大2倍:hom_mat2d_scale(HomMat2DRotate,2,2,
Px,Py,HomMat2DScale)。
2.应用仿射变换矩阵
仿射变换矩阵可以应用于像素点(Pixel)、二维点(Point)、图像(Image)、区域(Region)及XLD轮廓等对象。下面分别举例。
(1)应用于像素点:使用affine_trans_pixel算子。
(2)应用于二维点:使用affine_transpoint2d算子。
(3)应用于图像:使用affine_trans _image算子。
(4)应用于区域:使用affine_trans region算子。
(5)应用于XLD轮廓:使用affine_trans_contour_xld算子。
3. 投影变换
上文介绍的仿射变换其实是投影变换的一个特殊例子,其特殊性在于变换后图像的形状仍然维持原状。投影变换包括的情况很多,有可能变换前后图像的形状发生了很大的改变,如对边不再平行,或者发生了透视畸变等,这时可以使用投影变换使其恢复原状。其步骤与仿射变换类似,首先计算投影变换矩阵,然后计算投影变换参数,最后将投影变换矩阵映射到对象上。
要计算投影变换矩阵,应找出投影区域的特征点的位置及其投影后的位置,通过hom_vector to proj_hom_mat2d算子进行换算,就可以根据已知的投影对应的点的值计算投影变换矩阵。然后使用projective_trans_image对图像进行投射变换,就能得到投影后的图像了。下面用一个实例进行介绍。
4 实例:透视形变图像校正
透视形变图像校正步骤如下。
(1)读取图像,并对图像进行简单的处理,分割出目标形变区域。
(2)获取形变区域的轮廓,并计算出顶点坐标信息。
(3)利用上一步得出的坐标信息,计算投影变换矩阵。
(4)进行投影变换。
透视形变图像校正结果如图所示。
实现代码参考如下:
*关闭当前显示窗口,清空屏幕
dev_close_window ()
*读取测试图像
read _image (Image _display, 'data/display.jpg')
*将图像转化为灰度图像
rgbl_to_gray (Image _display, GrayImage)
*获取图像的尺寸
get_image_size (Image_display, imagewidth, imageHeight)
*新建显示窗口,适应图像尺寸
dev_open_window (0, 0, imageWidth, imageHeight, 'black', WindowHandlel)
dev_display (GrayImage)
*初始化角点坐标
XCoordCorners := []
YCoordCorners := []
*阈值处理,提取较暗的区域
threshold(GrayImage,DarkRegion,0,
*分离不相连的区域
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 (0bjectcurrent, 'tukey', -1, 0, 5, 2, RowBegin, ColBegin, RowEnd, ColEnd, NI, 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)