Finding defects in the contours of a mask, derived from a complex medical image and correcting them

asked 2017-11-27 06:50:46 -0500

SLFWalsh gravatar image

updated 2020-04-08 06:35:25 -0500

I have several thousand images of the lungs, taken from a CT scanner. An image looks like this.


I am attempting to extract the "lungs" section from the image by creating a mask. For example:


The problem is the edges of the lungs in the mask. Ideally, I could perform contour approximation to approximate the boundaries of the lungs in the mask and smooth them out so that bits weren't chopped out.

To begin with, I have tried the following code - the idea being to find the contours and then the "defects". However in this code example, defects returns None. I am new to OpenCV:

     mask = cv2.imread("mask.jpg", 0)
     _, contours, hierarchy = cv2.findContours(mask, 1, 2)
     cnt = contours[0]
     hull = cv2.convexHull(cnt, returnPoints = False)
     defects = cv2.convexityDefects(cnt, hull)

    for i in range(defects.shape[0]):
          s,e,f,d = defects[i,0]
          start = tuple(cnt[s][0])
          end = tuple(cnt[e][0])
          far = tuple(cnt[f][0])

This work is a follow on from this question on stackoverflow

Where it was suggested I look into contour approximation. I am wondering based on what I have researched so far, if it is contour hull I am really looking for. Any suggestions would be greatly appreciated.

edit retag flag offensive close merge delete


You're going to run into the same problem when using your own implementation of Marching Squares... I'm sorry, but what's wrong with the mask?

sjhalayka gravatar imagesjhalayka ( 2017-11-27 10:16:02 -0500 )edit

The edges of the mask cut out parts of the lung, because the bits of the lung on the original image at the edges are white (representing disease) - these white bits need to remain "within" the lung on the mask so that when I apply the mask to the lung image, those bits are preserved - they are important.

SLFWalsh gravatar imageSLFWalsh ( 2017-11-27 10:20:59 -0500 )edit

So basically, that particular lung slice is infested with diseased bits?

Anyway, your idea of grabbing the convex hull of the black region seems like a good solution.

You could also try running dilate() on the mask by like 10 pixels, and then erode() it by 10 pixels.

sjhalayka gravatar imagesjhalayka ( 2017-11-27 10:29:29 -0500 )edit

@SLFWalsh, the dilate() and erode() calls for Python are found here:

By dilating and eroding, resulting mask can be found here:

sjhalayka gravatar imagesjhalayka ( 2017-11-27 10:34:29 -0500 )edit

Can you provide this code in Python?

SLFWalsh gravatar imageSLFWalsh ( 2017-11-27 11:14:56 -0500 )edit

Sorry, I edited my last comment to remove the C++ code and put in a link to some Python code that dilates and erodes.

You can also try this code:

import cv2
import numpy as np

img = cv2.imread('input.png', 0)

kernel = np.ones((10, 10), np.uint8) # make a square dilation/erosion element

img = cv2.dilate(img, kernel, iterations=1)
img = cv2.erode(img, kernel, iterations=1)

cv2.imshow('Input', img)


Adjust the kernel size and iteration count to suit your needs. Also, look into getStructuringElement(), which provides circular or cross shaped (... not just square ...) dilation/erosion elements.

sjhalayka gravatar imagesjhalayka ( 2017-11-27 11:18:26 -0500 )edit

defects = cv2.convexityDefects(cnt, hull) is returning none value. Because of this I am not able to go further into defects.shape[0] where the error message is No shape attribute.

Could you please check this and let me know.

Sravan gravatar imageSravan ( 2018-02-05 08:23:33 -0500 )edit

@Sravan, please do not post answers here, if you have a question or comment, thank you.

berak gravatar imageberak ( 2018-02-05 09:13:20 -0500 )edit