Files
AVM360/1.py
2026-04-01 14:11:47 +08:00

200 lines
7.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.
import cv2
import threading
import sys
import os
import argparse
import numpy as np
from surround_view import FisheyeCameraModel, BirdView
import surround_view.param_settings as settings
class MultiCameraBirdView:
def __init__(self):
self.running = True
self.names = settings.camera_names
self.yamls = [os.path.join(os.getcwd(), "yaml", name + ".yaml") for name in self.names]
self.camera_models = [FisheyeCameraModel(camera_file, camera_name) for camera_file, camera_name in zip(self.yamls, self.names)]
# 初始化摄像头
self.caps = []
self.which_cameras = {
"front": 0,
"left": 1,
"back": 2,
"right":3
}
# 初始化摄像头捕获
for name in self.names:
cap = cv2.VideoCapture(self.which_cameras[name], cv2.CAP_V4L2)
cap.set(cv2.CAP_PROP_FOURCC, cv2.VideoWriter_fourcc(*"YUYV"))
cap.set(cv2.CAP_PROP_FRAME_WIDTH, 1280)
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 720)
cap.set(cv2.CAP_PROP_BUFFERSIZE, 3)
if not cap.isOpened():
print(f"[ERROR] Cannot open {name} camera", file=sys.stderr)
self.running = False
return
self.caps.append(cap)
# 初始化鸟瞰图
self.birdview = BirdView()
# 预先加载一次静态图像来初始化权重矩阵
self._initialize_weights()
def _initialize_weights(self):
"""使用静态图像初始化权重矩阵"""
try:
# 加载静态图像用于初始化权重
images = [os.path.join(os.getcwd(), "images", name + ".png") for name in self.names]
static_frames = []
for image_file, camera_model in zip(images, self.camera_models):
img = cv2.imread(image_file)
if img is None:
print(f"[ERROR] Cannot load static image: {image_file}")
continue
img = camera_model.undistort(img)
img = camera_model.project(img)
img = camera_model.flip(img)
static_frames.append(img)
if len(static_frames) == 4:
# 初始化权重和掩码矩阵
Gmat, Mmat = self.birdview.get_weights_and_masks(static_frames)
print("[INFO] Weights and masks initialized successfully")
else:
print("[WARNING] Could not load all static images for weight initialization")
except Exception as e:
print(f"[ERROR] Failed to initialize weights: {e}", file=sys.stderr)
def process_frame(self, img, camera_model):
"""处理单帧图像:去畸变 -> 投影 -> 翻转"""
img = camera_model.undistort(img)
img = camera_model.project(img)
img = camera_model.flip(img)
return img
def run(self):
# 获取屏幕分辨率(假设为 1920x1080如果不同可以手动指定
# 在 Linux 下全屏显示通常需要先创建一个窗口
# cv2.namedWindow("SurroundView_System", cv2.WND_PROP_FULLSCREEN)
# cv2.setWindowProperty("SurroundView_System", cv2.WND_PROP_FULLSCREEN, cv2.WINDOW_FULLSCREEN)
cv2.namedWindow("SurroundView_System", cv2.WINDOW_NORMAL)
# 2. 指定窗口大小 (宽度, 高度)
cv2.resizeWindow("SurroundView_System", 1024, 600)
SCREEN_W = 1024
SCREEN_H = 600
# 计算布局比例
# 鸟瞰图占 1/3 宽度: 1920 / 3 = 640
# 原始画面占 2/3 宽度: 1920 * 2 / 3 = 1280
BIRD_W = SCREEN_W // 3
FRONT_W = SCREEN_W - BIRD_W
while self.running:
frames = []
raw_front_frame = None
for i, (cap, camera_model) in enumerate(zip(self.caps, self.camera_models)):
ret, frame = cap.read()
if not ret or frame is None:
continue
# 保存一份原始的前向画面用于监视 (假设 front 是第一个摄像头)
if self.names[i] == "front":
raw_front_frame = frame.copy()
processed_frame = self.process_frame(frame, camera_model)
frames.append(processed_frame)
if len(frames) == 4 and raw_front_frame is not None:
try:
# 1. 处理鸟瞰图
self.birdview.update_frames(frames)
self.birdview.stitch_all_parts()
self.birdview.make_white_balance()
self.birdview.copy_car_image()
# 2. 缩放鸟瞰图 (保持比例,填满左侧 1/3)
# 假设原始 birdview.image 比较长,我们将其 resize 到 BIRD_W x SCREEN_H
bird_part = cv2.resize(self.birdview.image, (BIRD_W, SCREEN_H))
# 3. 处理前向原始画面 (缩放至右侧 2/3)
# raw_front_frame 是 1280x720, 缩放到 FRONT_W x SCREEN_H
front_part = cv2.resize(raw_front_frame, (FRONT_W, SCREEN_H))
# 4. 水平拼接 (左鸟瞰 + 右前视)
display_all = np.hstack((bird_part, front_part))
# 5. 全屏显示
cv2.imshow("SurroundView_System", display_all)
if cv2.waitKey(1) & 0xFF == ord('q'):
self.running = False
break
except Exception as e:
print(f"[ERROR] Processing error: {e}")
continue
for cap in self.caps:
cap.release()
cv2.destroyAllWindows()
def main():
parser = argparse.ArgumentParser(description="Real-time 4-Camera Bird's Eye View")
parser.add_argument("--mode", type=str, required=True,
choices=["realtime", "static"],
help="Mode: 'realtime' for live video, 'static' for static images")
args = parser.parse_args()
if args.mode == "static":
# 原有的静态图像处理代码
names = settings.camera_names
images = [os.path.join(os.getcwd(), "images", name + ".png") for name in names]
yamls = [os.path.join(os.getcwd(), "yaml", name + ".yaml") for name in names]
camera_models = [FisheyeCameraModel(camera_file, camera_name) for camera_file, camera_name in zip(yamls, names)]
projected = []
for image_file, camera in zip(images, camera_models):
img = cv2.imread(image_file)
img = camera.undistort(img)
img = camera.project(img)
img = camera.flip(img)
projected.append(img)
birdview = BirdView()
Gmat, Mmat = birdview.get_weights_and_masks(projected) # 初始化权重矩阵
birdview.update_frames(projected)
# birdview.get_weights_and_masks.stitch_all_parts()
# birdview.make_white_balance()
birdview.copy_car_image()
img_small = cv2.resize(birdview.image, (600, 1024))
cv2.imshow("BirdView Result", img_small)
while True:
key = cv2.waitKey(1) & 0xFF
if key == ord("q"):
cv2.destroyAllWindows()
return -1
elif args.mode == "realtime":
# 实时视频处理
print("Starting real-time 4-camera bird's eye view...")
print("Press 'q' to quit")
multi_cam = MultiCameraBirdView()
if multi_cam.running:
multi_cam.run()
else:
print("[ERROR] Failed to initialize cameras")
if __name__ == "__main__":
main()