Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Remove green background screen from image using OpenCV/Python

So I have this image below: enter image description here

As you can see, there is some noisy green outline in the image. This is by far, my latest output with OpenCV with Python. And I'm still a beginner with this so I need your help.

Assuming I were to create a completely new script and feed this image and 'clean' the image, how will I do it?

EDIT: This is the original image: enter image description here

like image 682
Jude Maranga Avatar asked Jul 16 '26 08:07

Jude Maranga


1 Answers

Here is a rather simple approach.

Background:

Dominant colors like red, green, blue and yellow can be segmented pretty easily when analyzed in LAB color space. LAB space has 3 channels, out of which only 2 are color channels while 1 is a brightness channel:

  • L-channel: represents the brightness
  • A-channel: represents the amount of red/green color
  • B-channel: represents the amount of blue/yellow color

enter image description here

Observing the plot above:

  1. a-axis clearly shows red/green color on its extremes
  2. b-axis shows blue/yellow color on its extremes

Applying a suitable threshold in the corresponding channels makes it easy for us to segment these colors.

Approach:

We will use the above info as a base to approach the problem at hand:

1. Perform basic masking:

-> Convert image to LAB space -> Threshold a-channel to isolate green background -> Masking original image with binary mask

img = cv2.imread('green_background.jpg')
lab = cv2.cvtColor(img, cv2.COLOR_BGR2LAB)
a_channel = lab[:,:,1]
th = cv2.threshold(a_channel,127,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)[1]
masked = cv2.bitwise_and(img, img, mask = th)    # contains dark background
m1 = masked.copy()
m1[th==0]=(255,255,255)                          # contains white background

enter image description here

2. Remove green shade along the border:

-> Convert masked image LAB space -> Normalize the a-channel mlab[:,:,1] to use the entire intensity range between [0-255] -> Inverse binary threshold to select area with green borders

mlab = cv2.cvtColor(masked, cv2.COLOR_BGR2LAB)
dst = cv2.normalize(mlab[:,:,1], dst=None, alpha=0, beta=255,norm_type=cv2.NORM_MINMAX, dtype=cv2.CV_8U)

enter image description here

Above image is the a-channel with dark pixels around the border.

threshold_value = 100
dst_th = cv2.threshold(dst, threshold_value, 255, cv2.THRESH_BINARY_INV)[1]

Above is the threshold image to segment green shaded regions.

enter image description here

In the a-channel, having green color represents the lower end of the range [0-255], while red color represents the higher end. We will set intensity value in the a-channel of the selected pixels to 127:

mlab2 = mlab.copy()
mlab[:,:,1][dst_th == 255] = 127

enter image description here

Now in the above image, we do not see the dark borders around the person.

Convert the image to BGR and the pixels that were dark (0) in the threshold image are set to white (255, 255, 255) in the color image

img2 = cv2.cvtColor(mlab, cv2.COLOR_LAB2BGR)
img2[th==0]=(255,255,255)

enter image description here

The resulting image looks like nothing much has changed, so here is a zoomed in comparison:

Before Step 2:

enter image description here

After Step 2:

enter image description here

Conclusion:

The noisy green outline around the border has improved to a certain extent. You can try varying threshold_value and experiment.

The green shade present within the person's face still remains. Sophisticated methods will be needed to get rid of those. Hope this approach helps.

like image 113
Jeru Luke Avatar answered Jul 18 '26 21:07

Jeru Luke



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!