Última atividade 1776306881

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

PowLu revisou este gist 1776306881. Ir para a revisão

Sem alterações

PowLu revisou este gist 1776301657. Ir para a revisão

1 file changed, 139 insertions

camera_undistorted_tool.py(arquivo criado)

@@ -0,0 +1,139 @@
1 + import cv2
2 + import threading
3 + import sys
4 + import os
5 + import argparse
6 + import numpy as np
7 + import time
8 +
9 +
10 + running = True
11 + capture_flag = False
12 +
13 + # 内参 (K) 与 畸变系数 (D)
14 + K = np.array([[ 3.9875655282072148e+02, 0., 6.3788553583130647e+02],
15 + [0.,3.7214138046449295e+02, 3.4915903287538981e+02],
16 + [ 0., 0., 1. ]])
17 + D = np.array([ 8.6662165805452579e-02, -2.8155159006680735e-02,
18 + -3.5111914522638211e-02, 1.4621518110074484e-02 ])
19 +
20 + W, H = 1280, 720
21 +
22 +
23 + def 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 +
42 + def 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 +
135 + if __name__ == "__main__":
136 + try:
137 + main()
138 + except KeyboardInterrupt:
139 + running = False
Próximo Anterior