Lew*_*ris 2 python opencv rtsp opencv3.0
我很难理解为什么我无法从我的网络摄像机获得“实时”反馈。
似乎存在一个缓冲区,如果不被读取,它会导致帧堆积 - 由于我的代码的每次迭代都需要一些时间,因此会出现积压,最终导致实际发生的情况几乎变慢。
我发现下面的代码会触发一个线程来循环读取相机,以尝试避免这种情况。但现在我得到了大约 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
Run Code Online (Sandbox Code Playgroud)
在这种情况下正确的做法是什么?有办法解决这个问题吗?
或者
我应该使用 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)
Run Code Online (Sandbox Code Playgroud)
显示框架可以如下完成
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()
Run Code Online (Sandbox Code Playgroud)
这个解决方案解决了我所有的缓冲区延迟和重复帧问题。#
希望它能帮助处于同样情况的其他人。