Halcon相机标定

news2025/2/21 1:40:51

1,前言。

        相机的成像过程实质上是坐标系的转换。首先空间中的点由“世界坐标系”转换到“相机坐标系”,然后再将其投影到成像平面(图像物理坐标系),最后再将成像的平面上的数据转换为图像像素坐标系。但是由于透镜的制造精度以及组装工艺的偏差会出现不同的畸变,导致图像失真。

        镜头畸变分为径向畸变和切向畸变。径向畸变是由镜头形状缺陷造成,它又分为枕形畸变和桶形畸变。

        对于一般低精度的场合,只考虑径向畸变即可,因为切向畸变的影响远小于径向畸变。因此如果要进行图像畸变矫正就需要通过标定获取相机的参数。同时为了将图像的坐标系中的像素坐标系与世界坐标系中的坐标距离对应起来,就需要了解相机的外部参数信息,换算其在世界坐标系中的实际距离。相机标定就是获取相机内部参数和外部参数的过程。

2,相机标定的方法。

        传统标定法:标定精度较高,但在非线性相机模型下计算十分复杂,标定速度较低,通常用于精度要求较高的线性系统。

        自标定法:不需要借助参考物,操作简单且计算速度较快,但其标度精度及鲁棒性较低,只适用于速度要求较高精度较低的系统。

        张正友标定:介于前面两种标定法之间,具有操作简单,标定精度高,鲁棒性好的优点,较为广泛使用。

3,内部参数和外部参数。

        内部参数:相机的焦距、畸变系数、像素间距、中心点坐标、图像的宽和高等。这些参数虽然可以从制造商提供的说明书中查询,单其精度性不一定满足要求,因此只能作为参考,在实际中还需要对其进行标定,通过标定可以对这些参数进行修正。不同的相机,其内部参数也不相同,这取决于相机和镜头的类型,以及选择的畸变类型。

        外部参数:相机的外部参数描述相机坐标系与世界坐标系的关系,即相机在世界坐标系中的三位位置,如相机的X轴坐标,Y轴坐标,Z轴坐标,以及相机的朝向。

4,相机的畸变。

        径向畸变:矢量端点沿长度方向的变化,即矢量长度的变化。

        切向畸变:矢量端点沿切线方向发生的变化,即矢量角度的变化。

5,Halcon标定。

1,准备标定板。

用halcon代码生成用于打印标定板的描述文件及标定板图像的ps文件。

*生成标定板文件
 gen_caltab (7, 7, 0.0125, 0.5, 'caltab.descr', 'caltab.ps')

生成的.descr与caltab.ps文件。

备注:

caltab.descr:对标记点的半径,坐标,行,列进行描述的文件。

有.cpd与.descr两种扩展 名的标定板描述文件:

    .cpd描述文件:使用create_caltab函数生成,这种格式适用于六边形排列的标定板,通常在深色背景上有浅色的标记。

     .descr文件:使用gen_caltab函数生成,用于矩形排列的标定板,通常用于浅色背景下深色标记。

Halcon已提供的.cpd与.descr文件位于:D:\Program Files\MVTec\HALCON-12.0\calib目录下。

caltab.descr文件详情如下:

# Plate Description Version 2
# HALCON Version 12.0 --  Sun Dec 29 11:09:19 2024
# Description of the standard calibration plate
# used for the camera calibration in HALCON
# (generated by gen_caltab)
#
#

# 7 rows x 7 columns
# Width, height of calibration plate [meter]: 0.1, 0.1
# Distance between mark centers [meter]: 0.0125

# Number of marks in y-dimension (rows)
r 7

# Number of marks in x-dimension (columns)
c 7

#   offset of coordinate system in z-dimension [meter] (optional):
z 0

# Rectangular border (rim and black frame) of calibration plate
#   rim of the calibration plate (min x, max y, max x, min y) [meter]:
o -0.05125 0.05125 0.05125 -0.05125
#   outer border of the black frame (min x, max y, max x, min y) [meter]:
i -0.05 0.05 0.05 -0.05 
#   triangular corner mark given by two corner points (x,y, x,y) [meter]
#   (optional):
t -0.05 -0.0375 -0.0375 -0.05

#   width of the black frame [meter]:
w 0.003125

# calibration marks:  x y radius [meter]

