init
This commit is contained in:
114
surround_view/capture_thread.py
Normal file
114
surround_view/capture_thread.py
Normal file
@@ -0,0 +1,114 @@
|
||||
import cv2
|
||||
from PyQt5.QtCore import qDebug
|
||||
|
||||
from .base_thread import BaseThread
|
||||
from .structures import ImageFrame
|
||||
from .utils import gstreamer_pipeline
|
||||
|
||||
|
||||
class CaptureThread(BaseThread):
|
||||
|
||||
def __init__(self,
|
||||
device_id,
|
||||
flip_method=2,
|
||||
drop_if_full=True,
|
||||
api_preference=cv2.CAP_GSTREAMER,
|
||||
resolution=None,
|
||||
use_gst=True,
|
||||
parent=None):
|
||||
"""
|
||||
device_id: device number of the camera.
|
||||
flip_method: 0 for identity, 2 for 180 degree rotation (if the camera is installed
|
||||
up-side-down).
|
||||
drop_if_full: drop the frame if buffer is full.
|
||||
api_preference: cv2.CAP_GSTREAMER for csi cameras, usually cv2.CAP_ANY would suffice.
|
||||
resolution: camera resolution (width, height).
|
||||
"""
|
||||
super(CaptureThread, self).__init__(parent)
|
||||
self.device_id = device_id
|
||||
self.flip_method = flip_method
|
||||
self.use_gst = use_gst
|
||||
self.drop_if_full = drop_if_full
|
||||
self.api_preference = api_preference
|
||||
self.resolution = resolution
|
||||
self.cap = cv2.VideoCapture()
|
||||
# an instance of the MultiBufferManager object,
|
||||
# for synchronizing this thread with other cameras.
|
||||
self.buffer_manager = None
|
||||
|
||||
def run(self):
|
||||
if self.buffer_manager is None:
|
||||
raise ValueError("This thread has not been binded to any buffer manager yet")
|
||||
|
||||
while True:
|
||||
self.stop_mutex.lock()
|
||||
if self.stopped:
|
||||
self.stopped = False
|
||||
self.stop_mutex.unlock()
|
||||
break
|
||||
self.stop_mutex.unlock()
|
||||
|
||||
# save capture time
|
||||
self.processing_time = self.clock.elapsed()
|
||||
# start timer (used to calculate capture rate)
|
||||
self.clock.start()
|
||||
|
||||
# synchronize with other streams (if enabled for this stream)
|
||||
self.buffer_manager.sync(self.device_id)
|
||||
|
||||
if not self.cap.grab():
|
||||
continue
|
||||
|
||||
# retrieve frame and add it to buffer
|
||||
_, frame = self.cap.retrieve()
|
||||
img_frame = ImageFrame(self.clock.msecsSinceStartOfDay(), frame)
|
||||
self.buffer_manager.get_device(self.device_id).add(img_frame, self.drop_if_full)
|
||||
|
||||
# update statistics
|
||||
self.update_fps(self.processing_time)
|
||||
self.stat_data.frames_processed_count += 1
|
||||
# inform GUI of updated statistics
|
||||
self.update_statistics_gui.emit(self.stat_data)
|
||||
|
||||
qDebug("Stopping capture thread...")
|
||||
|
||||
# 在surround-view-system-introduction/surround_view/capture_thread.py中修改connect_camera方法
|
||||
def connect_camera(self):
|
||||
# 如果设备ID是字符串且以rtsp开头,则视为RTSP地址
|
||||
if isinstance(self.device_id, str) and self.device_id.startswith('rtsp://'):
|
||||
# 使用FFmpeg的H265解码方式打开RTSP流
|
||||
# 降低延迟参数:-fflags nobuffer -flags low_delay -rtsp_transport tcp
|
||||
ffmpeg_cmd = (
|
||||
f"rtspsrc location={self.device_id} latency=0 ! "
|
||||
"rtph265depay ! h265parse ! avdec_h265 ! "
|
||||
"videoconvert ! video/x-raw,format=BGR ! appsink"
|
||||
)
|
||||
self.cap.open(ffmpeg_cmd, cv2.CAP_GSTREAMER)
|
||||
elif self.use_gst:
|
||||
options = gstreamer_pipeline(cam_id=self.device_id, flip_method=self.flip_method)
|
||||
self.cap.open(options, self.api_preference)
|
||||
else:
|
||||
self.cap.open(self.device_id)
|
||||
|
||||
if not self.cap.isOpened():
|
||||
qDebug(f"Cannot open camera {self.device_id}")
|
||||
return False
|
||||
|
||||
# 设置分辨率(RTSP流通常固定分辨率,可根据实际情况调整)
|
||||
if self.resolution is not None:
|
||||
width, height = self.resolution
|
||||
self.cap.set(cv2.CAP_PROP_FRAME_WIDTH, width)
|
||||
self.cap.set(cv2.CAP_PROP_FRAME_HEIGHT, height)
|
||||
|
||||
return True
|
||||
def disconnect_camera(self):
|
||||
# disconnect camera if it's already opened.
|
||||
if self.cap.isOpened():
|
||||
self.cap.release()
|
||||
return True
|
||||
# else do nothing and return
|
||||
else:
|
||||
return False
|
||||
|
||||
def is_camera_connected(self):
|
||||
return self.cap.isOpened()
|
||||
Reference in New Issue
Block a user