It is taking too much time to process frames while doing pixel by pixel operation of video frames

爱⌒轻易说出口 提交于 2021-01-28 20:13:07

问题


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

I have done almost everything I can and still I am not able to reslove this. Anybody who has some idea please help with some piece of code. When I put print outside the for loop then it was working fine. But then I was not getting the value of each pixel in the image.


回答1:


You really, really should avoid for loops and "pixel-by-pixel" operations on images in Python. Try to use OpenCV vectorised routines, like cv2.threshold(), or failing that, vectorised Numpy routines.

You mention in the comments that you want to do this:

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 

That takes 487 milliseconds on my machine. If you use Numpy, like this, it takes 56 microseconds. i.e. 9,000x faster.

im[ np.logical_and(im>140, im<160) ] = 255

That will make your code look more like this - untested:

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

You can also use OpenCV inRange() to select a range of shades of grey in a greyscale image, like this:

mask = cv2.inRange(im, 140, 160)

Then you could apply that to your image with:

frame[~mask] = 255

But I think that is slower.




回答2:


print is unavoidably slow (in comparison to the rest of the code). Assuming a 256x256 image, your code will print 65536 values. Depending on the format (I'm not familar with OpenCV, but lets assume 1 byte per pixel), that ranges from 2 to 4 bytes of output for every pixel (convert 8-bit unsigned byte to text + end of line), so 128kB-320kB, that your terminal then needs to scroll.

Your best bet is to limit the region of pixels you try to print: ie, specify a suitably small region using appropriate parameters to your range invocations.



来源:https://stackoverflow.com/questions/60318605/it-is-taking-too-much-time-to-process-frames-while-doing-pixel-by-pixel-operatio

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!