问题
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