如果兴趣

时间:2017-12-23 04:47:19

标签: python opencv image-processing computer-vision

为了定义可能根据输入视频而改变的ROI(感兴趣区域),我使用以下方法:

  • 创建一个空白的黑色图像

  • 使用opencv函数

  • 减去背景
  • 将白色像素(前景)复制到空白图像5分钟

问题:在2 for循环下,if语句及其中的指令正在减慢处理时间:

if opening[i][j] == 255 or opening[i][j] == 127:
    blank_image[i][j] = [255, 255, 255]

我不熟悉opencv,我对这些东西不熟悉,所以我不知道是否有更好的方法。

import numpy as np
import cv2
import sys
import time
from PIL import Image

fgbg = cv2.createBackgroundSubtractorMOG2(detectShadows = 0)
video = 'C:/Users/HP/Desktop/sentdex/testLongVideo.mp4'
cap = cv2.VideoCapture(video)

frame_height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))      #get the frame height
frame_width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))        #get the frame width
x = 0
start = time.process_time()     #start time

while(1 and time.process_time() - start < 300):
    ret,frame = cap.read()
    fgmask = fgbg.apply(frame)      #apply the MOG2 mask on the video
    erode = cv2.erode(fgmask, None, iterations = 1)     #erosion to erase unwanted small contours
    opening = cv2.morphologyEx(erode, cv2.MORPH_OPEN, None)     #eliminate false positive on erosion
    if x < 5:       #this condition is used because if the creation of the black image starts at the same time as the video all the pixels will be white
        blank_image = np.zeros((frame_height,frame_width,3), np.uint8)          #create a black image with the same height and width of the video
        x += 1
    else:
        for i in range(len(opening)):
            for j in range(len(opening[i])):
                if [i,j] not in checked and opening[i][j] == 255 or opening[i][j] == 127:       #skip the treated pixels and check which pixels of the treated frame are white or gray (moving objects and their shadows)
                    blank_image[i][j] = [255, 255, 255]     #turn the pixels in the black image to white from the treated video by the X and Y
                    checked.append([i,j])   #treated pixels

    cv2.imwrite('backgroundMask.png', blank_image)      #saving the background treated
    k = cv2.waitKey(30) & 0xff
    if k == 27:
        break

cap.release()
cv2.destroyAllWindows()

我尝试在没有任何内部的情况下运行循环,它运行得很好:

for i in range(len(opening)):
    for j in range(len(opening[i])):
        continue

当我添加一条没有if语句的指令时,它很慢:

for i in range(len(opening)):
    for j in range(len(opening[i])):
        blank_image[i][j] = [255, 255, 255]

但是当我添加if语句时,即使其中没​​有指令,它也会更慢:

for i in range(len(opening)):
    for j in range(len(opening[i])):
        if opening[i][j] == 255:
            continue

2 个答案:

答案 0 :(得分:0)

如评论中所述,您通常希望避免使用

等模式
for i in range(height):
    for j in range(width):
        array[i][j] = ...

循环numpy数组时。与C语言中的循环相比,Python中的循环速度很慢,部分原因是类型在它们被使用之前不是显式的或者是解释器已知的 - 因此类型检查发生在循环内的每个变量上。还有其他原因。但是numpy和类似的库实际上是用C和Fortran实现的,后端是这样的,所以如果你使用内置的numpy函数,你的代码会急剧加速。

如果要在数组中设置多个项目,可以通过多种方式实现。您可以同时使用一系列索引进行索引,而不是使用ij等单个数字进行索引,例如

>>> img
array([[0, 0, 0, 0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0, 0, 0, 0]], dtype=uint8)
>>> img[(0, 1, 2, 3), (1, 2, 3, 4)] = 1
>>> img
array([[0, 1, 0, 0, 0, 0, 0, 0],
       [0, 0, 1, 0, 0, 0, 0, 0],
       [0, 0, 0, 1, 0, 0, 0, 0],
       [0, 0, 0, 0, 1, 0, 0, 0],
       [0, 0, 0, 0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0, 0, 0, 0]], dtype=uint8)

