如何通过黑白棋盘进行定位配准融合?(前后安装的两个相机)
一.总结:
完整流程 :硬件准备 → 数据采集 → 空间统一 → 相机标定(内参+畸变) → 外参求解
→ 定位配准融合 → 校验 → 生成映射表 → 上线remap验证
我们场景流程 :硬件准备 → 数据采集 → 空间统一 → 定位配准融合 → 校验 → 生成映射表 → 上线remap验证 (少了内参标定和外参求解,根据自己的项目来定,如果要求的精度可以不是很高,内参和外参不是必要项)
我们算法流程:两个相机成像空间统一 → 定位配准融合(黑白棋盘) → 生成映射表 → 上线remap验证。
二.拆解:
1. 硬件准备
黑白棋盘格的板子,安装前后两个相机,传送带。
(1)使用两台分辨率的线扫描相机,同时拍摄带有黑白棋盘格的移动载物平台,确保所有图像都含有棋盘格背景,便于后续定位和配准。
2.数据采集
两个相机前后安装,等传送带速度稳定后,放上黑白棋盘和目标物,采集数据。
3.空间统一
3.1两相机空间分辨率统一
调节传送带移动速度,目标物在传送带经过两个相机后,计算黑白棋盘方格长宽比 scale=H/W (H为棋盘格高度,W为棋盘格宽度),直到 scale≈1(像素在扫描与列方向上等距),这样使两相机均达到统一的空间分辨率。
3.1.1 棋盘格角点作为空间基准
通过 Harris 角点检测识别棋盘格角点,排序后计算长宽比(scale=H/W≈1),排列角点序号和角点坐标,保存成json文件,方便后面 6. 定位配准融合
加载分析。
下面是 原始黑白棋盘图像 和 空间分辨率统一后的黑白棋盘图像。
核心代码:
# 下面自己调整参数
# quality_level: goodFeaturesToTrack 会把角点响应值低于 maxResponse × qualityLevel 的点直接丢弃
# min_distance:非极大值抑制阶段会把相邻角点“合并”掉
max_corners = 200 # 500
quality_level = 0.0001 # 0.01
min_distance = 5 # 20
corners = cv2.goodFeaturesToTrack(gray,maxCorners=max_corners,qualityLevel=quality_level,minDistance=min_distance,useHarrisDetector=True,k=0.04
)# 3. 亚像素角点优化
criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 40, 0.001)
if corners is not None:corners = cv2.cornerSubPix(gray, np.float32(corners), winSize=(5, 5), zeroZone=(-1, -1), criteria=criteria)
4. 相机标定(两个相机内参+畸变求解)(暂不用)
每个单目相机标定,确定内参。
主要的内参:焦距 fx、fy,主点 cx、cy;再配合内参矩阵 K1(相机1)、K2(相机2)和光学畸变系数D1(相机1)、D2(相机2)。
内参:从相机坐标系转换到像素坐标系中。
外参:从世界坐标系转换到相机坐标系中(用于有深度的重投影)。
里面的参数一般都是相机出厂就定下来的,可以通过相机标定的方式人为计算出来。
K1/K2:可见光/近红外相机的内参矩阵,决定成像几何映射。
D1/D2:可见光/近红外相机的畸变系数,描述光学形变。
(内参求解
暂时没用到,等以后实验再分析)
5. 外参求解(暂不用)
暂时用不到外参:
我们使用的两个相机都不是深度相机,而且也没有高度传感器/双目/结构光等,不能获取深度和高度。(外参求解
结合以后实验再分析)
6. 定位配准融合
图像配准与融合技术:透视变换和RANSAC迭代
基于棋盘格关键角点进行匹配配准,使用透视变换统一不同波段图像的视角差异,然后融合生成最终高光谱图像。该方法确保光谱和空间统一后的图像在几何上对齐, 最后通过感兴趣区域(ROI)裁剪后叠加,得到融合图像。
核心代码:
# 黑白棋盘角点位置坐标(手动给或json里面加载)if args.pts_json:src_pts, dst_pts, names = load_points_from_json(args.pts_json)else:src_pts, dst_pts, names = default_points()# 估计单应(相机1(低分辨率) -> 相机2(高分辨率))H, inlier_mask = cv2.findHomography(src_pts, dst_pts, method=cv2.RANSAC, ransacReprojThreshold=3.0)if H is None:raise RuntimeError("单应性矩阵估计失败,请检查点位。")# 透视变换到可见光坐标系(用于可视化验证)hs_warp = cv2.warpPerspective(hs, H, (w_rgb, h_rgb), flags=cv2.INTER_LINEAR)# 重投影误差(errors保存到文件中,用于分析哪些点pix匹配差异大)proj = cv2.perspectiveTransform(src_pts, H)errors = np.linalg.norm(dst_pts.reshape(-1,2) - proj.reshape(-1,2), axis=1)
下面2副图是两个相机定位配准融合后的图,两个图像几乎匹配上。
7. 检验
(1)用cv2.addWeighted 把两路图实时叠加,观察匹配后的物体是否有飘移。
(2)分析 errors = np.linalg.norm(dst_pts.reshape(-1,2) - proj.reshape(-1,2), axis=1)得到的errors,查看平均误差,中位误差,最大误差,进而消除一些异常点,使匹配精度得到提升。
8. 生成查找表
把映射矩阵通过LUT 打包成lut.npy,实际生产的时候,随软件升级同步。
生成这几个打包文件: lut.npy(包含mapx.npy和mapy.npy) 或者 单个mapx.npy 和 单独mapy.npy
def build_lut_from_H(H: np.ndarray, out_w: int, out_h: int):"""生成 remap 查找表 mapx/mapy:生成映射矩阵。remap 时:dst = remap(src=相机1(低分辨率), mapx, mapy) -> 输出尺寸与( out_w, out_h )一致。"""Hinv = np.linalg.inv(H).astype(np.float64)xs = np.arange(out_w, dtype=np.float32)ys = np.arange(out_h, dtype=np.float32)xg, yg = np.meshgrid(xs, ys) # (H,W)ones = np.ones_like(xg, dtype=np.float32)grid = np.stack([xg, yg, ones], axis=-1).reshape(-1,3).T # (3, H*W)src_h = (Hinv @ grid) # @是矩阵乘法,等同于np.dot()(在二维数组上)或np.matmul()src_h /= (src_h[2:3, :] + 1e-12)mapx = src_h[0, :].reshape(out_h, out_w).astype(np.float32)mapy = src_h[1, :].reshape(out_h, out_w).astype(np.float32)return mapx, mapy
最后remap映射矩阵文件即可:
加载lut.npy进行remap映射。
import cv2, numpy as np
import osroot_path = "xxxxxx"
hs = cv2.imread(os.path.join(root_path, "5.bmp")) # camera1图映射到camera2图# 加载映射矩阵文件
# mapx = np.load(os.path.join(root_path, "校准文件npy","mapx_20250731_142541.npy"))
# mapy = np.load(os.path.join(root_path, "校准文件npy","mapy_20250731_142541.npy"))with np.load(os.path.join(root_path, "校准文件npy","lut_20250731_142541.npz")) as d:mapx = d["mapx"]mapy = d["mapy"]hs_to_rgb = cv2.remap(hs, mapx, mapy, interpolation=cv2.INTER_LINEAR,borderMode=cv2.BORDER_CONSTANT, borderValue=0)
cv2.imwrite(os.path.join(root_path, "output","camera1_to_camera2_remap.png"), hs_to_rgb)
还存在的问题
:
1. 图像畸变问题:
即使做了6. 定位配准融合
,但由于没有做4. 相机标定(两个相机内参+畸变求解)
,所以相机1和相机2的成像图的畸变问题依旧存在。接下来要做4. 相机标定(两个相机内参+畸变求解)
,减少畸变对像素匹配的影响,提升像素匹配精度。
(生成 H 时只用背景平面点(例如 0–39 号),并先去畸变(单目标定一次即可),一般可把中位误差压到 ~2 px 以内。)
2. 实际产线目标物高度影响成像,影响像素匹配:
在实际产线上,由于相机1和相机2焦距不一样,视场角不一样,导致一些有高度的目标物在两个相机下成像不一样,最终导致两个相机的物体的像素不能完全匹配上,造成误差。这需要5. 外参求解
求解出目标物高度或者深度。