from __future__ import print_function from multiprocessing.pool import ThreadPool import cv2 import numpy as np import matplotlib.pyplot as plt import pylab as pl from PyQt5.QtWidgets import QFileDialog def showImg(imgName, img, wsize=(400, 400)): cv2.namedWindow(imgName, cv2.WINDOW_NORMAL) cv2.resizeWindow(imgName, wsize[0], wsize[1]) cv2.imshow(imgName, img) def homofilter(I): I = np.double(I) m, n = I.shape rL = 0.5 rH = 2 c = 2 d0 = 20 I1 = np.log(I + 1) FI = np.fft.fft2(I1) n1 = np.floor(m / 2) n2 = np.floor(n / 2) D = np.zeros((m, n)) H = np.zeros((m, n)) for i in range(m): for j in range(n): D[i, j] = ((i - n1) ** 2 + (j - n2) ** 2) H[i, j] = (rH - rL) * (np.exp(c * (-D[i, j] / (d0 ** 2)))) + rL I2 = np.fft.ifft2(H * FI) I3 = np.real(np.exp(I2) - 1) I4 = I3 - np.min(I3) I4 = I4 / np.max(I4) * 255 dstImg = np.uint8(I4) return dstImg def gaborfilter(srcImg): dstImg = np.zeros(srcImg.shape[0:2]) filters = [] ksize = [5, 7, 9, 11, 13] j = 0 for K in range(len(ksize)): for i in range(12): theta = i * np.pi / 12 + np.pi / 24 gaborkernel = cv2.getGaborKernel((ksize[K], ksize[K]), sigma=2 * np.pi, theta=theta, lambd=np.pi / 2, gamma=0.5) gaborkernel /= 1.5 * gaborkernel.sum() filters.append(gaborkernel) for kernel in filters: gaborImg = cv2.filter2D(srcImg, cv2.CV_8U, kernel) np.maximum(dstImg, gaborImg, dstImg) return np.uint8(dstImg) def process(img, filters): accum = np.zeros_like(img) for kern in filters: fimg = cv2.filter2D(img, cv2.CV_8U, kern, borderType=cv2.BORDER_REPLICATE) np.maximum(accum, fimg, accum) return accum def process_threaded(img, filters, threadn=8): accum = np.zeros_like(img) def f(kern): return cv2.filter2D(img, cv2.CV_8U, kern) pool = ThreadPool(processes=threadn) for fimg in pool.imap_unordered(f, filters): np.maximum(accum, fimg, accum) return accum ### Gabor特征提取 def getGabor(img, filters): res = [] # 滤波结果 for i in range(len(filters)): res1 = process(img, filters[i]) res.append(np.asarray(res1)) pl.figure(2) for temp in range(len(res)): pl.subplot(4, 6, temp + 1) pl.imshow(res[temp], cmap='gray') pl.show() return res # 返回滤波结果,结果为24幅图,按照gabor角度排列 def build_filters(): filters = [] ksize = 31 for theta in np.arange(0, np.pi, np.pi / 16): # kern = cv2.getGaborKernel((ksize, ksize), 4.0, theta, 10.0, 0.5, 0, ktype=cv2.CV_32F) kern = cv2.getGaborKernel((ksize, ksize), 2 * np.pi, theta, 17.0, 0.5, 0, ktype=cv2.CV_32F) kern /= 1.5 * kern.sum() filters.append(kern) return filters def print_gabor(filters): for i in range(len(filters)): showImg(str(i), filters[i]) def reverse_image(img): antiImg = np.zeros_like(img, dtype=np.uint8) for i in range(img.shape[0]): for j in range(img.shape[1]): antiImg[i][j] = 255 - img[i][j] return antiImg def pass_mask(mask, img): # qwe = reverse_image(img) qwe = img.copy() for i in range(mask.shape[0]): for j in range(mask.shape[1]): if mask[i][j] == 0: qwe[i][j] = 0 # asd = cv2.filter2D(qwe, cv2.CV_8U, mask) return qwe def showKern(filters): for i in list(range(16)): kern = filters[i] kern = kern - np.min(kern) kern = kern / np.max(kern) * 255 kern = np.clip(kern, 0, 255) kern = np.uint8(kern) plt.suptitle('Gabor matched filter kernel') plt.subplot(4,4,i+1), plt.imshow(kern, 'gray'), plt.axis('off'), plt.title('theta=' + str(i) + r'/pi') plt.show() def calcDice(predict_img, groundtruth_img): predict = predict_img.copy() groundtruth = groundtruth_img.copy() predict[predict < 128] = 0 predict[predict >= 128] = 1 groundtruth[groundtruth < 128] = 0 groundtruth[groundtruth >= 128] = 1 predict_n = 1 - predict groundtruth_n = 1 - groundtruth TP = np.sum(predict * groundtruth) FP = np.sum(predict * groundtruth_n) TN = np.sum(predict_n * groundtruth_n) FN = np.sum(predict_n * groundtruth) # print(TP, FP, TN, FN) dice = 2 * np.sum(predict * groundtruth) / (np.sum(predict) + np.sum(groundtruth)) return dice def adjust_gamma(imgs, gamma=1.0): # assert (len(imgs.shape)==4) #4D arrays # assert (imgs.shape[1]==1) #check the channel is 1 # build a lookup table mapping the pixel values [0, 255] to # their adjusted gamma values invGamma = 1.0 / gamma table = np.array([((i / 255.0) ** invGamma) * 255 for i in np.arange(0, 256)]).astype("uint8") # apply gamma correction using the lookup table new_imgs = np.zeros_like(imgs) for i in range(imgs.shape[0]): for j in range(imgs.shape[1]): new_imgs[i, j] = cv2.LUT(np.array(imgs[i, j], dtype=np.uint8), table) return new_imgs def build_filters2(sigma=1, YLength=10): filters = [] widthOfTheKernel = np.ceil(np.sqrt((6 * np.ceil(sigma) + 1) ** 2 + YLength ** 2)) if np.mod(widthOfTheKernel, 2) == 0: widthOfTheKernel = widthOfTheKernel + 1 widthOfTheKernel = int(widthOfTheKernel) # print(widthOfTheKernel) for theta in np.arange(0, np.pi, np.pi / 16): # theta = np.pi/4 matchFilterKernel = np.zeros((widthOfTheKernel, widthOfTheKernel), dtype=np.float64) for x in range(widthOfTheKernel): for y in range(widthOfTheKernel): halfLength = (widthOfTheKernel - 1) / 2 x_ = (x - halfLength) * np.cos(theta) + (y - halfLength) * np.sin(theta) y_ = -(x - halfLength) * np.sin(theta) + (y - halfLength) * np.cos(theta) if abs(x_) > 3 * np.ceil(sigma): matchFilterKernel[x][y] = 0 elif abs(y_) > (YLength - 1) / 2: matchFilterKernel[x][y] = 0 else: matchFilterKernel[x][y] = -np.exp(-.5 * (x_ / sigma) ** 2) / (np.sqrt(2 * np.pi) * sigma) m = 0.0 for i in range(matchFilterKernel.shape[0]): for j in range(matchFilterKernel.shape[1]): if matchFilterKernel[i][j] < 0: m = m + 1 mean = np.sum(matchFilterKernel) / m for i in range(matchFilterKernel.shape[0]): for j in range(matchFilterKernel.shape[1]): if matchFilterKernel[i][j] < 0: matchFilterKernel[i][j] = matchFilterKernel[i][j] - mean filters.append(matchFilterKernel) return filters def Z_ScoreNormalization(x, mu, sigma): x = (x - mu) / sigma return x def sigmoid(X): return 1.0 / (1 + np.exp(-float(X))) def Normalize(data): k = np.zeros(data.shape, np.float64) # k = np.zeros_like(data) # m = np.average(data) mx = np.max(data) mn = np.min(data) for i in range(data.shape[0]): for j in range(data.shape[1]): k[i][j] = (float(data[i][j]) - mn) / (mx - mn) * 255 qwe = np.array(k, np.uint8) return qwe def grayStretch(img, m=60.0/255, e=8.0): k = np.zeros(img.shape, np.float64) ans = np.zeros(img.shape, np.float64) mx = np.max(img) mn = np.min(img) for i in range(img.shape[0]): for j in range(img.shape[1]): k[i][j] = (float(img[i][j]) - mn) / (mx - mn) eps = 0.01 for i in range(img.shape[0]): for j in range(img.shape[1]): ans[i][j] = 1 / (1 + (m / (k[i][j] + eps)) ** e) * 255 ans = np.array(ans, np.uint8) return ans def vessel_division(image): # 原图 srcImg = image.copy() # 标定图 grayImg = cv2.split(srcImg)[1] # 提取掩膜 ret0, th0 = cv2.threshold(grayImg, 30, 255, cv2.THRESH_BINARY) mask = cv2.erode(th0, np.ones((7, 7), np.uint8)) # showImg("mask", mask) # 高斯滤波 blurImg = cv2.GaussianBlur(grayImg, (5, 5), 0) # cv2.imwrite("blurImg.png", blurImg) # HE heImg = cv2.equalizeHist(blurImg) # cv2.imwrite("heImg.png", heImg) # CLAHE 光均衡化+对比度增强 clahe = cv2.createCLAHE(clipLimit=2, tileGridSize=(10, 10)) claheImg = clahe.apply(blurImg) # cv2.imwrite("claheImg.png", claheImg) # 同态滤波 光均衡化 homoImg = homofilter(blurImg) preMFImg = adjust_gamma(claheImg, gamma=1.5) filters = build_filters2() # showKern(filters) gaussMFImg = process(preMFImg, filters) gaussMFImg_mask = pass_mask(mask, gaussMFImg) grayStretchImg = grayStretch(gaussMFImg_mask, m=30.0 / 255, e=8) # 二值化 ret1, th1 = cv2.threshold(grayStretchImg, 30, 255, cv2.THRESH_OTSU) predictImg = th1.copy() return predictImg