一、相机内参标定

目的:标定内参的目的是消除镜头的畸变。

面阵相机的内参由一个8位的数组组成包括:

startCamPar:=[Focus,Kappa,Sx,Sy,Cx,Cy,ImageWidth,ImageHeight]

Focus代表焦距,按照我们镜头参数进行填写,远心镜头填写0
Kappa为畸变大小,因为在标定之前,所以默认填写0
Sx, Sy像元的宽高填写相机的像元尺寸。可以查相机手册,或者咨询相机厂家。
Cx, Cy填写图像的中心坐标
ImageWidth, ImageHeight填写图像的宽高

通过查阅手册我们可以知道除Kappa以外的其他参数,将已知信息填入进去,就是未标定的初始相机内参。

有了初始内参就可以用下面算子设置进去:

set_calib_data_cam_param (CalibDataID, 0, [], startCamPar)

标定完成之后我的会得到标定后的相机内参,和标定前的区别是计算出了Kappa的值,不再是0,其他参数大致不变,所以内参标定就是计算出畸变系数的过程。

二、相机外参标定

目的:决定摄像机坐标系与世界坐标系之间相对位置关系,有了位置关系Pose,就可以将像素坐标系和世界坐标系的点进行互相转化,达到了标定的应用目的,所以外参标定就是求解要定位的产品相对于相机的位姿(位置)。

3D姿态中的7个参数代表的意义:[0,0,0,0,0,0,0]
前六个代表平移和旋转量,最后一个代表OrderOfTransform,OrderOfRotform,ViewOfTransform的组合类型。

位姿pose的参考文章:HALCON中create_pose和位姿中7个参数_m0_37833782的博客-CSDN博客

相机pose的理解-halcon标定-少有人走的路

三、参考代码

