Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Filling the outside of selected Hull Convex with black?

I created a convex hull of a hand from an X-ray. I did this by first creating contours along the edges of the hand. I am wanting to blacken the outside region of convex hull using OpenCV in Python. How do I approach this?

The code below creates the convex hull after doing contours:

img_path = 'sample_image.png'

# Getting the threshold of the image:
image = cv2.imread(img_path)
original = image.copy() 
blank = np.zeros(image.shape[:2], dtype = np.uint8)
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
blur = cv2.GaussianBlur(gray, (5,5), 0)
thresh = cv2.threshold(blur, 140, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)[1]

# Drawing the contours along the edges of the hand in X-ray:
contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, 
cv2.CHAIN_APPROX_SIMPLE)
contours = max(contours, key = lambda x: cv2.contourArea(x))
cv2.drawContours(image, [contours], -1, (255,255,0), 2)

# Drawing the hull along the digits along the edges: 
hull = cv2.convexHull(contours)
cv2.drawContours(image, [hull], -1, (0, 255, 255), 2)

Input image: Sample_image.png

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

Result image: Output from the code

Update

Answer given by @AKX below proposed to draw the contour with filled polygon onto a new white blank and then use bitwise_and. The result code:

# Merge text into a single contour
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5,5))
dilate = cv2.dilate(thresh, kernel, iterations = 2)

contours, hierarchy = cv2.findContours(dilate, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
contours = max(contours, key = lambda x: cv2.contourArea(x))

cv2.drawContours(image, [contours], -1, (255,255,0), 2)
plt.imshow(image)

# Created a new mask and used bitwise_and to select for contours:
hull = cv2.convexHull(contours)
mask = np.zeros_like(image)
cv2.drawContours(mask, [hull], -1, (255, 255, 255), -1)
masked_image = cv2.bitwise_and(image, mask)

plt.imshow(masked_image)

>Solution :

Masking

Instead of drawing the hull contour as a line, draw it as a filled polygon onto a blank image with white, then bitwise_and it onto the original so everything outside the polygon is blanked out.

mask = np.zeros_like(image)
cv2.drawContours(mask, [hull], -1, (255, 255, 255), -1)
masked_image = cv2.bitwise_and(image, mask)
cv2.imwrite(r'dog_masked.jpg', masked_image)

input image

(no idea why I called it dog.jpg, it doesn’t look like a dog)

enter image description here

result

(the line below the dog remains since it’s inside the hull created by the dog’s feet)

enter image description here

Cropping

To crop the image to only include the hull’s area, use cv2.boundingRect and slice the image array:

x, y, w, h = cv2.boundingRect(hull)
cropped = image[y:y + h, x:x + w]
cv2.imwrite(r'dog_crop.jpg', cropped)

Result

enter image description here

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading