Halcon 第七章『图像的几何变换』◆第2节:投影变换

        一、介绍

        投影变换也叫透射变换投影映射。透射变换是将图像投影到一个新的视平面,是一种二维坐标到三维坐标的变换。

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

        透射变换是三维空间上的变换,因此,对于二维图像,最后一个原坐标z恒为1,变换矩阵的最后一个参数也恒为1。

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

        所以,透射变换的矩阵有8个未知数,要求解就需要找到4组映射点,四个点就刚好确定了一个三维空间。图像经过透视变换后通常不是平行四边形。与仿射变换类似,在经过变换之后,图像的灰度值也要经过图像插值计算,得到变换后的图像。

二维坐标(u,v)到三维坐标(x,y,z)的变换数学表达式

        二、Halcon中相关算子 

        Transformations / 2D Transformations

        根据给定点的投影计算一个同质变换矩阵

hom_vector_to_proj_hom_mat2d( : : Px, Py, Pw, Qx, Qy, Qw, Method : HomMat2D)

        Px:输入参数,图像变换前图像的顶点x坐标。

        Py:输入参数,图像变换前图像的顶点y坐标。

        Pw:输入参数,图像变换前图像的顶点w坐标。

        Qx:输入参数,图像变换后图像的顶点x坐标。

        Qy:输入参数,图像变换后图像的顶点y坐标。

        Qw:输入参数,图像变换后图像的顶点w坐标。

        Method:输入参数,变换方式选择。默认'normalized_dlt',

列表【

'dlt'算法最快速简单,但是有相对的不准确的误差

'normalized_dlt'速度与精度较好

】。

        HomMat2D:输出参数,输出齐次投影变换矩阵。

        Transformations / 2D Transformations

        根据给定点的投影计算一个投影变换矩阵

vector_to_proj_hom_mat2d( : : Px, Py, Qx, Qy, Method, CovXX1, CovYY1, CovXY1, CovXX2, CovYY2, CovXY2 : HomMat2D, Covariance)

        Px:输入参数,图像变换前图像的顶点x坐标。

        Py:输入参数,图像变换前图像的顶点y坐标。

        Qx:输入参数,图像变换后图像的顶点x坐标。

        Qy:输入参数,图像变换后图像的顶点y坐标。

        Method:输入参数,变换方式选择。默认 'normalized_dlt',

列表【

'dlt'算法最快速简单,但是有相对的不准确的误差

'gold_standard'优化较好但速度较慢

'normalized_dlt'速度与精度较好

        CovXX1:输入参数,图像变换前图像对应x值坐标的row方向的变动。默认[]。

        CovYY1:输入参数,图像变换前图像对应y值坐标的col方向的变动。默认[]。

        CovXY1:输入参数,图像变换前图像对应点的协方差。默认[]。

        CovXX2:输入参数,图像变换后图像对应x值坐标的row方向的变动。默认[]。

        CovYY2:输入参数,图像变换后图像对应y值坐标的col方向的变动。默认[]。

        CovXY2:输入参数,图像变换后图像对应点的协方差。默认[]。

        HomMat2D:输出参数,输出映射变换矩阵。

        Covariance:输出参数,输出9×9协方差矩阵的投影变换矩阵。

        Filters / Geometric Transformations

        对图像应用投影变换

projective_trans_image(Image : TransImage : HomMat2D, Interpolation, AdaptImageSize, TransformDomain : )

        Image:输入参数,输入需要变换的多通道图像。

        TransImage:输出参数,输出变换后的图像。

        HomMat2D:输入参数,输入变换矩阵。

        Interpolation:输入参数,插值的方式。默认 'bilinear',列表【 'bilinear', 'nearest_neighbor'】。

        AdaptImageSize:输入参数,是否自动调整输出图像的大小。默认'false',列表【'false', 'true'】。

        TransformDomain:输入参数,输入图像的域也应该进行变换吗?。默认'false',列表【'false', 'true'】。

        Regions / Geometric Transformations

        对区域应用投影变换

projective_trans_region(Regions : TransRegions : HomMat2D, Interpolation : )

        Regions:输入参数,输入区域。

        TransRegions:输出参数,输出变换后的区域。

        HomMat2D:输入参数,输入映射变换矩阵。

        Interpolation:输入参数,插值的方式。默认 'bilinear',列表【 'bilinear', 'nearest_neighbor'】。

         三、投影变换的案例

        1、vector_to_proj_hom_mat2d案例 

dev_set_draw('margin')
read_image(Image,'ecc200_to_preprocess_001.png')
*灰度阈值分割出区域
threshold(Image, Region, 0, 90)
*改变区域的形状为凸性
shape_trans(Region, RegionTrans, 'convex')
*生成XLD亚像素级轮廓,'border'边框像素的外边框作为轮廓点
gen_contour_region_xld(RegionTrans, Contours, 'border')
*将XLD轮廓分割成线段。
segment_contours_xld(Contours, ContoursSplit, 'lines', 5, 10, 1)
*保存四边形的顶点X坐标
X:=[]
*保存四边形的顶点y坐标
Y:=[]
*根据轮廓的相对位置排序
sort_contours_xld(ContoursSplit, SortedRegions, 'lower_left', 'true', 'row')
*计算元组中的数量
count_obj(SortedRegions, Number)
for Index:=1 to Number by 1
    *按顺序选择数据
    select_obj(SortedRegions, ObjectSelected, Index)
    *拟合直线
    fit_line_contour_xld(ObjectSelected, 'tukey', -1, 0, 5, 2, RowBegin, ColBegin, RowEnd, ColEnd, Nr, Nc, Dist)
    *统一整合元组
    tuple_concat(X,RowBegin,X)
    tuple_concat(Y,ColBegin,Y)   
endfor
*为每个输入点生成一个十字形状的XLD轮廓线
gen_cross_contour_xld(Cross,X,Y,10, 0.785398)
*根据给的变换前和变换后的数据计算一个投影矩阵
*[0,400,400,0],[0,0,400,400]这里的顺序一定要注意!!!,必须按照上面X和Y元组中的变换前的点的顺序
*且每个元组内是4这,因为要和上面变换前的坐标数量对应
vector_to_proj_hom_mat2d(X,Y,[0,400,400,0],[0,0,400,400],'normalized_dlt', [], [], [], [], [], [], HomMat2D, Covariance)
*对图像应用投影变换
projective_trans_image(Image,TransImage1, HomMat2D, 'bilinear', 'false', 'false')
ecc200_to_preprocess_001.png

        2、hom_vector_to_proj_hom_mat2d 案例

read_image(Image,'ecc200_to_preprocess_001.png')
X:=[130,225,290,63]
Y:=[101,96,289,269]
hom_vector_to_proj_hom_mat2d(X,Y,[1,1,1,1],[0,400,400,0], [0,0,400,400],[1,1,1,1],'normalized_dlt', HomMat2D)
projective_trans_image(Image, TransImage, HomMat2D, 'bilinear', 'false', 'false')

        3、案例3

*关闭当前显示窗口,清空屏幕
*dev_close_window ()
*读取测试图像
read_image (Image_display, '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
* 投影变换给四个特征点与校正后的坐标建立关联
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)
display.jpg

猜你喜欢

转载自blog.csdn.net/qq_45336030/article/details/125192341