#python #opencv #image-processing #background-subtraction
#python #opencv #обработка изображений #фон-вычитание
Вопрос:
Я пытаюсь удалить фиксированный фон с изображения с помощью одного свободно падающего объекта. На изображении есть один свободно падающий объект, и он имеет белый фон с круглым пятном посередине.
Ниже приведен мой код для вышеупомянутой задачи. Для решения этой задачи я использовал алгоритм OpenCV BackgroundSubtractor knn и BackgroundSubtractor mog2. Левые изображения должны быть предоставлены в качестве входных данных, а код должен выдавать правильные изображения в качестве выходных данных.
import numpy as np
import cv2
import sys
import os
#backgroundSubtractor = cv2.createBackgroundSubtractorMOG2()
backgroundSubtractor = cv2.createBackgroundSubtractorKNN()
# apply the algorithm for background images using learning rate > 0
for i in range(1, 16):
bgImageFile = "background/BG.png"
print("Opening background", bgImageFile)
bg = cv2.imread(bgImageFile)
backgroundSubtractor.apply(bg, learningRate=0.5)
# apply the algorithm for detection image using learning rate 0
dirc = os.getcwd()
filepath = os.path.join(dirc,'data')
if not os.path.exists('saved_bgRemoved'):
os.makedirs('saved_bgRemoved')
for file in os.listdir(filepath):
stillFrame = cv2.imread(os.path.join(filepath,file))
fgmask = backgroundSubtractor.apply(stillFrame, learningRate=0)
bgImg = cv2.bitwise_and(stillFrame,stillFrame,mask=fgmask)
# show both images
cv2.imshow("original", stillFrame)
cv2.imshow("mask", fgmask)
cv2.imshow("Cut Image", bgImg)
cv2.waitKey()
cv2.destroyAllWindows()
cv2.imwrite(os.path.join('saved_bgRemoved',file), bgImg)
Мой код очень хорошо работает с приведенным выше набором данных, но он не работает с данными изображения ниже:
Это также не работает, если объект окрашен в сероватую текстуру. Я думаю, что это хорошо работает, когда распределение пикселей объекта является равномерным и отличается от фона (т. Е. Круговой патч).
Есть ли какой-либо другой наилучший способ решения этой задачи, чтобы он мог вычитать фон даже из области пустоты объекта, не вычитая части объекта?
Комментарии:
1. Почему бы вам просто не сравнить изображение с фоном?
Ответ №1:
используйте приведенный ниже код, я думаю, теперь он работает
import cv2, os
def remove_bg(bg_path,im_path):
bg = cv2.imread(bg_path)
im = cv2.imread(im_path)
row,col,_ = im.shape
for i in range(0,row):
for j in range(0,col):
if ( bg[i][j][0] == im[i][j][0] and bg[i][j][1] == im[i][j][1] and bg[i][j][2] == im[i][j][2] ):
im[i][j] = [0,0,0] #it will replace background with black color, you can change it for example to [255,0,0] to replace it with red
return(im)
directory,_=os.path.split(__file__)
bg_path = directory "\background.png"
im_path = directory "\data6.png"
result = remove_bg(bg_path,im_path)
cv2.imshow("result", result)
cv2.waitKey()
cv2.imwrite(directory "\Result.png", result)
Комментарии:
1. Вместо использования циклов for, использование функции сравнения и получение маски будет намного быстрее. В C эти операции соответствуют
operator ==
иcopytTo
с маской. Однако я не знаю функций numpy.2. Ваш код не работает. Он выводит все черным. Вот ссылка на фактическое изображение и фон: drive.google.com/drive/folders /…
3. @Neil вы правы. проблема была в состоянии, которое я использовал. Я обновил ответ, посмотрите, работает ли он сейчас
4. @Neil просто имейте в виду, что это работает только в двух условиях: оба изображения (bg и im) имеют одинаковый размер (вы можете проверить это с помощью
print(bg.shape == im.shape)
), а bg фиксирован в каждом изображении, то есть, если вы сдвинете фон изображения всего на пиксель в любом направлении, это не сработает.