在对视频帧进行逐像素操作时处理帧需要花费太多时间

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

不过我觉得这样比较慢。