1. 项目缘起:为什么胃部影像分类值得一做?
大家好,我是老张,在AI和医疗影像这个圈子里摸爬滚打了十来年。今天想和大家聊聊一个非常实际的项目:用卷积神经网络(CNN)给胃镜影像做疾病分类。你可能觉得这听起来挺高大上,但其实背后的逻辑很简单——就是教电脑“看”胃镜图片,然后判断是正常、胃癌、胃溃疡、胃糜烂还是胃息肉。
我为什么选这个方向?因为胃部疾病太常见了,而胃镜检查是金标准。但问题来了,一个经验丰富的医生每天要看海量的影像,疲劳在所难免,而且不同医生之间的诊断也可能存在主观差异。如果能有一个稳定、高效的AI助手,先做一遍初步筛查,把可疑的病例高亮出来,那不仅能减轻医生负担,更能提高早期病变的发现率,这可是能救命的事儿。
这个项目特别适合想入门AI医疗的开发者,或者相关专业的学生。你不需要是医学专家,但需要对图像处理和深度学习有基本热情。整个流程从数据准备、模型搭建、训练调优到最终评估,我会手把手带你走一遍,过程中踩过的坑、总结的经验,都会毫无保留地分享出来。咱们的目标不是发论文,而是做出一个在临床场景下真正能用、好用的原型系统。
2. 环境与数据:万事开头,稳字当先
2.1 搭建你的AI工作台
工欲善其事,必先利其器。我强烈建议你使用 Anaconda 来管理Python环境,它能完美解决包依赖的“地狱”问题。咱们这个项目基于 Python 3.8,框架选用 TensorFlow 2.x 和 Keras,它们的组合对新手非常友好,API清晰,社区资源也丰富。
# 创建一个新的conda环境
conda create -n stomach_cnn python=3.8
conda activate stomach_cnn
# 安装核心依赖
pip install tensorflow==2.10.0
pip install opencv-python pillow matplotlib scikit-learn pandas
编辑器方面,VS Code 是首选,装上Python插件后,调试、代码提示都非常方便。如果你习惯用 PyCharm 也行,看个人喜好。关键是要有一个能舒服写代码、看日志的环境。
2.2 搞定数据集:质量决定天花板
数据是模型的“粮食”。我们假设你有一个包含五类胃部影像的数据集,结构大概是这样:
stomach_dataset/
├── train/
│ ├── cancer_0/
│ ├── gastric_ulcer_1/
│ ├── gastric_erosion_2/
│ ├── gastric_polyps_3/
│ └── normal_4/
└── val/ (或者 test/)
├── cancer_0/
...
注意:原始数据往往不完美。比如我手头这个数据集,很多图片左侧带有文字描述(可能是患者信息或设备参数)。这些文字对于模型来说是纯粹的噪声,会严重干扰它学习真正的病理特征。
一开始我偷懒了,想用图像变换(比如错切)来“规避”文字区域,但实测下来效果很差。后来我明白了,对于这种位置固定、内容无关的噪声,最直接有效的方法就是裁剪掉。虽然会损失一小部分图像区域,但换来了特征纯净度的极大提升。
import cv2
from PIL import Image
def crop_text_region(image_path, save_path, crop_x=100):
"""
裁剪掉图片左侧可能存在的文字区域。
crop_x: 从左侧开始裁剪的像素宽度,需要根据你的数据集调整。
"""
img = cv2.imread(image_path)
height, width = img.shape[:2]
# 裁剪掉左侧 crop_x 像素
cropped_img = img[:, crop_x:width]
cv2.imwrite(save_path, cropped_img)
return cropped_img
另一个关键是数据量。深度学习是“数据饥渴”型技术。如果每类只有几十张图片,模型很难学到泛化能力。理想情况下,每类训练集能有500-2000张,验证集和测试集各有100-200张,这样训练出来的模型才比较可靠。如果数据不足,一定要善用数据增强。
3. 数据预处理:让模型“吃”得更舒服
原始图片不能直接扔给模型。预处理的目的,一是消除无关变量(如亮度、尺寸),二是增加数据多样性,提升模型鲁棒性。我用的是 ImageDataGenerator,这是Keras里非常强大的工具。
from tensorflow.keras.preprocessing.image import ImageDataGenerator
# 训练数据增强:要激进一些
train_datagen = ImageDataGenerator(
rescale=1./255, # 归一化到[0,1],加速收敛
rotation_range=20, # 随机旋转20度
width_shift_range=0.1, # 水平随机平移10%
he

374

被折叠的 条评论
为什么被折叠?