# calibration marks at y = -0.0375 m
-0.0375 -0.0375 0.003125
-0.025 -0.0375 0.003125
-0.0125 -0.0375 0.003125
0 -0.0375 0.003125
0.0125 -0.0375 0.003125
0.025 -0.0375 0.003125
0.0375 -0.0375 0.003125

# calibration marks at y = -0.025 m
-0.0375 -0.025 0.003125
-0.025 -0.025 0.003125
-0.0125 -0.025 0.003125
0 -0.025 0.003125
0.0125 -0.025 0.003125
0.025 -0.025 0.003125
0.0375 -0.025 0.003125

# calibration marks at y = -0.0125 m
-0.0375 -0.0125 0.003125
-0.025 -0.0125 0.003125
-0.0125 -0.0125 0.003125
0 -0.0125 0.003125
0.0125 -0.0125 0.003125
0.025 -0.0125 0.003125
0.0375 -0.0125 0.003125

# calibration marks at y = 0 m
-0.0375 0 0.003125
-0.025 0 0.003125
-0.0125 0 0.003125
0 0 0.003125
0.0125 0 0.003125
0.025 0 0.003125
0.0375 0 0.003125

# calibration marks at y = 0.0125 m
-0.0375 0.0125 0.003125
-0.025 0.0125 0.003125
-0.0125 0.0125 0.003125
0 0.0125 0.003125
0.0125 0.0125 0.003125
0.025 0.0125 0.003125
0.0375 0.0125 0.003125

# calibration marks at y = 0.025 m
-0.0375 0.025 0.003125
-0.025 0.025 0.003125
-0.0125 0.025 0.003125
0 0.025 0.003125
0.0125 0.025 0.003125
0.025 0.025 0.003125
0.0375 0.025 0.003125

# calibration marks at y = 0.0375 m
-0.0375 0.0375 0.003125
-0.025 0.0375 0.003125
-0.0125 0.0375 0.003125
0 0.0375 0.003125
0.0125 0.0375 0.003125
0.025 0.0375 0.003125
0.0375 0.0375 0.003125

caltab.ps:可直接用于打印的标定板图像文件。

打印出的标定板如下:

2,内部参数与外部参数获取
1,使用Halcon算子获取

相机内部参数标定算子所在位置:

算子如下:

*生成标定板文件
 *gen_caltab (7, 7, 0.0125, 0.5, 'caltab.descr', 'caltab.ps')
ImgPath := '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)
OpSystem := environment('OS')
set_display_font (WindowHandle, 14, 'mono', 'true', 'false')
* 
* Calibrate the camera.
* StartCamPar := [Focus,Kappa,Sx,Sy,Cx,Cy,ImageWidth,ImageHeight]
*Focus:相机的焦距,如果是远心相机,则焦距为0
*Kappa:畸变系数,初始值可以设置为0
*Sx、Sy:单个像元的宽,高(可从相机说明书中获取)
*Cx、Cy:图像的原点坐标,初始值可认为是图像的中心点,即坐标分为为图像的宽度和高度的一半
*ImageWidth,ImageHeight:采集图像的宽和高
StartCamPar := [0.016,0,0.0000074,0.0000074,326,247,652,494]
create_calib_data ('calibration_object', 1, 1, CalibDataID)
*设置为面阵模式
set_calib_data_cam_param (CalibDataID, 0, 'area_scan_division', StartCamPar)
*设置标定描述文件
set_calib_data_calib_object (CalibDataID, 0, 'caltab.descr')
NumImages := 10
* Note, we do not use the image from which the pose of the measurement plane can be derived
for I := 1 to NumImages by 1
    read_image (Image, ImgPath + 'calib_' + I$'02d')
    dev_display (Image)
    find_calib_object (Image, CalibDataID, 0, 0, I, [], [])
    get_calib_data_observ_contours (Caltab, CalibDataID, 'caltab', 0, 0, I)
    dev_set_color ('green')
    dev_display (Caltab)
endfor
*标定相机内参
calibrate_cameras (CalibDataID, Error)
*获取标定后的相机内部参数
get_calib_data (CalibDataID, 'camera', 0, 'params', CamParam)
* 将相机内部参数写入到文件
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')
clear_calib_data (CalibDataID)

相机外部参数标定算子所在位置:

算子如下:

