python - 提高 Matplotlib 绘图和 OpenCV 视频处理性能
问题描述
在以下代码数组中使用 Opencv 库进行对象检测过程之后,我将输出信息作为参数提供给 matplotlib。但是视频过程来得很慢。如果我只进行对象检测而不运行图形部分;实时目标检测做得很好。但是当你同时做这两件事时,对象检测过程会减慢。你对加快这个过程有什么建议吗?
pixel_number_row = []
while True:
ret, frame = cap.read()
if ret == True :
hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
y , x = hsv.shape[:2] #x = 320 , y = 240
# Define 'brown' range in HSV colorspace
lower = np.array([10, 100, 20])
upper = np.array([20, 255, 200])
# Threshold the HSV image to get only brown color
mask1 = cv2.inRange(hsv, lower, upper)
kernel = np.ones((5,5),np.uint8)
thresh = cv2.dilate(mask1,kernel,iterations = 2)
# find contours in thresholded image, then grab the largest
# one
cnts = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
cnts = imutils.grab_contours(cnts)
c = max(cnts, key=cv2.contourArea)
# determine the most extreme points along the contour
extLeft = tuple(c[c[:, :, 0].argmin()][0])
extRight = tuple(c[c[:, :, 0].argmax()][0])
extTop = tuple(c[c[:, :, 1].argmin()][0])
extBot = tuple(c[c[:, :, 1].argmax()][0])
cv2.drawContours(thresh, [c], -1, (0, 255, 255), 2)
cv2.circle(thresh, extLeft , 8, (0, 0, 255) , -1)
cv2.circle(thresh, extRight, 8, (0, 255, 0) , -1)
cv2.circle(thresh, extTop , 8, (255, 0, 0) , -1)
cv2.circle(thresh, extBot , 8, (255, 255, 0), -1)
x_center = (extLeft[0] + extRight[0] + extTop[0] + extBot[0])/4
y_center = (extLeft[1] + extRight[1] + extTop[1] + extBot[1])/4
cv2.circle(frame,(x_center, y_center), 3, (0,255,0), -1)
cv2.line(frame,(extLeft[0] ,0),(extLeft[0],y) ,(0,255,0),2) # y axis - binary
cv2.line(frame,(extRight[0],0),(extRight[0],y),(0,255,0),2) # y axis - binary
cv2.line(frame,(0,extTop[1]) ,(x,extTop[1]) ,(0,255,0),2) # x axis - binary
cv2.line(frame,(0,extBot[1]) ,(x,extBot[1]) ,(0,255,0),2) # x axis - binary
pixel_number_row.append(x_center)
plt.plot(pixel_number_row - pixel_number_row[0]) # plotting by columns
plt.xlabel('frame number')
plt.ylabel('x axis moving')
# fig.canvas.draw()
plt.pause(0.001)
if (cnt % 60 == 0):
pixel_number_row = []
plt.clf()
cnt += 1
# show the output image
# cv2.imshow("mask" , thresh)
cv2.imshow("Image", frame)
k = cv2.waitKey(1)
if k == 27:
break
print(end - start)
plt.show()
cv2.destroyAllWindows()
解决方案
一个潜在的原因可能是读取帧时的 I/O 延迟。由于cv2.VideoCapture().read()
是阻塞操作,因此主程序会停止,直到从相机设备读取一帧并返回。提高性能的一种方法是生成另一个线程来并行处理抓取帧,而不是依赖单个线程按顺序抓取帧。我们可以通过创建一个新线程来提高性能,该线程只轮询新帧,而主线程处理/绘制最近的帧。
您当前的方法(顺序):
线程1:抓取框架->
流程框架->
图
建议的方法(并行):
话题一:抓取框架
from threading import Thread
import time
def get_frames():
while True:
ret, frame = cap.read()
time.sleep(.01)
thread_frames = Thread(target=self.get_frames, args=())
thread_frames.daemon = True
thread_frames.start()
线程2:进程框架->
图
def process_frames():
while True:
# Grab most recent frame
# Process/plot frame
...
通过拥有单独的线程,您的程序将是并行的,因为总会有一个准备好处理的帧,而不是在处理可以完成之前等待一个帧被读入。
注意:此方法将基于 I/O 延迟减少为您提供性能提升。这并不是真正的 FPS 增加,因为它是延迟的显着减少(一帧始终可用于处理;我们不需要轮询相机设备并等待 I/O 完成)。
推荐阅读
- javascript - JavaScript 中能被 3 整除的数字
- java - TableViewer 不会更新单元格的默认值
- node.js - 使用 NestJS 和 Fastify 的多部分表单数据体为空
- python - 如何将列表数据附加到现有的 XML 文件?
- git - 通过github上的项目创建生成时如何将.gitignore链接到本地项目?
- c# - Entity Framework Core Value Conversion - 在查询中使用比较或其他函数
- mips - MIPS 移位量位数
- jupyter-notebook - 如何在jupyter的markdown中插入图像并导出为PDF
- nginx - NGINX QUIC 反向代理
- javascript - 单击后如何永久禁用按钮,使用循环从服务器数据创建的按钮?