Это занимает слишком много времени для обработки кадров при выполнении пиксельной операции видеокадров - PullRequest
1 голос
/ 20 февраля 2020
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()

Я сделал почти все, что мог, и до сих пор не могу восстановить это. Если у вас есть идеи, пожалуйста, помогите с кодом. Когда я положил печать вне для l oop, то это работало нормально. Но тогда я не получал значение каждого пикселя в изображении.

Ответы [ 2 ]

3 голосов
/ 21 февраля 2020

Вы действительно, действительно, должны избегать for циклов и "попиксельных" операций с изображениями в 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 микросекунд. т.е. в 9000 раз быстрее.

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() для выбора диапазона оттенков серого на изображении в оттенках серого, например:

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

Затем вы можете применить это к своему изображению с помощью:

frame[~mask] = 255

Но Я думаю, что это медленнее.

1 голос
/ 20 февраля 2020

печать неизбежно медленная (по сравнению с остальной частью кода). Предполагая, что изображение размером 256x256, ваш код напечатает 65536 значений. В зависимости от формата (я не знаком с OpenCV, но допустим 1 байт на пиксель), который варьируется от 2 до 4 байт для каждого пикселя (преобразовать 8-битный беззнаковый байт в текст + конец строки), поэтому 128 кБ-320 кБ, которую ваш терминал должен затем прокручивать.

Лучше всего ограничить область пикселей, которые вы пытаетесь напечатать: ie, укажите подходящую небольшую область, используя соответствующие параметры для вызовов диапазона.

...