2016-07-15 73 views
8

我想使用Python和OpenCV分割视网膜图像中的血管。这里是原始图像:如何分割血管python opencv

enter image description here

理想我希望所有的血管是这样的(不同图像)非常明显:

enter image description here

这里是我到目前为止已经试过。我拍摄了图像的绿色通道。

img = cv2.imread('images/HealthyEyeFundus.jpg') 
b,g,r = cv2.split(img) 

然后我试图通过以下this article创建一个匹配滤波器,这是输出图像是什么:

enter image description here

然后我试图做的最大熵阈值:

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) 

这是我得到的结果,显然没有显示所有的血管:

enter image description here

我也试着采取匹配的滤波器版本的图像,并采取其索贝尔值的大小。

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) 

这使得血管蹦出更多:

enter image description here

然后我尝试它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() 

大津并没有给予足够的结果。它结束了包括结果的噪音:

enter image description here

任何帮助表示赞赏血管怎么可以细分成功。

回答

1

我几年前在工作视网膜血管检测了一下,并有不同的方法来做到这一点:

  • 如果你并不需要一个顶级的结果,但快速的东西,你可以使用面向开口,see herehere
  • 然后你有另一个版本使用数学形态学version here

为了获得更好的结果,这里有一些想法: