Gkisi27
Gkisi27

Reputation: 177

Error while trying to get area of contour in opencv python

I have an small project where I need to calculate the area of hair portions and tell which one covers greater area among two images. I have another code for hair extraction. However it is not also giving result as expected.You may have guessed already from image below. I will work on it later.

I am trying to calculate the area from contours which is giving me error like:

OpenCV(3.4.4) C:\projects\opencv-python\opencv\modules\imgproc\src\contours.cpp:195: error: (-210:Unsupported format or combination of formats) [Start]FindContours supports only CV_8UC1 images when mode != CV_RETR_FLOODFILL otherwise supports CV_32SC1 images only in function 'cvStartFindContours_Impl'

So, why is findContours not supporting my image?

Another approach:

I only need to find the area of hair portion. So, I thought of calculating area covered by all the white pixels and then subtract it from area of whole image too. In this case, I do not know how to calculate area covered by all white pixels. I thought this way because, hair color can vary, but background will always be white.

So, is this technique possible? Or please suggest some solution for above mentioned error?

My image:

Hair

My code:

import cv2
import numpy as np

img = cv2.imread("Hair.jpg")

_, contours, _ = cv2.findContours(img, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)

c = max(contours, key = cv2.contourArea)

cv2.drawContours(img, [c], -1, (255,255, 255), -1) 

area = cv2.contourArea(c)
print(area)

cv2.imshow("contour", img)
cv2.waitKey(0)
cv2.destroyAllWindows()

Upvotes: 0

Views: 2069

Answers (1)

api55
api55

Reputation: 11420

Your error already tells what is wrong, specifically this part:

FindContours supports only CV_8UC1 images when mode

This means that it has to be a greyscale image. You pass an image loaded with:

img = cv2.imread("Hair.jpg")

Which by default returns the image in CV_8UC3 or in simple words, BGR colorspace. Even if your image only has black and white. Solution, load as greyscale:

img = cv2.imread("Hair.jpg", cv2.IMREAD_GRAYSCALE)

Also, I notice that this is a .jpg file, which may introduce some artifacts that you may not like/want. To remove them, use threshold:

ret,thresh1 = cv.threshold(img,127,255,cv.THRESH_BINARY)

I hope this helps you, if not, leave a comment


Update:

findContours function takes black as background and white as foreground. In your case is the other way around. But there is an easy way to solve this, just invert the image when it is being passed:

_, contours, _ = cv2.findContours(255-img, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)

255 is the max value the image can have, and this will turn black into white and white into black, giving you the correct contour.

Upvotes: 1

Related Questions