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

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

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