Reputation: 59
I am trying to remove a fixed background from an image with a single free-falling object. The image has a single free falling object and it has a white background with a circular patch in the middle.
Below is my code for the above task. I have used OpenCV BackgroundSubtractorKNN and BackgroundSubtractorMOG2 algorithm to achieve this task. The left images should be given as input and the code should produce the right images as output.
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)
My code works very well with the above dataset, but it fails to work with the image data below:
It also doesn't work if the object is colored in greyish texture. I think it works well when the pixel distribution of the object is uniform and different from the background (i.e. the circular patch).
Is there any other best way to achieve this task, so that it can subtract the background even from the hollow area of the object, without subtracting parts of the object?
Upvotes: 0
Views: 1428
Reputation: 522
use below code, I think it now works
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)
Upvotes: 1