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'】。

 

read_image (Image, 'BarCode.png')
*初始化角点存放
XCoordCorners:=[]
YCoordCorners:=[]
*二值化提取前景
threshold (Image, Regions, 0, 130)
*将前景融合为同一个前景
dilation_rectangle1(Regions, RegionDilation, 11, 11)
fill_up(RegionDilation, RegionFillUp)
erosion_rectangle1(RegionFillUp, RegionErosion, 11, 11)
union1(RegionErosion, RegionUnion)
*将区域转换为轮廓线进行拟合
gen_contour_region_xld(RegionUnion, Contours, 'border')
*线段分割及拟合
segment_contours_xld(Contours, ContoursSplit, 'lines_circles', 5, 7,7)
select_shape_xld (ContoursSplit, SelectedXLD1, 'contlength', 'and', 59.8, 5000000)
sort_contours_xld(SelectedXLD1, SortedContours, 'character', 'true', 'row')
gen_empty_obj(EmptyObject)
count_obj(SortedContours, Number)
RowBegin_totall:=[]
RowEnd_totall:=[]
ColBegin_totall:=[]
ColEnd_totall:=[]
for i:=1 to Number by 1
select_obj(SortedContours, ObjectSelected, i)
fit_line_contour_xld(ObjectSelected, 'tukey', -1, 0, 5, 2, RowBegin, ColBegin, RowEnd, ColEnd, Nr, Nc, Dist)
gen_contour_polygon_xld (Line1, [RowBegin,RowEnd], [ColBegin,ColEnd])
RowBegin_totall:=[RowBegin_totall,RowBegin]
RowEnd_totall:=[RowEnd_totall,RowEnd]
ColBegin_totall:=[ColBegin_totall,ColBegin]
ColEnd_totall:=[ColEnd_totall,ColEnd]
concat_obj(EmptyObject, Line1, EmptyObject)
endfor
*求线的交点
intersection_lines (RowBegin_totall[0], ColBegin_totall[0], RowEnd_totall[0], ColEnd_totall[0], \
RowBegin_totall[1], ColBegin_totall[1], RowEnd_totall[1], ColEnd_totall[1], RowUL, ColUL, IsOverlapping)
Corner_one:=[RowUL,ColUL]
intersection_lines (RowBegin_totall[0], ColBegin_totall[0], RowEnd_totall[0], ColEnd_totall[0], \
RowBegin_totall[2], ColBegin_totall[2], RowEnd_totall[2], ColEnd_totall[2], RowUL, ColUL, IsOverlapping)
Corner_two:=[RowUL,ColUL]
intersection_lines (RowBegin_totall[1], ColBegin_totall[1], RowEnd_totall[1], ColEnd_totall[1], \
RowBegin_totall[3], ColBegin_totall[3], RowEnd_totall[3], ColEnd_totall[3], RowUL, ColUL, IsOverlapping)
Corner_three:=[RowUL,ColUL]
intersection_lines (RowBegin_totall[2], ColBegin_totall[2], RowEnd_totall[2], ColEnd_totall[2], \
RowBegin_totall[3], ColBegin_totall[3], RowEnd_totall[3], ColEnd_totall[3], RowUL, ColUL, IsOverlapping)
Corner_four:=[RowUL,ColUL]
dev_close_window()
dev_open_window_fit_image(Image, 0, 0, -1, -1, WindowHandle)
dev_display(Image)

gen_empty_obj (CornerCrossAry)
gen_cross_contour_xld(Cross, Corner_one[0], Corner_one[1], 6, 0)
dev_display(Cross)
concat_obj (CornerCrossAry, Cross, CornerCrossAry)

gen_cross_contour_xld(Cross, Corner_two[0], Corner_two[1], 6, 0)
dev_display(Cross)
concat_obj (CornerCrossAry, Cross, CornerCrossAry)

gen_cross_contour_xld(Cross, Corner_three[0], Corner_three[1], 6, 0)
dev_display(Cross)
concat_obj (CornerCrossAry, Cross, CornerCrossAry)

gen_cross_contour_xld(Cross, Corner_four[0], Corner_four[1], 6, 0)
dev_display(Cross)
concat_obj (CornerCrossAry, Cross, CornerCrossAry)

*求需要校正后的坐标
Cornertrans_one:=[Corner_three[0],Corner_one[1]]
Cornertrans_two:=[Corner_four[0],Corner_one[1]]
Cornertrans_three:=[Corner_three[0],Corner_four[1]]
Cornertrans_four:=[Corner_four[0],Corner_four[1]]
dev_close_window()
dev_open_window_fit_image(Image, 0, 0, -1, -1, WindowHandle)
dev_display(Image)
gen_cross_contour_xld(Cross, Cornertrans_one[0], Cornertrans_one[1], 6, 0)
dev_display(Cross)
gen_cross_contour_xld(Cross, Cornertrans_two[0], Cornertrans_two[1], 6, 0)
dev_display(Cross)
gen_cross_contour_xld(Cross, Cornertrans_three[0], Cornertrans_three[1], 6, 0)
dev_display(Cross)
gen_cross_contour_xld(Cross, Cornertrans_four[0], Cornertrans_four[1], 6, 0)
dev_display(Cross)
*计算校正矩阵
ROWS:=[Corner_one[0],Corner_two[0],Corner_three[0],Corner_four[0]]
COLUMS:=[Corner_one[1],Corner_two[1],Corner_three[1],Corner_four[1]]
ROWS_TRANS:=[Cornertrans_one[0],Cornertrans_two[0],Cornertrans_three[0],Cornertrans_four[0]]
COLUMS_TRANS:=[Cornertrans_one[1],Cornertrans_two[1],Cornertrans_three[1],Cornertrans_four[1]]
hom_vector_to_proj_hom_mat2d(ROWS,COLUMS, [1,1,1,1], ROWS_TRANS, COLUMS_TRANS, [1,1,1,1], 'normalized_dlt', HomMat2D)
*投影变换


projective_trans_image(Image, TransImage, HomMat2D, 'bilinear', 'false', 'false')

 

posted @   QuincyYi  阅读(272)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律

喜欢请打赏

扫描二维码打赏

了解更多

点击右上角即可分享
微信分享提示