* Attention:
* This program reads the internal camera parameters from the file
* 'camera_parameters.dat', which, e.g., could be generated by the program
* 'camera_calibration_internal.hdev'
* 
ImgPath := '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 (1)
set_display_font (WindowHandle, 14, 'mono', 'true', 'false')
* 从文件中读取内部参数
try
    read_cam_par ('camera_parameters.dat', CamParam)
catch (Exception)
    * run 'camera_calibration_internal.hdev' first to generate camera
    * parameter file 'camera_parameters.dat'
    stop ()
endtry
* 
* Determine the external camera parameters and world coodinates from image points
* 
* The external camera parameters can be determined from an image, where the
* calibration plate is positioned directly on the measurement plane
read_image (Image, ImgPath + 'calib_11')
dev_display (Image)
*标定描述文件
CaltabName := 'caltab.descr'
create_calib_data ('calibration_object', 1, 1, CalibDataID)
* Here, the final camera parameters are already known and can be used instead
* of the starting values used in the program 'camera_calibration_internal.hdev'
set_calib_data_cam_param (CalibDataID, 0, 'area_scan_division', CamParam)
set_calib_data_calib_object (CalibDataID, 0, CaltabName)
find_calib_object (Image, CalibDataID, 0, 0, 1, [], [])
get_calib_data_observ_contours (Caltab, CalibDataID, 'caltab', 0, 0, 1)
*获取粗略估计的姿态(外部参数)
get_calib_data_observ_points (CalibDataID, 0, 0, 1, RCoord, CCoord, Index, PoseForCalibrationPlate)
dev_set_color ('green')
dev_display (Caltab)
dev_set_color ('red')
disp_caltab (WindowHandle, CaltabName, CamParam, PoseForCalibrationPlate, 1)
dev_set_line_width (3)
disp_circle (WindowHandle, RCoord, CCoord, gen_tuple_const(|RCoord|,1.5))
* caltab_points (CaltabName, X, Y, Z)
* calibrate_cameras (CalibDataID, Error)
* To take the thickness of the calibration plate into account, the z-value
* of the origin given by the camera pose has to be translated by the
* thickness of the calibration plate.
* Deactivate the following line if you do not want to add the correction.
*设置标定板的厚度,如果没有则省略
set_origin_pose (PoseForCalibrationPlate, 0, 0, 0.00075, PoseForCalibrationPlate)
disp_continue_message (WindowHandle, 'black', 'true')
stop ()
* Alternatively, the external camera parameters can  be determined from
* at least three point correspondances between the WCS and the pixel coordinate system
read_image (Image, ImgPath + 'caliper_01')
dev_display (Image)
* Set the world coordinates of three points on the rule
*在尺上选择点设置世界坐标
X := [0,50,100,80]
Y := [5,0,5,0]
Z := [0,0,0,0]
* Set the respective image plane coordinates of the three points
*设置选择点在图像上对应的像素坐标
RCoord := [414,227,85,128]
CCoord := [119,318,550,448]
* 
disp_cross (WindowHandle, RCoord, CCoord, 6, 0)
* create_pose (-50, 25, 400, 0, 0, -30, 'Rp+T', 'gba', 'point', InitialPose)
*生成外部参数(姿态参数)
vector_to_pose (X, Y, Z, RCoord, CCoord, CamParam, 'iterative', 'error', FinalPose, Errors)
*将外部参数写入到文件
write_pose (FinalPose, 'pose_from_three_points.dat')

* Now, transform a point measured interactively into the WCS
dev_update_window ('on')
dev_display (Image)
while (1)
    disp_message (WindowHandle, 'Measure one point: left mouse button', 'window', 12, 12, 'red', 'false')
    disp_message (WindowHandle, 'Exit measure mode: right mouse button', 'window', 36, 12, 'red', 'false')
    get_mbutton (WindowHandle, Row, Column, Button)
    if (Button == 4)
        break
    endif
    dev_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,使用助手获取相机内部参数与外部参数。

选择标定助手

设置参数

选择拍摄的各个角度标定板图像

不同角度的标定板图像

查看标定结果

6,应用。

