Extract Foreground from Background by making the background white

Question:

Thanks Your time, I am a newbie in opencv and I want to extract foreground from my image by making the background white. So far, I have been able to convert the image background to black, how can I make it white..??

Input Image and Output Image

import numpy as np
import cv2 as cv
import cv2
import glob
import os


image_data_path = os.path.abspath('../8470p/corn_weed_datasets/bluegrass')
gt_data_path = os.path.abspath('../8470p/GT data')
image_out_path = os.path.abspath('../8470p/corn_weed_datasets/corn1')

curr_image = 0 


for image_name in sorted(os.listdir(image_data_path)):

    curr_image += 1


    image_path = os.path.join(image_data_path, image_name)

    img = cv2.imread(image_path)



    hsv = cv.cvtColor(img, cv.COLOR_BGR2HSV)


    l_b = np.array([23,26,12])
    # the array is the our range of lower blue colors
    u_b = np.array([277,255,277])
    # the array is the our range of upper blue colors
    mask = cv.inRange(hsv, l_b, u_b)
    # threshold d hsv image to get only d blue color
    res = cv2.bitwise_and(img,img, mask = mask)

    Image = cv2.cvtColor(res, cv2.COLOR_RGB2BGR)

    cv.imshow('res',Image)
    k = cv.waitKey(0) & 0xFF
    if k ==27:
        break
for bb,file in enumerate (glob.glob(image_data_path)):
    cv2.imwrite('../8470p/corn_weed_datasets/corn1/bluegrass{}.png'.format(bb), Image)
#     cv2.imwrite(os.path.join(image_out_path,Image ))


cv.destroyAllWindows()
Asked By: chuky pedro

||

Answers:

Here is one way to do that in Python/OpenCV

  • Read the input
  • Convert to HSV color space
  • Do color thresholding on the green colors
  • Apply morphology to the thresholded image to remove extraneous white regions and save a mask
  • Apply the mask to the input image
  • Change black to white
  • Save the results

Input:

enter image description here

import cv2
import numpy as np

# load image
img = cv2.imread("green_plant.jpg")

# convert to hsv
hsv = cv2.cvtColor(img,cv2.COLOR_BGR2HSV)

# threshold using inRange
range1 = (30,0,100)
range2 = (255,255,255)
mask = cv2.inRange(hsv,range1,range2)

# apply morphology closing and opening to mask
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (7,7))
mask = cv2.morphologyEx(mask, cv2.MORPH_OPEN, kernel)
mask = cv2.morphologyEx(mask, cv2.MORPH_CLOSE, kernel)

# make mask 3 channel
mask = cv2.merge([mask,mask,mask])

# invert mask
mask_inv = 255 - mask

# create white image for background
white = np.full_like(img, (255,255,255))

# apply mask to input
img_masked = cv2.bitwise_and(img, mask)

# apply inverted mask to white image
white_masked = cv2.bitwise_and(white, mask_inv)

# combine inverted mask with masked image
result = cv2.add(img_masked, mask_inv)

# write result to disk
cv2.imwrite("green_plant_mask.png", mask)
cv2.imwrite("green_plant_white_background.jpg", result)

# display it
cv2.imshow("mask", mask)
cv2.imshow("mask_inv", mask_inv)
cv2.imshow("img_masked", img_masked)
cv2.imshow("result", result)
cv2.waitKey(0)
cv2.destroyAllWindows()

Mask:

enter image description here

Input masked:

enter image description here

Result:

enter image description here

Answered By: fmw42

This solution works well for uniform background. Here is the Java implementation for the same.

matImage – input image matrix

Mat mask = new Mat();
Core.inRange(matImage, new Scalar(30,0,100), new Scalar(255, 255, 255), mask);

Mat kernel = Imgproc.getStructuringElement(Imgproc.MORPH_ELLIPSE, new Size(7,7));

Imgproc.morphologyEx(mask, mask, Imgproc.MORPH_OPEN, kernel);
Imgproc.morphologyEx(mask, mask, Imgproc.MORPH_CLOSE, kernel);

List<Mat> maskList = new ArrayList();
maskList.add(mask);
maskList.add(mask);
maskList.add(mask);

Core.merge(maskList, mask);

Mat mask_inv = new Mat();

Core.invert(mask_inv, mask);

Mat background = new Mat(matImage.rows(), matImage.cols(), CvType.CV_8U, Scalar.all(1));

Mat img_masked = new Mat();
Core.bitwise_and(matImage, mask, img_masked);

Mat white_masked = new Mat();
Core.bitwise_and(background, mask_inv, white_masked);

Mat backgroundSubImage = new Mat();

Core.add(img_masked, white_masked, backgroundSubImage);
       
Answered By: shilpa gopi
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.