Última actividad 1776306881

测试相机内参矩阵参数,附带截图功能,左右对比校正前后对图像

camera_undistorted_tool.py Sin formato
1import cv2
2import threading
3import sys
4import os
5import argparse
6import numpy as np
7import time
8
9
10running = True
11capture_flag = False
12
13# 内参 (K) 与 畸变系数 (D)
14K = np.array([[ 3.9875655282072148e+02, 0., 6.3788553583130647e+02],
15 [0.,3.7214138046449295e+02, 3.4915903287538981e+02],
16 [ 0., 0., 1. ]])
17D = np.array([ 8.6662165805452579e-02, -2.8155159006680735e-02,
18 -3.5111914522638211e-02, 1.4621518110074484e-02 ])
19
20W, H = 1280, 720
21
22
23def input_thread():
24
25 global running, capture_flag
26 print("\n终端输入's'截图,'q'退出程序。")
27 while running:
28 try:
29 cmd = input().strip().lower()
30 if cmd == 's':
31 capture_flag = True
32 elif cmd == 'q':
33 print("退出命令触发")
34 running = False
35 break
36 except EOFError:
37 break
38 except Exception:
39 pass
40
41
42def main():
43 global running, capture_flag
44
45
46 parser = argparse.ArgumentParser(description="Multi-Camera Hardware Reference Tool")
47 parser.add_argument("--i", type=str, required=True,
48 choices=["front", "back", "left", "right"],
49 help="摄像头方位 (front, back, left, right)")
50 args = parser.parse_args()
51
52 camera_mapping = {"front": 0, "left": 1, "back": 2, "right": 3}
53 which_camera = camera_mapping[args.i]
54 cam_name = args.i.upper()
55 print(f"无法打开摄像头节点: {cam_name} (Node: /dev/video{which_camera})")
56
57
58 save_dir = os.path.join(os.getcwd(), "images")
59 if not os.path.exists(save_dir):
60 os.makedirs(save_dir)
61
62
63 cmd_listener = threading.Thread(target=input_thread, daemon=True)
64 cmd_listener.start()
65
66
67 cap = None
68 try:
69 cap = cv2.VideoCapture(which_camera, cv2.CAP_V4L2)
70 cap.set(cv2.CAP_PROP_FOURCC, cv2.VideoWriter_fourcc(*"YUYV"))
71 cap.set(cv2.CAP_PROP_FRAME_WIDTH, W)
72 cap.set(cv2.CAP_PROP_FRAME_HEIGHT, H)
73 cap.set(cv2.CAP_PROP_BUFFERSIZE, 3)
74
75 if not cap.isOpened():
76 print(f"[ERROR] Cannot open camera /dev/video{which_camera}", file=sys.stderr)
77 running = False
78 return
79
80
81 map1, map2 = cv2.fisheye.initUndistortRectifyMap(K, D, np.eye(3), K, (W, H), cv2.CV_16SC2) # 预计算鱼眼镜头的抗畸变映射矩阵
82
83 cv2.namedWindow('PowLu camera tools', cv2.WND_PROP_FULLSCREEN)
84 cv2.setWindowProperty('Video old vs new', cv2.WND_PROP_FULLSCREEN, cv2.WINDOW_FULLSCREEN)
85
86 while running:
87 ret, f = cap.read()
88 if not ret or f is None:
89 time.sleep(0.01)
90 continue
91
92 raw_frame = f.copy()
93
94 if capture_flag:
95 filename = os.path.join(save_dir, f"{args.i.lower()}.png")
96 cv2.imwrite(filename, raw_frame)
97 print(f"[SUCCESS] Image saved accurately: {filename}")
98 capture_flag = False
99
100 undistorted = cv2.remap(f, map1, map2, interpolation=cv2.INTER_LINEAR, borderMode=cv2.BORDER_CONSTANT)
101 comparison = np.hstack((f, undistorted))
102
103 scale = min(1920 / comparison.shape[1], 1080 / comparison.shape[0])
104 if scale < 1:
105 comparison = cv2.resize(comparison, (int(comparison.shape[1] * scale), int(comparison.shape[0] * scale)))
106
107 comparison = np.ascontiguousarray(comparison, dtype=np.uint8)
108
109 text_info = f"Camera: {cam_name} | Press 'q'='Quit', 's'='Screenshot'"
110 cv2.putText(comparison, text_info, (20, 50),
111 cv2.FONT_HERSHEY_SIMPLEX, 1.2, (0, 255, 255), 3, cv2.LINE_AA)
112
113 w_half = comparison.shape[1] // 2
114 h_bottom = comparison.shape[0] - 30
115 cv2.putText(comparison, "FISHEYE", (20, h_bottom),
116 cv2.FONT_HERSHEY_SIMPLEX, 1.5, (0, 255, 0), 3)
117 cv2.putText(comparison, "UNDISTORTED", (w_half + 20, h_bottom),
118 cv2.FONT_HERSHEY_SIMPLEX, 1.5, (0, 255, 0), 3)
119
120 cv2.imshow('PowLu camera tools', comparison)
121
122 key = cv2.waitKey(1) & 0xFF
123 if key == ord('q'):
124 running = False
125 break
126 elif key == ord('s'):
127 capture_flag = True
128
129 finally:
130 running = False
131 if cap is not None and cap.isOpened():
132 cap.release()
133 cv2.destroyAllWindows()
134
135if __name__ == "__main__":
136 try:
137 main()
138 except KeyboardInterrupt:
139 running = False
140