一、获取内参,参考例程camera_calibration_internalImgPath := '3d_machine_vision/calib/'
dev_close_window ()
dev_open_window (0, 0, 652, 494, '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.
*
*通过查阅手册等资料,创建初始的内参数据数组
gen_cam_par_area_scan_division (0.016, 0, 0.0000074, 0.0000074, 326, 247, 652, 494, StartCamPar)
*创建一个标定句柄,所有操作都在这个句柄上进行
create_calib_data ('calibration_object', 1, 1, CalibDataID)
*将上面创建的未标定的初始内参数据设置进去
set_calib_data_cam_param (CalibDataID, 0, [], StartCamPar)
*设置标定板的描述文件,用于后面从各个图片中查找标定板
set_calib_data_calib_object (CalibDataID, 0, 'caltab_30mm.descr')
NumImages := 10
* Note, we do not use the image from which the pose of the measurement plane can be derived
*10张标定板在视野中不同位置的图片
for I := 1 to NumImages by 1read_image (Image, ImgPath + 'calib_' + I$'02d')dev_display (Image)*自动查到标定板的位置信息find_calib_object (Image, CalibDataID, 0, 0, I, [], [])
endfor
*执行了find_calib_object之后就可以进行标定了,这里执行了10次就是标定了10个位置
calibrate_cameras (CalibDataID, Error)    *启动标定
*标定完成之后就可以用下面算子获得标定后的相机内参了
get_calib_data (CalibDataID, 'camera', 0, 'params', CamParam)
* Write the internal camera parameters to a file
*将标定后的相机内参保存成文件以使用
write_cam_par (CamParam, 'camera_parameters.dat')
Message := 'Interior camera parameters have'
Message[1] := 'been written to file'
disp_message (WindowHandle, Message, 'window', 12, 12, 'red', 'false')二、获取外参,参考例程camera_calibration_external*方法一、标定板确定位姿*外参的标定流程和内参一样,标定流程结束后内参和外参数据(就是位姿)都已经存在了
*同样用get_calib_data获得外参pose
get_calib_data (CalibHandle, 'calib_obj_pose', [0, 1], 'pose', CameraPose)
*第三个参数ItemIdx由两个参数的元组组成。[0, 1]代表第0号标定板的第1张图片中的标定位姿。
*我们标定了10张标定板在不同位置的图片,所以得到了10个位姿数据,选择其中一个作为参考位姿使用,
*以后我们要定位的产品的位置也要和参考位姿的位置一样,就可以使用该位姿实现像素坐标和世界坐标
*点位的转换
clear_calib_data (CalibDataID)*方法二、至少3点确定位姿*世界坐标系中的4个点
X := [0,50,100,80]
Y := [5,0,5,0]
Z := [0,0,0,0]
*对应像素坐标系中的4个点
RCoord := [414,227,85,128]
CCoord := [119,318,550,448]
*加载相机内参
read_cam_par ('camera_parameters.dat', CamParam)
*从图像点和世界坐标系点的对应中直接计算出位姿
vector_to_pose (X, Y, Z, RCoord, CCoord, CamParam, 'iterative', 'error', FinalPose, Errors)*(可选)set_origin_pose对一个位姿进行平行转换,和仿射变换功能一样
*所有方法最后求出的位姿都是默认在平面上的,没有考虑标定板的厚度,因此可以
*使用此方法在设置标定板的厚度,优化位姿参数
set_origin_pose (FinalPose, 0, 0, 0.00075, FinalPose)
*保存位姿数据为文件
write_pose (FinalPose, 'pose_from_three_points.dat')三、实际应用(1)点坐标转换
dev_update_window ('on')
dev_display (Image)
while (1)*获取鼠标点像素坐标get_mbutton (WindowHandle, Row, Column, Button)if (Button == 4)breakendifdev_display (Image)dev_set_color ('green')disp_cross (WindowHandle, Row, Column, 6, 0)*使用下面算子,使用指定的内参和外参,将图像坐标转换为世界坐标image_points_to_world_plane (CamParam, FinalPose, Row, Column, 1, X1, Y1)disp_message (WindowHandle, 'X = ' + X1, 'window', 320, 400, 'red', 'false')disp_message (WindowHandle, 'Y = ' + Y1, 'window', 340, 400, 'red', 'false')
endwhile(2)测量直线距离
* 该例程在世界坐标系中划出一个范围,测量包含在其中的多个直线的距离
*思路:在世界坐标系中确定ROI范围,转换到图像坐标系中的ROI,在图像中测量直线间的
*像素距离,将像素点转化位世界坐标系中的点,求出实际距离
dev_set_color ('red')
dev_display (Image)
* 设置世界坐标系中的ROI区域
ROI_X_WCS := [-2,-2,112,112]
ROI_Y_WCS := [0,0.5,0.5,0]
ROI_Z_WCS := [0,0,0,0]
*将位姿转换为3D变换矩阵,hom_mat3d_to_pose:3D变换矩阵转换为位姿
pose_to_hom_mat3d (FinalPose, CCS_HomMat_WCS)
*将世界坐标系中的点转换到相机坐标系中
affine_trans_point_3d (CCS_HomMat_WCS, ROI_X_WCS, ROI_Y_WCS, ROI_Z_WCS, CCS_RectangleX, CCS_RectangleY, CCS_RectangleZ)
*将相机坐标系中的点转换到图像坐标系中
project_3d_point (CCS_RectangleX, CCS_RectangleY, CCS_RectangleZ, CamParam, RectangleRow, RectangleCol)
*到这里就把世界坐标系中绝对ROI范围的点转换到了图像坐标系
*生成图像中的ROI
gen_region_polygon_filled (ROI, RectangleRow, RectangleCol)
*求最小外接矩形
smallest_rectangle2 (ROI, RowCenterROI, ColCenterROI, PhiROI, Length1ROI, Length2ROI)
* 准备测量,创建测量工具
gen_measure_rectangle2 (RowCenterROI, ColCenterROI, PhiROI, Length1ROI, Length2ROI, 652, 494, 'bilinear', MeasureHandle)
*启动测量
measure_pairs (Image, MeasureHandle, 0.4, 5, 'all_strongest', 'all', RowEdgeFirst, ColumnEdgeFirst, AmplitudeFirst, RowEdgeSecond, ColumnEdgeSecond, AmplitudeSecond, IntraDistance, InterDistance)
close_measure (MeasureHandle)
dev_display (Image)
disp_message (WindowHandle, 'Measuring the position of the pitch lines', 'window', 450, 25, 'red', 'false')
dev_set_color ('green')
*求出每条直线线宽的中点
RowPitchLine := (RowEdgeFirst + RowEdgeSecond) / 2.0
ColPitchLine := (ColumnEdgeFirst + ColumnEdgeSecond) / 2.0
disp_cross (WindowHandle, RowPitchLine, ColPitchLine, 6, 0)
*将图像坐标系中的直线上的点转换到世界坐标系
image_points_to_world_plane (CamParam, FinalPose, RowPitchLine, ColPitchLine, 1, X1, Y1)
for I := 1 to |X1| by 1*设置文本在窗体的输出位置set_tposition (WindowHandle, RowEdgeFirst[I - 1] + 5, ColumnEdgeFirst[I - 1] - 20)if (I == |X1|)set_tposition (WindowHandle, RowEdgeFirst[I - 1], ColumnEdgeFirst[I - 2])endif*展示信息write_string (WindowHandle, X1[I - 1]$'.3f' + 'mm')
endfor
disp_continue_message (WindowHandle, 'black', 'true')
stop ()(3)以指定点为中心,将图像转换成指定位姿的位置
dev_close_inspect_ctrl (YOfContour)
dev_close_inspect_ctrl (XOfContour)
* Now, transform the whole image
WidthMappedImage := 652
HeightMappedImage := 494
dev_display (Image)
* First, determine the scale for the mapping
* (here, the scale is determined such that in the
* surroundings of the points P0 and P1, the image scale of the
* mapped image is similar to the image scale of the original image)
*分别计算出世界坐标系和相应的图像坐标系中两点的距离
distance_pp (X[0], Y[0], X[1], Y[1], DistP0P1WCS)
distance_pp (RCoord[0], CCoord[0], RCoord[1], CCoord[1], DistP0P1PCS)
*求出世界坐标和图像坐标的比例关系
Scale := DistP0P1WCS / DistP0P1PCS
* Then, determine the parameter settings for set_origin_pose such
* that the point given via get_mbutton will be in the center of the
* mapped image
dev_display (Image)
disp_message (WindowHandle, 'Define the center of the mapped image', 'window', 12, 12, 'red', 'false')
*提取屏幕中的一点,后期以图像中这一点像素的位置将图片移动到屏幕中心
get_mbutton (WindowHandle, CenterRow, CenterColumn, Button1)
*将点转换为世界坐标系坐标
image_points_to_world_plane (CamParam, FinalPose, CenterRow, CenterColumn, 1, CenterX, CenterY)
*设置图片要转换的位姿,并将根据上面选的点平移图像
set_origin_pose (FinalPose, CenterX - Scale * WidthMappedImage / 2.0, CenterY - Scale * HeightMappedImage / 2.0, 0, PoseNewOrigin)
*生成一个从图像到世界坐标系的投影
gen_image_to_world_plane_map (Map, CamParam, PoseNewOrigin, 652, 494, WidthMappedImage, HeightMappedImage, Scale, 'bilinear')
*对图像应用投影
map_image (Image, Map, ImageMapped)
dev_clear_window ()
dev_display (ImageMapped)
* In the case that only one image has to be mapped, the operator
* image_to_world_plane can be used instead of the operators
* gen_image_to_world_plane_map and map_image.
*(可选)在只需要映射一个图像的情况下,可以使用操作符image_to_world_plane
*来代替操作符gen_image_to_world_plane_map和map_image。
image_to_world_plane (Image, ImageMapped, CamParam, PoseNewOrigin, WidthMappedImage, HeightMappedImage, Scale, 'bilinear')

四、补充,获取标定板的描述文件

Halcon标定板标定流程相关推荐

  1. Halcon 圆形标定板标定基本流程-标定助手操作

    Halcon 圆形标定板基本流程 1. 认识标定板: 2. 生成标定板的描述文件 3. 开始标定 4. 采集标定板的图像 5. 得到相机内外参 1. 认识标定板: 这个标定板的规格是 7×7: 标定板 ...

  2. Halcon——使用标定板标定像素当量

    使用标定板标定像素当量 1. 了解标定板的参数 2. 确定标定的方法 3. Halcon代码示例 1. 了解标定板的参数 拿到一块标定板,我们应该如何使用它,或者说该如何了解它的相关参数呢?如果你使用 ...

  3. Halcon单相机标定—标定板标定和自标定 线扫相机标定

    一.标定板标定 13.0 ************************************************************************************* * ...

  4. OpenCv相机标定——圆形标定板标定

    OpenCv相机标定--圆形标定板标定 0.前言 1.标定图案 2.OpenCv标定 3.标定结果分析 0.前言   OpenCv中,相机标定所使用的标定图案分为棋盘格.对称圆形及非对称圆形特征图.A ...

  5. VisionMaster标定板标定

    选择工具 标定板生成工具我比较喜欢用海康自己研发的标2定板  具体参数看自己需求  最后选择0  导出图像就行  一般不需要cad图纸 保存 去路径下打印看看你的按照路径 我的是D:\VisionMa ...

  6. Halcon标定板标定

    halcon标定有自己的标定助手可以演示,不过拿到VS里面却不是很适用.尤其是关于畸变矫正和透视矫正算子的解释也没有,下面两个算子set_origin_pose,gen_image_to_world_ ...

  7. 标定板标定和九点标定的区别_标定系列一 | 机器人手眼标定的基础理论分析

    旷视MegMaster机器人系列是旷视自主研发的一系列AI智能机器人硬件设备,基于旷视全球领先的人工智能算法及机器人技术,可实现搬运.分拣.托举.存储等功能,被广泛应用于物流仓储.工厂制造等场景.旷视 ...

  8. matlab生成棋盘标定板,勇哥的视觉实验:棋盘格标定板标定

    勇哥手里这块标定板的参数如下: (一)使用GML Camera Calibration进行标定 新建任务后,发现这个软件不让行列数量相同. 必须行列一个为奇数一个就为偶数. 由于勇哥手里的标定板就是9 ...

  9. 标定板标定和九点标定的区别_射频导纳物位计的标定方法

    射频导纳物位计使用前需要标定,为满足实际界位测量要求,根据现场条件,射频导纳物位计可以采用两种标定方法:湿标法,根据实际界位变化调整仪表的输出值进行标定的方法:干标法,利用标准电容器送电容值代替实际界 ...

最新文章

  1. 简单的 H5 视频推流解决方案
  2. Euro Truck Simulator 2欧洲卡车模拟2用VR玩
  3. Golang实践录:工程管理
  4. 旷视高调进军AIoT!先砸20亿建智能物流生态,发布机器人协作大脑河图
  5. weka连接mysql数据库
  6. Tensorflow的最佳实践
  7. eclipse哪个版本最稳定_新版鹿鼎记开播啦,你最喜欢哪个版本?最还原原著的原来是他...
  8. Win11、Linux 双系统安装方法
  9. 我在CSDN上使用了大半年的账号最后不属于自己,纵有疾风起,人生不言弃
  10. GridView样式用代码来设置
  11. BFS算法 (python)
  12. 解决/**/嵌套问题---条件编译:#if 0 statement #endif 帅帅哒洋办法
  13. 关于ruoyi框架整合ueditor富文本编辑器
  14. 北京文安科技发展有限公司招聘简介
  15. Android之集成极光推送消息
  16. vnc远程控制软件中文版,盘点六款好用的vnc远程控制软件中文版
  17. Python非线性回归
  18. 计算机网络课程实验4——编程实现路由算法(迪杰斯特拉算法)
  19. CPU load高但CPU usage低问题排查
  20. 芋道 Spring Boot 安全框架 Spring Security 入门

热门文章

  1. 听音乐学英语 (Tori Amos)
  2. GFS 分布式数据系统
  3. Verilog之非阻塞赋值(二)——赋值延后一个周期
  4. 【HDU】5343 MZL's Circle Zhou【后缀自动机】
  5. 辣鸡(ljh) NOIP模拟赛 模拟 平面几何 数论 化学相关(雾)
  6. TDD 的原理和场景
  7. CASIO MTP-1248 调整日期,时间,星期
  8. 抓翻倍牛股的简易方法 缘分战法(牛股突破战法)
  9. PHP上传图片进行等比缩放
  10. Nokia N900上安装fennec