OpenCV2_findContours: can i get just one big external contour? (the image has several particles)

Question:

i am new with CV2 with python.
i have many images, they have many big and small curvy structures.
and i have to get the biggest big one contour among all.
but i failed.
my codes and images are below…

import cv2 as cv

img_color = cv.imread('ex1.png')
img_gray = cv.cvtColor(img_color, cv.COLOR_BGR2GRAY)
ret, img_binary = cv.threshold(img_gray, 127, 255, 0)
#dbg contours, hierarchy = cv.findContours(img_binary, cv.RETR_LIST, cv.CHAIN_APPROX_SIMPLE)
_, contours, hierarchy = cv.findContours(img_binary, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)

for cnt in contours:
    cv.drawContours(img_color, [cnt], 0, (255, 0, 0), 3)  # blue
#dbg cv.imshow("result", img_color)
#dbg cv.waitKey(0)
cv.imwrite('save_image1.png', img_color)

for cnt in contours:
    hull = cv.convexHull(cnt)
    cv.drawContours(img_color, [hull], 0, (0, 0, 255), 5)
#dbg cv.imshow("result", img_color)
#dbg cv.waitKey(0)
cv.imwrite('save_image2.png', img_color)

example of input image ("ex1.png") is like…
enter image description here
the result output image ("save_image2.png") is like…
enter image description here

but,
what i want to retrieve is like below… (any of blue or red, i can use them 😉
enter image description here
i mean, the result contour must be just big one which includes everything.

thank you for reading util here(; )

Asked By: AJAMC

||

Answers:

Here is one way to do that in Python/OpenCV.

Use max(contours, key=cv2.contourArea) to get the largest one.

Input:

enter image description here

import cv2

img_color = cv2.imread('ex1.png')
img_gray = cv2.cvtColor(img_color, cv2.COLOR_BGR2GRAY)
img_binary = cv2.threshold(img_gray, 0, 255, cv2.THRESH_BINARY+cv2.THRESH_OTSU)[1]

contours = cv2.findContours(img_binary, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
contours = contours[0] if len(contours) == 2 else contours[1]
big_contour = max(contours, key=cv2.contourArea)

img_contour = img_color.copy()
cv2.drawContours(img_contour, [big_contour], 0, (0,0,255), 2)

cv2.imwrite('ex1_contour.png', img_contour)

cv2.imshow('img_contour', img_contour)
cv2.waitKey(0)
cv2.destroyAllWindows()

enter image description here

Answered By: fmw42

You asked for outline/contour of all regions rather than just the largest. So here is how to do that in Python/OpenCV.

  • Read the input
  • Convert to gray
  • Threshold to binary
  • Get all the points where the value is greater than 0 and transpose (since numpy use y,x convention and OpenCV wants x,y)
  • Compute the convex hull of the points
  • Draw a poly line on a copy of the input
  • Draw a white filled polygon on a black image
  • Get the contour of the white filled polygon
  • Draw the contour on a copy of the input
  • Save results

Input:

enter image description here

import cv2
import numpy as np

img_color = cv2.imread('ex1.png')
img_gray = cv2.cvtColor(img_color, cv2.COLOR_BGR2GRAY)
img_binary = cv2.threshold(img_gray, 0, 255, cv2.THRESH_BINARY+cv2.THRESH_OTSU)[1]

# get convex hull
points = np.column_stack(np.where(img_binary.transpose() > 0))
hull = cv2.convexHull(points)

# draw convex hull on input image in green
result = img_color.copy()
cv2.polylines(result, [hull], True, (0,0,255), 2)

# draw white filled hull polygon on black background
mask = np.zeros_like(img_binary)
cv2.fillPoly(mask, [hull], 255)

# get the largest contour from result2
contours = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
contours = contours[0] if len(contours) == 2 else contours[1]
big_contour = max(contours, key=cv2.contourArea)

# draw contour on copy of input
contr = img_color.copy()
contr = cv2.drawContours(contr, [big_contour], 0, (0,0,255), 2)

# save result2
cv2.imwrite('ex1_convex_hull.png', result)
cv2.imwrite('ex1_convex_hull_contour.png', contr)

# show result2
cv2.imshow('result', result)
cv2.imshow('contr', contr)
cv2.waitKey(0)
cv2.destroyAllWindows()

Resulting convex hull:

enter image description here

Contour of convex hull:

enter image description here

Answered By: fmw42
Categories: questions Tags: , , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.