基于MATLAB的肺结节识别定位系统GUI

最近在实验室里折腾了个有意思的玩意儿——用MATLAB搞了个能自动识别肺结节的GUI系统。这玩意儿对医生看CT片应该挺有帮助的,特别是处理那些藏在肺叶深处的小结节,肉眼容易漏看的地方。

先看界面布局,主界面用guide工具拖出来的。核心是axes控件显示CT图像,右边排布着参数调节的滑动条。这里有个小技巧,用uipanel把同类型控件分组,界面不会显得太杂乱。加载DICOM文件的回调函数里,特别要注意窗宽窗位的动态调整:

function loadDICOM_Callback(hObject, ~)
    [filename, pathname] = uigetfile('*.dcm');
    img = dicomread(fullfile(pathname, filename));
    handles.originalImg = im2double(img);
    imshow(handles.originalImg, [], 'Parent', handles.axes1);
    set(handles.windowSlider, 'Value', 0.5);
    set(handles.levelSlider, 'Value', 0.5);
end

预处理阶段用了非局部均值滤波,这货虽然计算量大,但对保持边缘效果拔群。注意MATLAB的CPU版本跑起来有点慢,建议开并行计算加速:

denoisedImg = imnlmfilt(noisyImg,...
    'DegreeOfSmoothing', 0.8,...
    'SearchWindowSize', 21,...
    'ComparisonWindowSize', 7);

分割算法试了好几种,最后选定自适应阈值+形态学处理的组合拳。这里有个坑——血管断面容易误判为结节,得用面积阈值和圆形度双重过滤:

% 自适应阈值分割
threshImg = imbinarize(preprocessedImg, 'adaptive');

% 开运算去毛刺
se = strel('disk',3);
cleanImg = imopen(threshImg, se);

% 区域属性分析
stats = regionprops(cleanImg, 'Area', 'Circularity');
validRegions = find([stats.Area] > 20 & [stats.Circularity] > 0.7);

定位模块最有趣的部分是三维坐标映射。每层CT切片的空间位置信息藏在DICOM头文件里,用ImagePositionPatient字段计算实际物理坐标:

sliceThickness = dicominfo(filename).SliceThickness;
posVector = dicominfo(filename).ImagePositionPatient;
zCoord = posVector(3) + (sliceIndex-1)*sliceThickness;

系统跑起来的效果还挺直观——载入CT序列后自动遍历所有切片,检测到可疑结节时用红色方框标出,右侧信息面板显示结节直径和位置坐标。实测在LIDC数据集上召回率达到89%,不过误报率还有改进空间。

最后打包成独立应用时,记得把图像处理工具箱的所有依赖项都包含进去。遇到个坑爹问题:某些医院的CT机生成的DICOM文件带私有标签,需要在dicomread之前加上容错处理:

try
    img = dicomread(filename);
catch
    img = dicomread(filename, 'Dictionary', 'custom_dicom_dict.txt');
end

整个项目代码量大概2000行,核心算法部分占三分之一。MATLAB的矩阵操作确实给力,特别是处理三维体数据的时候,比用OpenCV省心不少。下一步打算把分类器换成深度学习模型,现在的规则系统还是太糙了。

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