机器视觉6-halcon高级教程

机器视觉6-halcon高级教程

  • 双目立体视觉原理
    • 视差
    • 外极线几何
    • 双目标定
  • 双目立体视觉之Halcon标定
    • 一.标定结果
    • 二.Halcon标定过程
      • 1.获取左右相机图像中标定板的区域;
      • 2.提取左右相机图像中标定板的MARK点坐标和摄像机外部参数;
      • 3.执行双目标定;
      • 4.获取非标准外极线几何到标准外极线几何之间的变换矩阵;
      • 5.通过变换矩阵对未校正的图像进行图像校正
      • 6.显示图像校正后标准外极线几何时的图像.
  • 双目立体视觉测量零件的高度
    • 1.执行双目标定;
    • 2.获取非标准外极线几何到标准外极线几何之间的变换矩阵;
    • 3.通过变换矩阵对未校正的图像进行图像校正
    • 4.计算左右摄像机的视差图像
    • 5.通过视差计算距离图像
    • 代码示例
      • **1. 初始化设置与窗口管理**
      • **2. 图像读取与参数定义**
      • **3. 极线校正与图像映射**
      • **4. 视差与深度计算**
      • **5. 高度测量与结果显示**
      • **优化**

双目立体视觉原理

双目立体视觉是一种基于视差原理的三维信息获取技术,通过模拟人类双眼的视觉机制,从不同视角采集图像并计算对应点的位置差异(视差),从而重建目标物体的三维几何信息。其核心流程包括图像采集、相机标定、立体匹配和三维重建,具体原理如下:
双目摄像机如同人的两个眼睛
在这里插入图片描述


视差

  1. 视差与深度关系
    双目系统通过两个平行安装的相机(基线距离为 ( b ))同时拍摄同一场景。同一空间点 ( P ) 在左右图像中的水平像素坐标差称为视差 ( d ),深度 ( Z ) 可通过三角测量公式计算:

