为了定义可能根据输入视频而改变的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
答案 0 :(得分:0)
如评论中所述,您通常希望避免使用
等模式for i in range(height):
for j in range(width):
array[i][j] = ...
循环numpy数组时。与C语言中的循环相比,Python中的循环速度很慢,部分原因是类型在它们被使用之前不是显式的或者是解释器已知的 - 因此类型检查发生在循环内的每个变量上。还有其他原因。但是numpy和类似的库实际上是用C和Fortran实现的,后端是这样的,所以如果你使用内置的numpy函数,你的代码会急剧加速。
如果要在数组中设置多个项目,可以通过多种方式实现。您可以同时使用一系列索引进行索引,而不是使用i
和j
等单个数字进行索引,例如
>>> 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语言编写的。