123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181 |
- import inspect
- from random import random
- import cv2
- import numpy as np
- import pandas as pd
- from numba import jit
- np.set_printoptions(suppress=True) # 输出时禁止科学表示法,直接输出小数值
- column_all_c = ['面积', '周长', '重心x', '重心y', '似圆度', '灰度均值', '灰度方差', '灰度偏度',
- '灰度峰态', '小梯度优势', '大梯度优势', '灰度分布不均匀性', '梯度分布不均匀性', '能量', '灰度平均', '梯度平均',
- '灰度均方差', '梯度均方差', '相关', '灰度熵', '梯度熵', '混合熵', '惯性', '逆差矩']
- features_list = ['area', 'perimeter', 'focus_x', 'focus_y', 'ellipse', 'mean', 'std', 'piandu', 'fengdu',
- 'small_grads_dominance',
- 'big_grads_dominance', 'gray_asymmetry', 'grads_asymmetry', 'energy', 'gray_mean', 'grads_mean',
- 'gray_variance', 'grads_variance', 'corelation', 'gray_entropy', 'grads_entropy', 'entropy', 'inertia',
- 'differ_moment']
- # 获取变量的名
- def get_variable_name(variable):
- callers_local_vars = inspect.currentframe().f_back.f_locals.items()
- return [var_name for var_name, var_val in callers_local_vars if var_val is variable]
- def glcm(img_gray, ngrad=16, ngray=16):
- '''Gray Level-Gradient Co-occurrence Matrix,取归一化后的灰度值、梯度值分别为16、16'''
- # 利用sobel算子分别计算x-y方向上的梯度值
- gsx = cv2.Sobel(img_gray, cv2.CV_64F, 1, 0, ksize=3)
- gsy = cv2.Sobel(img_gray, cv2.CV_64F, 0, 1, ksize=3)
- height, width = img_gray.shape
- grad = (gsx ** 2 + gsy ** 2) ** 0.5 # 计算梯度值
- grad = np.asarray(1.0 * grad * (ngrad - 1) / grad.max(), dtype=np.int16)
- gray = np.asarray(1.0 * img_gray * (ngray - 1) / img_gray.max(), dtype=np.int16) # 0-255变换为0-15
- gray_grad = np.zeros([ngray, ngrad]) # 灰度梯度共生矩阵
- for i in range(height):
- for j in range(width):
- gray_value = gray[i][j]
- grad_value = grad[i][j]
- gray_grad[gray_value][grad_value] += 1
- gray_grad = 1.0 * gray_grad / (height * width) # 归一化灰度梯度矩阵,减少计算量
- get_glcm_features(gray_grad)
- @jit
- def get_gray_feature():
- # 灰度特征提取算法
- hist = cv2.calcHist([image_ROI_uint8[index]], [0], None, [256], [0, 256])
- # 假的 还没用灰度直方图
- c_features['mean'].append(np.mean(image_ROI[index]))
- c_features['std'].append(np.std(image_ROI[index]))
- s = pd.Series(image_ROI[index])
- c_features['piandu'].append(s.skew())
- c_features['fengdu'].append(s.kurt())
- def get_glcm_features(mat):
- '''根据灰度梯度共生矩阵计算纹理特征量,包括小梯度优势,大梯度优势,灰度分布不均匀性,梯度分布不均匀性,能量,灰度平均,梯度平均,
- 灰度方差,梯度方差,相关,灰度熵,梯度熵,混合熵,惯性,逆差矩'''
- sum_mat = mat.sum()
- small_grads_dominance = big_grads_dominance = gray_asymmetry = grads_asymmetry = energy = gray_mean = grads_mean = 0
- gray_variance = grads_variance = corelation = gray_entropy = grads_entropy = entropy = inertia = differ_moment = 0
- for i in range(mat.shape[0]):
- gray_variance_temp = 0
- for j in range(mat.shape[1]):
- small_grads_dominance += mat[i][j] / ((j + 1) ** 2)
- big_grads_dominance += mat[i][j] * j ** 2
- energy += mat[i][j] ** 2
- if mat[i].sum() != 0:
- gray_entropy -= mat[i][j] * np.log(mat[i].sum())
- if mat[:, j].sum() != 0:
- grads_entropy -= mat[i][j] * np.log(mat[:, j].sum())
- if mat[i][j] != 0:
- entropy -= mat[i][j] * np.log(mat[i][j])
- inertia += (i - j) ** 2 * np.log(mat[i][j])
- differ_moment += mat[i][j] / (1 + (i - j) ** 2)
- gray_variance_temp += mat[i][j] ** 0.5
- gray_asymmetry += mat[i].sum() ** 2
- gray_mean += i * mat[i].sum() ** 2
- gray_variance += (i - gray_mean) ** 2 * gray_variance_temp
- for j in range(mat.shape[1]):
- grads_variance_temp = 0
- for i in range(mat.shape[0]):
- grads_variance_temp += mat[i][j] ** 0.5
- grads_asymmetry += mat[:, j].sum() ** 2
- grads_mean += j * mat[:, j].sum() ** 2
- grads_variance += (j - grads_mean) ** 2 * grads_variance_temp
- small_grads_dominance /= sum_mat
- big_grads_dominance /= sum_mat
- gray_asymmetry /= sum_mat
- grads_asymmetry /= sum_mat
- gray_variance = gray_variance ** 0.5
- grads_variance = grads_variance ** 0.5
- for i in range(mat.shape[0]):
- for j in range(mat.shape[1]):
- corelation += (i - gray_mean) * (j - grads_mean) * mat[i][j]
- glgcm_features = [small_grads_dominance, big_grads_dominance, gray_asymmetry, grads_asymmetry, energy, gray_mean,
- grads_mean,
- gray_variance, grads_variance, corelation, gray_entropy, grads_entropy, entropy, inertia,
- differ_moment]
- for i in range(len(glgcm_features)):
- t = get_variable_name(glgcm_features[i])[0]
- c_features[t].append(np.round(glgcm_features[i], 4))
- def get_geometry_feature():
- # 形态特征 分割mask获得一些特征
- contours, x = cv2.findContours(mask_array.copy(), cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
- tarea = []
- tperimeter = []
- for c in contours:
- # 生成矩
- try:
- M = cv2.moments(c)
- cx = int(M['m10'] / M['m00'])
- cy = int(M['m01'] / M['m00'])
- c_features['focus_x'].append(cx)
- c_features['focus_y'].append(cy)
- except:
- print('error')
- # 椭圆拟合
- try:
- (x, y), (MA, ma), angle = cv2.fitEllipse(c)
- c_features['ellipse'].append((ma - MA))
- except:
- continue
- # 面积周长
- tarea.append(cv2.contourArea(c))
- tperimeter.append(cv2.arcLength(c, True))
- # 将mask里的最大值追加 有黑洞
- try:
- c_features['area'].append(max(tarea))
- c_features['perimeter'].append(round(max(tperimeter), 4))
- except:
- print('area error')
- # 提取肿瘤特征
- def get_feature(image, mask):
- global w
- global image_ROI_uint8, index, image_ROI_mini, image_ROI, mask_array
- mask_array = cv2.imread(mask, 0)
- image_arrary = cv2.imread(image)
- # 映射到CT获得特征
- image_ROI = np.zeros(shape=image_arrary.shape)
- index = np.nonzero(mask_array)
- if not index[0].any():
- # c_features['no'] = True
- return None
- image_ROI[index] = image_arrary[index]
- image_ROI_uint8 = np.uint8(image_ROI)
- # 获得只有肿瘤的图片
- x, y, w, h = cv2.boundingRect(mask_array)
- image_ROI_mini = np.uint8(image_arrary[y:y + h, x:x + w])
- w = image_ROI_mini
- # 灰度梯度共生矩阵提取纹理特征
- get_geometry_feature()
- # get_gray_feature()
- glcm(image_ROI_mini, 15, 15)
- return c_features
- def main(pid):
- global w
- person_id = pid
- global c_features
- c_features = {}
- for i in range(len(features_list)):
- c_features[features_list[i]] = [column_all_c[i], np.round(random(), 3)]
- return c_features
|