import numpy as np
import cv2, os
def CVShow(img, title = 'unNamed', max_h = 950, max_w = 1800):
img = np.array(img)
cv2.namedWindow(title, cv2.WINDOW_KEEPRATIO)
H,W = img.shape[:2]
if H > max_h:
ratio = max_h / H
H, W = int(ratio * H), int(ratio * W)
if W > max_w :
ratio = max_w / W
H, W = int(ratio * H), int(ratio * W)
cv2.resizeWindow(title, W, H)
cv2.imshow(title, img) # 自动适应图片大小的,不能缩放
key = cv2.waitKey(0)
if key == ord('s'): # wait for key to write or exit
cv2.imwrite(title+'.jpg', img)
cv2.destroyAllWindows()
return key
def Access_e_ophtha_MA(rootpath):
subdirs, imgpaths = os.listdir(rootpath), []
for subdir in subdirs: # 访问子文件夹
subdirpath = os.path.join(rootpath, subdir)
imgnames = os.listdir(subdirpath)
if 'Thumbs.db' in imgnames:imgnames.remove('Thumbs.db')
for name in imgnames: # 访问子文件夹下的图片
imgpaths.append((os.path.join(subdirpath, name), name))
return imgpaths
def enhance(img):
clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8, 8))
return clahe.apply(img)
def Morph_Operate(img):
r1 = cv2.morphologyEx(img, cv2.MORPH_OPEN, cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (5, 5)), iterations=1)
R1 = cv2.morphologyEx(r1, cv2.MORPH_CLOSE, cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (5, 5)), iterations=1)
r2 = cv2.morphologyEx(R1, cv2.MORPH_OPEN, cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (11, 11)), iterations=1)
R2 = cv2.morphologyEx(r2, cv2.MORPH_CLOSE, cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (11, 11)), iterations=1)
r3 = cv2.morphologyEx(R2, cv2.MORPH_OPEN, cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (23, 23)), iterations=1)
R3 = cv2.morphologyEx(r3, cv2.MORPH_CLOSE, cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (23, 23)), iterations=1)
return R3
def Vessels_Mask(f5):
ret, f6 = cv2.threshold(f5, 15, 255, cv2.THRESH_BINARY) # 用来计算 mask
# f7 = cv2.morphologyEx(f6, cv2.MORPH_OPEN, cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(3,3)), iterations=1)
mask = np.ones(f5.shape[:2], dtype="uint8") * 255
_, contours, hierarchy = cv2.findContours(f6, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
for cnt in contours:
if cv2.contourArea(cnt) <= 200:
cv2.drawContours(mask, [cnt], -1, 0, -1)
im = cv2.bitwise_and(f5, f5, mask=mask)
ret, fin = cv2.threshold(im, 15, 255, cv2.THRESH_BINARY_INV)
newfin = cv2.erode(fin, cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (3, 3)), iterations=1)
return newfin
def Vessels_Extract(newfin):
fundus_eroded = cv2.bitwise_not(newfin)
xmask = np.ones(fundus_eroded.shape[:2], dtype="uint8") * 255
_, xcontours, xhierarchy = cv2.findContours(fundus_eroded.copy(), cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
for cnt in xcontours:
shape = "unidentified"
peri = cv2.arcLength(cnt, True)
approx = cv2.approxPolyDP(cnt, 0.04 * peri, False)
condition = len(approx) > 4 and cv2.contourArea(cnt) <= 3000 and cv2.contourArea(cnt) >= 100
shape = "circle" if condition else "veins"
if shape == "circle": cv2.drawContours(xmask, [cnt], -1, 0, -1)
finimage = cv2.bitwise_and(fundus_eroded, fundus_eroded, mask=xmask)
blood_vessels = cv2.bitwise_not(finimage)
return blood_vessels
def Vessel_Segmentation_Demo(path):
img = cv2.imread(path)
_, green, _ = cv2.split(img)
contrast_enhanced_green = enhance(green)
morph_contrast_enhanced_green = Morph_Operate(contrast_enhanced_green)
f4 = cv2.subtract(morph_contrast_enhanced_green, contrast_enhanced_green)
f5 = enhance(f4)
newfin = Vessels_Mask(f5)
blood_vessels = Vessels_Extract(newfin)
result1 = np.hstack([contrast_enhanced_green, morph_contrast_enhanced_green])
result2 = np.hstack([f4, f5])
result3 = np.hstack([newfin, blood_vessels])
return np.vstack([result1, result2, result3])
if __name__ == '__main__':
e_ophtha_MA = r'J:\Image Projects\Microaneurysm Detection\Datasets\2013_e_ophtha\e_ophtha_MA'
imgpaths = Access_e_ophtha_MA(e_ophtha_MA + '\MA - CutBlack')
for path,name in imgpaths:
result = Vessel_Segmentation_Demo(path)
key = CVShow(result, name)
if key == ord('b'): break