2016-07-15 20 views
8

Tôi đang cố gắng phân đoạn các mạch máu trong hình ảnh võng mạc bằng cách sử dụng Python và OpenCV. Dưới đây là hình ảnh ban đầu:Làm thế nào để phân đoạn mạch máu python opencv

enter image description here

Lý tưởng nhất là tôi muốn tất cả các mạch máu là rất rõ ràng như thế này (hình ảnh khác nhau):

enter image description here

Dưới đây là những gì tôi đã cố gắng cho đến nay . Tôi lấy kênh màu xanh lục của hình ảnh.

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

Sau đó, tôi đã cố gắng để tạo ra một bộ lọc phù hợp bằng cách làm theo this article và đây là những gì hình ảnh đầu ra là:

enter image description here

Sau đó, tôi đã cố gắng làm tối đa entropy ngưỡng:

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) 

Đây là kết quả tôi nhận được, rõ ràng là không hiển thị tất cả các mạch máu:

enter image description here

Tôi cũng đã thử chụp phiên bản bộ lọc phù hợp của hình ảnh và lấy độ lớn các giá trị sobel của nó.

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) 

Điều này làm cho các mạch máu bật ra hơn:

enter image description here

Sau đó, tôi đã cố gắng Otsu ngưỡng trên nó:

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 không cho kết quả đầy đủ. Nó kết thúc bao gồm tiếng ồn trong các kết quả:

enter image description here

Any help is appreciated về cách tôi có thể phân khúc các mạch máu thành công.

Trả lời

1

tôi làm việc trên tàu phát hiện võng mạc cho một chút vài năm trước đây, và có những cách khác nhau để làm điều đó: mở

  • Nếu bạn không cần một kết quả hàng đầu nhưng một cái gì đó nhanh chóng, bạn có thể sử dụng theo định hướng , see herehere.
  • Sau đó, bạn có phiên bản khác sử dụng hình thái toán học version here.

Để có kết quả tốt hơn, sau đây là một số ý tưởng:

Các vấn đề liên quan