How to segment object from the background of an image Python OpenCV?

Issue

I’m trying to segregate a tower from its background. To do this I’ve defined an upper and lower limit HSV range of object color as shown below, but it only segregates partial object from its background, as the object has shades of two different colors, which are grey and white. Is there a possible way to segregate an object containing two different shade colors?

The image is

[![enter image description here][1]][1]

and the code I’m using is:

img = cv2.imread(r'source_img.jpg')
low = np.array([0,0,40])
high = np.array([180,18,230])
hsv = cv2.cvtColor(img,cv2.COLOR_RGB2HSV)
mask = cv2.inRange(hsv,low,high)
masked_img = cv2.bitwise_and(hsv,hsv,mask=mask)

The resultant output image contains only partial object segregation. I want to segregate the full tower excluding background grass, building and sky.

How can I segregate only the object tower without any background?

Solution

HSV color thresholding + two stage morphological operations

Binary image obtained from HSV color thresholding with this lower/upper range

lower = np.array([0, 0, 44])
upper = np.array([82, 78, 227])

There’s unwanted contours, so do morph open. Depending on the image you may need to adjust the kernel size or the number of iterations.

Result

import numpy as np
import imutils
import cv2

# Load image, resize smaller, HSV color threshold
image = cv2.imread('1.jpeg')
image = imutils.resize(image, width=600)
hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
lower = np.array([0, 0, 44])
upper = np.array([82, 78, 227])
mask = cv2.inRange(hsv, lower, upper)

# Remove small noise on mask with morph open
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (7,7))
opening = cv2.morphologyEx(mask, cv2.MORPH_OPEN, kernel, iterations=3)
smooth_kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (3,3))
opening = cv2.morphologyEx(opening, cv2.MORPH_OPEN, smooth_kernel, iterations=3)
result = cv2.bitwise_and(image, image, mask=opening)
# result[opening==0] = (255,255,255) # Optional for white background 

cv2.imshow('result', result)
cv2.imshow('mask', mask)
cv2.imshow('opening', opening)
cv2.waitKey()

Note: Lower/upper HSV ranges were obtained from choosing the correct upper and lower HSV boundaries for color detection with cv::inRange (OpenCV)

Answered By – nathancy

Answer Checked By – Timothy Miller (AngularFixing Admin)

Leave a Reply

Your email address will not be published.