How can I extract this watermelon from the image?

Viewed 84

I'm trying to get the watermelon from the image. I have tried doing hsv segmentation and grabcut but it doesn't give me the output I wanted. How can I get the watermelon only? Any method will do except for Neural Networks since I'm new to image processing.

# hsv segmentation
lb = (20, 50, 0)
ub = (100, 255, 255)
mask_hsv = cv.inRange(hsv, lb, ub)

image_copy = image.copy()
morph = cv.erode(mask_hsv, (3, 3), iterations=4)
output = cv.bitwise_and(image_copy, image_copy, mask=morph)

After I use hsv I find the largest contour in the image.

draw = image.copy()
contours, h = cv.findContours(morph, cv.RETR_LIST, cv.CHAIN_APPROX_NONE)

if contours != 0:
    for contour in contours:
        area = cv.contourArea(contour)
        if max_area < area:
            max_area = area
            cnt = contour
        # else:
        #     pass
else:
    print('No contours found!')

Then I find the boundingRect of the biggest contour and feed it to grabcut function

x, y, h, w = cv.boundingRect(cnt)
rect = (x, y, h, w)

output_rect = image.copy()
mask = np.ones(image.shape[:2], dtype=np.uint8) * cv.GC_PR_BGD

bgdModel = np.zeros((1, 65), dtype=np.float64)
fgdModel = np.zeros((1, 65), dtype=np.float64)

# performs grabCut
cv.grabCut(output_rect, mask, rect, bgdModel, fgdModel, 100, cv.GC_INIT_WITH_RECT)
mask = np.where((mask == 2)|(mask == 0), 0, 1).astype('uint8')
mask *= 255

# applying the genrated mask to the image
output_image = cv.bitwise_and(output_rect, output_rect, mask=mask)

# change black pixels to white
black_pixels = np.where(
                (output_image[:, :, 0] == 0) & (output_image[:, :, 1] == 0) & (output_image[:, :, 2] == 0)
                )

output_image[black_pixels] = [255, 255, 255]

Original Image

Biggest contour found

Output after grabcut

1 Answers

I got the correct outputs via drawing your detected contours on blank image, then applying erosion and finally finding HoughCircles. Feel Free to change hyper-parameters to obtain better results.

Code:

import cv2
import numpy as np

image = cv2.imread("watermelon.png")
image_hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
image_copy = image.copy()

lower_boundary = (20,50, 0)
upper_boundary = (100,255,255)

mask_hsv = cv2.inRange(image_hsv, lower_boundary, upper_boundary)
blank_im = np.zeros((image.shape[0], image.shape[1], 1), dtype=np.uint8)

morph = cv2.erode(mask_hsv, (3,3), iterations=4)

output = cv2.bitwise_and(image, image, mask=morph)

# Finding Contours
contours, _ = cv2.findContours(morph, cv2.RETR_LIST, cv2.CHAIN_APPROX_NONE)

if len(contours) != 0:
    # Rather than using long for loop, this is how you can find the max value with given function
    contour = max(contours, key=cv2.contourArea)
else:
    print("No contours found!")

# Draw Contours on Blank Image (np.zeros() with same shape as original image)
cv2.drawContours(blank_im, contour, -1, (255,255,255), 10)

# Eroding the Blank Image with Drawn Contours
blank_im = cv2.erode(blank_im, (3,3), iterations=4)

# Find The Possible Circles, (Feel Free to Change Hyperparameters)
circles = cv2.HoughCircles(blank_im, cv2.HOUGH_GRADIENT, 1, 20, param1=50, param2=30, minRadius=0, maxRadius=0)
circles = np.uint16(np.around(circles))

# Draw each circle in green and centers in red
for i in circles[0,:]:
    cv2.circle(image, (i[0],i[1]), i[2], (0,255,0), 2)
    cv2.circle(image, (i[0], i[1]), 2, (0,0,255), 3)

# Display Images
cv2.imshow('Original Image', image_copy)
cv2.imshow('Drawed Contours On Blank Image', blank_im)
cv2.imshow('Detected Circle', image)

Output:

enter image description here

Related