【相机标定篇】halcon自标定(3)

“一滴水,用显微镜看,也是一个大世界

在项目中,偶尔会遇到由于产品形状、拍摄位置等原因导致标定板很难放置的情况,此时可以考虑使用halcon自标定算法来标定相机。由于自标定可以在不使用用标定板情况下,进行畸变矫正。所以,极大地方便在设备现场进行调试。




1. 自标定处理流程

自标定原理来源于此论文:“Automatic line-based estimation of radial lens distortion”。

image.png

论文下载地址:

链接:https://pan.baidu.com/s/118YDti24nvbnsz2CbOJa1Q 提取码:5t67

从论文中可知自标定的一般流程:轮廓检测、共线线段连接、剔除干扰线、求取畸变参数。如下图所示。

image.png

在halcon我们可以对自标定流程梳理为两大步骤:1.检测直线轮廓XLD   2.图像畸变矫正,如下图所示。

image.png


2. 自标定相关算子

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:畸变中心的估算模式

PrincipalPointVar :偏差控制

CameraParam:输出相机内参数

change_radial_distortion_cam_par( : : Mode, CamParamIn, DistortionCoeffs : CamParamOut)

名字:矫正畸变参数

描述:根据指定的径向畸变系数,求取理想无畸变的相机内参。

参数:

Mode:畸变模式

CamParamIn:畸变的相机内部参数

DistortionCoeffs :畸变系数值

CamParamOut:已校正的相机内参

change_radial_distortion_image(Image, Region : ImageRectified : CamParamIn, CamParamOut : )

名字:矫正畸变图像

描述:根据指定图像和指定相加参数来矫正输入图像的畸变

参数:

Image:输入图像

Region :矫正图像的区域

ImageRectified :矫正图像

CamParamIn:输入相机参数

CamParamOut :输出相机参数




3. 实例分析

首先进行边缘检测, 选择包含一定长度,一定数量直线段的XLD轮廓

image.png


使用radial_distortion_self_calibration算子进行自标定,

得到相机内参以及用于标定的直线段



image.png


利用change_radial_distortion_cam_par 、以及change_radial_distortion_image

进行图像畸变矫正

image.png

完整源码如下:

*公众号:机器视觉那些事儿*
*1. 算法功能:径向畸变自校正
*2. 算法思路:
*(1)检测含直线轮廓XLD
*(2)矫正畸变图像
*---------初始化,读图------------
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 ()
*----------------(1)检测直线轮廓XLD=----------------
* i 利用canny滤波器提取图像边缘
edges_sub_pix (Image, Edges, 'canny', 1, 10, 40)
* ii 分割直线段以及圆弧线段
segment_contours_xld (Edges, SplitEdges, 'lines_circles', 5, 4, 2)
* iii 选择足够长的线段用于自标定
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')
*----------------(2)矫正畸变图像=----------------
* i 相机自标定,根据边缘求取内参
radial_distortion_self_calibration (SelectedEdges, CalibrationEdges, 646, 492, 0.08, 42, 'division', 'variable', 0, CamParSingleImage)
* ii 获取无畸变相机内参
get_domain (Image, Domain)
change_radial_distortion_cam_par ('fixed', CamParSingleImage, 0, CamParSingleImageRect)
* iii 根据内参,进行图像畸变矫正
change_radial_distortion_image (Image, Domain, ImageRectified, CamParSingleImage, CamParSingleImageRect)
*-----------结果显示------------
*显示原始图像XLD以及用于矫正图像所需的直线段
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 ()

4. 注意事项

  1. halcon的自标定是根据物体边缘的直线,来进行图像矫正,所以需保证图像畸变较大的边缘有足够的直线段;

  2. 实际项目中被检测物若没有理想的直线段,可以使用棋盘格、标准物、菲林片等代替;

  3. 运行内存大于等于4G。


5. 后续步骤

自标定只需要一张图片,即可标定相机内参,后续若需要将像素单位换算至公有制单位,需要使用棋盘格、标准物、菲林片等进行转换,便可应用于测量项目;也可以利用一定网格构建XY坐标系,用于定位项目。所以,相机标定后的应用,会在后续的测量篇以及手眼标定篇涉及,请持续关注。


另提供一份源码如下:

* This program shows how radial_distortion_self_calibration can be used to
* calibrate the radial distortion coefficient and the center of distortions. 
* 能够用于标定径向畸变参数和畸变中心
* In the first part of the program, the edges extracted from
* a single image are used for the calibration.  The results show that the
* radial distortions are extracted fairly accurately from the single image.
* 第一部分,单幅图像提取的边缘能够用于标定,结果显示径向畸变能够相当准确的从单幅图像中求解出。
* To increase the accuracy, the second part of the program shows
* how the edges extracted from 20 images can be used to perform the
* calibration.  Since the edges occur in many different orientations in
* the 20 images, the principal point can be determined significantly more accurately.
* 为了提高径向畸变的准确性,第二部分从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 ()
* 用canny算子提取亚像素精度的边缘
* 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')
* Perform the self-calibration of the radial distortions.
* 执行径向畸变的自标定  输出:需要用于标定的边、相机内参
radial_distortion_self_calibration (SelectedEdges, CalibrationEdges, 646, 492, 0.08, 42, 'division', 'variable', 0, CamParSingleImage)
* Rectify the image, i.e., remove the radial distortions.
* 矫正图像,去除径向畸变
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 ()
* 20张图像中提取边缘进行自标定,这些边缘会进行累加
* 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')
* Perform the self-calibration of the radial distortions.
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 ()
* Compute the camera parameters of the undistorted image.
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)
    * Rectify the image, i.e., remove the radial distortions.
    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

原图

image.png


image.png

校正畸变后的图像

image.png


本文出自勇哥的网站《少有人走的路》wwww.skcircle.com,转载请注明出处!讨论可扫码加群:

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

会员中心
搜索
«    2024年4月    »
1234567
891011121314
15161718192021
22232425262728
2930
网站分类
标签列表
最新留言
    热门文章 | 热评文章 | 随机文章
文章归档
友情链接
  • 订阅本站的 RSS 2.0 新闻聚合
  • 扫描加本站机器视觉QQ群,验证答案为:halcon勇哥的机器视觉
  • 点击查阅微信群二维码
  • 扫描加勇哥的非标自动化群,验证答案:C#/C++/VB勇哥的非标自动化群
  • 扫描加站长微信:站长微信:abc496103864
  • 扫描加站长QQ:
  • 扫描赞赏本站:
  • 留言板:

Powered By Z-BlogPHP 1.7.2

Copyright Your skcircle.com Rights Reserved.

鄂ICP备18008319号


站长QQ:496103864 微信:abc496103864