Удалить фон из изображения с фиксированным фоном

#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 фиксирован в каждом изображении, то есть, если вы сдвинете фон изображения всего на пиксель в любом направлении, это не сработает.