image - How to segment blood vessels python opencv -
i trying segment blood vessels in retinal images using python , opencv. here original image:
ideally want blood vessels visible (different image):
here have tried far. took green color channel of image.
img = cv2.imread('images/healthyeyefundus.jpg') b,g,r = cv2.split(img)
then tried create matched filter following this article , output image is:
then tried doing max entropy thresholding:
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 maximum max_ent, threshold = 0, 0 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 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 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, return threshold img = skimage.io.imread('image.jpg') # obtain histogram hist = np.histogram(img, bins=256, range=(0, 256))[0] # threshold th = max_entropy.max_entropy(hist) print th ret,th1 = cv2.threshold(img,th,255,cv2.thresh_binary)
this result i'm getting, not showing blood vessels:
i've tried taking matched filter version of image , taking magnitude of sobel values.
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)
this makes vessels pop out more:
then tried otsu thresholding on it:
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) 1 = image.fromarray(th2).show() 1 = image.fromarray(th3).show()
otsu doesn't give adequate results. ends including noise in results:
any appreciated on how can segment blood vessels successfully.
i worked on retina vessel detection bit few years ago, , there different ways it:
- if don't need top result fast, can use oriented openings, see here , here.
- then have other version using mathematical morphology version here.
for better results, here ideas:
- personally, used combination of gabor filters, , results pretty good. see the segmentation result here on first image of drive.
- and gabor can combined learning result, or here.
- few years ago, they claimed have best algorithm, i've never had opportunity test it. sceptic performance gap , way thresholded line detector results, kind of obscure.
- but know nowadays, many people try tackle problem using cnn, i've not heard significant improvements.
Comments
Post a Comment