emonigma
emonigma

Reputation: 4406

Find contiguous black pixels in image

I have been using OpenCV's findContours() to find areas of contiguous black pixels. Sometimes it selects the area of white pixels surrounding the black pixels, e.g. in this figure the "g", "e", and "n" are selected with black pixels as I expect, but the other three letters are selected by the surrounding area of white pixels, as shown by the green points of the contour:

example of selection of white area

Sometimes, the "g" with the white area inside the bowl is selected as a contour, and other times the white area inside the bowl is a different contour.

For both examples, I could deal with the hierarchy and check which contours are children of which other contours, but I think I am missing something simpler.

How can I get OpenCV to select and return each separate area of contiguous black pixels?

Upvotes: 2

Views: 2051

Answers (2)

J.D.
J.D.

Reputation: 4561

This is caused by findContours, that starts by looking for white shapes on a black background. Simply inverting you image will improve results. The code below will draw contours one by one with a keypress, so you can see that it is the black pixels that are selected.

enter image description here

import cv2
import numpy as np
# Read image in color (so we can draw in red)
img = cv2.imread("vBQa7.jpg")
# convert to gray and threshold to get a binary image
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
th, dst = cv2.threshold(gray, 20, 255, cv2.THRESH_BINARY)
# invert image
dst = cv2.bitwise_not(dst)
# find contours
countours,hierarchy=cv2.findContours(dst,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
# draw contours
for cnt in countours:
        cv2.drawContours(img,[cnt],0,(0,0,255),2)
        cv2.imshow("Result",img)
        cv2.waitKey(0)
# show image
cv2.imshow("Result",img)
cv2.waitKey(0)
cv2.destroyAllWindows()

You'll find that there are also some small black patches selected, as well as the background area. You can remove these by setting a minimum and maximum size and check the contourArea for each contour. (docs)

Upvotes: 3

Pidem
Pidem

Reputation: 270

I dont know whether this is an option for your use case, but you could take the following steps:

  1. identify the black pixels with filters/ thresholds

  2. use a clustering algorithm (DBscan here I think) to group the pixels together

Upvotes: 1

Related Questions