Reputation: 53
I have this original image:
then I have applied the following code to
Then using cv2.findContours()
I have made a list containing all the contours.
Then i have removed all the contours of area less than 30.
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
Reputation: 450
I assume you only need the inner spots inside a leaf.
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
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:
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