Files
AVM360/1.py

200 lines
7.8 KiB
Python
Raw Normal View History

2026-04-01 14:11:47 +08:00
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()