paulxiong / cervical Goto Github PK
View Code? Open in Web Editor NEWDoing something useful
Doing something useful
二、使用整个病列进行细胞团检测,对特别的几种fov背景进行说明。
1、切片做的相对模糊的情况,如下图,整个病列对细胞团的检测都不好,可能原因是和训练样本有光系,制作的训练样本是多个批次里面少部分细胞核明显的细胞团。
下图是该批次中检测出细胞团的fov,只有细胞核明显的细胞团被检测到。
2、下面为另外一个病列的检测情况,两个模型的检测结果都较好。和上面病列的细胞核明显不同,细胞核明显。
下图为检测不完全的情况,只检测到了部分的细胞团。
3、第三种情况为核浆比比较大的阴性细胞团,检测结果较搓可能也和训练样本有光,训练样本中没有阴性细胞团,标记的阴性细胞团过少,只有十多个,因此没有加入到训练样本中。
结论:由检测结果,faster-rcnn的检测效果相对好,漏检比较多,但是很少出现检测错误,而且检测正确的细胞团部分都是核浆明显的细胞团。
分析了下Unet 细胞分割后生成的图像,大多数情况下分割正常,可以成功识别出细胞核并切割出来,但在有些批次的图片进行切割时,发现了不少把细胞质当成细胞核给分割出来,使用这些只包含细胞质无细胞核的细胞图,会导致分类器判别失败,分类器只会识别包含细胞核的细胞。下图用红线标示的就是切割错误的细胞图,没有包含细胞核。之前测试已经充分说明,改用unet的切割后比原始nugan 切割的性能要提高很多。现在想要再提高nugan分类的性能,得先提高unet的切割质量。
为了解决这个问题,有两个技术方案可以解决。
一,增加一个单独的分类器,专门负责判定unet 切割后的图片是否是正常的细胞核,如果判定是异常的切割图,则会丢弃掉,训练集为切割正常与不正常细胞核分割图。
二,增加人工标注后的细胞分割mask图,然后结合kaggle dsb 训练集,重新训练unet 模型,让unet 直接分割正确。
这两个方案的训练集都需要人工标注整理下,第一种标注稍简单点,只要判定是不是切割正常。第二种有点麻烦,需要把细胞核的轮廓线给圈画出来后再转换成mask true 图。
第一种方案稍简单点,先做第一种方案的切割正确分类器,目前分类器代码已基本完成,在开始做第一种方案的训练集整理工作,
训练集只包含两类数据,切割正常的包含细胞核的图,切割不正常只包含了细胞质,没有包含细胞核的图。
看到martin 还有张俊在做医生标注图片的图像处理器fiji +OMERO, 正好可以把它用于正常与非正常切割的图片训练集整理工作上来,相关的这些软件使用文档介绍说明一下。
$ cd yourdir/
$ git clone https://github.com/paulxiong/cervical
$ cd cervical
$ git checkout origin/add_final_medical_cervix -b add_final_medical_cervix
$ cd final_medical_cervix
$ rm -rf datasets/classify/*
$ git checkout ./datasets
$ rm -rf datasets/origin_test/negative_test_images/
$ mkdir ./src/SEGMENT/kaggle-dsb2018/src/all_output
$ sudo cp /opt/yunhai/final_medical_cervix/datasets/segment/stage1_train datasets/segment/stage1_train -a
$ sudo chmod 777 datasets/segment/stage1_train/ -R
$ sudo mkdir ./src/SEGMENT/kaggle-dsb2018/src/all_output/models_colour
$ sudo cp /opt/yunhai/final_medical_cervix/src/SEGMENT/kaggle-dsb2018/src/all_output/models_colour/single--2018-12-22-02-17-32.h5 ./src/SEGMENT/kaggle-dsb2018/src/all_output/models_colour/
$ sudo chmod a+rw ./src/SEGMENT/kaggle-dsb2018/src/all_output/models_colour -R
datasets/origin_test/negative_test_images/放入negitive图片, 然后执行下面脚本
$ ./run_slide_negitive_test.sh all
$ rm yourdir/yourdir/cervical/experiment/data/segmented/negative_test_npy/160/*
$ cp datasets/classify/npy/* yourdir/cervical/experiment/data/segmented/negative_test_npy/160/
$ rm -rf datasets/classify/*
$ cp /opt/yunhai/final_medical_cervix/datasets/segment/test datasets/segment/ -a
datasets/origin_test/positive_test_images/放入positive图片, 然后执行下面脚本
$ ./run_slide_positive_test.sh all
$ rm -rf yourdir/cervical/experiment/data/segmented/positive_test_npy/160/*
$ cp datasets/classify/npy/* yourdir/cervical/experiment/data/segmented/positive_test_npy/160/ -a
2.随机将同一类的细胞分为两类,将2019-05-23和FJ妇幼的细胞共分成14类进行训练GAN,在Test1和Test2中,结果还是不行,正常都预测为异常FOV。
目前同正常异常FOV同批次的无法分辨,没有太好的解决思路,可能数据上有瑕疵(来自异常Slide的正常FOV可能不准确),继续跟踪
(2)、下图为游散细胞较多,细胞浆背景和细胞核染色都均匀的检测结果。
(3)、下图为背景干扰比较大的fov图片,算法把许多不是细胞核的粒子检测成了细胞核。
(4)、下图为参杂细胞图的fov检测结果。细胞团干扰比较大的位置无法准确检测出细胞核的位置。
(5)、下面两张图为细胞背景干扰大,参杂细胞团的fov检测结果。
(6)、使用不同的尺寸的fov生成的对比图片如下,随机选了两张背景不同的fov图;其中红色框为原图片尺寸检测到的细胞情况,绿色框为缩小一半尺寸后细胞的检测情况。
(7)、下面两张图为灰度化后和彩色图像的检测结果,灰度化后去除了颜色带来的干扰,检测效果更加好;彩色图片检测细胞核时,算法把部分染色为红色的细胞浆检测成了细胞核。
1、进入网站 https://chart-studio.plot.ly/feed/#/,可以登录也可以直接使用。
2、选择数据分析的方式,包括各种图表和散点图。
3、选择需要的分析方式,点击编辑。
4、进入数据分析页面。
5、点击左上角导入数据。
指定一个目录,该目录下有若干图片;
根据上述目录产生N倍的FAKE图片;
要点:N倍对应到每张图片。
目前与医生讨论后,确定label与细胞分类的对应关系
1: 'Norm',
2: 'LSIL',#鳞状上皮细胞低度病变
3: 'HSIL',#鳞状上皮细胞高度病变
4: 'HPV', #HPV感染
5: 'NILM',#未见上皮内病变
6: 'SCC', #鳞状上皮细胞癌
7: 'ASCUS', #不典型鳞状细胞低
8: 'ASCH', #不典型鳞状细胞高
9: 'AGC', #不典型腺细胞
10:'AIS', #颈管原位腺癌
11:'ADC', #腺癌
12:'T', #滴虫
13:'M', #霉菌
14:'HSV'#疱疹
图1:医生诊断标准一
图2:医生诊断标准二
参考图一与图二,其中可诊断为宫颈细胞病变主要为两类:
1.鳞状上皮细胞病变: ASCUS, ASC-H, LSIL(HPV),HSIL,SCC
2.腺细胞病变:AGC, AIS, ADC
而未见异常宫颈细胞的诊断:
1.生物性病原体:T,M,HSV
2.其它正常细胞:Norm, NILM
我们当前主要专注于宫颈细胞病变的检测,主要针对第一类病变诊断。
链接:https://pan.baidu.com/s/1ktcTzUXE3NH9QYTL3rUHjw
提取码:ad6s
阴性细胞团
├── glandular 3824
└── squamous-pm-two 4015
阳性细胞团
├── glandular-adcae 51
├── squamous-asc-h 3091
├── squamous-asc-us 2717
通过使用前端GUI,从用户角度给出以下关于医疗GUI界面的建议:
(标注页面)
Bug——Critical
1.(2019-11-11)UC、猎豹、搜狗浏览器不能标注、IE不显示页面
2.(2019-11-11)保存之后点击刷新按钮(或者点击“上一张”、下一张之后切换回来),删除的框一部分再次出现——已验证
3.(2019-11-11)“类型下拉框”选择没有响应——已验证
Bug——High
4.(2019-11-11)页面刷新之后需要从新选择数据集
建议
1.需要添加上传文件功能(压缩包或者文件类型)
2.未选择数据集之前隐藏“上一张”“下一张”按钮
3.不同细胞类型颜色也不同
4.当点击“下一张”到列表最后一张图片提示已到最后一张(“上一张”同理)
5.“请选择数据集”下拉框内的字体颜色醒目一些
$ docker run -d --name='autokeras' -v "$(pwd)":/app python:3.6.8-slim-jessie sleep 100h
$ docker exec -it -e LINES=$(tput lines) -e COLUMNS=$(tput cols) autokeras /bin/bash
docker里面执行
# apt-get update
# apt-get install vim git wget -y
# pip install autokeras==0.4.0 -i https://pypi.tuna.tsinghua.edu.cn/simple --no-cache-dir
# pip install keras==2.2.4 -i https://pypi.tuna.tsinghua.edu.cn/simple --no-cache-dir
docker里面执行
# curl https://raw.githubusercontent.com/keras-team/autokeras/master/examples/a_simple_example/mnist.py --output mnist.py
# python3.6 mnist.py
Using TensorFlow backend.
Better speed can be achieved with apex installed from https://www.github.com/nvidia/apex.
Downloading data from https://s3.amazonaws.com/img-datasets/mnist.npz
11493376/11490434 [==============================] - 118s 10us/step
Saving Directory: /tmp/autokeras_ZYZ97D
Preprocessing the images.
Preprocessing finished.
Initializing search.
Initialization finished.
+----------------------------------------------+
| Training model 0 |
+----------------------------------------------+
Epoch-15, Current Metric - 0.978: 30%|██████▉ | 140/465 [00:27<01:08, 4.76 batch/s]
import PIL.Image as Image
file1 = 'my_data_batch'
def unpickle(file):
import pickle
with open(file, 'rb') as fo:
dict = pickle.load(fo, encoding='iso-8859-1')
return dict
dict_train_batch1 = unpickle(file1)
data_train_batch1 = dict_train_batch1.get('data')
labels = dict_train_batch1.get('labels')
img1 = dict_train_batch1['data'][10]
a = img1.reshape(3, 32, 32)
# 得到RGB通道
r = Image.fromarray(a[0]).convert('L')
g = Image.fromarray(a[1]).convert('L')
b = Image.fromarray(a[2]).convert('L')
image = Image.merge("RGB", (r, g, b))
# 显示图片
image.save("lambda.png", 'png')
input/
├── 1
│ ├── 0227_17P0603_1904202B_IMG027x003.JPG_1143_1929.png.png
│ ├── ...
│ └── 0464_17P0603_1904188B_IMG005x017.JPG_1167_177.png.png
└── 7
├── 0192_20190523_1812302_IMG004x019.JPG_1302_194.png.png
├── ...
└── 0291_17P0603_1904852_IMG020x006.JPG_2096_704.png.png
from PIL import Image
import numpy as np
import os, pickle
def img21Dnumpy(imgpath):
img = Image.open(imgpath,"r")
w, h = img.size[0], img.size[1]
if w != h:
print("w!=h, skip !")
return None
img = img.resize((32, 32), Image.BILINEAR)
r, g, b = img.split()
r1, g1, b1 = np.asarray(r), np.asarray(g), np.asarray(b)
r2, g2, b2 = r1.flatten(), g1.flatten(), b1.flatten()
data = np.concatenate((r2, g2, b2))
return data
def get_train_test(inputdir):
x_train = None
y_train = []
imgpathlists = []
labels = os.listdir(inputdir)
for label in labels:
path1 = os.path.join(inputdir, label)
for imgname in os.listdir(path1):
imgpath = os.path.join(path1, imgname)
imgnpy = img21Dnumpy(imgpath)
if imgnpy is None:
continue
y_train.append(imgname)
imgpathlists.append(imgname)
if x_train is None:
x_train = np.array([img21Dnumpy(imgpath)])
else:
x_train = np.concatenate((x_train, [img21Dnumpy(imgpath)]))
return x_train, y_train, imgpathlists
#生成data_batch文件
def make_data_batch(x, y, filenames):
dic = {}
dic['batch_label'] = "training batch 1 of 5"
dic['labels'] = y
dic['data'] = x
dic['filenames'] = filenames
#print(dic)
with open('my_data_batch', 'wb') as f:
pickle.dump(dic, f)
x, y, filenames = get_train_test("input")
make_data_batch(x, y, filenames)
http://2j592d3300.wicp.vip:8711/terminals/1
f774dcf5115d4004679015e9236344a4b430fe46da3ba449
# cd /notebooks/lambda/Faster-RCNN_TF/
测试
python demo.py --model model/VGGnet_fast_rcnn_iter_70000.ckpt
训练
DEV=GPU
DEV_ID=0
TRAIN_IMDB="voc_2007_trainval"
TEST_IMDB="voc_2007_test"
PT_DIR="pascal_voc"
ITERS=70000
EXTRA_ARGS=""
python ./tools/train_net.py --device ${DEV} --device_id ${DEV_ID} \
--weights data/pretrain_model/VGG_imagenet.npy \
--imdb ${TRAIN_IMDB} \
--iters ${ITERS} \
--cfg experiments/cfgs/faster_rcnn_end2end.yml \
--network VGGnet_train \
${EXTRA_ARGS}
root@a5a5ba0db669:
USER | URL | token | ENV | GPU | TS |
---|---|---|---|---|---|
yin_htk | medical.raidcdn.cn:8001/terminals/1 | b75fa88ce5f9fef9bd0bc0e589b2e40c3035c2409344b0ee | tensorflow:1.13.2-gpu | gpu2 | 2020-01-14 |
Segment_Paul | medical.raidcdn.cn:8899/terminals/1 | 8fd07e2208f1fc686b590d902726378c0f831dceee284943 | tensorflow:1.13.2-gpu | gpu? | 2020-01-14 |
VAE | medical.raidcdn.cn:8888/terminals/1 | 991377cba44531759a60de195c2a78219d542bb56a280057 | tensorflow:1.13.2-gpu | gpu? | 2020-01-14 |
Segment_yin | medical.raidcdn.cn:8890/terminals/1 | db16d2fd3e4568aff561eb5a0bebbb92f167257d7fa69f68 | tensorflow:1.13.2-gpu | gpu2 | 2020-01-14 |
fixmatch_hou | medical.raidcdn.cn:8892/terminals/1 | 5f1e0d3f9a82e8dff602865a61b6223b20cf2f5256023a04 | tensorflow:1.13.2-gpu | gpu2 | 2020-01-14 |
hou | medical.raidcdn.cn:8896/terminals/1 | 2a21b16ab9d7524c1529f28299724c739e81d8ede2668388 | tensorflow:1.13.2-gpu | gpu2 | 2020-01-14 |
yin_mala | medical.raidcdn.cn:8897/terminals/1 | 39ddc5340c0a8476f66d4733617e371fd72acefa70daeb3c | tensorflow:1.13.2-gpu | gpu0 | 2020-01-14 |
先创建:logs_r/record.txt,每次运行时请清空文件内容
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Mon Oct 28 16:34:02 2019
@author: yfq
"""
from keras import Sequential, initializers, optimizers
from keras.layers import Activation, Dense
import numpy as np
import pylab as pl
from IPython import display
from keras.callbacks import Callback
from keras.datasets import mnist
import keras
from keras.layers import Conv2D, MaxPooling2D
from keras.layers import Dense, Dropout, Flatten
#定义回调函数
class DrawCallback(Callback):
#初始化
def __init__(self, runtime_plot=True):
self.init_loss = None
self.init_val_loss = None
self.init_acc = None
self.init_val_acc = None
self.runtime_plot = runtime_plot
self.xdata = []
self.ydata = []
self.ydata2 = []
self.ydata3 = []
self.ydata4 = []
#画图
def _plot(self, epoch=None):
epochs = self.params.get("epochs")
pl.subplot(121)
pl.ylim(0, int(self.init_loss*1.2))
pl.xlim(0, epochs)
pl.plot(self.xdata, self.ydata,'r', label='loss')
pl.plot(self.xdata, self.ydata2, 'b--', label='val_loss')
pl.xlabel('Epoch {}/{}'.format(epoch or epochs, epochs))
pl.ylabel('Loss {:.4f}'.format(self.ydata[-1]))
pl.legend()
pl.title('loss')
pl.subplot(122)
pl.ylim(0, 1.2)
pl.xlim(0, epochs)
pl.plot(self.xdata, self.ydata3,'r', label='acc')
pl.plot(self.xdata, self.ydata4, 'b--', label='val_acc')
pl.xlabel('Epoch {}/{}'.format(epoch or epochs, epochs))
pl.ylabel('Loss {:.4f}'.format(self.ydata[-1]))
pl.legend()
pl.title('acc')
#清屏
def _runtime_plot(self, epoch):
self._plot(epoch)
display.clear_output(wait=True)
display.display(pl.gcf())
pl.gcf().clear()
#显示窗口
def plot(self):
self._plot()
pl.show()
#获取keras训练参数
def on_epoch_end(self, epoch, logs = None):
logs = logs or {}
epochs = self.params.get("epochs")
loss = logs.get("loss")
val_loss = logs.get("val_loss")
acc = logs.get("acc")
val_acc = logs.get("val_acc")
#转为字符型,限制数据有效长度
epochs_str = str(epochs)[0:6]
loss_str = str(loss)[0:6]
val_loss_str = str(val_loss)[0:6]
acc_str = str(acc)[0:6]
val_acc_str = str(val_acc)[0:6]
#数据写入txt
f = open('logs_r/record.txt','a')
f.write('epochs:{}-loss:{}-val_loss:{}-acc:{}-val_acc{}'.format(epochs_str,loss_str,val_loss_str,acc_str,val_acc_str))
f.write('\n')
f.close()
#更新xdata/ydata
if self.init_loss is None:
self.init_loss = loss
self.init_val_loss = val_loss
self.xdata.append(epoch)
self.ydata.append(loss)
self.ydata2.append(val_loss)
self.ydata3.append(acc)
self.ydata4.append(val_acc)
if self.runtime_plot:
self._runtime_plot(epoch)
#搭建keras需要的东西
def viz_keras_fit(runtime_plot=False):
d = DrawCallback(runtime_plot = runtime_plot)#实例化回调函数
#获取训练/测试数据
(x_train, y_train), (x_test, y_test) = mnist.load_data()
x_train = x_train.reshape(-1,28,28,1)
x_test = x_test.reshape(-1,28,28,1)
input_shape = (28,28,1)
x_train = x_train/255
x_test = x_test/255
y_train = keras.utils.to_categorical(y_train,10)
y_test = keras.utils.to_categorical(y_test,10)
#较少计算量
x_train = x_train[0:600,:,:,:]
x_test = x_test[0:100,:,:,:]
y_train = y_train[0:600,:]
y_test = y_test[0:100,:]
#定义网络
model = Sequential()
model.add(Conv2D(filters=32, kernel_size=(3,3),
activation='relu', input_shape=input_shape,
name='conv1'))
model.add(Conv2D(64,(3,3),activation='relu',name='conv2'))
model.add(MaxPooling2D(pool_size=(2,2),name='pool2'))
model.add(Dropout(0.25,name='dropout1'))
model.add(Flatten(name='flat1'))
model.add(Dense(128,activation='relu'))
model.add(Dropout(0.5,name='dropout2'))
model.add(Dense(10,activation='softmax',name='output'))
#编译网络
model.compile(loss=keras.losses.categorical_crossentropy,
optimizer=keras.optimizers.Adadelta(),
metrics=['accuracy'])
#训练模型
model.fit(x = x_train,
y = y_train,
epochs=100,
verbose=0,
validation_data=(x_test, y_test),
callbacks=[d]) # verbose=1可显示训练过程,validation_data加入测试数据,否则有些参数不显示,callbacks指定回调函数
return d
viz_keras_fit(runtime_plot=True)
$ ls /opt/lambda_workspace/datasets/ -l
total 4
drwxrwxr-x 4 atec atec 24 Jun 6 15:30 0606
-rw-rw-r-- 1 atec atec 982 Jun 11 15:35 README.md
$ ls /opt/zhuoyao_workspace/medical_ai/datasets/origin_train/
$ ls /opt/zhuoyao_workspace/medical_ai/datasets/origin_annotation/
下面是文件夹的描述
文件夹 | 数据集描述 |
---|---|
a | Margin 切割出来的,没做其他处理 |
a2 | 在a的基础上删除Norm, 原始数据医生只标注了阴性,阳性没标注所以认为阳性数据不准确 |
a3 | 在a2的基础上删除认为不清晰的,留下认为清晰的 |
a4 | 被删除的,认为是不清晰的 |
b | Mask 切割出来的,没做其他处理 |
b2 | 在b的基础上删除Norm, 原始数据医生只标注了阴性,阳性没标注所以认为阳性数据不准确 |
b3 | 在b2的基础上删除认为不清晰的,留下认为清晰的 |
b4 | 被删除的,认为是不清晰的 |
创建如下目录结构的目录,把对应的图片拷贝到名字对应的目录,执行generate_npy.py就生成了npy
train_datasets/
├── HPV
├── HSIL
├── LSIL
├── Norm
└── SCC
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.