正如您所见,img中将此设置为(0,1),(1,2),...设为1。

您也可以一次设置整个子区域:

>>> img[2:6, 2:6] = 1
>>> img
array([[0, 1, 0, 0, 0, 0, 0, 0],
       [0, 0, 1, 0, 0, 0, 0, 0],
       [0, 0, 1, 1, 1, 1, 0, 0],
       [0, 0, 1, 1, 1, 1, 0, 0],
       [0, 0, 1, 1, 1, 1, 0, 0],
       [0, 0, 1, 1, 1, 1, 0, 0],
       [0, 0, 0, 0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0, 0, 0, 0]], dtype=uint8)

但你要找的是boolean or masked indexing。这取代了模式:

for i in range(height):
    for j in range(width):
        if array[i][j] == 1:
            array[i][j] = 2

用简单的线

array[array==1] = 2

如果您将这些部分分开,很容易看出发生了什么:

>>> img
array([[0, 1, 0, 0, 0, 0, 0, 0],
       [0, 0, 1, 0, 0, 0, 0, 0],
       [0, 0, 1, 1, 1, 1, 0, 0],
       [0, 0, 1, 1, 1, 1, 0, 0],
       [0, 0, 1, 1, 1, 1, 0, 0],
       [0, 0, 1, 1, 1, 1, 0, 0],
       [0, 0, 0, 0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0, 0, 0, 0]], dtype=uint8)
>>> img==1
array([[False,  True, False, False, False, False, False, False],
       [False, False,  True, False, False, False, False, False],
       [False, False,  True,  True,  True,  True, False, False],
       [False, False,  True,  True,  True,  True, False, False],
       [False, False,  True,  True,  True,  True, False, False],
       [False, False,  True,  True,  True,  True, False, False],
       [False, False, False, False, False, False, False, False],
       [False, False, False, False, False, False, False, False]], dtype=bool)

所以这里有一个与img形状相同的数组,但是布尔值告诉我们感兴趣的项。这个布尔数组可以用来索引原始阵列。

>>> img[img==1]
array([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], dtype=uint8)

在这里,我们看到数组img的值为img==1。我们可以将img中的所有这些值设置为另一个值:

>>> img[img==1] = 2
>>> img
array([[0, 2, 0, 0, 0, 0, 0, 0],
       [0, 0, 2, 0, 0, 0, 0, 0],
       [0, 0, 2, 2, 2, 2, 0, 0],
       [0, 0, 2, 2, 2, 2, 0, 0],
       [0, 0, 2, 2, 2, 2, 0, 0],
       [0, 0, 2, 2, 2, 2, 0, 0],
       [0, 0, 0, 0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0, 0, 0, 0]], dtype=uint8)

简而言之,看起来你只需要

blank_image[(opening==255) | (opening==127)] = 255

答案 1 :(得分:0)

希望这可以提供帮助

如果我理解正确

for i in range(len(opening)):
    for j in range(len(opening[i])):
        if [i,j] not in checked and opening[i][j] == 255 or opening[i][j] == 127:       #skip the treated pixels and check which pixels of the treated frame are white or gray (moving objects and their shadows)
            blank_image[i][j] = [255, 255, 255]     #turn the pixels in the black image to white from the treated video by the X and Y
            checked.append([i,j])   #treated pixels

此代码

Checks if opening[i][j] is either 255 or 127

如果这个条件成立

black_image pixel is turned white

检查此解决方案

black_image[np.where((opening ==255).all(axis=2)) or np.where((opening ==127).all(axis=2))] = [255,255,255]

我尝试了类似的方法,使用

更改图像中某些BGR值的值

img[np.where((img == [__b,__g,__r]).all(axis=2))] = [255, 255, 255]

您可以查看OpenCV: setting all pixels of specific BGR value to another BGR value

尽可能尝试在代码中使用numpy,因为它是使用C语言编写的。