* gen_caltab (7, 7, 0.0125, 0.5, 'caltab.descr', 'caltab.ps')
dev_close_window ()
read_image (Image, '3d_machine_vision/calib/calib_10')
get_image_size(Image, Width, Height)
dev_open_window (0, 0, Width, Height, 'black', WindowHandle)
dev_display (Image)
*测量两个点之间的世界距离
*因为标定板相邻的两个圆远心之间的距离是12.5mm,所以用这个进行测试
*读取相机内参
read_cam_par ('camera_parameters.dat', CameraParam)
*读取相机的外参
read_pose ('pose_from_three_points.dat', Pose)
*获取两个相邻圆的圆形图像距离
threshold (Image, Region, 0, 100)
connection (Region, ConnectedRegions)
select_shape (ConnectedRegions, SelectedRegions, ['area','row','column'], 'and', [0,305.96,360.09], [131651,345.41,500])
*获取该两点的相机坐标
gen_contour_region_xld (SelectedRegions, Contours, 'border')
dev_set_color ('green')
dev_set_line_width (2)

dev_display (Image)
dev_display (Contours)
*获取两个选定区域的坐标
area_center (SelectedRegions, Area, Row, Column)

*映射成世界坐标
image_points_to_world_plane (CameraParam, Pose, Row, Column, 'mm', X, Y)
*计算两点之间的距离
distance_pp (X[1], Y[1], X[0], Y[0], Distance)
dev_set_color ('red')
disp_line (WindowHandle, Row[0], Column[0], Row[1], Column[1])
disp_message (WindowHandle,'Distance:'+ Distance$'.2f'+'mm', 'window', 20, 20, 'green', 'false')

 

7,代码文件资源链接。

https://download.csdn.net/download/lingxiao16888/90384839

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2299000.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Linux 配置 MySQL 定时自动备份到另一台服务器

Linux 配置 MySQL 定时自动备份到另一台服务器 前言1、配置服务器通信1.1:配置过程 2、编写自动备份sh脚本文件3:设置定时自动执行 前言 此方案可使一台服务器上的 MySQL 中的所有数据库每天 0 点自动转储为 .sql 文件,然后将文件同步到另一…

《安富莱嵌入式周报》第350期:Google开源Pebble智能手表,开源模块化机器人平台,开源万用表,支持10GHz HRTIM的单片机,开源CNC控制器

周报汇总地址:嵌入式周报 - uCOS & uCGUI & emWin & embOS & TouchGFX & ThreadX - 硬汉嵌入式论坛 - Powered by Discuz! 视频版: https://www.bilibili.com/video/BV1YPKEeyEeM/ 《安富莱嵌入式周报》第350期:Google开…

LabVIEW与小众设备集成

在LabVIEW开发中,当面临控制如布鲁克OPUS红外光谱仪这类小众专业设备的需求,而厂家虽然提供了配套软件,但由于系统中还需要控制其他设备且不能使用厂商的软件时,必须依赖特定方法通过LabVIEW实现设备的控制。开发过程中&#xff0…

无人机之无线传输技术!

一、Lightbridge和OcuSync图传技术 Lightbridge技术:这是大疆自主研发的一种专用通信链路技术,使用单向图像数据传输,类似于电视广播塔的数据传输形式。它主要采用2.4GHz频段进行传输,并且可以实现几乎“零延时”的720p高清图像传…

移远通信边缘计算模组成功运行DeepSeek模型,以领先的工程能力加速端侧AI落地

近日,国产大模型DeepSeek凭借其“开源开放、高效推理、端侧友好”的核心优势,迅速风靡全球。移远通信基于边缘计算模组SG885G,已成功实现DeepSeek模型的稳定运行,并完成了针对性微调。 目前,该模型正在多款智能终端上进…

rust学习一、入门之搭建简单开发环境

1、搭建开发环境(windows11) a.登录官网 一看就明白,此处略。 b.安装rustup 一看就明白,此处略。 c.安装 cargo script 或者 rust-script script cargo install cargo-script 完成后 注意:时间有一点点久。 测试 cargo s…

FANUC机器人示教器中如何显示或关闭寄存器或IO的注释信息?

FANUC机器人示教器中如何显示或关闭寄存器或IO的注释信息? 如下图所示,我们打开一个子程序,可以看到程序中的寄存器和IO是显示注释信息的, 如果想关闭注释显示的话,怎么设置? 如下图所示,按下下一页的箭头(NEXT键), 如下图所示,点击“编辑”,在弹出的窗口中,选择“…

在springboot加vue项目中加入图形验证码