Z = b ⋅ f d Z = \frac{b \cdot f}{d} Z=dbf
其中 ( f ) 为相机焦距。视差越大,物体距离越近;视差趋近于0时,物体接近无限远。
在这里插入图片描述
坐标系以左相机为准,右相机相对于左相机是简单的平移,用坐标表示为(Tx,0,0
2. 极线约束与校正
为简化匹配过程,需对图像进行极线校正,使对应点在左右图像中位于同一水平线上。这通过标定相机内外参数并消除畸变实现,确保匹配搜索仅需在水平方向进行,显著降低计算复杂度。

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
视差公式
在这里插入图片描述
在这里插入图片描述


外极线几何

非标准外极线几何图
在这里插入图片描述

1.极平面
⒉极线
3.极点
4.极线约束

在这里插入图片描述
在这里插入图片描述

双目标定

双目标定技术获取非标准外极线几何到标准外极线几何的变换矩阵,校正两个相机的图像。根据两个相机的相对位姿,从而在标准外极线几何图像中获取物体在另一个相机成像中位置。

一、双目标定的定义与目的
双目标定是双目视觉系统的核心步骤,旨在确定双目相机的内参(焦距、主点、畸变系数)和外参(两相机间的旋转矩阵 ( R ) 和平移向量 ( T )),从而建立三维空间与二维图像之间的映射关系。其核心目标包括:

  1. 消除畸变:校正镜头畸变(径向畸变、切向畸变)对成像的影响。
  2. 坐标系对齐:通过外参矩阵实现左右相机坐标系的统一,便于后续立体匹配和三维重建。

二、双目标定流程

  1. 标定板准备
    • 使用棋盘格标定板(如8×5黑白格),需保证打印精度高、表面平整且无反光,方格尺寸根据相机视场选择(短焦相机建议20mm,长焦相机建议60mm)。

    • 标定板应覆盖图像1/4至1/2区域,且在不同角度(俯仰、倾斜、平移)下拍摄15-60组图像以覆盖全视场。

  2. 图像采集与角点提取
    • 左右相机同步拍摄标定板图像,确保标定板完整且无模糊。常用工具包括OpenCV或MATLAB脚本自动保存图像。

    • 使用Canny算子检测边缘,结合Zernike矩亚像素提取或椭圆拟合获取角点坐标,精度可达0.1像素。

  3. 单应性矩阵计算
    • 通过针孔模型建立世界坐标系与图像坐标系的线性关系,求解单应性矩阵 ( H ) 描述平面投影变换。

    • 公式:( s \cdot [u \quad v \quad 1]^T = H \cdot [X \quad Y \quad 1]^T ),其中 ( s ) 为比例因子,( H ) 包含内参和外参信息。

  4. 参数优化
    • 传统方法:基于最小二乘法或奇异值分解(SVD)求解初始参数,再通过Levenberg-Marquardt算法优化。

    • 智能优化算法:如混沌粒子群优化(CPSO),引入动态惯性权重和邻域混沌搜索,避免局部最优,提升标定精度。

  5. 立体校正
    • 使用Bouguet算法将左右图像投影到同一极平面,使极线水平对齐,简化立体匹配计算。

    • 变换矩阵 ( R_{rect} ) 构造方式:基于平移向量 ( T ) 方向,使基线与成像平面平行。


三、关键技术解析

  1. 内参标定
    • 焦距 ( f ):通过棋盘格角点计算归一化焦距 ( f_x, f_y ) 及主点 ( (c_x, c_y) )。

    • 畸变校正:二阶径向畸变(( k_1, k_2 ))和切向畸变(( p_1, p_2 ))模型,公式:

x c o r r e c t e d = x ( 1 + k 1 r 2 + k 2 r 4 ) + 2 p 1 x y + p 2 ( r 2 + 2 x 2 ) x_{corrected} = x(1 + k_1 r^2 + k_2 r^4) + 2p_1 xy + p_2 (r^2 + 2x^2) xcorrected=x(1+k1r2+k2r4)+2p1xy+p2(r2+2x2)
y c o r r e c t e d = y ( 1 + k 1 r 2 + k 2 r 4 ) + p 1 ( r 2 + 2 y 2 ) + 2 p 2 x y y_{corrected} = y(1 + k_1 r^2 + k_2 r^4) + p_1 (r^2 + 2y^2) + 2p_2 xy ycorrected=y(1+k1r2+k2r4)+p1(r2+2y2)+2p2xy
其中 r 2 = x 2 + y 2 r^2 = x^2 + y^2 r2=x2+y2

  1. 外参标定
    • 旋转矩阵 ( R ):分解为绕X/Y/Z轴旋转角度 α , β , γ \alpha, \beta, \gamma α,β,γ,通过欧拉角或四元数表示。

    • 平移向量 ( T ):描述右相机相对于左相机的空间位移,基线长度 b = ∥ T ∥ b = \| T \| b=T 直接影响深度分辨率。

  2. 标定工具与算法
    • MATLAB工具箱:stereoCameraCalibrator 支持自动角点检测、参数优化及重投影误差分析。

    • OpenCV函数:cv2.stereoCalibrate() 结合张正友平面标定法,适用于实时系统开发。


四、应用场景与优化建议

  1. 典型应用
    • 机器人导航:结合SLAM技术实现环境三维建模与避障。

    • 工业检测:高精度测量零件尺寸(误差<0.1mm)。

    • 自动驾驶:通过视差计算障碍物距离,支持路径规划。

  2. 优化建议
    • 标定板多样性:使用多尺寸标定板适应不同工作距离。

    • 光照控制:均匀照明避免反光或阴影干扰角点检测。

    • 动态标定:在相机移动或变焦后需重新标定。


五、常见问题与解决方案

  1. 重投影误差过大
    • 原因:角点提取不准确或标定板姿态单一。

    • 解决:增加标定图像数量(建议≥20组),覆盖更多视角。

  2. 极线未对齐
    • 原因:外参矩阵 ( R, T ) 计算误差。

    • 解决:使用Bouguet校正法强制极线水平化。

  3. 镜头畸变残留
    • 原因:畸变模型阶数不足(如仅使用一阶径向畸变)。

    • 解决:扩展至二阶径向+切向畸变模型。


总结
双目标定是双目视觉系统的基石,其精度直接影响三维重建与测距的可靠性。通过合理设计标定流程、选择优化算法并严格把控拍摄条件,可实现亚毫米级标定精度。未来,结合深度学习的自标定方法有望进一步简化流程并提升鲁棒性。

双目立体视觉之Halcon标定

一.标定结果

在这里插入图片描述

二.Halcon标定过程

1.获取左右相机图像中标定板的区域;

find_caltab(Image : CalPlate : CalPlateDescr, SizeGauss, MarkThresh, MinDiamMarks :)
参数含义:
Image : 		输入图像
CalPlate : 		标定板区域
CalPlateDescr:	标定板描述文件
SizeGauss: 		高斯滤波核;
MarkThresh,       提取mark的阈值
MinDiamMarks :    标定板中MARK圆的最小半径

2.提取左右相机图像中标定板的MARK点坐标和摄像机外部参数;

find_marks_and_pose(Image, CalPlateRegion : : CalPlateDescr, StartCamParam, StartThresh, DeltaThresh, MinThresh,Alpha, MinContLength, MaxDiamMarks : RCoord, CCoord, StartPose)
参数含义:
Image:			输入图像
CalPlateRegion:	标定板区域
CalPlateDescr:     标定板描述文件
StartCamParam:     摄像机内部参数
DeltaThresh:       提取MARK黑点所需的初始阈值
MinThresh:         提取MARK黑点步进阈值
Alpha:             提取MARK黑点轮廓的滤波参数
MinContLength:     MARK黑点轮廓的最小长度
MaxDiamMarks:      MARK黑点轮廓的最大直径
RCoord:            探测到MARK黑点的行坐标
CCoord:			探测到MARK黑点的列坐标
StartPose          输出摄像机外部参数

3.执行双目标定;

binocular_calibration( : : NX, NY, NZ, NRow1, NCol1, NRow2, NCol2, StartCamParam1, StartCamParam2, NStartPose1,NStartPose2, EstimateParams : CamParam1, CamParam2, NFinalPose1, NFinalPose2, RelPose, Errors)
参数含义:
NX:			标定板MARK点行坐标(经过排序的,单位是米)
NY:			标定板MARK点列坐标(经过排序的,单位是米)
NZ:			标定板MARK点Z坐标(经过排序的,单位是米)
NRow1:        左面相机中标定板提取出的MARK点行坐标(经过排序的,单位是像素)
NCol1:		左面相机中标定板提取出的MARK点列坐标(经过排序的,单位是像素)
NRow2:		右面相机中标定板提取出的MARK点行坐标(经过排序的,单位是像素)
NCol2:		右面相机中标定板提取出的MARK点列坐标(经过排序的,单位是像素)
StartCamParam1:左面相机的摄像机内部参数
StartCamParam2:右面相机的摄像机内部参数
NStartPose1:	 左面相机的摄像机外部参数
NStartPose2:	 右面相机的摄像机外部参数
EstimateParams: 选择要标定出哪些相机参数,”all”代表所有的参数
CamParam1:     标定后得到的左面相机的摄像机内部参数
CamParam2:     标定后得到的右面相机的摄像机内部参数
NFinalPose1:   标定后得到的左面相机的摄像机外部参数
NFinalPose2:   标定后得到的右面相机的摄像机外部参数
RelPose:		 右边相机相对于左面相机的位姿
Errors         平均错误误差

4.获取非标准外极线几何到标准外极线几何之间的变换矩阵;

gen_binocular_rectification_map( : Map1, Map2 : CamParam1, CamParam2, RelPose, SubSampling, Method, MapType :CamParamRect1, CamParamRect2, CamPoseRect1, CamPoseRect2, RelPoseRect)
参数含义:
Map1:左面相机校正映射数据
Map2:右面相机校正映射数据
CamParam1:左面相机的摄像机内部参数
CamParam2:右面相机的摄像机内部参数
RelPose:  右相机相对左相机的位姿
SubSampling:采样因子
Method:    映射校正方法
MapType:   映射校正类型
CamParamRect1: 左面相机校正以后的摄像机内部参数
CamParamRect2: 右面相机校正以后的摄像机内部参数
CamPoseRect1:  校正以后的左面相机相对原始相机的位姿
CamPoseRect2:校正以后的右面相机相对原始相机的位姿
RelPoseRect:校正以后的右面相机相对校正以后的左面相机的位姿关系

5.通过变换矩阵对未校正的图像进行图像校正

map_image(Image, Map : ImageMapped : : )
参数含义:
Image:			待校正图像
Map:  			相机校正映射数据
ImageMapped: 	校正后的图像

6.显示图像校正后标准外极线几何时的图像.

check_epipolar_constraint(ImageRectifiedL, ImageRectifiedR : : RectCamParL, RectCamParR, WindowHandle1, WindowHandle2, CaltabFile :EpipolarError)
参数含义:
ImageRectifiedL:左面相机校正以后的图像
ImageRectifiedR:右面相机校正以后的图像
RectCamParL:左面相机校正以后的摄像机内部参数
RectCamParR:右面相机校正以后的摄像机内部参数
WindowHandle1:左面摄像机图像窗口
WindowHandle2:右面摄像机图像窗口
CaltabFile:标定板文件
EpipolarError:错误信息

*设置离线图像存放的路径
ImgPath := 'stereo/board/'Index := 1
*读取左边相机离线图像
read_image (ImageL, ImgPath + 'calib_l_' + Index$'02d')*读取右边相机离线图像
read_image (ImageR, ImgPath + 'calib_r_' + Index$'02d')*关闭已经打开的窗口
dev_close_window ()*关闭程序计数器,变量更新,图像更新窗口
dev_update_off ()*获取左边相机图像大小
get_image_size (ImageL, WidthL, HeightL)*创建左边的窗口
dev_open_window (0, 0, WidthL, HeightL, 'black', WindowHandle1)*设置区域填充模式为边缘模式
dev_set_draw ('margin')*设置输出对象的颜色为绿色
dev_set_color ('green')*设置字体信息
set_display_font (WindowHandle1, 14, 'mono', 'true', 'false')*获取右边相机图像大小
get_image_size (ImageR, WidthR, HeightR)*创建右边的窗口
dev_open_window (0, WidthL + 12, WidthL, HeightL, 'black', WindowHandle2)*设置区域填充模式为边缘模式
dev_set_draw ('margin')*设置输出对象的颜色为绿色
dev_set_color ('green')* 校正文件
CaltabFile := 'caltab_30mm.descr'*获取标定板中所有mark点的中心坐标
caltab_points (CaltabFile, X, Y, Z)* 设置左右两个相机的摄像机内部参数[Focus,Kappa,SxSy,CxCy,WhithHeight]
StartCamParL := [0.0125,0,1.48e-5,1.48e-5,WidthL / 2.0,HeightL / 2.0,WidthL,HeightL]
StartCamParR := StartCamParL
* Parameter settings for find_caltab and find_marks_and_pose
SizeGauss := 3
MarkThresh := 120
MinDiamMarks := 5
StartThresh := 128
DeltaThresh := 10
MinThresh := 18
Alpha := 0.9
MinContLength := 15
MaxDiamMarks := 100
* Create the tuples in which the image coordinates of the
* calibration marks and the initial poses will be accumulated
RowsL := []
ColsL := []
StartPosesL := []
RowsR := []
ColsR := []
StartPosesR := []
* Start the loop over the calibration images
for Index := 1 to 15 by 1* 读取左面相机拍照的标定板图像read_image (ImageL, ImgPath + 'calib_l_' + Index$'02d')* 读取右面相机拍照的标定板图像read_image (ImageR, ImgPath + 'calib_r_' + Index$'02d')* 分割左面相机拍照的标定板图像标定板区域find_caltab (ImageL, CaltabL, CaltabFile, SizeGauss, MarkThresh, MinDiamMarks)* 分割右面相机拍照的标定板图像标定板区域find_caltab (ImageR, CaltabR, CaltabFile, SizeGauss, MarkThresh, MinDiamMarks)*激活左面的窗口dev_set_window (WindowHandle1)*显示左面相机拍照的标定板图像dev_display (ImageL)*显示左面相机拍照的标定板图像标定板区域dev_display (CaltabL)*激活右面的窗口dev_set_window (WindowHandle2)*显示右面相机拍照的标定板图像dev_display (ImageR)*显示右面相机拍照的标定板图像标定板区域dev_display (CaltabR)*提取左面相机拍照的标定板中MARK点坐标和摄像机外部参数find_marks_and_pose (ImageL, CaltabL, CaltabFile, StartCamParL, StartThresh, DeltaThresh, MinThresh, Alpha, MinContLength, MaxDiamMarks, RCoordL, CCoordL, StartPoseL)*显示左面图像中标定板三维模型disp_caltab (WindowHandle1, CaltabFile, StartCamParL, StartPoseL, 1)*提取右面相机拍照的标定板中MARK点坐标和摄像机外部参数find_marks_and_pose (ImageR, CaltabR, CaltabFile, StartCamParR, StartThresh, DeltaThresh, MinThresh, Alpha, MinContLength, MaxDiamMarks, RCoordR, CCoordR, StartPoseR)*显示右面图像中标定板三维模型disp_caltab (WindowHandle2, CaltabFile, StartCamParR, StartPoseR, 1)*17张左面相机拍照图像的MARK点行坐标连接起来RowsL := [RowsL,RCoordL]*17张左面相机拍照图像的MARK点列坐标连接起来ColsL := [ColsL,CCoordL]*将左面相机的摄像机外部参数连接起来StartPosesL := [StartPosesL,StartPoseL]*17张右面相机拍照图像的MARK点行坐标连接起来RowsR := [RowsR,RCoordR]*17张右面相机拍照图像的MARK点列坐标连接起来ColsR := [ColsR,CCoordR]*将右面相机的摄像机外部参数连接起来StartPosesR := [StartPosesR,StartPoseR]
endfor* 执行双目标定
binocular_calibration (X, Y, Z, RowsL, ColsL, RowsR, ColsR, StartCamParL, StartCamParR, StartPosesL, StartPosesR, 'all', CamParamL, CamParamR, NFinalPoseL, NFinalPoseR, cLPcR, Errors)
* If required, save the results to disk:
* write_cam_par (CamParamL, 'cam_left-125.dat')
* write_cam_par (CamParamR, 'cam_right-125.dat')
* write_pose (cLPcR, 'pos_right2left.dat')* 获取非标准外极线几何到标准外极线几何之间的变换关系
gen_binocular_rectification_map (MapL, MapR, CamParamL, CamParamR, cLPcR, 1, 'geometric', 'bilinear', RectCamParL, RectCamParR, CamPoseRectL, CamPoseRectR, RectLPosRectR)*读取左相机拍照的一张图
read_image (ImageL, ImgPath + 'calib_l_01')*读取右相机拍照的一张图
read_image (ImageR, ImgPath + 'calib_r_01')*根据上述变换关系,对左相机拍照图进行校正
map_image (ImageL, MapL, ImageRectifiedL)*根据上述变换关系,对右相机拍照图进行校正
map_image (ImageR, MapR, ImageRectifiedR)*显示最后的双目标定结果,得到标准外极线几何时的图像.
check_epipolar_constraint (ImageRectifiedL, ImageRectifiedR, RectCamParL, RectCamParR, WindowHandle1, WindowHandle2, CaltabFile, EpipolarError)

以下是针对提供的HALCON双目相机标定与校正代码的逐步解释和优化建议:

逐步解释

  1. 初始化设置:
    • 定义图像路径ImgPath,初始化索引Index

    • 读取左右相机的第一对标定板图像(可能用于测试,后续循环处理所有图像)。

  2. 窗口管理:
    • 关闭已有窗口,禁用自动更新以提高性能。

    • 根据左图像尺寸创建左窗口,设置绘图参数(边缘模式、颜色、字体)。

    • 创建右窗口,位置在左窗口右侧,使用左图像尺寸(假设左右图像尺寸相同)。

  3. 标定板参数:
    • 加载标定板描述文件caltab_30mm.descr,获取标定板点的世界坐标(X, Y, Z)

    • 初始化左右相机的内部参数(焦距、畸变、像素尺寸、中心点等)。

  4. 参数配置:
    • 设置find_caltabfind_marks_and_pose的参数(高斯滤波、阈值、标记尺寸等)。

    • 初始化数组存储左右相机的图像坐标和初始位姿。

  5. 循环处理标定图像:
    • 遍历15对图像,逐对处理:

    ◦ 读取左右图像,检测标定板区域CaltabL/R并显示。

    ◦ 提取标记点坐标(RCoordL/R, CCoordL/R)和初始位姿StartPoseL/R

    ◦ 显示标定板3D模型,收集坐标和位姿数据。

  6. 双目标定:
    • 使用binocular_calibration优化相机参数和相对位姿,输出最终参数CamParamL/RcLPcR

  7. 生成校正映射:
    • 调用gen_binocular_rectification_map生成校正映射MapL/R,将图像校正为标准极线几何。

  8. 验证校正结果:
    • 读取并校正一对图像,使用check_epipolar_constraint检查极线误差,验证校正效果。

优化建议

  1. 窗口尺寸适配:

    * 获取右图像实际尺寸
    get_image_size (ImageR, WidthR, HeightR)
    * 创建右窗口时使用实际尺寸
    dev_open_window (0, WidthL + 12, WidthR, HeightR, 'black', WindowHandle2)
    

    确保右窗口尺寸与右图像匹配,避免显示不全。

  2. 错误处理:

    tryfind_caltab (ImageL, CaltabL, CaltabFile, SizeGauss, MarkThresh, MinDiamMarks)
    catch (Exception)* 处理异常,如打印错误信息并跳出循环dev_disp_text ('标定板检测失败: ' + Exception, 'window', WindowHandle1, 'left', 'red', 'box')break
    endtry
    

    添加异常捕获,增强鲁棒性。

  3. 字符串格式化修正:

    * 使用正确的格式化语法
    IndexStr := Index$'02d'
    read_image (ImageL, ImgPath + 'calib_l_' + IndexStr)
    

    确保文件名正确生成,避免因格式错误导致读取失败。

  4. 参数保存:

    * 保存标定结果
    write_cam_par (CamParamL, 'cam_left_final.dat')
    write_cam_par (CamParamR, 'cam_right_final.dat')
    write_pose (cLPcR, 'stereo_pose.dat')
    * 保存校正映射
    write_map (MapL, 'map_left.bin')
    write_map (MapR, 'map_right.bin')
    

    便于后续应用,无需重复标定。

  5. 循环结构优化:

    for Index := 1 to 15 by 1* 统一处理左右图像process_stereo_pair (Index, ImgPath, WindowHandle1, WindowHandle2, ...)
    endfor
    

    封装重复操作为函数,提升代码可读性和维护性。

  6. 动态参数调整:
    • 可交互式调整MarkThresh等参数,或通过循环寻找最佳参数组合,确保标定板检测稳定。

  7. 可视化增强:

    * 在显示校正结果时叠加极线
    disp_epipolar_line (ImageRectifiedL, ImageRectifiedR, RectCamParL, RectCamParR, WindowHandle1, WindowHandle2)
    

    直观展示极线对齐效果。

修正后的关键代码片段

* 创建右窗口时使用右图像尺寸
get_image_size (ImageR, WidthR, HeightR)
dev_open_window (0, WidthL + 12, WidthR, HeightR, 'black', WindowHandle2)* 循环处理中添加错误处理
for Index := 1 to 15 by 1tryread_image (ImageL, ImgPath + 'calib_l_' + Index$'02d')read_image (ImageR, ImgPath + 'calib_r_' + Index$'02d')* 检测标定板find_caltab (ImageL, CaltabL, CaltabFile, SizeGauss, MarkThresh, MinDiamMarks)find_caltab (ImageR, CaltabR, CaltabFile, SizeGauss, MarkThresh, MinDiamMarks)* 提取标记点及位姿find_marks_and_pose (...)* 收集数据...catch (Exception)dev_clear_window ()dev_disp_text ('错误: ' + Exception, 'window', WindowHandle1, 'left', 'red', 'box')breakendtry
endfor* 标定后保存参数
write_cam_par (CamParamL, 'cam_left_final.dat')
write_cam_par (CamParamR, 'cam_right_final.dat')
write_pose (cLPcR, 'stereo_pose.dat')

总结

通过修正窗口尺寸、增强错误处理、优化参数保存及代码结构,提升了程序的稳健性和实用性。确保实际应用中左右相机图像尺寸一致或正确适配,参数文件路径正确,并根据实际标定场景调整检测参数,以获得最佳标定效果。

双目立体视觉测量零件的高度

在这里插入图片描述
高度测量步骤:

1.执行双目标定;

binocular_calibration( : : NX, NY, NZ, NRow1, NCol1, NRow2, NCol2, StartCamParam1, StartCamParam2, NStartPose1,NStartPose2, EstimateParams : CamParam1, CamParam2, NFinalPose1, NFinalPose2, RelPose, Errors)
参数含义:
NX:			标定板MARK点行坐标(经过排序的,单位是米)
NY:			标定板MARK点列坐标(经过排序的,单位是米)
NZ:			标定板MARKZ坐标(经过排序的,单位是米)
NRow1:        左面相机中标定板提取出的MARK点行坐标(经过排序的,单位是像素)
NCol1:		左面相机中标定板提取出的MARK点列坐标(经过排序的,单位是像素)
NRow2:		右面相机中标定板提取出的MARK点行坐标(经过排序的,单位是像素)
NCol2:		右面相机中标定板提取出的MARK点列坐标(经过排序的,单位是像素)
StartCamParam1:左面相机的摄像机内部参数
StartCamParam2:右面相机的摄像机内部参数
NStartPose1:	 左面相机的摄像机外部参数
NStartPose2:	 右面相机的摄像机外部参数
EstimateParams: 选择要标定出哪些相机参数,all”代表所有的参数
CamParam1:     标定后得到的左面相机的摄像机内部参数
CamParam2:     标定后得到的右面相机的摄像机内部参数
NFinalPose1:   标定后得到的左面相机的摄像机外部参数
NFinalPose2:   标定后得到的右面相机的摄像机外部参数
RelPose:		 右边相机相对于左面相机的位姿
Errors         平均错误误差

2.获取非标准外极线几何到标准外极线几何之间的变换矩阵;

gen_binocular_rectification_map( : Map1, Map2 : CamParam1, CamParam2, RelPose, SubSampling, Method, MapType :CamParamRect1, CamParamRect2, CamPoseRect1, CamPoseRect2, RelPoseRect)
参数含义:
Map1:左面相机校正映射数据
Map2:右面相机校正映射数据
CamParam1:左面相机的摄像机内部参数
CamParam2:右面相机的摄像机内部参数
RelPose:  右相机相对左相机的位姿
SubSampling:采样因子
Method:    映射校正方法
MapType:   映射校正类型
CamParamRect1: 左面相机校正以后的摄像机内部参数
CamParamRect2: 右面相机校正以后的摄像机内部参数
CamPoseRect1:  校正以后的左面相机相对原始相机的位姿
CamPoseRect2:校正以后的右面相机相对原始相机的位姿
RelPoseRect:校正以后的右面相机相对校正以后的左面相机的位姿关系

3.通过变换矩阵对未校正的图像进行图像校正

map_image(Image, Map : ImageMapped : : )
参数含义:
Image:			待校正图像
Map:  			相机校正映射数据
ImageMapped: 	校正后的图像

4.计算左右摄像机的视差图像

binocular_disparity(ImageRect1, ImageRect2 : Disparity, Score : Method, MaskWidth, MaskHeight, TextureThresh,MinDisparity, MaxDisparity, NumLevels, ScoreThresh, Filter, SubDisparity:)
参数含义:
ImageRect1:左边相机校正后的图像
ImageRect2:右边相机校正后的图像
Disparity:视差映射图
Score:视差值得匹配分数
Method:匹配方法
MaskWidth:校正窗口的宽度
MaskHeight:校正窗口的高度
TextureThresh:匹配需要的阈值
MinDisparity:视差的最小值
MaxDisparity:视差的最大值
NumLevels:金字塔层级
ScoreThresh:相关函数的最小分值,保证匹配质量
Filter:增加匹配的鲁棒性
SubDisparity :视差图是否采用亚像素

5.通过视差计算距离图像

binocular_distance_mg(ImageRect1, ImageRect2 : Distance, Score : CamParamRect1, CamParamRect2, RelPoseRect,GrayConstancy, GradientConstancy, Smoothness, InitialGuess, CalculateScore, MGParamName, MGParamValue : )
参数含义:
ImageRect1:左边相机校正后的图像
ImageRect2:右边相机校正后的图像
Distance:距离图像
Score:视差值得匹配分数
CamParamRect1:左边相机校正后的摄像机内部参数
CamParamRect2:右边相机校正后的摄像机内部参数
RelPoseRect:校正后的右相机相对左相机的位姿
GrayConstancy:距离图像中灰度值的权重
GradientConstancy:距离图像中梯度的权重
Smoothness:图像滤波权重
InitialGuess:初始的视差
CalculateScore:匹配分数
MGParamName:多重网格算法
MGParamValue :
//多重网格法:求解偏微分问题离散方程的一种快速迭代方法

代码示例

*关闭图像窗口更新
dev_update_window ('off')*关闭变量更新
dev_update_var ('off')*关闭程序计数器更新
dev_update_pc ('off')*关闭窗口
dev_close_window ()*打开新窗口
dev_open_window (0, 0, 672, 484, 'black', WindowHandle)*设置字体显示信息
set_display_font (WindowHandle, 16, 'mono', 'true', 'false')*读取左面相机采集的图像
read_image (ImageL, 'stereo/board/board_l_01')*读取右面相机采集的图像
read_image (ImageR, 'stereo/board/board_r_01')*获取图像的大小
get_image_size (ImageR, Width, Height)*根据双目立体视觉标定获取到左右相机的摄像机内部参数和右相机相对左相机的位姿
*左相机的摄像机内部参数
CamParamL := [0.0130507774353,-665.817817207,1.4803417027e-5,1.48e-5,155.89225769,126.70664978,320,240]
*右相机的摄像机内部参数
CamParamR := [0.0131776504517,-731.860636733,1.47997569293e-5,1.48e-5,162.98210144,119.301040649,320,240]
*右相机相对左相机的位姿
RelPose := [0.153573364258,-0.00373362231255,0.0447351264954,0.174289124775,319.843388114,359.894955219,0]*获取非标准外极限图像和标准外极限图像之间的变换矩阵(映射图像)
gen_binocular_rectification_map (MapL, MapR, CamParamL, CamParamR, RelPose, 1, 'geometric', 'bilinear', RectCamParL, RectCamParR, CamPoseRectL, CamPoseRectR, RectLPosRectR)*根据变换矩阵对左边相机进行图像校正
map_image (ImageL, MapL, ImageRectifiedL)*根据变换矩阵对右边相机进行图像校正
map_image (ImageR, MapR, ImageRectifiedR)binocular_disparity (ImageRectifiedL, ImageRectifiedR, Disparity, Score1, 'ncc', 17, 17, 5, 0, 60, 1, 0.1, 'none', 'none')
*根据左右相机的校正图像计算深度信息
binocular_distance_mg (ImageRectifiedL, ImageRectifiedR, Distance, Score, RectCamParL, RectCamParR, RectLPosRectR, 1, 10, 5, 0, 'false', 'default_parameters', 'accurate')*清除窗口内容
dev_clear_window ()*显示距离图像
dev_display (Distance)*计算IC的高度
gen_rectangle2 (IC, 107.276, 62.0363, rad(-25.6343), 7.64174, 6.41978)
gen_rectangle2 (PCB, 101.986, 145.771, rad(4.75463), 7.97698, 6.76498)
get_grayval (Distance, 107.276, 62.0363, IC_Grayval)
get_grayval (Distance, 101.986, 145.771, PCB_Grayval)
IC_Height:=(PCB_Grayval-IC_Grayval)*100*显示结果
dev_display (ImageRectifiedL)
set_tposition (WindowHandle, 103, 54)
write_string (WindowHandle, 'IC零件的高度是:'+IC_Height+'cm')

1. 初始化设置与窗口管理

* 关闭窗口更新、变量更新、程序计数器更新
dev_update_window ('off')
dev_update_var ('off')
dev_update_pc ('off')
* 关闭所有窗口并打开新窗口
dev_close_window ()
dev_open_window (0, 0, 672, 484, 'black', WindowHandle)
set_display_font (WindowHandle, 16, 'mono', 'true', 'false')

• 功能:

关闭自动更新以提高性能,创建新窗口并设置字体。
• 关键点:

dev_update_off系列命令用于禁用HDevelop的自动刷新,减少资源占用。

dev_open_window参数依次为窗口左上角坐标、宽度、高度、背景颜色和窗口句柄。


2. 图像读取与参数定义

* 读取左右相机图像
read_image (ImageL, 'stereo/board/board_l_01')
read_image (ImageR, 'stereo/board/board_r_01')
get_image_size (ImageR, Width, Height)* 定义相机参数和相对位姿
CamParamL := [0.01305..., ...]  ; 左相机内参
CamParamR := [0.01317..., ...]  ; 右相机内参
RelPose := [0.15357..., ...]    ; 右相机相对于左相机的位姿

• 参数解析:

• 内参:[Focus, Kappa, Sx, Sy, Cx, Cy, Width, Height]

◦ `Focus`:焦距(单位:米),远心镜头设为0。  ◦ `Kappa`:畸变系数,通常初始化为0(Division模型)。  ◦ 问题:用户代码中`Kappa`值异常(如-665),需检查是否误用参数。  

• 位姿:[Tx, Ty, Tz, RotX, RotY, RotZ, Angle](轴角表示法)。

◦ 需验证`RelPose`是否为标定输出的正确格式(单位是否为弧度)。

3. 极线校正与图像映射

* 生成校正映射并校正图像
gen_binocular_rectification_map (MapL, MapR, CamParamL, CamParamR, RelPose, ...)
map_image (ImageL, MapL, ImageRectifiedL)
map_image (ImageR, MapR, ImageRectifiedR)

• 功能:

将原始图像投影到公共平面,消除极线倾斜,使匹配点位于同一行。
• 参数说明:

gen_binocular_rectification_map:输入内参、相对位姿,输出映射表MapL/R和校正后参数。

map_image:根据映射表对图像进行几何变换。


4. 视差与深度计算

* 计算视差图
binocular_disparity (ImageRectifiedL, ImageRectifiedR, Disparity, ..., 'ncc', 17, 17, ...)
* 计算深度图
binocular_distance_mg (..., Distance, ...)

• 算法细节:

• 视差计算:使用归一化互相关(NCC)方法,窗口大小17x17,适用于纹理丰富场景,但可能降低实时性。

• 深度转换:基于视差图与校正参数,通过三角测量生成三维距离图。


5. 高度测量与结果显示

* 在距离图上定义ICPCB区域
gen_rectangle2 (IC, 107.276, 62.0363, rad(-25.6343), 7.64174, 6.41978)
gen_rectangle2 (PCB, 101.986, 145.771, rad(4.75463), 7.97698, 6.76498)
* 获取灰度值计算高度差
get_grayval (Distance, IC_Grayval, PCB_Grayval)
IC_Height := (PCB_Grayval - IC_Grayval) * 100
* 显示结果
dev_display (ImageRectifiedL)
write_string (WindowHandle, 'IC高度: ' + IC_Height + 'cm')

• 关键点:

get_grayval:假设Distance图像的像素值表示实际距离(单位:米/毫米),需确认单位一致性。

• 问题:rad()函数在HALCON中需替换为tuple_rad或直接输入弧度值,否则可能报错。

• 结果需格式化输出,如IC_Height$'.2f',避免字符串拼接错误。


优化

  1. 参数验证:
    • 检查CamParamL/R中的畸变系数Kappa是否合理(通常接近0)。

    • 确认RelPose的旋转参数单位是否为弧度。

  2. 性能优化:
    • 缩小视差计算窗口(如9x9)以提升速度。

  3. 异常处理:
    • 添加try-catch块捕获read_image或标定步骤的异常。

  4. 单位与显示:
    • 明确Distance的单位,调整高度计算系数(如毫米则无需*100)。


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

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

相关文章

板凳-------Mysql cookbook学习 (六)

2025年Pytorch-gpu版本安装&#xff08;各种情况适用自己的安装需求&#xff0c;亲测绝对有效&#xff0c;示例安装torch2.6.0&#xff0c;过程详细面向小白&#xff09;_torch gpu版本-CSDN博客 https://blog.csdn.net/OpenSeek/article/details/145795127 2.2 查错 import s…

Spring boot和SSM项目对比

目录对比 springboot目录 project├─src│ ├─main│ │ ├─java│ │ │ ├─com.example.demo│ │ │ │ ├─config // 存放SpringBoot的配置类│ │ │ │ ├─controller // 存放控制器类│ │ │ │ ├─entity // 存…

《关于浔川社团退出DevPress社区及内容撤回的声明》

《关于浔川社团退出DevPress社区及内容撤回的声明》 尊敬的DevPress社区及读者&#xff1a; 经浔川社团内部决议&#xff0c;我社决定自**2025年5月26日**起正式退出DevPress社区&#xff0c;并撤回所有由我社成员在该平台发布的原创文章。相关事项声明如下&#xff1a; …

Python性能优化利器:__slots__的深度解析与避坑指南

核心场景&#xff1a;当需要创建数百万个属性固定的对象时&#xff0c;默认的__dict__字典存储会造成巨大内存浪费。此时__slots__能通过元组结构取代字典&#xff0c;显著提升内存效率&#xff08;实测节省58%内存&#xff09;&#xff01; 底层原理&#xff1a;为何能节省内…

Go 语言中的 Struct Tag 的用法详解

在 Go 语言中&#xff0c;结构体字段标签&#xff08;Struct Tag&#xff09; 是一种用于给字段添加元信息&#xff08;metadata&#xff09;的机制&#xff0c;常用于序列化&#xff08;如 JSON、XML&#xff09;、ORM 映射、验证等场景。你在开发 Web 应用或处理数据交互时&a…

微软正式发布 SQL Server 2025 公开预览版,深度集成AI功能

微软在今年的 Build 2025 大会上正式发布了 SQL Server 2025 公开预览版&#xff0c;标志着这一经典数据库产品在 AI 集成、安全性、性能及开发者工具方面的全面升级。 AI 深度集成与创新 原生向量搜索&#xff1a;SQL Server 2025 首次将 AI 功能直接嵌入数据库引擎&#xff…

React从基础入门到高级实战:React 基础入门 - React 的工作原理:虚拟 DOM 与 Diff 算法

React 的工作原理&#xff1a;虚拟 DOM 与 Diff 算法 引言 React 是现代前端开发的明星框架&#xff0c;它的出现彻底改变了我们构建用户界面的方式。无论是动态的 Web 应用还是复杂的单页应用&#xff08;SPA&#xff09;&#xff0c;React 都能以高效的渲染机制和简洁的组件…

解释一下NGINX的反向代理和正向代理的区别?

大家好&#xff0c;我是锋哥。今天分享关于【解释一下NGINX的反向代理和正向代理的区别?】面试题。希望对大家有帮助&#xff1b; 解释一下NGINX的反向代理和正向代理的区别? NGINX的反向代理和正向代理的区别主要体现在它们的功能和使用场景上。下面我会详细解释它们的定义…

Python学习——执行python时,键盘按下ctrl+c,退出程序

在 Python 中&#xff0c;当用户按下 CtrlC 时&#xff0c;程序默认会触发 KeyboardInterrupt 异常并终止。 1. 捕获 KeyboardInterrupt 异常&#xff08;推荐&#xff09; 使用 try-except 块直接捕获 KeyboardInterrupt 异常&#xff0c;适用于简单场景。 示例代码&#xff…

C++ 反向迭代器(Reverse Iterator)实现详解

目录 1. 反向迭代器概述 2. 代码实现分析 3. 关键点解析 3.1 模板参数设计 3.2 核心操作实现 4. 使用示例 1. 反向迭代器概述 反向迭代器是STL中一种重要的适配器&#xff0c;它允许我们以相反的顺序遍历容器。本文将详细讲解如何实现一个自定义的反向迭代器模板类。 2.…

动态DNS管理:【etcd+CoreDNS】 vs【BIND9】便捷性对比

对比 BIND9 集群和 etcdCoreDNS 集群在便捷性方面&#xff0c;通常情况下&#xff0c;对于需要动态、频繁变更 DNS 记录以及追求云原生和自动化集成的场景&#xff0c;etcdCoreDNS 方案更加便捷。 然而&#xff0c;“便捷性”也取决于具体的应用场景、团队的技术栈和运维习惯。…

基于大模型的短暂性脑缺血发作预测与干预全流程系统技术方案大纲

目录 一、系统概述二、系统架构(一)数据采集层(二)大模型核心层(三)应用服务层(四)数据存储与管理层三、全流程技术方案(一)术前阶段(二)术中阶段(三)术后阶段(四)并发症风险预测(五)手术方案制定(六)麻醉方案制定(七)术后护理(八)统计分析(九)技术验…

MSP430通用电机控制代码(Motor)设计与实现

一、代码结构概览 // Motor.h // Motor.h #ifndef __MOTOR_H_ #define __MOTOR_H_#include "A_include.h"void Motor_Init(void); // 初始化函数 void PWM_SET(int duty0, int duty1); // PWM设置函数#endif// Motor.c // Motor.c #include "Motor.h"…

25年软考架构师真题(回忆更新中)

论文题: 系统负载均衡设计方法事件驱动架构多模型数据库应用软件测试架构案例分析: 必选题:1.1填写质量属性的质量属性名 1.2解释器风格架构的组成图填空,以及解释为什么该模型适用解释器风格 选做题1redis2.1全量复制的流程图 <

优化用户体验:拦截浏览器前进后退、刷新、关闭、路由跳转等用户行为并弹窗提示

&#x1f9d1;‍&#x1f4bb; 写在开头 点赞 收藏 学会&#x1f923;&#x1f923;&#x1f923; 需求 首先列举一下需要拦截的行为&#xff0c;接下来我们逐个实现。 浏览器前进后退标签页刷新和关闭路由跳转 1、拦截浏览器前进后退 这里的实现是核心&#xff0c;涉及到大…

Docker:容器化技术

引言 传统部署环境逐渐不适应现在的企业开发&#xff0c;为了追求更加轻量&#xff0c;更加容易管理项目&#xff0c;引入了docker容器化技术去实现更加高效的部署环境。 一.docker风光下的内核功能和常用命令 1.docker容器和虚拟机的区别 我们在底层和应用层之间引入了一层do…

ping命令常用参数以及traceout命令

在网络故障排查和性能分析中&#xff0c;ping和 traceroute&#xff08;Windows中通常称为 tracert&#xff09;是两个极为重要的工具。它们帮助诊断网络连接问题&#xff0c;了解数据在网络中的传输路径。下面将详细介绍这两个命令的常用参数及其应用。 ping命令 ping命令用…

SpringBoot开发——Spring Boot异常处理全攻略:五大方案实战对比

文章目录 一、血泪教训:异常处理的代价二、五大异常处理方案详解2.1 全局异常处理(推荐方案)2.2 控制器级处理2.3 HTTP状态码注解2.4 ResponseEntity精细控制2.5 自定义异常体系(企业级方案)三、五大方案对比决策表四、四大避坑指南4.1 异常吞噬陷阱4.2 循环依赖问题4.3 异…

CodeBuddy 实现图片转素描手绘工具

本文所使用的 CodeBuddy 免费下载链接&#xff1a;腾讯云代码助手 CodeBuddy - AI 时代的智能编程伙伴 前言 最近在社交媒体上&#xff0c;各种素描风格的图片火得一塌糊涂&#xff0c;身边不少朋友都在分享自己的 “素描照”&#xff0c;看着那些黑白线条勾勒出的独特韵味&a…

2025.05.21华为暑期实习机考真题解析第二题

📌 点击直达笔试专栏 👉《大厂笔试突围》 💻 春秋招笔试突围在线OJ 👉 笔试突围OJ 02. 灾区物资调度路径规划 问题描述 在一次严重的自然灾害后,LYA负责协调救援物资的配送工作。救援区域包含多个受灾乡镇和一个物资集结点,各个地点之间的道路状况各异,有些甚至…