halcon定位测量(Halcon自标定做畸变校正)
一 、Halcon有个算子可以实现利用单张图像 ,标定出相机内参 ,用来做畸变校正 。不过对图片有要求 ,因为畸变越靠近图像边缘 ,就会越严重 。所以要求图片的四周有足够的直线 ,最好图像中间部分也有足够的直线。提取这些直线 ,后面标定之后会把这些产生畸变的直线拉直 ,实现畸变校正 。这个功能类似Visionpro里面的CheckBoard标定 ,只不过CheckBoard标定后 ,可以直接把像素坐标转换到世界坐标,转换后的图用来测量可以直接输出毫米mm 。而Halcon自标定算子标定后 ,只能用于畸变校正 。如需要用于转换到世界坐标 ,需要另加计算像素当量 。
二 、算子详解
2.1 radial_distortion_self_calibration(Contours : SelectedContours : Width, Height, InlierThreshold, RandSeed, DistortionModel, DistortionCenter, PrincipalPointVar : CameraParam)名字:径向畸变自标定
描述:此算子通过XLD轮廓数据来估算镜头的畸变参数和畸变中心 。其获得的即便参数通过相机内参数CameraParam返回 。此算子不能矫正焦距和比例因子,因此不能用于3D测量中 。参数:
Contours :输入用来矫正的轮廓数据
SelectedContours :矫正后的轮廓数据
Width:获取轮廓数据的图像宽度
Height:获取轮廓数据的图像高度
InlierThreshold:分类阈值
RandSeed:随机种子
DistortionModel:畸变模式
DistortionCenter:畸变中心的估算模式 ,决定使用何种方式估计失真中心 。有 ‘variable’(默认 ,适用于图像边缘轮廓线很多或者失真应该很高 。否则,在寻找畸变中心时可能会出现不适定性 ,从而导致不稳定性。)‘adaptive’(如果可以假定畸变中心位于图像中心附近 ,并且只有很少的等值线可用或其他等值线的位置不好(例如等值线方向相同) ,则应使用这种方法), ‘fixed’(该方法适用于失真很弱或轮廓线少的情况下 ,在不好的位置 。)
PrincipalPointVar :偏差控制 ,控制畸变中心与图像中心的偏差
CameraParam:输出相机内参数2.2 change_radial_distortion_cam_par( : : Mode, CamParamIn, DistortionCoeffs : CamParamOut)
名字:矫正畸变参数
描述:根据指定的径向畸变系数 ,求取理想无畸变的相机内参 。
参数:Mode:畸变模式
CamParamIn:畸变的相机内部参数
DistortionCoeffs :畸变系数值
CamParamOut:已校正的相机内参2.3 change_radial_distortion_image(Image, Region : ImageRectified : CamParamIn, CamParamOut : )
名字:矫正畸变图像
描述:根据指定图像和指定相加参数来矫正输入图像的畸变。change_radial_distortion_image根据摄像机内部参数CamParamIn和CamParamOut对输入图像图像的径向畸变进行改变 。使用CamParamOut将位于区域区域内的输出图像的每个像素转换为图像平面 ,然后使用CamParamIn将其投影为图像的亚像素 。通过双线性插值确定得到的灰度值。如果该亚像素在图像之外 ,则将图像重建中的对应像素设置为“黑色 ”并从图像域中消除 。参数:
Image:输入图像
Region :矫正图像的区域
ImageRectified :矫正图像
CamParamIn:输入相机参数
CamParamOut :输出相机参数
2.4 gen_radial_distortion_map(Map, CameraParam, CamParamOut, ‘bilinear’)
map_image(Imagecalib, Map, ImageMapped)
这两个算子联合可以实现2.3的图像畸变校正功能 。
三 、案例
3.1 Halcon官方案例 *这个程序展示了如何radial_distortion _selfcalibration可以用来 *校准径向畸变系数和中心 *扭曲 。在程序的第一部分 ,从边缘提取 *一个图像用于校准 。结果表明 *径向畸变提取相当准确的从单一 *图像 。为了提高准确性,程序的第二部分显示 *如何从20张图像中提取的边缘可以用来执行 *校准 。因为这些边出现在很多不同的方向 * 20张图片 ,主点可以确定的明显更多 *准确 。 dev_update_off () read_image (Image, board/board-01) dev_close_window () dev_open_window_fit_image (Image, 0, 0, -1, -1, WindowHandle) set_display_font (WindowHandle, 16, mono, true, false) dev_display (Image) disp_message (WindowHandle, Image with radial distortions, window, 0, 0, black, true) disp_continue_message (WindowHandle, black, true) stop () * Extract subpixel-precise edges using the Canny filter. edges_sub_pix (Image, Edges, canny, 1, 10, 40) * Segment the edges into lines and circular arcs. segment_contours_xld (Edges, SplitEdges, lines_circles, 5, 4, 2) * Select edges that are long enough to be useful for the calibration. select_shape_xld (SplitEdges, SelectedEdges, contlength, and, 30, 100000) dev_display (Image) dev_set_colored (12) dev_display (SelectedEdges) disp_message (WindowHandle, Extracted edges, window, 0, 0, black, true) disp_continue_message (WindowHandle, black, true) stop () dev_clear_window () disp_message (WindowHandle, Performing self-calibration..., window, 0, 0, black, true) *执行径向畸变的自我校准 。 radial_distortion_self_calibration (SelectedEdges, CalibrationEdges, 646, 492, 0.08, 42, division, variable, 0, CamParSingleImage) *校正图像 ,即去除径向畸变 。 get_domain (Image, Domain) change_radial_distortion_cam_par (fixed, CamParSingleImage, 0, CamParSingleImageRect) change_radial_distortion_image (Image, Domain, ImageRectified, CamParSingleImage, CamParSingleImageRect) * Display the distorted and undistorted image five times to visualize the * differences between the images. dev_display (Image) dev_display (CalibrationEdges) disp_message (WindowHandle, Edges used for calibration, window, 0, 0, black, true) disp_continue_message (WindowHandle, black, true) stop () dev_display (ImageRectified) disp_message (WindowHandle, Image without radial distortions, window, 0, 0, black, true) disp_continue_message (WindowHandle, black, true) stop () * Now perform the self-calibration using edges extracted from 20 images. * The variable Edges will accumulate the edges extracted from the images. gen_empty_obj (Edges) for J := 1 to 20 by 1 read_image (Image, board/board- + J$02d) * Extract subpixel-precise edges using the Canny filter. edges_sub_pix (Image, ImageEdges, canny, 1, 10, 40) * Segment the edges into lines and circular arcs. segment_contours_xld (ImageEdges, SplitEdges, lines_circles, 5, 4, 2) * Select edges that are long enough to be useful for the calibration. select_shape_xld (SplitEdges, SelectedEdges, contlength, and, 30, 100000) * Accumulate the edges. concat_obj (Edges, SelectedEdges, Edges) dev_display (Image) dev_set_colored (12) dev_display (SelectedEdges) disp_message (WindowHandle, Edges extracted from image + J$d, window, 0, 0, black, true) endfor dev_clear_window () dev_set_colored (12) dev_display (Edges) disp_message (WindowHandle, Collected edges from multiple images, window, 0, 0, black, true) disp_continue_message (WindowHandle, black, true) stop () dev_clear_window () disp_message (WindowHandle, Performing self-calibration..., window, 0, 0, black, true) *执行径向畸变的自我校准。 radial_distortion_self_calibration (Edges, CalibrationEdges, 646, 492, 0.08, 42, division, variable, 0, CamParMultiImage) dev_clear_window () dev_set_colored (12) dev_display (CalibrationEdges) disp_message (WindowHandle, Edges used for calibration, window, 0, 0, black, true) disp_continue_message (WindowHandle, black, true) stop () *计算未失真图像的相机参数 。 change_radial_distortion_cam_par (fixed, CamParMultiImage, 0, CamParMultiImageRect) for J := 1 to 20 by 1 read_image (Image, board/board- + J$02d) get_domain (Image, Domain) *校正图像,即去除径向畸变 。 change_radial_distortion_image (Image, Domain, ImageRectified, CamParMultiImage, CamParMultiImageRect) * Display the distorted and undistorted image to visualize the * differences between the images. dev_display (Image) disp_message (WindowHandle, Image with radial distortions, window, 0, 0, black, true) wait_seconds (0.5) dev_display (ImageRectified) disp_message (WindowHandle, Image without radial distortions, window, 0, 0, black, true) wait_seconds (0.5) endfor原图
用来畸变校正的XLD
畸变校正后的图
3.2 个人编写案例 dev_update_off () read_image (Image, C:/Users/Dell/Desktop/Halocn自标定畸变校正/畸变校正.jpg) get_image_size (Image, Width, Height) dev_close_window () dev_open_window_fit_image (Image, 0, 0, -1, -1, WindowHandle) set_display_font (WindowHandle, 16, mono, true, false) dev_display (Image) disp_message (WindowHandle, Image with radial distortions, window, 0, 0, black, true) disp_continue_message (WindowHandle, black, true) stop () * Extract subpixel-precise edges using the Canny filter. edges_sub_pix (Image, Edges, canny, 1, 10, 40) * Segment the edges into lines and circular arcs. segment_contours_xld (Edges, SplitEdges, lines_circles, 5, 4, 2) * Select edges that are long enough to be useful for the calibration. select_shape_xld (SplitEdges, SelectedEdges, contlength, and, 30, 100000) dev_display (Image) dev_set_colored (12) dev_display (SelectedEdges) disp_message (WindowHandle, Extracted edges, window, 0, 0, black, true) disp_continue_message (WindowHandle, black, true) stop () dev_clear_window () disp_message (WindowHandle, Performing self-calibration..., window, 0, 0, black, true) *名字:径向畸变自标定 *描述:此算子通过XLD轮廓数据来估算镜头的畸变参数和畸变中心。其获得的即便参数通过相机内参数CameraParam返回 。 *此算子不能矫正焦距和比例因子 ,因此不能用于3D测量中 。 *若相机模型为area(division) ,则相机参数为7个,若area(多项式) ,则相机参数12个。 *InlierThreshold值在0.01到0.5之间 。值越小 ,精度越高 ,但是运算耗时长;值越大 ,越能容忍偏差 。默认值0.05 。 radial_distortion_self_calibration (SelectedEdges, CalibrationEdges, Width, Height, 0.08, 42, division, fixed, 0, CameraParam) *名字:校正畸变参数 *描述:根据指定的径向畸变系数 ,求取理想无畸变的相机内参 。 get_domain (Image, Domain) change_radial_distortion_cam_par (fixed, CameraParam, 0, CamParamOut) *名字:校正畸变图像方法1 *描述:根据指定图像和指定相加参数来矫正输入图像的畸变 。 change_radial_distortion_image (Image, Domain, ImageRectified, CameraParam, CamParamOut) dev_display (Image) dev_display (CalibrationEdges) *校正畸变图像方法2,效果与方法1完全相同 gen_radial_distortion_map(Map, CameraParam, CamParamOut, bilinear) map_image(Image, Map, ImageMapped) dev_display (Image) dev_display (ImageMapped) *读写参数 * write_cam_par (CameraParam, D:/CameraParam.dat) * write_cam_par (CamParamOut, D:/CamParamOut.dat) * read_cam_par (D:/CameraParam.dat, CameraParam1) * read_cam_par (D:/CamParamOut.dat, CamParamOut1)原图
用来畸变校正的XLD
畸变校正后的图
原图
用来畸变校正的XLD
畸变校正后的图
四 、遇到的问题
执行到radial_distortion_self_calibration函数的时候 ,报这个错误 No stable solution found: please change the inlier threshold or select contours manually (HALCON错误代码: 3661) 。
解决方法:
把算子radial_distortion_self_calibration的DistortionCenter参数设置为’fixed’或者’adaptive’即可
如果改成了’fixed’或者’adaptive’仍然报错 ,那么:
(1)把InlierThreshold的数值需要适当增大
(2)棋盘格的行与列数目需要适当增大
五 、总结
halcon自标定的算子 ,它可以在不用标定板的情况下 ,标定出相机内参(无焦距),相对于多幅标定无法获取相机的外参 。因为畸变一般在图像的边缘更严重 ,所以需要保证在图像的四周边缘有足够的直线线段 。在实际项目中拍摄物体不可能都像例程中一样有理想的直线边缘 ,替代方法是:用菲林片制作一张网格黑色印制(10*10,可以根据自己实际情况调整)充满整个视野 。求出了相机内参就可以进行畸变校正 ,因而自标定相对于多幅标定 ,在畸变校正方面更快捷,这样设备在现场更容易操作 、维护。在畸变校正以后我们同样可以放置一个参考物求取像素当量 ,构建XY世界坐标系,以用于测量 、定位等应用 。后续若需要将像素单位换算至公有制单位 ,也可使用棋盘格 、标准物 、菲林片等进行转换 ,便可应用于测量项目;也可以利用一定网格构建XY坐标系 ,用于定位项目 ,这样在不借助标定板的情况下就可以畸变校正和测量类的项目 。创心域SEO版权声明:以上内容作者已申请原创保护,未经允许不得转载,侵权必究!授权事宜、对本内容有异议或投诉,敬请联系网站管理员,我们将尽快回复您,谢谢合作!