Files
ADAS360/test.py
2025-10-28 18:46:04 +08:00

183 lines
6.8 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env python3
"""
test.py
摄像头畸变校正效果测试 - 仅显示校正前后对比画面
"""
import cv2
import numpy as np
import argparse
import os
def is_rtsp_url(input_str):
"""检查输入是否为RTSP URL"""
return input_str.startswith('rtsp://')
def load_calibration_params(yaml_file):
"""从YAML文件加载标定参数"""
if not os.path.exists(yaml_file):
raise FileNotFoundError(f"标定文件 {yaml_file} 不存在")
fs = cv2.FileStorage(yaml_file, cv2.FILE_STORAGE_READ)
if not fs.isOpened():
raise IOError(f"无法打开标定文件 {yaml_file}")
# 读取参数
camera_matrix = fs.getNode("camera_matrix").mat()
dist_coeffs = fs.getNode("dist_coeffs").mat()
fs.release()
print(f"✓ 成功加载标定参数")
print(f" 相机矩阵:\n{camera_matrix}")
print(f" 畸变系数: {dist_coeffs.flatten()}")
return camera_matrix, dist_coeffs
def main():
parser = argparse.ArgumentParser(description='摄像头畸变校正效果测试')
parser.add_argument("-i", "--input", type=str, required=True,
help="输入源摄像头设备索引、视频文件路径或RTSP URL")
parser.add_argument("-c", "--calibration", type=str, required=True,
help="标定参数YAML文件路径")
parser.add_argument("-f", "--fisheye", action="store_true",
help="是否为鱼眼相机")
args = parser.parse_args()
# 加载标定参数
try:
camera_matrix, dist_coeffs = load_calibration_params(args.calibration)
except Exception as e:
print(f"❌ 加载标定参数失败: {e}")
return
# 初始化视频源
if is_rtsp_url(args.input):
# RTSP流
cap = cv2.VideoCapture(args.input, cv2.CAP_FFMPEG)
try:
cap.set(cv2.CAP_PROP_FFMPEG_OPTION, "rtsp_transport", "tcp")
cap.set(cv2.CAP_PROP_BUFFERSIZE, 1)
except:
pass
elif args.input.isdigit():
# 摄像头设备索引
cap = cv2.VideoCapture(int(args.input))
else:
# 视频文件
cap = cv2.VideoCapture(args.input)
if not cap.isOpened():
print(f"❌ 无法打开视频源: {args.input}")
return
# 获取实际分辨率
actual_w = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
actual_h = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
print(f"视频源分辨率: {actual_w}x{actual_h}")
print("✓ 准备开始校正")
print("'q' 键退出")
print("'s' 键切换校正方法")
window_name = "畸变校正对比 - 原始(左) vs 校正后(右)"
cv2.namedWindow(window_name, cv2.WINDOW_NORMAL)
# 校正方法选择
use_remap = True # 默认使用remap方法
frame_count = 0
while True:
ret, frame = cap.read()
if not ret:
print("读取帧失败")
# 对于RTSP流尝试重新连接
if is_rtsp_url(args.input):
cap.release()
cap = cv2.VideoCapture(args.input, cv2.CAP_FFMPEG)
continue
break
frame_count += 1
# 应用畸变校正
try:
if args.fisheye:
if use_remap:
# 使用映射方法
new_camera_matrix = cv2.fisheye.estimateNewCameraMatrixForUndistortRectify(
camera_matrix, dist_coeffs, (actual_w, actual_h), np.eye(3), balance=0.8)
map1, map2 = cv2.fisheye.initUndistortRectifyMap(
camera_matrix, dist_coeffs, np.eye(3), new_camera_matrix,
(actual_w, actual_h), cv2.CV_16SC2)
undistorted = cv2.remap(frame, map1, map2,
interpolation=cv2.INTER_LINEAR,
borderMode=cv2.BORDER_CONSTANT)
else:
# 使用直接校正方法
undistorted = cv2.fisheye.undistortImage(frame, camera_matrix, dist_coeffs)
else:
# 普通相机校正
undistorted = cv2.undistort(frame, camera_matrix, dist_coeffs)
except Exception as e:
print(f"校正失败: {e}")
undistorted = frame.copy() # 失败时使用原图
# 检查校正后的图像是否有效
if undistorted is None or undistorted.size == 0:
print(f"警告: 第 {frame_count} 帧校正失败")
undistorted = frame.copy()
# 调整大小以便显示
max_height = 600
scale_orig = max_height / frame.shape[0]
orig_resized = cv2.resize(frame,
(int(frame.shape[1] * scale_orig),
int(frame.shape[0] * scale_orig)))
scale_undist = max_height / undistorted.shape[0]
undistorted_resized = cv2.resize(undistorted,
(int(undistorted.shape[1] * scale_undist),
int(undistorted.shape[0] * scale_undist)))
# 确保两个图像高度相同
min_height = min(orig_resized.shape[0], undistorted_resized.shape[0])
orig_resized = orig_resized[:min_height, :]
undistorted_resized = undistorted_resized[:min_height, :]
# 水平拼接显示对比
comparison = np.hstack((orig_resized, undistorted_resized))
# 添加文本说明
cv2.putText(comparison, "原始图像 (有畸变)",
(10, 30), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 255, 0), 2)
cv2.putText(comparison, "校正后图像",
(orig_resized.shape[1] + 10, 30),
cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 255, 0), 2)
# 显示相机类型和校正方法
camera_type = "鱼眼相机" if args.fisheye else "普通相机"
method_type = "映射方法" if use_remap else "直接方法"
cv2.putText(comparison, f"类型: {camera_type} | 方法: {method_type}",
(10, 60), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 255, 255), 1)
cv2.putText(comparison, "'s' 切换方法 | 按 'q' 退出",
(10, 90), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 255, 255), 1)
cv2.imshow(window_name, comparison)
key = cv2.waitKey(1) & 0xFF
if key == ord('q'):
break
elif key == ord('s'):
use_remap = not use_remap
method_name = "映射方法" if use_remap else "直接方法"
print(f"切换到 {method_name}")
cap.release()
cv2.destroyAllWindows()
print("测试完成")
if __name__ == "__main__":
main()