import cv2 import matplotlib.pyplot as plt import numpy as np def _pad_to_square(image, long_side=None, border=0): h, w, _ = image.shape if long_side == None: long_side = max(h, w) l_pad = (long_side - w) // 2 + border r_pad = (long_side - w) // 2 + border t_pad = (long_side - h) // 2 + border b_pad = (long_side - h) // 2 + border if w % 2 != 0: r_pad = r_pad + 1 if h % 2 != 0: b_pad = b_pad + 1 image = np.pad( image, ((t_pad, b_pad), (l_pad, r_pad), (0, 0)), 'constant') return image def _get_retina_bb(image): # make image greyscale and normalise image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) image = cv2.normalize(image, None, 0, 255, cv2.NORM_MINMAX) # calculate threshold perform threshold threshold = np.mean(image)/3-7 ret, thresh = cv2.threshold(image, max(0, threshold), 255, cv2.THRESH_BINARY) # median filter, erode and dilate to remove noise and holes thresh = cv2.medianBlur(thresh, 25) thresh = cv2.erode(thresh, None, iterations=2) thresh = cv2.dilate(thresh, None, iterations=2) # find mask contour cnts = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) cnts = cnts[0] if len(cnts) == 2 else cnts[1] c = max(cnts, key=cv2.contourArea) # Get bounding box from mask contour x, y, w, h = cv2.boundingRect(c) # Get mask from contour mask = np.zeros_like(image) cv2.drawContours(mask, [c], -1, (255, 255, 255), -1) return x, y, w, h, mask def _get_retina_bb2(image, skips=4): ''' Experimental Retina Bounding Box detector based on Convexity Defect Points ''' # make image greyscale and normalise image = cv2.cvtColor(image, cv2.COLOR_RGB2GRAY) image = cv2.normalize(image, None, 0, 255, cv2.NORM_MINMAX) # calculate threshold perform threshold threshold = np.mean(image)/3-7 ret, thresh = cv2.threshold(image, max(0, threshold), 255, cv2.THRESH_BINARY) # median filter, erode and dilate to remove noise and holes thresh = cv2.medianBlur(thresh, 25) thresh = cv2.erode(thresh, None, iterations=2) thresh = cv2.dilate(thresh, None, iterations=2) # Find contours contours, hierarchy = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE) # Find the index of the largest contour areas = [cv2.contourArea(c) for c in contours] max_index = np.argmax(areas) cnt = contours[max_index] # Get convexity defect points hull = cv2.convexHull(cnt, returnPoints=False) hull[::-1].sort(axis=0) defects = cv2.convexityDefects(cnt, hull) ConvexityDefectPoint = [] for i in range(0, defects.shape[0], skips): s, e, f, d = defects[i, 0] ConvexityDefectPoint.append(tuple(cnt[f][0])) # Get minimum enclosing circle as retina estimate (x, y), radius = cv2.minEnclosingCircle(np.array(ConvexityDefectPoint)) # Get mask from contour mask = np.zeros_like(image) cv2.circle(mask, (x, y), radius, (255, 255, 255), -1) # return (x, y, w, h) bounding box return int(x - radius), int(y - radius), int(2 * radius - 1), int(2 * radius - 1), mask def rgb_clahe(image, clipLimit=2.0, tileGridSize=(16, 16)): lab = cv2.cvtColor(image, cv2.COLOR_RGB2LAB) clahe = cv2.createCLAHE(clipLimit=clipLimit, tileGridSize=tileGridSize) lab[..., 0] = clahe.apply(lab[..., 0]) return cv2.cvtColor(lab, cv2.COLOR_LAB2RGB) if __name__ == '__main__': # image_file = '/vol/biomedic3/bh1511/retina/IDRID/segmentation/0_Original_Images/IDRiD_65.jpg' # image_file = '/vol/biomedic3/bh1511/retina/CHASE_DB1/images/Image_08R.jpg' # image_file = '/vol/vipdata/data/retina/kaggle-diabetic-retinopathy-detection/train/16_right.jpeg' # image_file = '/vol/vipdata/data/retina/IDRID/a_segmentation/images/train/IDRiD_01.jpg' image_file = 'preprocessing/Image_10L.png' # Load Image image = cv2.imread(image_file) image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB) plt.imshow(image); plt.show() # Localise and center retina image x, y, w, h, _ = _get_retina_bb(image) image = image[y:y + h, x:x + w, :] image = _pad_to_square(image, border=0) image = cv2.resize(image, (1024, 1024)) # Apply CLAHE pre-processing image = rgb_clahe(image) # Display or save image plt.imshow(image); plt.show() # cv2.imwrite('processed_image.png', image)