Paras Kumar Langyan
Paras Kumar Langyan

Reputation: 53

I want to remove the boundary using opencv

I have this original image:

image

then I have applied the following code to

  1. Converted the Original image to HSV image
  2. Then using cv2.findContours() I have made a list containing all the contours.

  3. Then i have removed all the contours of area less than 30.

  4. Then I got the following image:

image

What I want is to remove the boundary from the resulting image it is of no use (outer boundary of leaf).I only need the inner patches of the leaf. This is the code i used.

import cv2
import numpy as np
img = cv2.imread('Apple___Blackrot30.JPG')
hsv = cv2.cvtColor(img,cv2.COLOR_BGR2HSV)     
lower_gr = np.array([25,0,0])
upper_gr = np.array([90,255,255])
mask = cv2.inRange(hsv,lower_gr,upper_gr)
mask=~mask   
res = cv2.bitwise_and(img,img,mask = mask)
blur = cv2.bilateralFilter(res,9,75,75)
im2,cont,_ = cv2.findContours(mask,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
areas = [cv2.contourArea(each_conts) for each_conts in cont]
cont_counter = 0
for each_conts in areas:
    if each_conts < 30:
        cv2.fillPoly(im2, pts =[cont[cont_counter]], color=(0,0,0))
    if each_conts > 1024:
        cv2.drawContours(mask, cont[cont_counter], 0, (255,255,255), -1)    
    cont_counter+=1

cv2.imshow('cn',im2)

Upvotes: 1

Views: 1404

Answers (2)

burhan rashid
burhan rashid

Reputation: 450

I assume you only need the inner spots inside a leaf.

  1. Segment using the otsu algorithm
  2. apply the flood-fill operation to ensure you capture all leaf pixels
  3. Extract only the inner contour All can simply be done using opencv below are the codes:
import cv2
import numpy as np

def flood_fill_binary(binary):
    hh = binary.shape[0]
    ww = binary.shape[1]
    xx = 10
    yy = 10
    black = [0,0,0]
    binary = cv2.copyMakeBorder(binary,10,10,10,10,cv2.BORDER_CONSTANT,value=black)
    im_floodfill = binary.copy()
    h, w = binary.shape[:2]
    mask = np.zeros((h+2, w+2), np.uint8)
    cv2.floodFill(im_floodfill, mask, (0,0), 255)
    im_floodfill_inv = cv2.bitwise_not(im_floodfill)
    im_out = binary | im_floodfill_inv
    crop_og = im_out[yy:yy+hh,xx:xx+ww]
    return crop_og

def leaf_spots_detector(image):
    image = image.astype('uint8')
    hh = image.shape[0]
    ww = image.shape[1]
    xx = 10
    yy = 10
    #kernel = np.ones((3,3),np.uint8)
    grayed_image = cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)
    _, segmented = cv2.threshold(grayed_image,0, 255, 
    cv2.THRESH_BINARY+cv2.THRESH_OTSU)
    segmented = flood_fill_binary(segmented)
    segmented = cv2.copyMakeBorder(segmented,xx,xx,yy,yy,cv2.BORDER_CONSTANT,value= 
    [0,0,0])
    major = cv2.__version__.split('.')[0]
    if major == '3':
        ret, contours, hierarchy = cv2.findContours(segmented, cv2.RETR_TREE, 
   cv2.CHAIN_APPROX_SIMPLE)
    else:
        contours, hierarchy = cv2.findContours(segmented, cv2.RETR_TREE, 
   cv2.CHAIN_APPROX_SIMPLE)
        print(hierarchy.shape)
    image_external = np.zeros(segmented.shape, segmented.dtype)
    for i in range(1,len(contours)):
         #if hierarchy[0][i][3] == -1:
        cv2.drawContours(image_external, contours, i,(225,255,255), -1)
    image_external = image_external[yy:yy+hh,xx:xx+ww]
    #image_external = cv2.dilate(image_external,kernel,iterations = 1)
    return image_external

image = cv2.imread('image/path.png')
leaf_spots = leaf_spots_detector(image)
cv2.imshow("detected spots", leaf_spots)
cv2.waitKey(0)
cv2.destroyAllWindow()

Upvotes: 0

Jeru Luke
Jeru Luke

Reputation: 21203

You can use the concept of hierarchy of contours to solve this problem. But there is a caveat, all your images must be the same as the one in the question.

I just added some additional stuff to your code.

Code:

img2 = img.copy()
im2, cont, hierarchy = cv2.findContours(mask, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)

l = []
for e, h in enumerate(hierarchy[0]):
    #print (e, h[3])
    if h[3] == -1:
        l.append(e)

for i in l:
    if cv2.contourArea(cont[i]) < 1000:   
        cv2.drawContours(img2, [cont[i]], -1, (0, 255, 255), 2)

cv2.imshow('img2', img2)

Result:

enter image description here

hierarchy returns an array expressing the parent-child relationship of contours. As per the documentation link,

it as an array of four values : [Next, Previous, First_Child, Parent].

In the hierarchy array I scanned the Parent column (4th column) to see whether it has no parent contours (-1) and drew them

Upvotes: 1

Related Questions