You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

271 lines
9.2 KiB

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