一.總結:
完整流程 :硬件準備 → 數據采集 → 空間統一 → 相機標定(內參+畸變) → 外參求解
→ 定位配準融合 → 校驗 → 生成映射表 → 上線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. 定位配準融合
加載分析。
下面是 原始黑白棋盤圖像 和 空間分辨率統一后的黑白棋盤圖像。
(運行代碼:black_white_chessboard_corner_point_detect_sorting_save_json.py)
核心代碼:
# 下面自己調整參數
# 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)裁剪后疊加,得到融合圖像。
(運行代碼register_hyperspectral_to_rgb.py)
核心代碼:
# 黑白棋盤角點位置坐標(手動給或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映射矩陣文件即可:
(運行代碼remap_hyper_to_rgb.py)
加載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. 外參求解
求解出目標物高度或者深度。