1. 单标外参使用背景
- 如果摄像机系统没有变化,只是测量面发生了移动或旋转,此时重标相机外参可以解决问题,这种方法可以解决斜测的问题。
2. 主要函数:
vector_to_pose( : : WorldX, WorldY, WorldZ, ImageRow, ImageColumn,CameraParam, Method, QualityType : Pose, Quality)
- //功能:利用世界坐标和像素坐标之间的关系计算出摄像机在世界坐标系中的姿态
- //WorldX, WorldY, WorldZ:世界坐标
- //mageRow, ImageColumn:像素坐标
- //CameraParam:内参
- //Method, QualityType :计算姿态方法,质量评估方法
- //Pose, Quality:返回姿态,质量
3. 代码
- 下面这两种情况是等价的,都属于斜测,用相机测量斜面上的目标。由两种方法可以解决此问题,透视变换法和单标法,这里先介绍单标法:
- 资源下载地址:
链接:https://pan.baidu.com/s/1DUQJjr9ntyKGb_etGs57fQ
提取码:2u20
halcon代码实现4点单标相机外参
* 1.读入已经标定好的相机内参
read_cam_par ('./campar.dat', CameraParam)
* 2.读入标定外参使用的图像(斜面上的标定板)
read_image (Image, './斜侧标定板图片.jpg')
* 3.处理图像,得到至少4个Mark点
binary_threshold (Image, Region, 'max_separability', 'dark', UsedThreshold)
connection (Region, ConnectedRegions)
select_shape (ConnectedRegions, SelectedRegions, ['area','row','column'], 'and', [0,372.22,575.99], [10113.8,574.44,868.94])
sort_region (SelectedRegions, SortedRegions, 'character', 'true', 'row')
area_center (SortedRegions, Area, Row, Column)
* 4.手动写入4个mark点的世界坐标
X:=[0,0.0037,0,0.0037]
Y:=[0,0,0.0037,0.0037]
Z:=[0,0,0,0]
* 5.标定相机外参
vector_to_pose (X, Y, Z, Row, Column, CameraParam, 'iterative', 'error', Pose, Quality)
write_pose (Pose, './4Pointcampose.dat')
*************至此,4点单标外参已经全部完成**********************************
*************以下使用一维测量标定板外边框尺寸来验证相机外参是否正确************
dev_display (Image)
Row:=694
Column:=987
Angle:=rad(90)//选择编写较大的一条边测量
Length1:=300
Length2:=10
get_image_size (Image, Width, Height)
gen_measure_rectangle2 (Row, Column, Angle, Length1, Length2, Width, Height, 'nearest_neighbor', MeasureHandle)
gen_rectangle2 (Rectangle,Row, Column, Angle, Length1, Length2)
measure_pos (Image, MeasureHandle, 2, 30, 'all', 'all', RowEdge, ColumnEdge, Amplitude, Distance)
dev_set_color ('green')
dev_set_draw ('margin')
dev_set_line_width (3)
dev_get_window (WindowHandle)
set_display_font (WindowHandle, 26, 'mono', 'true', 'false')
gen_empty_obj (ContoursObject)
dev_display (Image)
if(|RowEdge|==4)
gen_contour_polygon_xld (Contour1, \
[RowEdge[0]+Length2*cos(Angle),RowEdge[0]-Length2*cos(Angle)], \
[ColumnEdge[0]+Length2*sin(Angle),ColumnEdge[0]-Length2*sin(Angle)])
gen_contour_polygon_xld (Contour1, \
[RowEdge[3]+Length2*cos(Angle),RowEdge[3]-Length2*cos(Angle)], \
[ColumnEdge[3]+Length2*sin(Angle),ColumnEdge[3]-Length2*sin(Angle)])
dev_display (ContoursObject)
image_points_to_world_plane (CameraParam, Pose, RowEdge, ColumnEdge, 'mm', X1, Y1)
distance_pp (X1[0], Y1[0], X1[3], Y1[3], Distance1)
distance_pp (RowEdge[0], ColumnEdge[0], RowEdge[3], ColumnEdge[3], Distance2)
disp_line (WindowHandle, RowEdge[0], ColumnEdge[0], RowEdge[3], ColumnEdge[3])
disp_message (WindowHandle, 'L1='+Distance1, 'image', 12, 12, 'black', 'true')
disp_message (WindowHandle, 'L2='+Distance2, 'image', 12+100, 12, 'black', 'true')
disp_message (WindowHandle, '像素当量='+Distance1/Distance2, 'image', 12+200, 12, 'black', 'true')
endif
stop()
dev_display (Image)
Row:=633
Column:=956
Angle:=rad(0)
Length1:=300
Length2:=10
gen_measure_rectangle2 (Row, Column, Angle, Length1, Length2, Width, Height, 'nearest_neighbor', MeasureHandle)
gen_rectangle2 (Rectangle,Row, Column, Angle, Length1, Length2)
measure_pos (Image, MeasureHandle, 2, 30, 'all', 'all', RowEdge, ColumnEdge, Amplitude, Distance)
dev_display (Image)
if(|RowEdge|==4)
gen_contour_polygon_xld (Contour1, \
[RowEdge[0]+Length2*cos(Angle),RowEdge[0]-Length2*cos(Angle)], \
[ColumnEdge[0]+Length2*sin(Angle),ColumnEdge[0]-Length2*sin(Angle)])
gen_contour_polygon_xld (Contour1, \
[RowEdge[3]+Length2*cos(Angle),RowEdge[3]-Length2*cos(Angle)], \
[ColumnEdge[3]+Length2*sin(Angle),ColumnEdge[3]-Length2*sin(Angle)])
dev_display (ContoursObject)
image_points_to_world_plane (CameraParam, Pose, RowEdge, ColumnEdge, 'mm', X1, Y1)
distance_pp (X1[0], Y1[0], X1[3], Y1[3], Distance1)
distance_pp (RowEdge[0], ColumnEdge[0], RowEdge[3], ColumnEdge[3], Distance2)
disp_line (WindowHandle, RowEdge[0], ColumnEdge[0], RowEdge[3], ColumnEdge[3])
disp_message (WindowHandle, 'L1='+Distance1, 'image', 12, 12, 'black', 'true')
disp_message (WindowHandle, 'L2='+Distance2, 'image', 12+100, 12, 'black', 'true')
disp_message (WindowHandle, '像素当量='+Distance1/Distance2, 'image', 12+200, 12, 'black', 'true')
endif