I'm trying to extract the lung region from chest x-ray images using the method described in - L.P Wong, H.T Ewe. "A Study of Lung Cancer Detection using Chest X-ray Images". 3rd APT Telemedicine Workshop 2005, 27-28th January 2005, Kuala Lumpur, Malaysia. Pages 210-214. The code I'm tring to replicate in Python is present here - http://www.mathworks.com/matlabcentral/mlc-downloads/downloads/submissions/12543/versions/1/previews/EulerMinMax.m/index.html.
In translating the code I have come across the following issues:
- Calculating Euler Number for images using OpenCV in Python - I've tried to implement this using "findContours" method in OpenCV but am not getting satisfactory results.
I have attached my code below. I would greatly appreciate any comments regarding the same.
import cv2
import numpy as np
import matplotlib.pyplot as plt
img = cv2.imread('chest.jpg',cv2.CV_LOAD_IMAGE_GRAYSCALE)
a = cv2.equalizeHist(img)
b = 255
arr_b = [i for i in range(b)]
trans_thresh = [float(i)/float(b) for i in arr_b]
result4_trans1 = []
def euler_number(image):
contours, hierarchy = cv2.findContours(a,cv2.RETR_CCOMP, cv2.CHAIN_APPROX_SIMPLE)
objects = len(contours)
holes = 0
for h in hierarchy[0]:
if h[2] == -1:
holes += 1
eulerNumber = objects - holes
return eulerNumber
def convert_to_binary_image(image, threshold, maxVal):
ret, thresh = cv2.threshold(image, threshold, maxVal, cv2.THRESH_BINARY | cv2.THRESH_OTSU)
return thresh
for j in range(b):
value_trans1 = trans_thresh[j]
binary_image = convert_to_binary_image(a, value_trans1, b)
result4_trans1.append(euler_number(binary_image))
max_result4_trans1 = max(result4_trans1)
min_result4_trans1 = min(result4_trans1)
m = 0
n = 0
max_sum_result4_trans1 = 0
min_sum_result4_trans1 = 0
for j in range(b):
if result4_trans1[j] == max_result4_trans1:
m += 1
max_sum_result4_trans1 += j
elif result4_trans1[j] == min_result4_trans1:
n += 1
min_sum_result4_trans1 += j
threshold_I1 = (float(max_sum_result4_trans1)+float(min_sum_result4_trans1))/float(m+n)
c = convert_to_binary_image(a, threshold_I1/float(b+1), b)
plt.imshow(c, cmap='gray')
plt.show()
Edit: The images that I have used and the ones that I have obtained can be viewed here. The folder contains the following:
- Original Image
- Result obtained by implementing the algorithm in Octave
- Result obtained by implementing the algorithm in Python
- PDF of a paper that uses the said algorithm for their work. Their results can be seen in Figure 4 of the paper.
Although the result obtained by Octave is not as 'clear' as the one depicted in the paper, that level of quality is what I'm first trying to achieve through Python. Based on trying to debug the code I have found the following issues:
The 'convert_to_binary_image' provides correct results if I'm calling it as a standalone function to test such as
plt.imshow(convert_to_binary_image(a, trans_thresh[1], b), cmap='gray')
However while trying to debug the code I tried to display the image in each iteration of
for j in range(b):
value_trans1 = trans_thresh[j]
binary_image = convert_to_binary_image(a, value_trans1, b)
result4_trans1.append(euler_number(binary_image))
The images displayed within this iteration were inconsistent with the ones displayed while testing and resembled the final image obtained (link given above).
In trying to calculate the Euler Number I tried two approaches - one using 'findContours' in OpenCV and the other using 'regionprops' in skimage. The results that I got from both were different (1 for OpenCV and 55 for skimage). The approach using skimage is
region = regionprops(label(image, 4)) e = 0 for r in region: e += r.euler_number return e
I would greatly appreciate comments regardiong the above two issues - instability of the images being plotted for 'convert_to_binary_image' and the proper implementation for calculating the Euler number.