我正在尝试使用 Python 和 OpenCV 分割视网膜图像中的血管。这是原始图像:
理想情况下,我希望所有的血管都像这样非常明显(不同的图像):
这是我到目前为止尝试过的方法。我拍摄了图像的绿色 channel 。
img = cv2.imread('images/HealthyEyeFundus.jpg')
b,g,r = cv2.split(img)
然后我尝试按照 this article 创建一个匹配的过滤器这就是输出图像:
然后我尝试进行最大熵阈值处理:
def max_entropy(data):
# calculate CDF (cumulative density function)
cdf = data.astype(np.float).cumsum()
# find histogram's nonzero area
valid_idx = np.nonzero(data)[0]
first_bin = valid_idx[0]
last_bin = valid_idx[-1]
# initialize search for maximum
max_ent, threshold = 0, 0
for it in range(first_bin, last_bin + 1):
# Background (dark)
hist_range = data[:it + 1]
hist_range = hist_range[hist_range != 0] / cdf[it] # normalize within selected range & remove all 0 elements
tot_ent = -np.sum(hist_range * np.log(hist_range)) # background entropy
# Foreground/Object (bright)
hist_range = data[it + 1:]
# normalize within selected range & remove all 0 elements
hist_range = hist_range[hist_range != 0] / (cdf[last_bin] - cdf[it])
tot_ent -= np.sum(hist_range * np.log(hist_range)) # accumulate object entropy
# find max
if tot_ent > max_ent:
max_ent, threshold = tot_ent, it
return threshold
img = skimage.io.imread('image.jpg')
# obtain histogram
hist = np.histogram(img, bins=256, range=(0, 256))[0]
# get threshold
th = max_entropy.max_entropy(hist)
print th
ret,th1 = cv2.threshold(img,th,255,cv2.THRESH_BINARY)
这是我得到的结果,显然没有显示所有的血管:
我还尝试采用图像的匹配滤波器版本并获取其 sobel 值的大小。
img0 = cv2.imread('image.jpg',0)
sobelx = cv2.Sobel(img0,cv2.CV_64F,1,0,ksize=5) # x
sobely = cv2.Sobel(img0,cv2.CV_64F,0,1,ksize=5) # y
magnitude = np.sqrt(sobelx**2+sobely**2)
这使得容器更多地弹出:
然后我尝试对其进行 Otsu 阈值处理:
img0 = cv2.imread('image.jpg',0)
# # Otsu's thresholding
ret2,th2 = cv2.threshold(img0,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)
# Otsu's thresholding after Gaussian filtering
blur = cv2.GaussianBlur(img0,(9,9),5)
ret3,th3 = cv2.threshold(blur,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)
one = Image.fromarray(th2).show()
one = Image.fromarray(th3).show()
Otsu 没有给出足够的结果。它最终会在结果中包含噪音:
感谢任何有关我如何成功分割血管的帮助。
最佳答案
几年前我从事视网膜血管检测工作,有不同的方法:
- 如果您不需要最好的结果但需要快速的结果,您可以使用定向开口,see here和 here .
- 然后你有另一个使用数学形态学的版本version here .
为了获得更好的结果,这里有一些想法:
- 就我个人而言,我使用了 Gabor 过滤器的组合,结果非常好。参见 the segmentation result here on the first image of drive .
- 和Gabor can be combined with learning for a good result , 或 here .
- 几年前,they claimed to have the best algorithm ,但我一直没有机会测试它。我对性能差距以及他们对线检测器结果进行阈值处理的方式表示怀疑,这有点模糊。
- 但我知道现在很多人尝试使用 CNN 来解决问题,但我还没有听说有重大改进。
关于python - python opencv如何分割血管,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38403205/