由于相机拍摄的时候可能存在角度偏差,因此实际获得的画面可能会与想象中有所差异。为了校正图像在拍摄中的失真问题,可以对图像进行一些简单的几何变换,如平移、缩放和旋转等,这些是图形学中的基本几何变换。
图像的几何变换只改变图像的位置、形状、尺寸等几何特征,不改变图像的拓扑信息。适当的几何变换可以在很大程度上消除由于成像角度、透视关系乃至镜头自身原因造成的图像几何失真。
图像的几何变换又称为图像空间变换,它将一副图像中像素映射到另一幅图像中的新位置。几何变换不改变图像的像素值,只是在图像平面上进行像素的重新安排。
在数字图像处理中,一个几何变换需要两部分的运算:
①首先是空间变换所需的运算,如平移、旋转、镜像等,需要用它来表示输出图像和输入图像之间的像素的映射关系。
②空间变换计算出的输出图像的像素很可能被映射到非整数坐标上,因此,还需要进行灰度插值计算,这部分运算处理空间变换后图像中像素灰度级的赋值。
常见的图像几何变换包括:位置变换(图像平移、镜像、旋转)、形状变换(处理图像的缩放、错切、透射)等。
图像的位置变换是指图像的尺寸和形状不发生变换,只是将图像进行平移、镜像或旋转。图像的位置变换经常应用在目标配准领域。
注意:平移、缩放和旋转都需要有一个参考点,围绕该点进行仿射变换操作。
1、图像的平移变换
图像是由像素组成的,而像素的集合就相当于一个二维的矩阵,每一个像素都有一个“位置”,也就是坐标。平移变换是将图像中的点按照要求进行平移。平移变换是一种“刚体变换”,图像不会产生形变,线段的长度、线与线的夹角都不会变换,只有图像的位置会发生变化。变换的矩阵为:
如果将这个点移动个向量,相当于在p坐标的左边乘以一个平移矩阵T。则
平移后的图像内容没有变化,但是“画布”一定要扩大,否则会丢失信息。
Transformations / 2D Transformations 设置平移矩阵 hom_mat2d_translate( : : HomMat2D, Tx, Ty : HomMat2DTranslate) HomMat2D:输入参数,输入变换矩阵。 Tx:输入参数,x的平移量,即沿着x轴平移的像素。默认64,建议值【0, 16, 32, 64, 128, 256, 512, 1024】。 Ty:输入参数,y的平移量,即沿着y轴平移的像素。默认64,建议值【0, 16, 32, 64, 128, 256, 512, 1024】。 HomMat2DTranslate:输出参数,输出变换矩阵。 |
2、图像的旋转变换
图像的旋转是指以图像中的某点为原点,按照顺时针或逆时针旋转一定的角度。旋转变换也是一种“刚体变换”,图像不会产生形变,线段的长度、线与线的夹角都不会变化,只有图像的位置会发生变化。变换矩阵为:
如果将这个点在二维平面上绕坐标原点旋转角度γ,相当于在坐标的左边乘以一个旋转矩阵R。设旋转后的点为Pr
θ为旋转角度,读法“西塔”。
Transformations / 2D Transformations 设置旋转矩阵 hom_mat2d_rotate( : : HomMat2D, Phi, Px, Py : HomMat2DRotate) HomMat2D:输入参数,输入变换矩阵。 Phi:输入参数,输入旋转的角度。默认0.78,建议值【 0.1, 0.2, 0.3, 0.4, 0.78, 1.57, 3.14】,典型值范围【0 ≤ Phi ≤ 6.28318530718】。 Px:输入参数,输入选择的定位点,x值坐标。默认0,建议值【0, 16, 32, 64, 128, 256, 512, 1024】。 Py:输入参数,输入选择的定位点,y值坐标。默认0,建议值【0, 16, 32, 64, 128, 256, 512, 1024】。 HomMat2DRotate:输出参数,输出变换矩阵。 |
3、图像的镜像变换
镜像变换是以x轴、y轴或者对角线为镜像轴,对图像进行镜像变换。
镜像矩阵如上,左边矩阵是以x轴为镜像轴,中间矩阵是以y轴为镜像轴,右边矩阵是以对角线为镜像轴。
Filters / Geometric Transformations 对图像进行镜像变换 mirror_image(Image : ImageMirror : Mode : ) Image:输入参数,输入图像。 ImageMirror:输出参数,输出图像。 Mode:输入参数,选择镜像轴。默认'row',列表【'column'列镜像轴, 'diagonal'对角镜像轴, 'row'行镜像轴】。 |
Regions / Geometric Transformations 对区域进行镜像变换 mirror_region(Region : RegionMirror : Mode, WidthHeight : ) Region:输入参数,输入区域。 RegionMirror:输出参数,输出区域。 Mode:输入参数,默认'row',列表【'column'列镜像轴, 'diagonal'对角镜像轴, 'row'行镜像轴】。 WidthHeight:输入参数,在图像中,镜像线的位置。默认512(输入值除以2),建议值【128, 256, 512, 525, 768, 1024】,典型值范围【 1 ≤ WidthHeight ≤ 1024 (lin)】,最小增量1,范围【 WidthHeight > 0】。 |
图像的形状变换是指图像的形状发生了变化,主要包括放大、缩小、错切。
1、图像的缩小
图像的缩小有按比例缩小和不安比例缩小两种情况。图像缩小后,像素的个数减少,承载的信息量少了,图像尺寸可以相应缩小。
图形缩小有两个方法和区别:
①基于等间隔采样的缩小方法:通过对原图的均匀采样,等间隔地选取一部分像素,从而获得小尺寸图像的数据,并且尽量保持原有图像特征不丢失。但是因为采样点选择不同,有可能得到不同的计算结果,所以实际上无法反映被采样的像素的真实值。
②基于局部均值的缩小方法:先按行列缩小比例,计算采样间隔Δi=1/k1,Δj=1/k2,得到采样点的坐标,其中k1和k2上图像缩小的比例;再以采样点为中心,在一定局域内,求区域内所有原图像的像素值的均值,作为新图像的像素值。这样缩小的图像效果会比较自然,因为包含了所有像素的信息。
备注: Δ,是希腊字母中的一个大写字母,其小写形式为δ,读音是"德尔塔",音标中为/deltə/。
2、图像的放大
图像放大有两种方法
①基于像素放大原理的图像放大方法
基于像素放大原理的图像放大方法的思想是:如果需要将原图放大k倍,则将原图像中的每个像素值,填在新图像中对应的k×k大小的子块中。缺点在于这种方法会导致所有的像素放大后呈现出一个矩形块,因此图像中会出现“马赛克现象”。
②基于双线性插值的图像放大方法
基于双线性插值的图像放大方法能够有效消除图像放大时出现的“马赛克现象”,使得图像的放大效果更加自然。
基于双线性插值的图像放大步骤如下:
⑴确定每一个原图像的像素所在新图像中对应的子块。
⑵对新图像中的每一个子块,仅对其一个像素进行填充。在每个子块中选取一个填充像素的方法如下:
对右下角的子块,选取子块中的右下角的像素。
对末列、非末行子块,选取子块的右上角像素。
对末行、非末列子块,选取子块的左下角像素。
对剩余的子块,选取子块中的左上角像素。
⑶通过双线性插值方法计算剩余像素的值:对所有填充像素所在的列中的其他像素的值,可以根据该像素的上方与下方的已填充的像素值,采用双线性插值方法计算得到。
⑷对剩余像素的值,可以利用该像素的左方与右方的已填充像素的值,通过线性插值方法计算得到。
Filters / Geometric Transformations 把图像缩放到指定比例大小 zoom_image_factor(Image : ImageZoomed : ScaleWidth, ScaleHeight, Interpolation : ) Image:输入参数,输入图像。 ImageZoomed:输出参数,输出缩放后的图像。 ScaleWidth:输入参数,宽度反向的比例。默认0.5,典型值范围【 0.001 ≤ ScaleWidth ≤ 10.0】,最小增量0.001。 ScaleHeight:输入参数,高度反向的比例。默认0.5,典型值范围【 0.001 ≤ ScaleWidth ≤ 10.0】,最小增量0.001。 Interpolation:输入参数,插值的类型。默认'constant',列表【 'bilinear'双线性插值, 'constant'等权双线性插值法, 'nearest_neighbor'最近邻插值, 'weighted'高斯加权双线性插值法】。 其他的插值:双三次插值法(bicubic) 【Halcon】插值算法通俗讲解_熊猫袋鼠骆驼的博客-CSDN博客_什么叫插值法通俗易懂 |
Filters / Geometric Transformations 将图形缩放到指定的大小(分辨率) zoom_image_size(Image : ImageZoom : Width, Height, Interpolation : ) Image:输入参数,输入图像。 ImageZoom:输出参数,输出缩放后的图像。 Width:输入参数,生成后图像的宽度。默认512,典型值范围【2 ≤ Width ≤ 512】,最小增量1。 Height:输入参数,生成后图像的高度。默认512,典型值范围【2 ≤ Width ≤ 512】,最小增量1。 Interpolation:输入参数,插值的类型。默认'constant',列表【 'bilinear', 'constant', 'nearest_neighbor', 'weighted'】。 |
Regions / Geometric Transformations 缩放一个区域,以原点为中心。 zoom_region(Region : RegionZoom : ScaleWidth, ScaleHeight : ) Region:输入参数,输入区域。 RegionZoom:输出参数,输出缩放后的区域。 ScaleWidth:输入参数,x反向(宽度)的放大倍数。默认2.0,典型值范围【0.0 ≤ ScaleWidth ≤ 100.0 (lin)】,最小增量0.01。 ScaleHeight:输入参数,y反向(高度)的放大倍数。默认2.0,典型值范围【0.0 ≤ ScaleWidth ≤ 100.0 (lin)】,最小增量0.01。 |
图像的缩放数学表达式:假设这个点在二维平面上,沿x轴方向放大Sx倍,沿y轴方向放大Sy倍,那么变化后的该点的坐标为Ps
3、图像的错切(也叫剪切变换)
图像的错切变换可以看成是平面景物在投影平面上的非垂直投影效果。
错切变换可分为两种。一种上水平错切,水平方向的线段发生倾斜。另一种垂直错切,垂直方向的线段发生倾斜。
Transformations / 2D Transformations 错切算子,为一个齐次二维矩阵添加一个拉伸 hom_mat2d_slant( : : HomMat2D, Theta, Axis, Px, Py : HomMat2DSlant) HomMat2D:输入参数,输入变换矩阵。 Theta:输入参数,输入倾斜角度。单位弧度。默认0.78,建议值【 0.1, 0.2, 0.3, 0.4, 0.78, 1.57, 3.14】,典型值范围【0 ≤ Theta ≤ 6.28318530718】。 Axis:输入参数,输入倾斜的轴为x轴或y轴。列表【'x', 'y'】。 Px:输入参数,输入倾斜的中心点x值坐标。默认0,建议值【0, 16, 32, 64, 128, 256, 512, 1024】。 Py:输入参数,输入倾斜的中心点y值坐标。默认0,建议值【0, 16, 32, 64, 128, 256, 512, 1024】。 HomMat2DSlant:输出参数,输出倾斜变换后的矩阵。 |
Transformations / 2D Transformations 错切算子,为一个齐次二维矩阵添加一个拉伸(以指定位置) hom_mat2d_slant_local( : : HomMat2D, Theta, Axis : HomMat2DSlant) HomMat2D:输入参数,输入变换矩阵。 Theta:输入参数,输入倾斜角度。单位弧度。默认0.78,建议值【 0.1, 0.2, 0.3, 0.4, 0.78, 1.57, 3.14】,典型值范围【0 ≤ Theta ≤ 6.28318530718】。 Axis::输入参数,输入倾斜的轴为x轴或y轴。列表【'x', 'y'】。 HomMat2DSlant:输出参数,输出倾斜变换后的矩阵。 |
把平移、旋转和缩放结合起来,可以在Halcon中使用仿射变换的相关算子。一个仿射变换矩阵包括平移向量和旋转向量。
1、仿射变换矩阵
在仿射变换前,先确定仿射变换矩阵。
①使用hom_mat2d_identity(HomMat2DIdentity)创建一个空的仿射变换矩阵。
Transformations / 2D Transformations 构建一个2D变换的仿射变换矩阵 hom_mat2d_identity( : : : HomMat2DIdentity) HomMat2DIdentity:输出参数,输出变换矩阵。 |
②指定变换的参数,这里可以指定平移、缩放、旋转参数。
例如:
设置平移矩阵,向x轴正方向平移30个像素,向y轴正方向平移30个像素:hom_mat2d_translate(HomMat2DIdentity,30,30,HomMat2DTranslate)。
设置旋转矩阵,以点(Px,Py)为参考点,旋转角度phi:hom_mat2d_rotate(HomMat2DIdentity,rad(phi), Px, Py : HomMat2DRotate)。
设置错切矩阵,以点(Px,Py)为参考点,放大2倍:hom_mat2d_scale(HomMat2DRotate,2,2,Px,Py,HomMat2DScale)。
备注:在Halcon中缩放变换zoom_image_factor,zoom_image_size,zoom_region和镜像变换mirror_image、mirror_region直接可以输出结果。
2、应用仿射变换矩阵
仿射变换矩阵可以应用于像素点(Pixel)、二维点(Point)、图像(Image)、区域(Region)及XLD轮廓等对象。
①应用于像素点:使用affine_trans_pixel算子
Transformations / 2D Transformations 对像素坐标应用仿射2D变换 affine_trans_pixel( : : HomMat2D, Row, Col : RowTrans, ColTrans) HomMat2D:输入参数,输入一个二维变换矩阵。 Row:输入参数,输入图像点阵的x值坐标。默认64,建议值【0, 16, 32, 64, 128, 256, 512, 1024】。 Col:输入参数,输入图像点阵的y值坐标。默认64,建议值【0, 16, 32, 64, 128, 256, 512, 1024】。 RowTrans:输出参数,输出转换后的图像点阵的y值坐标。 ColTrans:输出参数,输出转换后的图像点阵的x值坐标。 |
②应用于二维点:使用affine_trans_point_2d算子
Transformations / 2D Transformations 对点应用仿射2D变换 affine_trans_point_2d( : : HomMat2D, Px, Py : Qx, Qy) HomMat2D:输入参数,输入一个二维变换矩阵。 Px:输入参数,输入坐标x点。默认64,建议值【0, 16, 32, 64, 128, 256, 512, 1024】。 Py:输入参数,输入坐标y点。默认64,建议值【0, 16, 32, 64, 128, 256, 512, 1024】。 Qx:输出参数,输出变换后的x点坐标。 Qy:输出参数,输出变换后的y点坐标。 |
③应用于图像:affine_trans_image算子
Filters / Geometric Transformations 对图像应用仿射2D变换 affine_trans_image(Image : ImageAffineTrans : HomMat2D, Interpolation, AdaptImageSize : ) Image:输入参数,输入一个多通道图像。 ImageAffineTrans:输出参数,输出转换后的图像。 HomMat2D:输入参数,输入变换矩阵。 Interpolation:输入参数,插值类型的选择。默认'constant',列表【'bilinear', 'constant', 'nearest_neighbor', 'weighted'】。 AdaptImageSize:输入参数,适应大小的结果图像。默认'false',列表【'false', 'true'】。 |
Filters / Geometric Transformations 对图像应用仿射2D变换,并且指定输出图像的大小。 affine_trans_image_size(Image : ImageAffinTrans : HomMat2D, Interpolation, Width, Height : ) Image:输入参数,输入一个多通道图像。 ImageAffinTrans:输出参数,输出转换后的图像。 HomMat2D:输入参数,输入变换矩阵。 Interpolation:输入参数,插值类型的选择。 Width:输入参数,指定输出图像的宽度。 Height:输入参数,指定输出图像的高度。 |
④应用于区域:affine_trans_region算子
Regions / Geometric Transformations 对区域应用仿射2D变换 affine_trans_region(Region : RegionAffineTrans : HomMat2D, Interpolate : ) Region:输入参数,输入需要进行变换的区域。 RegionAffineTrans:输出参数,输出变换后的区域。 HomMat2D:输入参数,输入变换矩阵。 Interpolate:输入参数,变换被当作插入使用。 |
⑤应用于XLD轮廓:affine_trans_contour_xld算子
XLD / Geometric Transformations 对XLD轮廓应用仿射2D变换 affine_trans_contour_xld(Contours : ContoursAffineTrans : HomMat2D : ) Contours:输入参数,输入XLD轮廓。 ContoursAffineTrans:输出参数,输出变换后的XLD轮廓。 HomMat2D:输入参数,输入变换矩阵。 |
XLD / Geometric Transformations 对XLD多边形应用仿射2D变换 affine_trans_polygon_xld(Polygons : PolygonsAffinTrans : HomMat2D : ) Polygons:输入参数,输入XLD多边形。 PolygonsAffinTrans:输出参数,输出变换后的XLD多边形。 HomMat2D:输入参数,输入变换矩阵。 |
1、图像旋转变换
read_image(Image,'25interleaved_exposure_04.png')
*灰度阈值分割出较为明亮的区域
threshold(Image, Regions, 49, 255)
*将相连的区域分别连通为一体
connection(Regions, ConnectedRegions)
*筛选出面积最大的那个
select_shape(ConnectedRegions, SelectedRegions, 'area', 'and', 78000, 230000)
*改变SelectedRegions区域的形状,rectangle2为最小的封闭矩形。
shape_trans(SelectedRegions, RegionTrans, 'rectangle2')
*计算区域的RegionTrans的面积和中心坐标
area_center(RegionTrans, Area, Row, Column)
*以原图为底,提取出原图RegionTrans区域内的像素。
reduce_domain(Image, RegionTrans, ImageReduced)
*计算区域的朝向角度
orientation_region(RegionTrans, Phi)
*构建一个空的仿射2d变换矩阵
hom_mat2d_identity(HomMat2DIdentity)
*设置旋转矩阵
hom_mat2d_rotate(HomMat2DIdentity, -Phi, Row, Column, HomMat2DRotate)
*应用仿射变换
affine_trans_image(ImageReduced, ImageAffineTrans, HomMat2DRotate, 'constant', 'false')
原图 进行旋转变换后的图像
2、图像镜像变换
read_image(Image, 'green-dot.png')
threshold(Image, Region, 0, 133)
connection(Region, ConnectedRegions)
*筛选出面积范围内的区域
select_shape(ConnectedRegions, SelectedRegions, 'area', 'and', 8900, 67000)
*沿着x轴方向镜像
mirror_region(SelectedRegions, RegionMirror1, 'row', 512)
*沿着y轴方向镜像
mirror_region(SelectedRegions, RegionMirror2, 'column', 512)
green-dot.png
参考文献:
杨青—《Halcon机器视觉算法原理与编程实战》
郭森—《工业机器视觉基础教程 HALCON篇》