一、标定板标定 13.0

*************************************************************************************
*****在工业镜头选型过程中,为了方便各位朋友计算工业镜头参数,现提供靶面尺寸表供参考。
*****1.1英寸————靶面尺寸为宽12mm*高12mm,对角线17mm
*****1英寸————靶面尺寸为宽12.7mm*高9.6mm,对角线16mm
*****2/3英寸————靶面尺寸为宽8.8mm*高6.6mm,对角线11mm
*****1/1.6英寸————靶面尺寸为宽8.08mm*高6.01mm,对角线10.07mm
*****1/1.7英寸————靶面尺寸为宽7.6mm*高5.7mm,对角线9.5mm
*****1/1.8英寸————靶面尺寸为宽7.2mm*高5.4mm,对角线9mm
*****1/2英寸————靶面尺寸为宽6.4mm*高4.8mm,对角线8mm
*****1/3英寸————靶面尺寸为宽4.8mm*高3.6mm,对角线6mm
*****1/4英寸————靶面尺寸为宽3.2mm*高2.4mm,对角线4mm
*****1/2.5英寸————靶面尺寸为宽5.76mm*高4.29mm,对角线7.182mm*****初始参数的确定*****
*****针孔摄像机模型为6个参数(Focus,Kappa,Sx,Sy,Cx,Cy)**********
*****焦距F = 镜头的标称焦距   【貌似可以随便填】
*****畸变系数K = 0
*****Sx = 靶面尺寸宽÷分辨率宽(例如靶面尺寸为1/3 分辨率为1292*964,Sx=4.8÷1292=0.00371mm=3.71e-006m) 标定助手上说是像元的尺寸,但是查到的相机资料像元尺寸又有点不一致,就按照现在的这种方法计算
*****Sy = 靶面尺寸高÷分辨率高(例如靶面尺寸为1/3 分辨率为1292*964,Sx=3.6÷964=0.00373mm=3.73e-006m)
*****Sx = 靶面尺寸宽÷分辨率宽(例如靶面尺寸为1/1.7 分辨率为4024*3036,Sx=7.6÷4024=0.00188mm=1.88e-006m)(hk相机MV-CE120-10GC)
*****Sy = 靶面尺寸高÷分辨率高(例如靶面尺寸为1/1.7 分辨率为4024*3036,Sx=5.7÷3036=0.00188mm=1.88e-006m)
*****Cx = 分辨率宽÷2
*****Cy = 分辨率高÷2**********
*****原文链接:https://blog.csdn.net/c1learning/article/details/96480168
*****靶面尺寸:https://blog.csdn.net/maopig/article/details/80773739
*************************************************************************************
*
* Initialize the program
dev_close_window ()
dev_open_window (0, 0, 768, 576, 'black', WindowHandle)
dev_update_off ()
dev_set_draw ('margin')
dev_set_line_width (3)
set_display_font (WindowHandle, 14, 'mono', 'true', 'false')
*
* Calibrate the camera
*
***6毫米标定板
CalTabDescrFile := 'caltab_6mm.descr'
*****单位是m*****初始参数
gen_cam_par_area_scan_division (0.025, 0, 0.0000037, 0.0000037, 1292/2, 964/2, 1292, 964, StartCamPar)
**gen_cam_par_area_scan_polynomial (0.025, 0, 0, 0, 0, 0, 0.0000037, 0.0000037, 1292/2, 964/2, 1292, 964, StartCamPar)
create_calib_data ('calibration_object', 1, 1, CalibDataID)
set_calib_data_cam_param (CalibDataID, 0, [], StartCamPar)
**set_calib_data_cam_param (CalibDataID, 0, 'area_scan_division', StartCamPar)
set_calib_data_calib_object (CalibDataID, 0, CalTabDescrFile)
NumImages := 10
for I := 1 to NumImages by 1read_image (Image, 'E:/Kell/AOI/Calibration/CalibImgs/' + I$'02d')get_image_size (Image, Width, Height)dev_display (Image)Message := 'Find calibration plate in\nall calibration images (' + I + '/' + NumImages + ')'disp_message (WindowHandle, Message, 'window', 12, 12, 'black', 'true')* Find the calibration platefind_calib_object (Image, CalibDataID, 0, 0, I - 1, [], [])get_calib_data (CalibDataID, 'camera', 0, 'init_params', StartCamPar)get_calib_data_observ_points (CalibDataID, 0, 0, I - 1, Row, Column, Index, Pose)get_calib_data_observ_contours (Contours, CalibDataID, 'caltab', 0, 0, I - 1)gen_cross_contour_xld (Cross, Row, Column, 6, 0.785398)dev_set_color ('green')dev_display (Contours)dev_set_color ('yellow')dev_display (Cross)wait_seconds (0.5)
endfor
disp_continue_message (WindowHandle, 'black', 'true')
stop ()
calibrate_cameras (CalibDataID, Error)
get_calib_data (CalibDataID, 'camera', 0, 'params', CamParam)get_calib_data (CalibDataID, 'calib_obj_pose', [0,1], 'pose', Pose)
**位姿旋转90度
tuple_replace (Pose, 5, Pose[5] + 90, PoseRotate)***设置标定板厚度 单位是m
set_origin_pose (Pose, 0, 0, 0.0023, PoseNewOrigin)*选取两个像素点 计算Scale,就是像素精度
ImageRows:=[100,200]
ImageCols:=[100,200]
image_points_to_world_plane (CamParam, PoseNewOrigin, ImageRows, ImageCols, 'm', SX, SY)
distance_pp (ImageRows[0], ImageCols[0], ImageRows[1], ImageCols[1], DistanceImage)
distance_pp (SX[0], SY[0], SX[1], SY[1], DistanceWorld)
*****单位是m*****
*每米世界坐标距离对应的像素点个数
DistanceOneMeter:=DistanceImage/DistanceWorld
*每个像素对应的世界坐标距离
DistanceOnePixel:=DistanceWorld/DistanceImage**********
**世界坐标系中心偏移量
OffSetX:=(Width/2)*DistanceOnePixel
OffSetY:=(Height/2)*DistanceOnePixel
**设定世界坐标系到图像左上角,不然生成出来的map是从图像中心开始的,map_image只有右下角的部分图像
set_origin_pose (PoseNewOrigin, -OffSetX, -OffSetY, 0, PoseNewOriginFinal)
************ Generate map
*Scale的单位是m
gen_image_to_world_plane_map (MapSingle, CamParam, PoseNewOriginFinal, Width, Height, Width, Height, DistanceOnePixel, 'bilinear')
*
* Perform measurements
*
for I := 1 to NumImages by 1read_image (Image1, 'E:/Kell/AOI/Calibration/CalibImgs/' + I$'02d')  **read_image (Image1, 'E:/Kell/AOI/AOI Image2/_01.bmp')  * * Now, measure the size of the black border of the platemap_image (Image1, MapSingle, ImageMapped)    change_radial_distortion_cam_par ('fixed', CamParam, 0, CamParSingleImageRect)change_radial_distortion_image (Image1, Image1, ImageRectified, CamParam, CamParSingleImageRect)
endforwrite_image (MapSingle, 'tiff', 0, 'E:/Kell/AOI/Calibration/CalibImgs/ImageMap.tif')
read_image (Image2, 'E:/Kell/AOI/Calibration/CalibImgs/ImageMap.tif')
write_calib_data (CalibDataID, 'E:/Kell/AOI/Calibration/CalibImgs/CalibData.ccd')
read_calib_data ('E:/Kell/AOI/Calibration/CalibImgs/CalibData.ccd', CalibDataID1)clear_calib_data (CalibDataID)


