在对视频帧进行逐像素操作时处理帧需要花费太多时间
It is taking too much time to process frames while doing pixel by pixel operation of video frames
import cv2
import numpy as np
cap = cv2.VideoCapture(0)
def threshold_slow(image):
h = image.shape[0]
w = image.shape[1]
for x in range(0, w):
for y in range(0, h):
k = np.array(image[x, y])
print(k)
def video():
while True:
ret,frame = cap.read()
frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
threshold_slow(frame)
cv2.imshow('frame',frame)
key = cv2.waitKey(25)
if key == ord('q'):
break
if __name__ == '__main__':
video()
cap.release()
cv2.destroyAllWindows()
我几乎已经做了我能做的一切,但我仍然无法重新爱上它。任何有想法的人请帮助编写一些代码。当我将 print 放在 for 循环之外时,它工作正常。但是后来我没有得到图像中每个像素的值。
print 不可避免地很慢(与其余代码相比)。假设一张 256x256 的图像,您的代码将打印 65536 个值。根据格式(我不熟悉 OpenCV,但假设每个像素 1 个字节),每个像素的输出范围从 2 到 4 个字节(将 8 位无符号字节转换为文本 + 行尾),所以128kB-320kB,您的终端需要滚动。
最好的办法是限制您尝试打印的像素区域:即,使用适当的参数为您的范围调用指定一个适当的小区域。
你真的,真的应该避免 for
循环和 "pixel-by-pixel" 对 Python 中图像的操作。尝试使用 OpenCV 矢量化例程,例如 cv2.threshold()
,否则,使用矢量化 Numpy 例程。
您在评论中提到您想这样做:
h = im.shape[0]
w = im.shape[1]
for x in range(0, w):
for y in range(0, h):
if im[y,x]>140 and im[y,x]<160:
im[y,x]=255
这在我的机器上需要 487 毫秒。如果你像这样使用 Numpy,它需要 56 微秒。即快 9,000 倍。
im[ np.logical_and(im>140, im<160) ] = 255
这将使您的代码看起来更像这样 - 未经测试:
import cv2
import numpy as np
cap = cv2.VideoCapture(0)
def video():
while True:
ret,frame = cap.read()
frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
frame[ np.logical_and(frame>140, frame<160) ] = 255
cv2.imshow('frame',frame)
key = cv2.waitKey(25)
if key == ord('q'):
break
if __name__ == '__main__':
video()
cap.release()
cv2.destroyAllWindows()
您还可以使用 OpenCV inRange()
来 select 灰度图像中的一系列灰色阴影,如下所示:
mask = cv2.inRange(im, 140, 160)
然后您可以将其应用到您的图像中:
frame[~mask] = 255
不过我觉得这样比较慢。
import cv2
import numpy as np
cap = cv2.VideoCapture(0)
def threshold_slow(image):
h = image.shape[0]
w = image.shape[1]
for x in range(0, w):
for y in range(0, h):
k = np.array(image[x, y])
print(k)
def video():
while True:
ret,frame = cap.read()
frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
threshold_slow(frame)
cv2.imshow('frame',frame)
key = cv2.waitKey(25)
if key == ord('q'):
break
if __name__ == '__main__':
video()
cap.release()
cv2.destroyAllWindows()
我几乎已经做了我能做的一切,但我仍然无法重新爱上它。任何有想法的人请帮助编写一些代码。当我将 print 放在 for 循环之外时,它工作正常。但是后来我没有得到图像中每个像素的值。
print 不可避免地很慢(与其余代码相比)。假设一张 256x256 的图像,您的代码将打印 65536 个值。根据格式(我不熟悉 OpenCV,但假设每个像素 1 个字节),每个像素的输出范围从 2 到 4 个字节(将 8 位无符号字节转换为文本 + 行尾),所以128kB-320kB,您的终端需要滚动。
最好的办法是限制您尝试打印的像素区域:即,使用适当的参数为您的范围调用指定一个适当的小区域。
你真的,真的应该避免 for
循环和 "pixel-by-pixel" 对 Python 中图像的操作。尝试使用 OpenCV 矢量化例程,例如 cv2.threshold()
,否则,使用矢量化 Numpy 例程。
您在评论中提到您想这样做:
h = im.shape[0]
w = im.shape[1]
for x in range(0, w):
for y in range(0, h):
if im[y,x]>140 and im[y,x]<160:
im[y,x]=255
这在我的机器上需要 487 毫秒。如果你像这样使用 Numpy,它需要 56 微秒。即快 9,000 倍。
im[ np.logical_and(im>140, im<160) ] = 255
这将使您的代码看起来更像这样 - 未经测试:
import cv2
import numpy as np
cap = cv2.VideoCapture(0)
def video():
while True:
ret,frame = cap.read()
frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
frame[ np.logical_and(frame>140, frame<160) ] = 255
cv2.imshow('frame',frame)
key = cv2.waitKey(25)
if key == ord('q'):
break
if __name__ == '__main__':
video()
cap.release()
cv2.destroyAllWindows()
您还可以使用 OpenCV inRange()
来 select 灰度图像中的一系列灰色阴影,如下所示:
mask = cv2.inRange(im, 140, 160)
然后您可以将其应用到您的图像中:
frame[~mask] = 255
不过我觉得这样比较慢。