Буферная задержка открытого RTSP камеры - PullRequest
0 голосов
/ 23 марта 2020

Я изо всех сил пытаюсь понять, почему я не могу получить канал «LIVE» от своей IP-камеры.

Похоже, что существует буфер, и он вызывает наращивание кадров, если их не читают, - и так как каждая итерация моего кода занимает некоторое время, возникает отставание, и оно заканчивается почти медленным морем к тому, что происходит на самом деле.

Я обнаружил приведенный ниже код, который запускает поток для чтения камеры на всех oop чтобы попытаться избежать этого. Но теперь я получаю «живую» ленту примерно для 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 примеров того, как это работает? Я не мог найти много об этом смысла для меня.

спасибо

1 Ответ

0 голосов
/ 26 марта 2020

После поиска в Интернете на нескольких ресурсах появилось предложение использовать потоки для удаления кадров из буфера ALOT. И хотя, казалось, какое-то время это работало, это вызывало у меня проблемы с отображением дублированных кадров по какой-то причине, из-за которых я не мог работать.

Затем я попытался собрать opencv из исходного кода с поддержкой gstreamer, но даже однажды это было скомпилировано правильно, но все равно не похоже, что он корректно взаимодействует с gstreamer.

В конце концов я подумал, что лучше всего было бы go отказаться от подхода с многопоточностью, но снова не смог заставить его работать. Итак, я дал многопроцессорную съемку.

Я написал следующий класс для обработки подключения камеры:

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()

Это решение решило все мои проблемы с задержкой буфера, а также повторяющиеся кадры. #

Надеюсь, это поможет кому-то еще в такой же ситуации.

...