一、自标定

* 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.
dev_update_off ()
read_image (Image, 'E:/Kell/AOI/Calibration/SelfCalibImgs/c_01.bmp')
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, 30)
union_collinear_contours_xld (Edges, Edges, 10, 1, 2, 0.1, 'attr_keep')
* 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, 1292, 964, 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)read_image (Image1, 'E:/Kell/AOI/AOI Image1/_01.bmp')
change_radial_distortion_image (Image1, Domain, ImageRectified1, CamParSingleImageRect, 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, 'E:/Kell/AOI/Calibration/SelfCalibImgs/c_' + J$'02d')* Extract subpixel-precise edges using the Canny filter.edges_sub_pix (Image, ImageEdges, 'canny', 1, 10, 30)union_collinear_contours_xld (ImageEdges, ImageEdges, 10, 1, 2, 0.1, 'attr_keep')* 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, 1292, 964, 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 1read_image (Image, 'E:/Kell/AOI/Calibration/SelfCalibImgs/c_' + 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 (1)dev_display (ImageRectified)disp_message (WindowHandle, 'Image without radial distortions', 'window', 0, 0, 'black', 'true')wait_seconds (1)
endforread_image (Image1, 'E:/Kell/AOI/AOI Image1/_01.bmp')
change_radial_distortion_image (Image1, Domain, ImageRectified1, CamParMultiImage, CamParMultiImageRect)write_cam_par (CamParMultiImageRect, 'E:/Kell/AOI/Calibration/SelfCalib/CamparRect.dat')
write_cam_par (CamParMultiImage, 'E:/Kell/AOI/Calibration/SelfCalib/Campar.dat')read_cam_par ('E:/Kell/AOI/Calibration/SelfCalib/Campar.dat', CamParMulti)


一、线阵相机标定

我是使用halcon标定助手来标定线阵相机的,对于里面的一些参数来做一个记录说明:

首先下面的两个数组就是标定之后得到的相机内参和外参

内参:CameraParameters := [0.0357809  ,  -61.3384  ,  6e-006  ,  6e-006  ,  915.932  ,  182.341  ,  2048  ,  3840  ,  1.41028e-006  ,  5.45462e-005  ,  3.86866e-006]
外参:CameraPose := [-0.0160874,0.0553653,0.255282,28.5899,6.24194,8.48283,0]

内参的11个参数分别是什么意思呢?内参一共十一个参数分别为  [Focus, Kappa, Sx, Sy, Cx, Cy, ImageWidth, ImageHeight, Vx, Vy, Vz]
Focus : 镜头焦距长度

Kappa: 镜头畸变系数,正负分别表示枕形畸变和桶状畸变

Sx: 表示相机单个像元宽度

Sy: 表示相机单个像元高度

Cx: 表示镜头光轴在像平面坐标上的投影横坐标,一般初始化的时候设置为width/2

Cy: 表示镜头光轴在像平面坐标上的投影纵坐标,一般初始化的时候设置为0,因为是一帧是一条线,所以纵坐标为0

ImageWidth: 表示一整副图片像素宽度

ImageHeight: 表示一整幅图片像素高度
Vx : x方向上运动速度,其实就是每拍摄一条线,x方向的走的距离,因为安装有误差,相机和运动方向不可能完全垂直,理论上为0最理想

Vy: y方向上运动速度,其实就是在扫描的时候,多远距离拍摄一条线

Vz: z方向上运动速度,其实就是每拍摄一条线,z方向上走的距离,也是因为安装有误差,理论上为0最理想

外参的六个参数表示由世界坐标系转换成相机坐标系的变换参数,六个参数分别为x,y,z三个轴的旋转角度和x,y,x三个轴的平移量

1.在halcon中使用标定助手对线扫相机进行标定,首先设置标定板描述文件路径,和镜头等相关参数

2.加载用于标定的图片,一般20张左右,注意加载的图片必须都找到标定板,显示检测品质出问题如果精度要求不是很高也可以接受。然后选定一张照片设置为参考位姿,设置参考位姿的作用是什么呢?当你标定完成之后,使用相机内参外参进行矫正之后的图片,会将这个图片上的标定板中心点作为远点坐标,并且这张变换后的图片作为相机垂直照射的平面参考。如果加载的图片找不到标定板,可以在最下方的标定板提取参数中改变参数,一般就能找提取到标定板了。最后点击标定按钮,就可以得到标定的参数了。

3.得到的内参,如何进行畸变矫正呢?

你希望映射过后的图片的宽度(一条线)内视野为多少,这里为30mm,然后除以1000换算成m

TmpCtrl_RectificationWidth := 30
TmpCtrl_RectificationWidth := TmpCtrl_RectificationWidth / 1000.0

生成用于矫正的映射图,着重说一下这几个输入参数

CameraParameters:标定得到的相机内参

CameraPose:标定得到的相机位姿外参

2048:待转换图的宽度

3840:待转换图的高度

2048:转换之后的图像希望的宽度

3840:转换之后的图像希望的高度

TmpCtrl_RectificationWidth / 2048:表示希望转换后的图,每个像素代表的长度,单位是m。这里因为宽度视野(一条线覆盖的视野宽度)希望是30mm,而希望转换后的图像宽度为2048,所以这里用TmpCtrl_RectificationWidth / 2048,也就是说你可以自定义转换之后的图像每隔像素代表多少精度,这里的精度就是30mm/2048pix = 0.014mm/pix .注意下面的这个函数就是将图片转换成了z=0,垂直视角的函数,参看halcon函数说明。

gen_image_to_world_plane_map (TmpObj_RectificationMap, CameraParameters, CameraPose, 2048, 3840, 2048, 3840, TmpCtrl_RectificationWidth / 2048, 'bilinear')

最终使用map_image来转换图片,转换之后的图片在理论上横向纵向的坐标缩放比例是相等的,换句话来说一个正方形两个方向上的像素个数是一样的,并且是垂直拍摄的。
map_image (Image, TmpObj_RectificationMap, TmpObj_RectifiedImage)

如何制作标定板

https://blog.csdn.net/mvtechnology/article/details/9388219

生成标定板描述文件

1.gen_caltab

60mm*60mm大小的标定板:圆点行数和列数都是7,圆点之间的距离8mm,圆点直径4mm

gen_caltab (7, 7, 0.008, 0.5, 'C:/Users/MS/Desktop/caltab_60mm.descr', 'C:/Users/MS/Desktop/caltab_60mm.ps')

2.create_caltab

Halcon单相机标定—标定板标定和自标定 线扫相机标定相关推荐

  1. 线扫相机——机器视觉中无限制物体的检测

    点击上方"小白学视觉",选择加"星标"或"置顶" 重磅干货,第一时间送达 在机器视觉中,在检测连续物体或者滚动物体时,线扫相机是最佳的解决方 ...

  2. 线扫相机的行频计算方法

    一,变量的定义 首先设定以下变量: (1)线阵相机的每线像素数(单位:pixel):Hc (2)目标物的宽幅(单位:m):Lo (3)目标物运行速率(单位:m/s):Vo (4)线阵相机线扫描速率(单 ...

  3. 【halcon 线扫相机二维码矫正算法】

    halcon 线扫相机畸变二维码矫正算法 线扫相机拍照畸变 1.二维码定位与裁剪 图像矫正 运行结果 总结 线扫相机拍照畸变 线扫相机拍摄图片分辨率较高,但是由于相机本身或者或者拍照目标的运动,容易造 ...

  4. 一种简化的线扫相机单维度标定法

    点击上方"3D视觉工坊",选择"星标" 干货第一时间送达 线扫相机精度高.速度快.抗干扰能力强,适用于连续性产品的在线检测.针对产品的测量,要获得产品边界的精确 ...

  5. DALSA网口线扫相机SDK开发详解例程(C#版)

    首先吐槽一句,官方的demos写的真的不好,坑爹啊.对于小白来说,开发官方demos为我所用太难了.为什么呢?因为它Dalsa的DALSA.SaperaLT.SapClassBasic.dll中,不仅 ...

  6. 3D线扫相机-沙姆成像原理

    3D线扫相机,又名激光轮廓仪,3D线激光测量仪,基本原理:通过向物体表面投射线激光平面,从而获取该平面与待测物体表面交线处三维点坐标,解算物体深度信息.主要器件:线激光器.镜头.芯片.处理板.接口板. ...

  7. 线扫相机 编码器_面阵和线扫工业相机选型

    版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.csdn.net/snowbird13/article/d ...

  8. basler相机的触发线是那两脚_探究机器视觉领域线扫相机和面阵相机的区别

    首先,我们从使用用途上来了解这两种工业相机的区别. 芯片对比 面阵相机芯片是有x*y个像素构成,是一个平面.线扫秒相机一般情况下是有x*1个像素构成一条线,从形状上来说是一条线.高端的线扫相机也有x* ...

  9. 线扫相机DALSA-Image Format(读图格式设置)

    专业于机器视觉visionman团队教学,重于实践.当然很多不切实际,尚不成熟的教学的想法尽快抛弃,完善.这个过程是令我们教学更加骄傲.-专业于机器视觉visionman团队教学宣言 Binning是 ...

最新文章

  1. ads无法启用状态服务器,NAC ADSSO 无法工作在Microsoft 2008服务器版本
  2. myeclipse文件目录自动定位(右编辑界面点击 左边Package Explorer导航自动定位)...
  3. 用select 语句中的START WITH...CONNECT BY PRIOR子句实现递归查询
  4. Struts1与Struts2的区别
  5. 机器学习:结点的实现,决策树代码实现(二)
  6. springboot导包显示不存在_基础篇:Spring Boot入门体验(图文教程)
  7. 同样是点工,凭什么他拿月薪20k,你却只有10k?
  8. pdo mysql_num_rows_PHP-mysql_num_rows()期望参数1为资源,给定布尔...
  9. 哈弗h2s车内时间怎么调_你想拥抱的品质生活,就让哈弗H4乐享版帮你实现吧
  10. 北斗导航 | BDS RTK高精度定位算法在形变检测中的应用(算法原理讲解)
  11. rk356x-Android 刷机
  12. NRF52832 SDK 15.2.0设置内部32768
  13. java 接收 gprs通信_java 接收GPRS数据
  14. 游戏服务器网络出现波动排查方法
  15. 高考英语50分学计算机,高三英语50分到100分学习窍门
  16. H5前端输入和展示 表情 三种解决方案
  17. Gamemaker小实例——马里奥实现(后附资源+exe文件)
  18. NOSQL之Neo4j:Neo4j的简介、安装、使用方法(Neo4j搭配JDK安装的图文教程)之详细攻略
  19. 依托同济大学建设的中国(上海)数字城市研究院揭牌成立
  20. 利用webSocket实现扫码登录PC端

热门文章

  1. 苹果明年弃用高通基带/ 腾讯回应进军ChatGPT/ 百度首席战略官辞职…今日更多新鲜事在此...
  2. 通用路由封装协议-GRE
  3. 【从零开始学Spring笔记】工厂类
  4. 手动收回应用权限对android app的影响
  5. 大家好,新入驻cson希望大家多多支持,谢谢
  6. 纯css3可爱的Loading加载动画特效
  7. 启辰t90服务器不显示了,启辰T90更换车联网屏幕的方法分享
  8. JavaEE之Spring框架(Spring IOC)的使用
  9. 出口信用证项下的融资——出口押汇
  10. DatabaseMetaData类