第一步:定义校正后图像的尺寸
WidthMappedImage := 652
HeightMappedImage := 494
设定校正后图像的宽度为 652 像素,高度为 494 像素。
第二步:根据世界坐标系(WCS)与图像坐标系(ICS)中点间距的比值,确定像素尺度(Scale)
为了使校正图像的局部尺度与原始图像在关注区域附近尽可能一致,程序通过以下方式计算 Scale:
Dist_ICS := 1 // 在图像坐标系中取1个像素的距离
将中心点及其上下/左右偏移1像素的点转换到世界坐标系:
image_points_to_world_plane(CamParam, Pose, CenterRow, CenterCol, 1, CenterX, CenterY)
// 向下偏移1像素(行+1)
image_points_to_world_plane(CamParam, Pose, CenterRow + Dist_ICS, CenterCol, 1, BelowCenterX, BelowCenterY)
// 向右偏移1像素(列+1)
image_points_to_world_plane(CamParam, Pose, CenterRow, CenterCol + Dist_ICS, 1, RightOfCenterX, RightOfCenterY)
计算世界坐标系中对应的垂直和水平距离:
distance_pp(CenterY, CenterX, BelowCenterY, BelowCenterX, Dist_WCS_Vertical)
distance_pp(CenterY, CenterX, RightOfCenterY, RightOfCenterX, Dist_WCS_Horizontal)
由此得到局部尺度:
ScaleVertical := Dist_WCS_Vertical / Dist_ICS // 每像素对应的世界垂直距离
ScaleHorizontal := Dist_WCS_Horizontal / Dist_ICS // 每像素对应的世界水平距离
ScaleForCenteredImage := (ScaleVertical + ScaleHorizontal) / 2.0 // 取平均作为最终Scale
✅ 这样可确保在校正图像中心区域,像素密度与原始图像接近,避免过度拉伸或压缩。
第三步:调整测量平面的位姿,使指定点位于校正图像中心
为了让 (CenterRow, CenterCol) 对应的世界点 (CenterX, CenterY) 出现在校正图像的正中心,需平移世界坐标系原点:
DX := CenterX - ScaleForCenteredImage * WidthMappedImage / 2.0
DY := CenterY - ScaleForCenteredImage * HeightMappedImage / 2.0
DZ := 0
set_origin_pose(Pose, DX, DY, DZ, PoseForCenteredImage)
🔍 原理:
校正图像左上角 = WCS 原点;
图像中心 = (Width/2, Height/2) × Scale;
因此,要让
(CenterX, CenterY)落在中心,需将 WCS 原点设为(CenterX - W/2×S, CenterY - H/2×S)
封装为 HDevelop 过程(Procedure)
上述逻辑被封装在以下过程里:
parameters_image_to_world_plane_centered(
:: CamParam, Pose, CenterRow, CenterCol, WidthMappedImage, HeightMappedImage :
ScaleForCenteredImage, PoseForCenteredImage )
该过程属于示例程序:
%HALCONEXAMPLES%\solution_guide\3d_vision\transform_image_into_wcs.hdev
第四步:执行图像校正
使用计算好的参数生成映射并校正图像:
gen_image_to_world_plane_map(
Map, CamParam, PoseForCenteredImage,
WidthOriginalImage, HeightOriginalImage,
WidthMappedImage, HeightMappedImage,
ScaleForCenteredImage, 'bilinear')
map_image(Image, Map, ImageMapped)
✅ 此方法高效,适用于多帧图像处理。
示例程序第二部分:确保整幅原始图像可见于校正图像中
若目标是完整保留原始图像内容 (而非聚焦某一点),则需将原始图像的四个边界映射到世界坐标系,并据此设定校正图像的范围:
full_domain(Image, ImageFull) // 获取图像完整区域
get_domain(ImageFull, Domain) // 提取定义域
gen_contour_region_xld(Domain, ImageBorder, 'border') // 生成边界轮廓
contour_to_world_plane_xld(ImageBorder, ImageBorderWCS, CamParam, Pose, 1)
后续可从
ImageBorderWCS中提取世界坐标的最小/最大 X、Y 值,从而确定:
- 校正图像的
WidthMappedImage/HeightMappedImage- 新的
PoseForCenteredImage(使整个区域居中)- 合适的
ScaleForCenteredImage
这样可生成一张包含全部原始图像信息的无畸变校正图。
然后,确定图像在世界坐标系中的范围(extent):
smallest_rectangle1_xld (ImageBorderWCS, MinY, MinX, MaxY, MaxX)
ExtentX := MaxX - MinX
ExtentY := MaxY - MinY
该步骤计算原始图像边界轮廓(已转换到世界坐标系)的最小外接矩形,从而得到其在 X 和 Y 方向上的总跨度。
接着,计算校正图像的像素尺度(Scale),即世界坐标系中的物理尺寸 与校正图像的像素尺寸之比:
ScaleX := ExtentX / WidthMappedImage
ScaleY := ExtentY / HeightMappedImage
为保证整个原始图像内容都能完整容纳在校正图像内且不发生裁剪 ,需选择两个方向中较大的尺度值作为最终统一的缩放比例(避免某方向被压缩):
ScaleForEntireImage := max([ScaleX, ScaleY])
最后,将世界坐标系的原点平移到该外接矩形的左下角(或左上角,取决于坐标系定义),以确保校正图像覆盖全部区域:
set_origin_pose (Pose, MinX, MinY, 0, PoseForEntireImage)
✅ 此操作使校正后图像的左上角对应世界坐标
(MinX, MinY),从而完整包含原始图像投影区域。
封装过程
上述逻辑已被封装为 HDevelop 过程:
parameters_image_to_world_plane_entire (
Image : : CamParam, Pose, WidthMappedImage, HeightMappedImage :
ScaleForEntireImage, PoseForEntireImage )
该过程是示例程序的一部分:
%HALCONEXAMPLES%\solution_guide\3d_vision\transform_image_into_wcs.hdev
应用对比总结
| 目标 | 推荐方法 |
|---|---|
| 完整显示整幅图像内容(平面场景) | parameters_image_to_world_plane_entire + gen_image_to_world_plane_map |
| 聚焦某点并保持局部尺度一致 | parameters_image_to_world_plane_centered |
| 非平面物体校正 | gen_grid_rectification_map |
| 仅去除镜头畸变(保留原始视角) | gen_radial_distortion_map |