Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python OpenCV pure white background

I have a DIY home photo studio to take photos. I want them to be on pure white background (#FFFFFF) with minimum user interaction

This is original picture i have (no any processing, just raw JPG from camera) original image

I implement simple python program with opencv and Tkinter for UI

1) Get rect with object (ROI)

I decide to select ROI with UI, maybe later i will write code to automatically recognize object on the photo.

select ROI

2) With cv2.grabCut function i try to cut background from this rect

grab cut with rect

cv2.grabCut(image, self.mask, rect, bgdmodel, fgdmodel, 5, cv2.GC_INIT_WITH_RECT)

3) If necessary i create custom mask for grabcut which can provide more accuracy object extraction

grab cut with mask

cv2.grabCut(image, self.mask, rect, bgdmodel, fgdmodel, 5, cv2.GC_INIT_WITH_MASK)

4) After this step i can create mask where my object is located. I also resize mask by 30px

mask = cv2.resize(mask, ( crop_img.shape[1] + 30,  crop_img.shape[0] + 30))
mask = mask[30 : crop_img.shape[0], 30 : crop_img.shape[1]]

so this mask have more width and height

object mask

5) I use this mask for seamlessClone method

src_bg = 255 * np.ones(self.src.shape, self.src.dtype)

width, height, channels = src_bg.shape
center = (int(height / 2), int((width / 2)))
output = cv2.seamlessClone(crop_img, src_bg, mask, center, cv2.MIXED_CLONE)

And get such result: output

Looks good except some artifacts on the right side of object. It seems like my mask isnt fit good. This is not a real problem. Real problem is: seamlessClone give me not really white background. Take a look at levels:

levels

Some strange gradients and background isn't really white on bottom right corner. I try with many images and there is often such things.

My question is: what is a proper way to do what i want? Is my approach can used for this task and how to make really white (#FFFFFF) background without such gradients. Thanks

like image 750
striker Avatar asked Oct 17 '22 21:10

striker


1 Answers

Not sure if you are willing to consider another tool, but if you are on Linux, ImageMagick is probably installed and is able to do this very easily without any coding. It is also available for OS X and Windows.

So, if we start with this image:

enter image description here

and let's assume that the coordinates for the red lines correspond to an image that is 550px wide by 480px tall and offset 250,200 from the top-left of the picture. Then, just at the command-line in Terminal, you can run:

convert photo.jpg -crop 550x480+250+200 \
   -fuzz 25% -fill white -draw 'color 0,0 floodfill' -trim result.jpg

giving you this:

enter image description here

That command-line means... "Open photo.jpg and crop out the red part. Allow 25% variation in colour from the pixel at top-left corner and flood-fill the image with pure white. Trim it. Save as result.jpg"

You can set the fuzz percentage higher for a harder edge.

like image 81
Mark Setchell Avatar answered Oct 21 '22 09:10

Mark Setchell