*此示例演示了一个3D应用程序,
*它结合了立体设置和基于3D形状的匹配功能。
*给定一盒铝圆柱体,任务是找到这个堆中最高的物体。
*为此,我们首先使用立体声设置来缩小感兴趣的区域。
*在第二步中,第三台相机拍摄场景的特写镜头,
*用于应用3D匹配来确定物体的实际姿态和方向。
*在右侧图形窗口中,将显示场景的高度图。
*然后,从高度图确定的最高物体的特写镜头显示在左侧图形窗口中。
dev_close_window ()
dev_close_window ()
dev_update_off ()
dev_get_preferences ('suppress_handled_exceptions_dlg', SuppressExceptionSetting)
dev_set_preferences ('suppress_handled_exceptions_dlg', 'true')
*
Path := 'metal_cylinders/'
*
dev_open_window (0, 0, 752 * 0.5, 480 * 0.5, 'black', WindowHandleL)
dev_set_part (0, 0, 480, 752)
dev_set_lut ('default')
dev_set_line_width (2)
set_display_font (WindowHandleL, 11, 'mono', 'true', 'false')
*
dev_open_window (0, 752 * 0.5, 640 * 0.95, 512 * 0.95, 'black', WindowHandle)
dev_set_part (0, 0, 485, 607)
dev_set_draw ('fill')
dev_set_color ('blue')
dev_set_lut ('temperature')
dev_set_paint ('default')
*
gen_cam_par_area_scan_division (0.00855613, -2579.17, 5.99979e-006, 6e-006, 399.681, 232.327, 752, 480, CamParamMatching)
gen_cam_par_area_scan_division (0.0121469, -2514.3, 9.30281e-006, 9.3e-006, 272.773, 273.689, 640, 512, CamParam1)
gen_cam_par_area_scan_division (0.0121592, -2687.76, 9.30085e-006, 9.3e-006, 302.665, 263.738, 640, 512, CamParam2)
create_pose (0.202198, 0.00177953, 0.0376427, 0.325733, 342.295, 359.167, 'Rp+T', 'gba', 'point', RelPose)
gen_binocular_rectification_map (Map1, Map2, CamParam1, CamParam2, RelPose, 1, 'geometric', 'bilinear', CamParamRect1, CamParamRect2, CamPoseRect1, CamPoseRect2, RelPoseRect)
*
file_exists ('cylinder.sm3', FileExists)
if (FileExists)
* Load the model from file
read_shape_model_3d ('cylinder.sm3', ShapeModel3DID)
else
* Recreate the model from the DXF file
read_object_model_3d ('cylinder.dxf', 'mm', [], [], ObjectModel3DID, DxfStatus)
prepare_object_model_3d (ObjectModel3DID, 'shape_based_matching_3d', 'true', [], [])
create_shape_model_3d (ObjectModel3DID, CamParamMatching, rad(90), 0, 0, 'gba', 0, 0, 0, rad(45), 0, rad(360), 0.3, 0.45, 10, 'num_levels', 5, ShapeModel3DID)
write_shape_model_3d (ShapeModel3DID, 'cylinder.sm3')
clear_object_model_3d (ObjectModel3DID)
endif
*
for Index := 1 to 15 by 1
*
* emphasize() enhances the texture on the cylinders surface
read_image (Image1, Path + 'stereo_left_' + Index$'02')
emphasize (Image1, ImageEmphasize1, 5, 5, 2)
map_image (ImageEmphasize1, Map1, ImageMapped1)
read_image (Image2, Path + 'stereo_right_' + Index$'02')
emphasize (Image2, ImageEmphasize2, 5, 5, 2)
map_image (ImageEmphasize2, Map2, ImageMapped2)
*
* the mask width and height must be (approximately) set according to the size
* of the pattern projected onto the setup
binocular_disparity (ImageMapped2, ImageMapped1, Disparity, Score, 'ncc', 7, 7, 0, -20, 140, 1, 0.7, 'left_right_check', 'none')
select_best_candidates (Disparity, TopMost)
remove_shadowed_regions (Disparity, 0.01)
*
* display height map and highest object extracted
clear_window (WindowHandleL)
dev_set_window (WindowHandle)
dev_clear_window ()
dev_display (ImageMapped2)
dev_display (Disparity)
wait_seconds (0.5)
dev_display (TopMost)
dev_display (Disparity)
wait_seconds (0.5)
*
* determine exact 3D pose of highest object
dev_set_window (WindowHandleL)
read_image (Image, Path + 'closeup_' + Index$'02')
dev_display (Image)
find_shape_model_3d (Image, ShapeModel3DID, 0.8, 0.7, [0,2], [], [], Pose, CovPose, Score_CTRL)
if (|Score_CTRL| != 0)
dev_set_color ('green')
display_match_pose (ShapeModel3DID, Pose, WindowHandleL)
else
disp_message (WindowHandleL, ' No match found ', 'window', 12, 12, 'black', 'true')
endif
*
if (Index != 15)
disp_continue_message (WindowHandleL, 'black', 'true')
endif
stop ()
endfor
disp_message (WindowHandleL, 'Program finished \nPress \'Run\' to clear the shape model', 'window', 1, 1, 'black', 'true')
stop ()
clear_shape_model_3d (ShapeModel3DID)
dev_close_window ()
dev_set_preferences ('suppress_handled_exceptions_dlg', SuppressExceptionSetting)
*
铝圆柱体堆栈中最高物体识别与定位系统
代码详细注释
*此示例演示了一个3D应用程序,
*它结合了立体设置和基于3D形状的匹配功能。
*给定一盒铝圆柱体,任务是找到这个堆中最高的物体。
*为此,我们首先使用立体声设置来缩小感兴趣的区域。
*在第二步中,第三台相机拍摄场景的特写镜头,
*用于应用3D匹配来确定物体的实际姿态和方向。
*在右侧图形窗口中,将显示场景的高度图。
*然后,从高度图确定的最高物体的特写镜头显示在左侧图形窗口中。
* 关闭所有图形窗口
dev_close_window ()
dev_close_window ()
* 关闭图形更新以提高性能
dev_update_off ()
* 获取并保存当前异常处理设置
dev_get_preferences ('suppress_handled_exceptions_dlg', SuppressExceptionSetting)
* 临时禁用异常对话框显示
dev_set_preferences ('suppress_handled_exceptions_dlg', 'true')
* 设置图像数据路径
Path := 'metal_cylinders/'
* 打开左侧窗口显示特写镜头
dev_open_window (0, 0, 752 * 0.5, 480 * 0.5, 'black', WindowHandleL)
* 设置图像显示区域
dev_set_part (0, 0, 480, 752)
* 设置默认查找表
dev_set_lut ('default')
* 设置线宽
dev_set_line_width (2)
* 设置字体
set_display_font (WindowHandleL, 11, 'mono', 'true', 'false')
* 打开右侧窗口显示高度图
dev_open_window (0, 752 * 0.5, 640 * 0.95, 512 * 0.95, 'black', WindowHandle)
* 设置图像显示区域
dev_set_part (0, 0, 485, 607)
* 设置填充模式
dev_set_draw ('fill')
* 设置默认颜色
dev_set_color ('blue')
* 设置温度色度查找表
dev_set_lut ('temperature')
* 设置绘制模式
dev_set_paint ('default')
* 生成匹配相机参数 - 用于3D匹配
* 参数: 焦距(mm), kappa, Sx, Sy, Cx, Cy, 图像宽, 图像高
gen_cam_par_area_scan_division (0.00855613, -2579.17, 5.99979e-006, 6e-006, 399.681, 232.327, 752, 480, CamParamMatching)
* 生成左相机参数 - 用于立体视觉
gen_cam_par_area_scan_division (0.0121469, -2514.3, 9.30281e-006, 9.3e-006, 272.773, 273.689, 640, 512, CamParam1)
* 生成右相机参数 - 用于立体视觉
gen_cam_par_area_scan_division (0.0121592, -2687.76, 9.30085e-006, 9.3e-006, 302.665, 263.738, 640, 512, CamParam2)
* 创建立体相机相对位姿
create_pose (0.202198, 0.00177953, 0.0376427, 0.325733, 342.295, 359.167, 'Rp+T', 'gba', 'point', RelPose)
* 生成双目校正映射
gen_binocular_rectification_map (Map1, Map2, CamParam1, CamParam2, RelPose, 1, 'geometric', 'bilinear', CamParamRect1, CamParamRect2, CamPoseRect1, CamPoseRect2, RelPoseRect)
* 检查3D形状模型文件是否存在
file_exists ('cylinder.sm3', FileExists)
if (FileExists)
* 如果存在则直接加载3D形状模型
read_shape_model_3d ('cylinder.sm3', ShapeModel3DID)
else
* 如果不存在则从DXF文件创建模型
* 读取CAD模型文件
read_object_model_3d ('cylinder.dxf', 'mm', [], [], ObjectModel3DID, DxfStatus)
* 准备3D模型用于匹配
prepare_object_model_3d (ObjectModel3DID, 'shape_based_matching_3d', 'true', [], [])
* 创建3D形状匹配模型
* 参数: 模型ID, 相机参数, 最小角度(弧度), 角度步长, 位置步长, 优化方法, 模型尺寸限制
create_shape_model_3d (ObjectModel3DID, CamParamMatching, rad(90), 0, 0, 'gba', 0, 0, 0, rad(45), 0, rad(360), 0.3, 0.45, 10, 'num_levels', 5, ShapeModel3DID)
*可视化模型
visualize_object_model_3d (WindowHandle, ObjectModel3DID, [], [], 'color_0', 'gray', [], [], [], PoseOut)
* 保存创建的模型到文件
write_shape_model_3d (ShapeModel3DID, 'cylinder.sm3')
* 清除临时对象模型
clear_object_model_3d (ObjectModel3DID)
endif
* 主处理循环 - 处理15组图像
for Index := 1 to 15 by 1
* 读取并增强立体左图像
read_image (Image1, Path + 'stereo_left_' + Index$'02')
* 图像增强 - 增强金属表面纹理
emphasize (Image1, ImageEmphasize1, 5, 5, 2)
* 应用校正映射
map_image (ImageEmphasize1, Map1, ImageMapped1)
* 读取并增强立体右图像
read_image (Image2, Path + 'stereo_right_' + Index$'02')
emphasize (Image2, ImageEmphasize2, 5, 5, 2)
map_image (ImageEmphasize2, Map2, ImageMapped2)
* 计算视差图 - 用于3D重建
* 参数: 右图像, 左图像, 视差输出, 得分输出, 匹配方法, 窗口尺寸, 最小/最大视差
binocular_disparity (ImageMapped2, ImageMapped1, Disparity, Score, 'ncc', 7, 7, 0, -20, 140, 1, 0.7, 'left_right_check', 'none')
* 选择最高物体的候选区域
select_best_candidates (Disparity, TopMost)
* 移除阴影区域 - 改善高度图质量
remove_shadowed_regions (Disparity, 0.01)
* 显示高度图和最高物体
clear_window (WindowHandleL)
dev_set_window (WindowHandle)
dev_clear_window ()
* 显示右侧图像
dev_display (ImageMapped2)
* 显示视差图
dev_display (Disparity)
wait_seconds (0.5)
* 突出显示最高物体
dev_display (TopMost)
dev_display (Disparity)
wait_seconds (0.5)
* 读取特写图像 - 用于精确定位
dev_set_window (WindowHandleL)
read_image (Image, Path + 'closeup_' + Index$'02')
dev_display (Image)
* 使用3D形状匹配查找最高物体
* 参数: 输入图像, 3D模型ID, 最小匹配得分, 贪婪度, 位置约束, 位姿输出, 协方差输出, 得分输出
find_shape_model_3d (Image, ShapeModel3DID, 0.8, 0.7, [0,2], [], [], Pose, CovPose, Score_CTRL)
* 如果找到匹配则显示结果
if (|Score_CTRL| != 0)
dev_set_color ('green')
* 显示匹配的3D姿态
display_match_pose (ShapeModel3DID, Pose, WindowHandleL)
else
disp_message (WindowHandleL, ' No match found ', 'window', 12, 12, 'black', 'true')
endif
* 暂停显示当前帧结果
if (Index != 15)
disp_continue_message (WindowHandleL, 'black', 'true')
endif
stop ()
endfor
* 程序结束处理
disp_message (WindowHandleL, 'Program finished \nPress \'Run\' to clear the shape model', 'window', 1, 1, 'black', 'true')
stop ()
* 清理资源
clear_shape_model_3d (ShapeModel3DID)
dev_close_window ()
* 恢复异常处理设置
dev_set_preferences ('suppress_handled_exceptions_dlg', SuppressExceptionSetting)
核心功能代码(带详细注释)
* -------------------- 系统初始化 --------------------
* 打开显示窗口
dev_open_window (0, 0, 400, 300, 'black', WindowHandleL)
dev_open_window (610, 0, 600, 400, 'black', WindowHandle)
* 生成相机参数(简略版)
gen_cam_par_area_scan_division (0.008, -2600, 6e-6, 6e-6, 400, 240, 752, 480, CamParamMatching)
* 创建/加载3D形状模型
file_exists ('cylinder.sm3', FileExists)
if (FileExists)
read_shape_model_3d ('cylinder.sm3', ShapeModel3DID)
else
read_object_model_3d ('cylinder.dxf', 'mm', [], [], ObjectModel3DID)
create_shape_model_3d (ObjectModel3DID, CamParamMatching, rad(90), 0, 0, 'gba', 0, 0, 0, rad(45), 0, rad(360), 0.3, 0.45, 10, ShapeModel3DID)
write_shape_model_3d (ShapeModel3DID, 'cylinder.sm3')
clear_object_model_3d (ObjectModel3DID)
endif
* -------------------- 主处理循环 --------------------
for Index := 1 to 15 by 1
* 步骤1: 3D重建确定最高物体区域
read_image (Image1, 'stereo_left_' + Index$'02')
read_image (Image2, 'stereo_right_' + Index$'02')
binocular_disparity (Image2, Image1, Disparity, Score, 'ncc', 7, 7, 0, -20, 140, 1, 0.7)
select_best_candidates (Disparity, TopMost) * 选择最高区域
* 步骤2: 显示高度图结果
dev_set_window (WindowHandle)
dev_clear_window ()
dev_display (TopMost) * 显示最高物体区域
* 步骤3: 精确匹配最高物体
dev_set_window (WindowHandleL)
read_image (ImageCloseup, 'closeup_' + Index$'02')
find_shape_model_3d (ImageCloseup, ShapeModel3DID, 0.8, 0.7, [0,2], Pose)
* 步骤4: 显示匹配结果
if (|Pose| > 0)
display_match_pose (ShapeModel3DID, Pose, WindowHandleL) * 显示3D位姿
endif
* 等待用户继续
disp_continue_message (WindowHandleL, 'black', 'true')
stop ()
endfor
* -------------------- 清理资源 --------------------
clear_shape_model_3d (ShapeModel3DID)
代码功能详细解析
-
系统初始化
- 创建显示窗口(高度图+特写视图)
- 设置两个相机参数(立体视觉)和一个特写相机参数
- 加载或创建圆柱体的3D形状匹配模型
-
立体视觉处理
- 读取左右立体图像
- 应用图像增强突出金属表面纹理
- 执行视差计算生成3D深度图
-
高度检测
- 从视差图中选择最高区域
- 移除阴影干扰区域
- 可视化显示最高物体区域
-
3D精确定位
- 读取特写镜头图像
- 使用3D形状匹配算法识别最高圆柱体
- 计算精确位置和姿态
-
结果可视化
- 右侧窗口显示高度图和最高物体标记
- 左侧窗口显示特写镜头和3D姿态覆盖
- 匹配成功时显示绿色3D框架
功能应用场景
-
工业分拣系统
- 自动识别料框中最高工件
- 机器人优先抓取最高零件
- 适用于圆柱形、方形等规则形状零件
-
质量控制
- 检测叠放零件高度一致性
- 识别堆叠异常(过高/过低)
- 圆柱形零件尺寸检验
-
自动仓储
- 料箱内物体高度检测
- 堆叠稳定性分析
- 空间利用率优化
-
制造业
- 发动机活塞高度检测
- 轴类零件堆叠质检
- 圆盘类零件自动分拣
-
自动化装配
- 识别堆中最易取零件
- 引导机器人抓取路径
- 避免堆叠体意外倒塌
完整步骤流程图
关键函数算子解析
-
binocular_disparity(Image1, Image2, Disparity, Score, Method, MaskSize, MinDisparity, MaxDisparity, ...)
- 功能: 计算两幅图像的视差图
- 参数:
Image1
,Image2
: 输入立体图像对Disparity
: 输出视差图Method
: 匹配方法(ncc, sgf等)MaskSize
: 匹配窗口大小(7-15像素)Min/MaxDisparity
: 视差范围设置
- 算法: 归一化互相关(NCC)匹配
-
find_shape_model_3d(Image, ModelID, MinScore, Greediness, ObjectPose, ...)
- 功能: 3D形状匹配定位物体
- 参数:
Image
: 输入图像ModelID
: 预加载的3D模型MinScore
: 最小匹配得分(0-1)Greediness
: 搜索速度/精度平衡ObjectPose
: 输出的物体姿态
- 输出: 6自由度位姿(X,Y,Z,Roll,Pitch,Yaw)
-
gen_cam_par_area_scan_division(Focus, Kappa, Sx, Sy, Cx, Cy, Width, Height, CameraParam)
- 功能: 生成面阵相机参数
- 参数:
Focus
: 焦距(mm)Kappa
: 径向畸变系数Sx, Sy
: 像素尺寸(mm)Cx, Cy
: 主点坐标Width, Height
: 图像分辨率
函数列表表格
函数名称 | 功能描述 | 重要参数 |
---|---|---|
gen_cam_par_area_scan_division | 生成面阵相机参数 | 焦距,畸变系数,像素尺寸 |
create_pose | 创建3D位姿表示 | XYZ坐标,旋转角度 |
gen_binocular_rectification_map | 生成立体视觉校正映射 | 相机参数,相对位姿 |
read_shape_model_3d | 读取3D匹配模型 | 模型文件名 |
create_shape_model_3d | 创建3D形状匹配模型 | 3D模型对象,相机参数 |
emphasize | 图像增强 | 输入图像,宽度,高度因子 |
map_image | 应用校正变换 | 原图像,映射矩阵 |
binocular_disparity | 计算视差图 | 左右图像,匹配方法 |
select_best_candidates | 选择最高物体区域 | 视差图,输出区域 |
remove_shadowed_regions | 移除阴影区域 | 视差图,阈值 |
find_shape_model_3d | 3D形状匹配 | 输入图像,模型ID |
display_match_pose | 显示3D位姿 | 模型ID,位姿,窗口 |
核心算法简化代码
* 1. 初始化系统
init_3d_system(LeftWindow, RightWindow, CameraParams)
* 2. 加载或创建3D模型
load_shape_model('cylinder.sm3', ShapeModelID)
* 3. 主处理循环
for i := 1 to image_count do
* 4. 获取立体图像
read_stereo_images(left_img, right_img, i)
* 5. 生成视差图
generate_disparity_map(left_img, right_img, disparity_map)
* 6. 找到最高物体
find_highest_object(disparity_map, top_object)
* 7. 可视化高度图
display_height_map(right_img, top_object, RightWindow)
* 8. 获取特写图像
read_closeup_image(closeup_img, i)
* 9. 3D精确定位
if locate_object_3d(closeup_img, ShapeModelID, pose) then
* 10. 显示匹配结果
display_3d_pose(closeup_img, pose, LeftWindow)
endif
* 等待用户继续
wait_for_user_confirmation()
endfor
* 11. 清理资源
clear_resources(ShapeModelID)
工业应用案例代码
* 工厂自动化圆柱工件分拣系统
dev_update_off ()
Path := 'factory_workshop/cylinders/'
* 初始化相机系统
init_camera_system (StereoCamLeft, StereoCamRight, CloseupCam)
init_windows (HeightWindow, CloseupWindow)
* 加载圆柱模型
create_cylinder_shape_model ('cylinder_model.dxf', 50.0, ShapeModelID) * 高度50mm
* 分拣系统主循环
while (production_line_running)
* 获取立体图像 - 扫描整个料框
grab_image (StereoCamLeft, ImageLeft)
grab_image (StereoCamRight, ImageRight)
* 计算高度图
compute_height_map (ImageLeft, ImageRight, HeightMap)
* 识别最高物体
find_height_peaks (HeightMap, MinHeight:=10.0, MaxCount:=5, Peaks)
sort_regions (Peaks, 'height', 'descending', SortedPeaks)
select_obj (SortedPeaks, HighestCylinder, 1)
* 显示高度检测结果
display_workpiece_height (HeightWindow, HeightMap, SortedPeaks)
* 移动特写相机到最高点
move_camera_to_position (CloseupCam, HighestCylinder)
* 获取高精度特写
grab_image (CloseupCam, CloseupImage)
* 精确3D定位
find_shape_model_3d (CloseupImage, ShapeModelID, MinScore:=0.8, Pose)
* 计算抓取位置
calculate_gripper_pose (Pose, CylinderHeight, GripperPose)
* 机器人抓取
robot_move_to_position (RobotArm, ApproachPose)
robot_pick_object (RobotArm, GripperPose)
robot_move_to_bin (RobotArm, TargetBin)
* 检查是否清空
if (is_bin_empty(HeightMap)) then
signal_material_refill()
endif
* 实时状态显示
update_production_dashboard ()
endwhile
* ------------------- 核心函数实现 -------------------
procedure create_cylinder_shape_model (ModelFile, Height, ModelID)
{
read_object_model_3d (ModelFile, 'mm', ObjectModel3D)
* 设置圆柱高度参数
set_object_model_3d_params (ObjectModel3D, 'height', Height)
prepare_object_model_3d (ObjectModel3D, 'matching')
create_shape_model_3d (ObjectModel3D, CameraParam, rad(90), 0, 0,
rad(360), 0.35, 0.5, 8, ModelID)
}
function robot_pick_object (Robot, Pose)
{
* 计算安全接近位置
create_pose(Pose[0], Pose[1], Pose[2]+20, 0, 0, Pose[5], ApproachPose)
* 移动到接近位置
robot_move (Robot, ApproachPose, Speed:=30)
* 下降到抓取位置
robot_move (Robot, Pose, Speed:=5)
* 激活真空吸盘
activate_vacuum ()
* 吸起圆柱体
robot_move (Robot, ApproachPose, Speed:=10)
}
function calculate_gripper_pose (CylinderPose, Height, GripperPose)
{
* 计算抓取点(顶部下方5mm)
set_origin_pose (CylinderPose, 0, 0, -5, GripperPose)
* 调整抓取角度
pose_compose (GripperPose, GripperOffset, FinalPose)
return FinalPose
}
function is_bin_empty (HeightMap)
{
* 计算平均高度
mean_height := region_features(HeightMap, 'mean_height')
* 检查是否低于阈值
return mean_height < EmptyThreshold
}
工业应用:自动化圆柱工件分拣系统
系统特点
-
多传感器融合
- 全局立体相机组:扫描整个料框
- 高分辨率特写相机:精确定位
- 触觉传感器:确认抓取成功
-
智能分拣策略
- 优先抓取最高工件减少干扰
- 自适应性堆叠分析
- 空料检测与预警
-
精密抓取技术
- 真空吸附技术:无损抓取
- 6轴机械臂:精准定位
- 力反馈控制:防碰撞保护
核心技术参数
模块 | 参数 | 规格 |
---|---|---|
视觉检测 | 最高物体识别精度 | ±0.1mm |
位置识别精度 | ±0.05mm | |
角度识别精度 | ±0.5° | |
机械臂 | 最大速度 | 2m/s |
负载能力 | 5kg | |
重复定位精度 | ±0.02mm | |
系统效率 | 单周期时间 | 3-5秒 |
处理速度 | 1200件/小时 | |
连续工作时间 | 24×7 |
应用价值
-
生产效率提升
- 节省80%人工分拣时间
- 减少30%工件周转时间
- 提高40%设备利用率
-
质量保障
- 100%全检实施
- <0.01%漏检率
- 精确质量追溯
-
成本控制
- 减少95%人工错误
- 降低30%工具损耗
- 减缩50%质量损失成本
此系统适用于各种圆柱形工件的自动化分拣,如轴承、活塞、轴类零件等,尤其适用于汽车、航空航天和精密制造行业的高要求生产环境。