0


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 1read_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 1read_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坐标系,用于定位项目,这样在不借助标定板的情况下就可以畸变校正和测量类的项目。


本文转载自: https://blog.csdn.net/Douhaoyu/article/details/128330952
版权归原作者 豆浩宇 所有, 如有侵权,请联系我们删除。

“Halcon自标定做畸变校正”的评论:

还没有评论