镜像自地址
https://github.com/xming521/CTAI.git
已同步 2025-12-06 14:46:48 +00:00
upload flask
这个提交包含在:
107
CTAI_flask/app.py
普通文件
107
CTAI_flask/app.py
普通文件
@@ -0,0 +1,107 @@
|
|||||||
|
import datetime
|
||||||
|
import logging as rel_log
|
||||||
|
import os
|
||||||
|
import shutil
|
||||||
|
from datetime import timedelta
|
||||||
|
|
||||||
|
import torch
|
||||||
|
from flask import *
|
||||||
|
|
||||||
|
import core.main
|
||||||
|
import core.net.unet as net
|
||||||
|
|
||||||
|
UPLOAD_FOLDER = r'./uploads'
|
||||||
|
|
||||||
|
ALLOWED_EXTENSIONS = set(['dcm'])
|
||||||
|
app = Flask(__name__)
|
||||||
|
app.secret_key = 'secret!'
|
||||||
|
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
|
||||||
|
|
||||||
|
werkzeug_logger = rel_log.getLogger('werkzeug')
|
||||||
|
werkzeug_logger.setLevel(rel_log.ERROR)
|
||||||
|
|
||||||
|
# 解决缓存刷新问题
|
||||||
|
app.config['SEND_FILE_MAX_AGE_DEFAULT'] = timedelta(seconds=1)
|
||||||
|
|
||||||
|
|
||||||
|
# 添加header解决跨域
|
||||||
|
@app.after_request
|
||||||
|
def after_request(response):
|
||||||
|
response.headers['Access-Control-Allow-Origin'] = '*'
|
||||||
|
response.headers['Access-Control-Allow-Credentials'] = 'true'
|
||||||
|
response.headers['Access-Control-Allow-Methods'] = 'POST'
|
||||||
|
response.headers['Access-Control-Allow-Headers'] = 'Content-Type, X-Requested-With'
|
||||||
|
return response
|
||||||
|
|
||||||
|
|
||||||
|
def allowed_file(filename):
|
||||||
|
return '.' in filename and filename.rsplit('.', 1)[1] in ALLOWED_EXTENSIONS
|
||||||
|
|
||||||
|
|
||||||
|
@app.route('/')
|
||||||
|
def hello_world():
|
||||||
|
return redirect(url_for('static', filename='./index.html'))
|
||||||
|
|
||||||
|
|
||||||
|
@app.route('/upload', methods=['GET', 'POST'])
|
||||||
|
def upload_file():
|
||||||
|
file = request.files['file']
|
||||||
|
print(datetime.datetime.now(), file.filename)
|
||||||
|
if file and allowed_file(file.filename):
|
||||||
|
src_path = os.path.join(app.config['UPLOAD_FOLDER'], file.filename)
|
||||||
|
file.save(src_path)
|
||||||
|
shutil.copy(src_path, './tmp/ct')
|
||||||
|
image_path = os.path.join('./tmp/ct', file.filename)
|
||||||
|
# print(image_path)
|
||||||
|
pid, image_info = core.main.c_main(image_path, current_app.model)
|
||||||
|
# return jsonify({'status': 1,
|
||||||
|
# 'image_url': 'http://127.0.0.1:5003/tmp/image/' + pid,
|
||||||
|
# 'draw_url': 'http://127.0.0.1:5003/tmp/draw/' + pid,
|
||||||
|
# 'image_info': image_info
|
||||||
|
# })
|
||||||
|
|
||||||
|
return jsonify({'status': 1,
|
||||||
|
'image_url': 'http://58.87.66.50:5003/tmp/image/' + pid,
|
||||||
|
'draw_url': 'http://58.87.66.50:5003/tmp/draw/' + pid,
|
||||||
|
'image_info': image_info
|
||||||
|
})
|
||||||
|
return jsonify({'status': 0})
|
||||||
|
|
||||||
|
|
||||||
|
@app.route("/download", methods=['GET'])
|
||||||
|
def download_file():
|
||||||
|
# 需要知道2个参数, 第1个参数是本地目录的path, 第2个参数是文件名(带扩展名)
|
||||||
|
return send_from_directory('data', 'testfile.zip', as_attachment=True)
|
||||||
|
|
||||||
|
|
||||||
|
# show photo
|
||||||
|
@app.route('/tmp/<path:file>', methods=['GET'])
|
||||||
|
def show_photo(file):
|
||||||
|
# print(file)
|
||||||
|
if request.method == 'GET':
|
||||||
|
if file is None:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
image_data = open(f'tmp/{file}', "rb").read()
|
||||||
|
response = make_response(image_data)
|
||||||
|
response.headers['Content-Type'] = 'image/png'
|
||||||
|
return response
|
||||||
|
else:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
def init_model():
|
||||||
|
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
|
||||||
|
model = net.Unet(1, 1).to(device)
|
||||||
|
if torch.cuda.is_available():
|
||||||
|
model.load_state_dict(torch.load("./core/net/model.pth"))
|
||||||
|
else:
|
||||||
|
model.load_state_dict(torch.load("./core/net/model.pth", map_location='cpu'))
|
||||||
|
model.eval()
|
||||||
|
return model
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
with app.app_context():
|
||||||
|
current_app.model = init_model()
|
||||||
|
app.run(host='127.0.0.1', port=5003, debug=True)
|
||||||
200
CTAI_flask/core/get_feature.py
普通文件
200
CTAI_flask/core/get_feature.py
普通文件
@@ -0,0 +1,200 @@
|
|||||||
|
import inspect
|
||||||
|
|
||||||
|
import SimpleITK as sitk
|
||||||
|
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获得一些特征
|
||||||
|
im2, 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 = sitk.ReadImage(image)
|
||||||
|
image_arrary = sitk.GetArrayFromImage(image)[0, :, :]
|
||||||
|
# 映射到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]]
|
||||||
|
|
||||||
|
get_feature(f'tmp/ct/{pid}.dcm', f'tmp/mask/{pid}_mask.png')
|
||||||
|
|
||||||
|
for j in c_features:
|
||||||
|
if j == 'id':
|
||||||
|
continue
|
||||||
|
c_features[j][1] = np.round(np.mean(c_features[j][1]), 4)
|
||||||
|
|
||||||
|
return c_features
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
||||||
15
CTAI_flask/core/main.py
普通文件
15
CTAI_flask/core/main.py
普通文件
@@ -0,0 +1,15 @@
|
|||||||
|
from core import process, predict, get_feature
|
||||||
|
|
||||||
|
|
||||||
|
def c_main(path,model):
|
||||||
|
image_data = process.pre_process(path)
|
||||||
|
# print(image_data)
|
||||||
|
predict.predict(image_data,model)
|
||||||
|
process.last_process(image_data[1])
|
||||||
|
image_info = get_feature.main(image_data[1])
|
||||||
|
|
||||||
|
return image_data[1] + '.png', image_info
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
pass
|
||||||
68
CTAI_flask/core/net/unet.py
普通文件
68
CTAI_flask/core/net/unet.py
普通文件
@@ -0,0 +1,68 @@
|
|||||||
|
import torch.nn as nn
|
||||||
|
import torch
|
||||||
|
from torch import autograd
|
||||||
|
|
||||||
|
class DoubleConv(nn.Module):
|
||||||
|
def __init__(self, in_ch, out_ch):
|
||||||
|
super(DoubleConv, self).__init__()
|
||||||
|
self.conv = nn.Sequential(
|
||||||
|
nn.Conv2d(in_ch, out_ch, 3, padding=1),
|
||||||
|
nn.BatchNorm2d(out_ch),
|
||||||
|
nn.ReLU(inplace=True),
|
||||||
|
nn.Conv2d(out_ch, out_ch, 3, padding=1),
|
||||||
|
nn.BatchNorm2d(out_ch),
|
||||||
|
nn.ReLU(inplace=True)
|
||||||
|
)
|
||||||
|
|
||||||
|
def forward(self, input):
|
||||||
|
return self.conv(input)
|
||||||
|
|
||||||
|
|
||||||
|
class Unet(nn.Module):
|
||||||
|
def __init__(self,in_ch,out_ch):
|
||||||
|
super(Unet, self).__init__()
|
||||||
|
|
||||||
|
self.conv1 = DoubleConv(in_ch, 64)
|
||||||
|
self.pool1 = nn.MaxPool2d(2)
|
||||||
|
self.conv2 = DoubleConv(64, 128)
|
||||||
|
self.pool2 = nn.MaxPool2d(2)
|
||||||
|
self.conv3 = DoubleConv(128, 256)
|
||||||
|
self.pool3 = nn.MaxPool2d(2)
|
||||||
|
self.conv4 = DoubleConv(256, 512)
|
||||||
|
self.pool4 = nn.MaxPool2d(2)
|
||||||
|
self.conv5 = DoubleConv(512, 1024)
|
||||||
|
self.up6 = nn.ConvTranspose2d(1024, 512, 2, stride=2)
|
||||||
|
self.conv6 = DoubleConv(1024, 512)
|
||||||
|
self.up7 = nn.ConvTranspose2d(512, 256, 2, stride=2)
|
||||||
|
self.conv7 = DoubleConv(512, 256)
|
||||||
|
self.up8 = nn.ConvTranspose2d(256, 128, 2, stride=2)
|
||||||
|
self.conv8 = DoubleConv(256, 128)
|
||||||
|
self.up9 = nn.ConvTranspose2d(128, 64, 2, stride=2)
|
||||||
|
self.conv9 = DoubleConv(128, 64)
|
||||||
|
self.conv10 = nn.Conv2d(64,out_ch, 1)
|
||||||
|
|
||||||
|
def forward(self,x):
|
||||||
|
c1=self.conv1(x)
|
||||||
|
p1=self.pool1(c1)
|
||||||
|
c2=self.conv2(p1)
|
||||||
|
p2=self.pool2(c2)
|
||||||
|
c3=self.conv3(p2)
|
||||||
|
p3=self.pool3(c3)
|
||||||
|
c4=self.conv4(p3)
|
||||||
|
p4=self.pool4(c4)
|
||||||
|
c5=self.conv5(p4)
|
||||||
|
up_6= self.up6(c5)
|
||||||
|
merge6 = torch.cat([up_6, c4], dim=1)
|
||||||
|
c6=self.conv6(merge6)
|
||||||
|
up_7=self.up7(c6)
|
||||||
|
merge7 = torch.cat([up_7, c3], dim=1)
|
||||||
|
c7=self.conv7(merge7)
|
||||||
|
up_8=self.up8(c7)
|
||||||
|
merge8 = torch.cat([up_8, c2], dim=1)
|
||||||
|
c8=self.conv8(merge8)
|
||||||
|
up_9=self.up9(c8)
|
||||||
|
merge9=torch.cat([up_9,c1],dim=1)
|
||||||
|
c9=self.conv9(merge9)
|
||||||
|
c10=self.conv10(c9)
|
||||||
|
out = nn.Sigmoid()(c10)
|
||||||
|
return out
|
||||||
39
CTAI_flask/core/predict.py
普通文件
39
CTAI_flask/core/predict.py
普通文件
@@ -0,0 +1,39 @@
|
|||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import cv2
|
||||||
|
import torch
|
||||||
|
import core.net.unet as net
|
||||||
|
import numpy as np
|
||||||
|
|
||||||
|
os.environ["CUDA_VISIBLE_DEVICES"] = "0"
|
||||||
|
torch.set_num_threads(4)
|
||||||
|
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
|
||||||
|
torch.cuda.empty_cache()
|
||||||
|
|
||||||
|
import os
|
||||||
|
|
||||||
|
rate = 0.5
|
||||||
|
|
||||||
|
|
||||||
|
def predict(dataset,model):
|
||||||
|
|
||||||
|
# unet = torch.load('./core/0.5unet.pkl').to(device)
|
||||||
|
# torch.save(unet.state_dict(), "model_new.pth")
|
||||||
|
|
||||||
|
global res, img_y, mask_arrary
|
||||||
|
with torch.no_grad():
|
||||||
|
x = dataset[0][0].to(device)
|
||||||
|
file_name = dataset[1]
|
||||||
|
y = model(x)
|
||||||
|
img_y = torch.squeeze(y).cpu().numpy()
|
||||||
|
img_y[img_y >= rate] = 1
|
||||||
|
img_y[img_y < rate] = 0
|
||||||
|
img_y = img_y * 255
|
||||||
|
cv2.imwrite(f'./tmp/mask/{file_name}_mask.png', img_y,
|
||||||
|
(cv2.IMWRITE_PNG_COMPRESSION, 0))
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
# 写保存模型
|
||||||
|
# train()
|
||||||
|
predict()
|
||||||
50
CTAI_flask/core/process.py
普通文件
50
CTAI_flask/core/process.py
普通文件
@@ -0,0 +1,50 @@
|
|||||||
|
import os
|
||||||
|
|
||||||
|
import SimpleITK as sitk
|
||||||
|
import cv2
|
||||||
|
import numpy as np
|
||||||
|
import torch
|
||||||
|
|
||||||
|
|
||||||
|
def data_in_one(inputdata):
|
||||||
|
if not inputdata.any():
|
||||||
|
return inputdata
|
||||||
|
inputdata = (inputdata - inputdata.min()) / (inputdata.max() - inputdata.min())
|
||||||
|
return inputdata
|
||||||
|
|
||||||
|
|
||||||
|
def pre_process(data_path):
|
||||||
|
global test_image, test_mask
|
||||||
|
image_list, mask_list, image_data, mask_data = [], [], [], []
|
||||||
|
|
||||||
|
image = sitk.ReadImage(data_path)
|
||||||
|
image_array = sitk.GetArrayFromImage(image)
|
||||||
|
|
||||||
|
ROI_mask = np.zeros(shape=image_array.shape)
|
||||||
|
ROI_mask_mini = np.zeros(shape=(1, 160, 100))
|
||||||
|
ROI_mask_mini[0] = image_array[0][270:430, 200:300]
|
||||||
|
ROI_mask_mini = data_in_one(ROI_mask_mini)
|
||||||
|
ROI_mask[0][270:430, 200:300] = ROI_mask_mini[0]
|
||||||
|
test_image = ROI_mask
|
||||||
|
image_tensor = torch.from_numpy(ROI_mask).float().unsqueeze(1)
|
||||||
|
# print(image_tensor.shape)
|
||||||
|
image_data.append(image_tensor)
|
||||||
|
file_name = os.path.split(data_path)[1].replace('.dcm', '')
|
||||||
|
|
||||||
|
# 转为图片写入image文件夹
|
||||||
|
|
||||||
|
image_array = image_array.swapaxes(0, 2)
|
||||||
|
image_array = np.rot90(image_array, -1)
|
||||||
|
image_array = np.fliplr(image_array).squeeze()
|
||||||
|
# ret, image_array = cv2.threshold(image_array, 150, 255, cv2.THRESH_BINARY)
|
||||||
|
cv2.imwrite(f'./tmp/image/{file_name}.png', image_array, (cv2.IMWRITE_PNG_COMPRESSION, 0))
|
||||||
|
|
||||||
|
return image_data, file_name
|
||||||
|
|
||||||
|
|
||||||
|
def last_process(file_name):
|
||||||
|
image = cv2.imread(f'./tmp/image/{file_name}.png')
|
||||||
|
mask = cv2.imread(f'./tmp/mask/{file_name}_mask.png', 0)
|
||||||
|
thresh, contours, hierarchy = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
|
||||||
|
draw = cv2.drawContours(image, contours, -1, (0, 255, 0), 2)
|
||||||
|
cv2.imwrite(f'./tmp/draw/{file_name}.png', draw)
|
||||||
二进制
CTAI_flask/data/testfile.zip
普通文件
二进制
CTAI_flask/data/testfile.zip
普通文件
二进制文件未显示。
6
CTAI_flask/requirements.txt
普通文件
6
CTAI_flask/requirements.txt
普通文件
@@ -0,0 +1,6 @@
|
|||||||
|
pandas==0.23.4
|
||||||
|
Flask==1.1.1
|
||||||
|
numpy==1.15.0
|
||||||
|
SimpleITK==1.2.2
|
||||||
|
numba==0.45.1
|
||||||
|
torch==1.2.0
|
||||||
17
CTAI_flask/static/index.html
普通文件
17
CTAI_flask/static/index.html
普通文件
@@ -0,0 +1,17 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<title>Title</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
|
||||||
|
<form action="/upload" method=post enctype=multipart/form-data>
|
||||||
|
<p><input type=file name=file>
|
||||||
|
<input type=submit value=Upload>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<a href="/download">下载</a>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
在新工单中引用
屏蔽一个用户