I want to get rid of the skeletonized lines except the contours using python.
And, want to extract only the largest contour.
(Actually, I tried to make skeletonized line from the segmented mask. And, I got the main stem with contour like above picture. Among the contours, I want to extract only the contour with largest area.)
I don't know how to do it. Please help me if you have any idea.
Thanks in advance.
import os
import numpy as np
import cv2
from plantcv.plantcv import find_objects
from plantcv.plantcv import image_subtract
from plantcv.plantcv.morphology import segment_sort
from plantcv.plantcv.morphology import segment_skeleton
from plantcv.plantcv.morphology import _iterative_prune
from plantcv.plantcv import print_image
from plantcv.plantcv import plot_image
from plantcv.plantcv import params
from cv2.ximgproc import thinning
def find_large_contour(img, mask):
params.device += 1
mask1 = np.copy(mask)
ori_img = np.copy(img)
# If the reference image is grayscale convert it to color
if len(np.shape(ori_img)) == 2:
ori_img = cv2.cvtColor(ori_img, cv2.COLOR_GRAY2BGR)
objects, hierarchy = cv2.findContours(mask1, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)[-2:]
for i, cnt in enumerate(objects):
cv2.drawContours(ori_img, objects, i, (255, 102, 255), -1, lineType=8, hierarchy=hierarchy)
if params.debug == 'print':
print_image(ori_img, os.path.join(params.debug_outdir, str(params.device) + '_id_objects.png'))
elif params.debug == 'plot':
plot_image(ori_img)
return objects, hierarchy, ori_img
def prune(skel_img, size=2, mask=None):
# Store debug
debug = params.debug
params.debug = None
pruned_img = skel_img.copy()
# Check to see if the skeleton has multiple objects
skel_objects, _ = find_objects(skel_img, skel_img)
_, objects = segment_skeleton(skel_img)
kept_segments = []
removed_segments = []
if size > 0:
# If size>0 then check for segments that are smaller than size pixels long
# Sort through segments since we don't want to remove primary segments
secondary_objects, primary_objects = segment_sort(skel_img, objects)
# Keep segments longer than specified size
for i in range(0, len(secondary_objects)):
if len(secondary_objects[i]) > size:
kept_segments.append(secondary_objects[i])
else:
removed_segments.append(secondary_objects[i])
# Draw the contours that got removed
removed_barbs = np.zeros(skel_img.shape[:2], np.uint8)
cv2.drawContours(removed_barbs, removed_segments, -1, 255, 1,
lineType=8)
# Subtract all short segments from the skeleton image
pruned_img = image_subtract(pruned_img, removed_barbs)
pruned_contour_img = image_subtract(pruned_img, removed_barbs)
pruned_img = _iterative_prune(pruned_img, 1)
# Reset debug mode
params.debug = debug
# Make debugging image
if mask is None:
pruned_plot = np.zeros(skel_img.shape[:2], np.uint8)
else:
pruned_plot = mask.copy()
pruned_plot = cv2.cvtColor(pruned_plot, cv2.COLOR_GRAY2RGB)
pruned_obj, pruned_hierarchy, large_contour = find_large_contour(pruned_img, pruned_img)
cv2.drawContours(pruned_plot, removed_segments, -1, (0, 0, 255), params.line_thickness, lineType=8)
cv2.drawContours(pruned_plot, pruned_obj, -1, (150, 150, 150), params.line_thickness, lineType=8)
# Auto-increment device
params.device += 1
if params.debug == 'print':
print_image(pruned_img, os.path.join(params.debug_outdir, str(params.device) + '_pruned.png'))
print_image(pruned_plot, os.path.join(params.debug_outdir, str(params.device) + '_pruned_debug.png'))
elif params.debug == 'plot':
plot_image(pruned_img, cmap='gray')
plot_image(pruned_plot)
# Segment the pruned skeleton
segmented_img, segment_objects = segment_skeleton(pruned_img, mask)
return pruned_img, segmented_img, segment_objects, large_contour
vseg = cv2.imread("vseg.png", cv2.IMREAD_GRAYSCALE)
gray = thinning(vseg, thinningType=cv2.ximgproc.THINNING_GUOHALL)
pruned, seg_img, edge_objects, large_contour = prune(skel_img=gray, size=3, mask=vseg)
img_cont_gray = cv2.cvtColor(large_contour, cv2.COLOR_BGR2GRAY)
ret_cont, thresh_cont = cv2.threshold(img_cont_gray, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
cv2.imwrite("first_cont111.png", thresh_cont)
## then I want to extract the only contour with largest area


