get_feature.py 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. import inspect
  2. from random import random
  3. import cv2
  4. import numpy as np
  5. import pandas as pd
  6. from numba import jit
  7. np.set_printoptions(suppress=True) # 输出时禁止科学表示法,直接输出小数值
  8. column_all_c = ['面积', '周长', '重心x', '重心y', '似圆度', '灰度均值', '灰度方差', '灰度偏度',
  9. '灰度峰态', '小梯度优势', '大梯度优势', '灰度分布不均匀性', '梯度分布不均匀性', '能量', '灰度平均', '梯度平均',
  10. '灰度均方差', '梯度均方差', '相关', '灰度熵', '梯度熵', '混合熵', '惯性', '逆差矩']
  11. features_list = ['area', 'perimeter', 'focus_x', 'focus_y', 'ellipse', 'mean', 'std', 'piandu', 'fengdu',
  12. 'small_grads_dominance',
  13. 'big_grads_dominance', 'gray_asymmetry', 'grads_asymmetry', 'energy', 'gray_mean', 'grads_mean',
  14. 'gray_variance', 'grads_variance', 'corelation', 'gray_entropy', 'grads_entropy', 'entropy', 'inertia',
  15. 'differ_moment']
  16. # 获取变量的名
  17. def get_variable_name(variable):
  18. callers_local_vars = inspect.currentframe().f_back.f_locals.items()
  19. return [var_name for var_name, var_val in callers_local_vars if var_val is variable]
  20. def glcm(img_gray, ngrad=16, ngray=16):
  21. '''Gray Level-Gradient Co-occurrence Matrix,取归一化后的灰度值、梯度值分别为16、16'''
  22. # 利用sobel算子分别计算x-y方向上的梯度值
  23. gsx = cv2.Sobel(img_gray, cv2.CV_64F, 1, 0, ksize=3)
  24. gsy = cv2.Sobel(img_gray, cv2.CV_64F, 0, 1, ksize=3)
  25. height, width = img_gray.shape
  26. grad = (gsx ** 2 + gsy ** 2) ** 0.5 # 计算梯度值
  27. grad = np.asarray(1.0 * grad * (ngrad - 1) / grad.max(), dtype=np.int16)
  28. gray = np.asarray(1.0 * img_gray * (ngray - 1) / img_gray.max(), dtype=np.int16) # 0-255变换为0-15
  29. gray_grad = np.zeros([ngray, ngrad]) # 灰度梯度共生矩阵
  30. for i in range(height):
  31. for j in range(width):
  32. gray_value = gray[i][j]
  33. grad_value = grad[i][j]
  34. gray_grad[gray_value][grad_value] += 1
  35. gray_grad = 1.0 * gray_grad / (height * width) # 归一化灰度梯度矩阵,减少计算量
  36. get_glcm_features(gray_grad)
  37. @jit
  38. def get_gray_feature():
  39. # 灰度特征提取算法
  40. hist = cv2.calcHist([image_ROI_uint8[index]], [0], None, [256], [0, 256])
  41. # 假的 还没用灰度直方图
  42. c_features['mean'].append(np.mean(image_ROI[index]))
  43. c_features['std'].append(np.std(image_ROI[index]))
  44. s = pd.Series(image_ROI[index])
  45. c_features['piandu'].append(s.skew())
  46. c_features['fengdu'].append(s.kurt())
  47. def get_glcm_features(mat):
  48. '''根据灰度梯度共生矩阵计算纹理特征量,包括小梯度优势,大梯度优势,灰度分布不均匀性,梯度分布不均匀性,能量,灰度平均,梯度平均,
  49. 灰度方差,梯度方差,相关,灰度熵,梯度熵,混合熵,惯性,逆差矩'''
  50. sum_mat = mat.sum()
  51. small_grads_dominance = big_grads_dominance = gray_asymmetry = grads_asymmetry = energy = gray_mean = grads_mean = 0
  52. gray_variance = grads_variance = corelation = gray_entropy = grads_entropy = entropy = inertia = differ_moment = 0
  53. for i in range(mat.shape[0]):
  54. gray_variance_temp = 0
  55. for j in range(mat.shape[1]):
  56. small_grads_dominance += mat[i][j] / ((j + 1) ** 2)
  57. big_grads_dominance += mat[i][j] * j ** 2
  58. energy += mat[i][j] ** 2
  59. if mat[i].sum() != 0:
  60. gray_entropy -= mat[i][j] * np.log(mat[i].sum())
  61. if mat[:, j].sum() != 0:
  62. grads_entropy -= mat[i][j] * np.log(mat[:, j].sum())
  63. if mat[i][j] != 0:
  64. entropy -= mat[i][j] * np.log(mat[i][j])
  65. inertia += (i - j) ** 2 * np.log(mat[i][j])
  66. differ_moment += mat[i][j] / (1 + (i - j) ** 2)
  67. gray_variance_temp += mat[i][j] ** 0.5
  68. gray_asymmetry += mat[i].sum() ** 2
  69. gray_mean += i * mat[i].sum() ** 2
  70. gray_variance += (i - gray_mean) ** 2 * gray_variance_temp
  71. for j in range(mat.shape[1]):
  72. grads_variance_temp = 0
  73. for i in range(mat.shape[0]):
  74. grads_variance_temp += mat[i][j] ** 0.5
  75. grads_asymmetry += mat[:, j].sum() ** 2
  76. grads_mean += j * mat[:, j].sum() ** 2
  77. grads_variance += (j - grads_mean) ** 2 * grads_variance_temp
  78. small_grads_dominance /= sum_mat
  79. big_grads_dominance /= sum_mat
  80. gray_asymmetry /= sum_mat
  81. grads_asymmetry /= sum_mat
  82. gray_variance = gray_variance ** 0.5
  83. grads_variance = grads_variance ** 0.5
  84. for i in range(mat.shape[0]):
  85. for j in range(mat.shape[1]):
  86. corelation += (i - gray_mean) * (j - grads_mean) * mat[i][j]
  87. glgcm_features = [small_grads_dominance, big_grads_dominance, gray_asymmetry, grads_asymmetry, energy, gray_mean,
  88. grads_mean,
  89. gray_variance, grads_variance, corelation, gray_entropy, grads_entropy, entropy, inertia,
  90. differ_moment]
  91. for i in range(len(glgcm_features)):
  92. t = get_variable_name(glgcm_features[i])[0]
  93. c_features[t].append(np.round(glgcm_features[i], 4))
  94. def get_geometry_feature():
  95. # 形态特征 分割mask获得一些特征
  96. contours, x = cv2.findContours(mask_array.copy(), cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
  97. tarea = []
  98. tperimeter = []
  99. for c in contours:
  100. # 生成矩
  101. try:
  102. M = cv2.moments(c)
  103. cx = int(M['m10'] / M['m00'])
  104. cy = int(M['m01'] / M['m00'])
  105. c_features['focus_x'].append(cx)
  106. c_features['focus_y'].append(cy)
  107. except:
  108. print('error')
  109. # 椭圆拟合
  110. try:
  111. (x, y), (MA, ma), angle = cv2.fitEllipse(c)
  112. c_features['ellipse'].append((ma - MA))
  113. except:
  114. continue
  115. # 面积周长
  116. tarea.append(cv2.contourArea(c))
  117. tperimeter.append(cv2.arcLength(c, True))
  118. # 将mask里的最大值追加 有黑洞
  119. try:
  120. c_features['area'].append(max(tarea))
  121. c_features['perimeter'].append(round(max(tperimeter), 4))
  122. except:
  123. print('area error')
  124. # 提取肿瘤特征
  125. def get_feature(image, mask):
  126. global w
  127. global image_ROI_uint8, index, image_ROI_mini, image_ROI, mask_array
  128. mask_array = cv2.imread(mask, 0)
  129. image_arrary = cv2.imread(image)
  130. # 映射到CT获得特征
  131. image_ROI = np.zeros(shape=image_arrary.shape)
  132. index = np.nonzero(mask_array)
  133. if not index[0].any():
  134. # c_features['no'] = True
  135. return None
  136. image_ROI[index] = image_arrary[index]
  137. image_ROI_uint8 = np.uint8(image_ROI)
  138. # 获得只有肿瘤的图片
  139. x, y, w, h = cv2.boundingRect(mask_array)
  140. image_ROI_mini = np.uint8(image_arrary[y:y + h, x:x + w])
  141. w = image_ROI_mini
  142. # 灰度梯度共生矩阵提取纹理特征
  143. get_geometry_feature()
  144. # get_gray_feature()
  145. glcm(image_ROI_mini, 15, 15)
  146. return c_features
  147. def main(pid):
  148. global w
  149. person_id = pid
  150. global c_features
  151. c_features = {}
  152. for i in range(len(features_list)):
  153. c_features[features_list[i]] = [column_all_c[i], np.round(random(), 3)]
  154. return c_features