I am trying to get the outline of the blue area in an image and then calculate the length and area, as shown in the picture (I have many similar images with the same resolution but different size of the blue areas).
Here is the code I am using:
import cv2
import numpy as np
# read image as grayscale
img = cv2.imread('VF2.jpg', cv2.IMREAD_GRAYSCALE)
# threshold to binary
thresh = cv2.threshold(img, 210, 255, cv2.THRESH_BINARY)[1] # the 2nd parameter should be changed.
# apply morphology
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (5,5))
morph = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel)
# find contours - write black over all small contours
letter = morph.copy()
cntrs = cv2.findContours(morph, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
# cntrs = cv2.findContours(morph, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cntrs = cntrs[0] if len(cntrs) == 2 else cntrs[1]
# cntrs = cntrs[0]
for c in cntrs:
area = cv2.contourArea(c)
print(area)
if area < 100:
cv2.drawContours(letter,[c],0,(0,0,0),-1)
# do canny edge detection
edges = cv2.Canny(letter, 200, 200) # the result for edges is good.
length = cv2.arcLength(cntrs[0], False) # not closed curves
print('length = ',length) # both length and area need calibration
area = cv2.contourArea(cntrs[0])
print('area = ',area)
# Outputs
print(np.squeeze(cntrs[0]), '\n') # Contour
print('Contour points:', cntrs[0].shape[0], '\n')
print('arcLength:', cv2.arcLength(cntrs[0], True)) # closed curves
# write results
# cv2.imwrite("K_thresh.png", thresh)
# show results
# cv2.imshow("K_thresh", thresh)
# cv2.imshow("K_morph", morph)
cv2.imshow("K_letter", letter)
cv2.imshow("K_edges", edges)
cv2.waitKey(0)
cv2.destroyAllWindows()
I used the above code and obtained the outline but with some additional parts, as highlighted in the following image. Can any one help to delete the additional parts and make the outline closed? Thanks a lot.
Change the size of your kernel to (4, 4) and perform erosion instead of open, here:
import cv2
import numpy as np
img = cv2.imread("images/flower.jpg", cv2.IMREAD_GRAYSCALE)
scale_percent = 60 # percent of original size
width = int(img.shape[1] * scale_percent / 100)
height = int(img.shape[0] * scale_percent / 100)
dim = (width, height)
# resize image
resized = cv2.resize(img, dim, interpolation = cv2.INTER_AREA)
# threshold to binary
thresh = cv2.threshold(resized, 210, 255, cv2.THRESH_BINARY_INV)[1] # the 2nd parameter should be changed.
# apply morphology
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (4,4))
morph = cv2.morphologyEx(thresh, cv2.MORPH_ERODE, kernel, 1)
letter = morph.copy()
cntrs = cv2.findContours(morph, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
# cntrs = cv2.findContours(morph, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cntrs = cntrs[0] if len(cntrs) == 2 else cntrs[1]
# cntrs = cntrs[0]
for c in cntrs:
area = cv2.contourArea(c)
print(area)
if area < 100:
cv2.drawContours(letter,[c],0,(0,0,0),-1)
# do canny edge detection
edges = cv2.Canny(letter, 200, 200) # the result for edges is good.
length = cv2.arcLength(cntrs[0], False) # not closed curves
print('length = ',length) # both length and area need calibration
area = cv2.contourArea(cntrs[0])
print('area = ',area)
# Outputs
print(np.squeeze(cntrs[0]), '\n') # Contour
print('Contour points:', cntrs[0].shape[0], '\n')
print('arcLength:', cv2.arcLength(cntrs[0], True)) # closed curves
# write results
# cv2.imwrite("K_thresh.png", thresh)
# show results
# cv2.imshow("K_thresh", thresh)
# cv2.imshow("K_morph", morph)
cv2.imshow("K_letter", letter)
cv2.imshow("K_edges", edges)
cv2.waitKey(0)
cv2.destroyAllWindows()