Reputation: 177
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?
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:
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
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
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