后端 首先先要创建一个CaptchaController的类,可以在下面的代码中看到 在getCaptcha的方法里面写好了生成随机的4位小写字母或数字的验证码,然后通过BufferedImage类变为图片,顺便加上了干扰线。之后把图片转为Base64编码方便传给前端 为了…

23. AI-大语言模型

文章目录 前言一、LLM1. 简介2. 工作原理和结构3. 应用场景4. 最新研究进展5. 比较 二、Transformer架构1. 简介2. 基本原理和结构3. 应用场景4. 最新进展 三、开源1. 开源概念2. 开源模式3. 模型权重 四、再谈DeepSeek 前言 AI‌ 一、LLM LLM(Large Language Mod…

Spring Cloud-Sentinel

Sentinel服务熔断与限流 Sentinel 是面向分布式、多语言异构化服务架构的流量治理组件,主要以流量为切入点,从流量控制、流量路由、熔断降级、系统自适应保护等多个维度来帮助用户保障微服务的稳定性。 官网地址:home | Sentinelhttps://sen…

Java中使用EasyExcel

Java中使用EasyExcel 文章目录 Java中使用EasyExcel一:EasyExcel介绍1.1、核心函数导入数据导出数据 1.2、项目实际应用导入数据导出数据 1.3、相关注解ExcelProperty作用示例 二:EasyExcel使用2.1、导入功能2.2、导出功能 三:EasyExcel完整代…

建筑兔零基础自学python记录18|实战人脸识别项目——视频检测07

本次要学视频检测,我们先回顾一下图片的人脸检测建筑兔零基础自学python记录16|实战人脸识别项目——人脸检测05-CSDN博客 我们先把上文中代码复制出来,保留红框的部分。 ​ 然后我们来看一下源代码: import cv2 as cvdef face_detect_demo(…

自定义基座实时采集uniapp日志

自定义基座实时采集uniapp日志 打测试包给远端现场(测试/客户)实际测试时也能实时看到日志了,也有代码行数显示。 流程设计 #mermaid-svg-1I5W9r1DU4xUsaTF {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid…

AI知识库 - Cherry Studio

1 引言: 最近 DeepSeek 很火啊,想必大家都知道,DeepSeek 这个开源的模型出来后,因其高质量能力和R1 的思维链引发了大家本地部署的热潮。我也不例外,本地部署了一个 14B 的模型,然后把,感觉傻傻…

20250213 隨筆 雪花算法

雪花算法(Snowflake Algorithm) 雪花算法(Snowflake) 是 Twitter 在 2010 年開發的一種 分布式唯一 ID 生成算法,它可以在 高併發場景下快速生成全局唯一的 64-bit 長整型 ID,且不依賴資料庫,具…

(前端基础)HTML(一)

前提 W3C:World Wide Web Consortium(万维网联盟) Web技术领域最权威和具有影响力的国际中立性技术标准机构 其中标准包括:机构化标准语言(HTML、XML) 表现标准语言(CSS) 行为标准&#xf…

pdf.js默认显示侧边栏和默认手形工具

文章目录 默认显示侧边栏(切换侧栏)默认手形工具(手型工具) 大部分的都是在viewer.mjs中的const defaultOptions 变量设置默认值,可以使用数字也可以使用他们对应的变量枚举值 默认显示侧边栏(切换侧栏) 在viewer.mjs中找到defaultOptions,大概在732行,或则搜索sidebarViewOn…

学习总结三十三

括号序列 如果它是一个右括号,考察它与它左侧离它最近的未匹配的的左括号。如果该括号与之对应(即小括号匹配小括号,中括号匹配中括号),则将二者配对。简单理解,找到一个右括号,向左找一个左括号…

解决DeepSeek服务器繁忙问题

目录 解决DeepSeek服务器繁忙问题 一、用户端即时优化方案 二、高级技术方案 三、替代方案与平替工具(最推荐简单好用) 四、系统层建议与官方动态 用加速器本地部署DeepSeek 使用加速器本地部署DeepSeek的完整指南 一、核心原理与工具选择 二、…

Huatuo热更新--安装HybridCLR

1.自行安装unity编辑器 支持2019.4.x、2020.3.x、2021.3.x、2022.3.x 中任一版本。推荐安装2019.4.40、2020.3.26、2021.3.x、2022.3.x版本。 根据你打包的目标平台,安装过程中选择必要模块。如果打包Android或iOS,直接选择相应模块即可。如果你想打包…