python - 打开 CV RTSP 相机缓冲区滞后

标签 python opencv opencv3.0 rtsp

我很难理解为什么我无法从我的 IP 摄像机获得“实时”信息。

似乎有一个缓冲区,如果不被读取,它会导致帧堆积 - 由于我的代码的每次迭代都需要一些时间,因此存在积压,最终几乎慢到实际发生的事情。

我发现下面的代码会触发一个线程来循环读取相机,以尝试避免这种情况。但现在我得到了大约 5 帧的“实时”提要,然后它停止并显示了另外几帧的相同图像。

##camera class - this stops the RTSP feed getting caught in the buffer 

class Camera:

    def __init__(self, rtsp_link):

        #init last ready and last frame
        self.last_frame = None
        self.last_ready = None
        self.lock = Lock()

        #set capture decive
        capture = cv2.VideoCapture(rtsp_link,apiPreference=cv2.CAP_FFMPEG)

        #set thread to clear buffer
        thread = threading.Thread(target=self.rtsp_cam_buffer, args=(capture,), name="rtsp_read_thread")
        thread.daemon = True
        thread.start()

        #delay start of next step to avoid errors
        time.sleep(2)

    def rtsp_cam_buffer(self, capture):
        #loop forever 
        while True:
            with self.lock:           
                capture.grab()
                self.last_ready, self.last_frame = capture.retrieve()


    def getFrame(self):        
        #get last frame
        if (self.last_ready is not None) and (self.last_frame is not None):
            return self.last_frame.copy())
        else:
            return None

在这种情况下,正确的做法是什么?有办法解决这个问题吗?

我应该使用 gstreamer 或 ffmpeg 之类的东西来获取相机画面吗?如果是这样哪个更好,为什么?有什么建议或页面可以给我一些让它工作的 python 示例吗?我找不到对我有意义的负载。

谢谢

最佳答案

通过多种资源在线搜索后,使用线程从缓冲区中删除帧的建议出现了很多。虽然它似乎工作了一段时间,但由于某些我无法解决的原因导致我出现重复帧的问题。

然后我尝试使用 gstreamer 支持从源代码构建 opencv,但即使它被正确编译,它似乎仍然不喜欢与 gstreamer 正确连接。

最终我认为最好的选择是返回线程方法,但再次无法使其工作。所以我尝试了多处理。

我写了下面的类来处理相机连接:

import cv2
import time
import multiprocessing as mp

class Camera():
    
    def __init__(self,rtsp_url):        
        #load pipe for data transmittion to the process
        self.parent_conn, child_conn = mp.Pipe()
        #load process
        self.p = mp.Process(target=self.update, args=(child_conn,rtsp_url))        
        #start process
        self.p.daemon = True
        self.p.start()
        
    def end(self):
        #send closure request to process
        
        self.parent_conn.send(2)
        
    def update(self,conn,rtsp_url):
        #load cam into seperate process
        
        print("Cam Loading...")
        cap = cv2.VideoCapture(rtsp_url,cv2.CAP_FFMPEG)   
        print("Cam Loaded...")
        run = True
        
        while run:
            
            #grab frames from the buffer
            cap.grab()
            
            #recieve input data
            rec_dat = conn.recv()
            
            
            if rec_dat == 1:
                #if frame requested
                ret,frame = cap.read()
                conn.send(frame)
                
            elif rec_dat ==2:
                #if close requested
                cap.release()
                run = False
                
        print("Camera Connection Closed")        
        conn.close()
    
    def get_frame(self,resize=None):
        ###used to grab frames from the cam connection process
        
        ##[resize] param : % of size reduction or increase i.e 0.65 for 35% reduction  or 1.5 for a 50% increase
             
        #send request
        self.parent_conn.send(1)
        frame = self.parent_conn.recv()
        
        #reset request 
        self.parent_conn.send(0)
        
        #resize if needed
        if resize == None:            
            return frame
        else:
            return self.rescale_frame(frame,resize)
        
    def rescale_frame(self,frame, percent=65):
        
        return cv2.resize(frame,None,fx=percent,fy=percent) 

显示框架可以如下完成

cam = Camera("rtsp://admin:[somepassword]@192.168.0.40/h264Preview_01_main")

print(f"Camera is alive?: {cam.p.is_alive()}")

while(1):
    frame = cam.get_frame(0.65)
    
    cv2.imshow("Feed",frame)
    
    key = cv2.waitKey(1)

    if key == 13: #13 is the Enter Key
        break

cv2.destroyAllWindows()     

cam.end()

这个解决方案解决了我所有的缓冲滞后和重复帧的问题。 #

希望它能帮助处于相同情况的其他人。

关于python - 打开 CV RTSP 相机缓冲区滞后,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60816436/

相关文章:

Python 生成器的起源

python - 连接两列

c++ - OpenCV:与包含 Vec3d 的矩阵和包含 double 的矩阵的矩阵乘法

android - 找不到OpenCV Android C++写入

c++ - OpenCV 错误 : “LINK : fatal error LNK1104: cannot open file ' opencv_core300d. 库'”

python - OpenCV 3 Python - Haar Cascade Upper Body Detector 不适用于半身(腰部向上)照片?

python - Anaconda: cannot import cv2 even though opencv is installed (how to install opencv3 for python3)

python - 谷歌Oauth2.0与Python : How do I limit access to a specific domain?

python - 分割线不丢失定界符

c++ - 没有卡尔曼滤波器的 BackgroundSubtractorGMG?