Matlab肺结节分割(肺结节提取)源程序,也有GUI人机界面版本。使用传统图像分割方法,非深度学习方法。使用LIDC-IDRI数据集。
工作如下:
1、读取图像。读取原始dicom格式的CT图像,并显示,绘制灰度直方图;
2、图像增强。对图像进行图像增强,包括Gamma矫正、直方图均衡化、中值滤波、边缘锐化;
3、肺质分割。基于阈值分割,从原CT图像中分割出肺质;
4、肺结节分割。肺质分割后,进行特征提取,计算灰度特征、形态学特征来分割出肺结节;
5、可视化标注文件。读取医生的xml标注文件,可视化出医生的标注结果;
6、计算IOU、DICE、PRE三个参数评价分割效果好坏。
7、做成GUI人机界面。
注:需要2022b及以上版本。因为参数是根据这两张图片设置的,所以只可分割压缩包里这两张图像,替换成其他的图像效果不好。
基于MATLAB的传统图像分割方法实现肺结节分割的完整项目,包括读取DICOM图像、图像增强、肺质分割、肺结节分割、可视化标注文件以及计算评价指标。此外,还包括一个GUI人机界面版本。
项目结构
深色版本
PulmonaryNoduleSegmentation/
├── data/
│ ├── LIDC-IDRI-0001/
│ │ ├── 1.3.6.1.4.1.14519.5.2.1.6279.6001.298806137288633453246975630178.dcm
│ │ └── 1.3.6.1.4.1.14519.5.2.1.6279.6001.298806137288633453246975630179.dcm
│ └── LIDC-IDRI-0002/
│ ├── 1.3.6.1.4.1.14519.5.2.1.6279.6001.490157381160200744294022685271.dcm
│ └── 1.3.6.1.4.1.14519.5.2.1.6279.6001.490157381160200744294022685272.dcm
├── labels/
│ ├── LIDC-IDRI-0001.xml
│ └── LIDC-IDRI-0002.xml
├── src/
│ ├── main.m
│ ├── gui/
│ │ ├── PulmonaryNoduleSegmentation.fig
│ │ └── PulmonaryNoduleSegmentation.m
│ ├── image_processing/
│ │ ├── read_dicom.m
│ │ ├── enhance_image.m
│ │ ├── segment_lung.m
│ │ ├── segment_nodule.m
│ │ ├── visualize_annotations.m
│ │ └── evaluate_segmentation.m
│ └── utils/
│ ├── read_xml.m
│ └── calculate_metrics.m
└── README.md
-
读取图像
src/image_processing/read_dicom.m
matlab
深色版本
function [img, info] = read_dicom(file_path)
% 读取DICOM图像
info = dicominfo(file_path);
img = dicomread(info);
end -
图像增强
src/image_processing/enhance_image.m
matlab
深色版本
function img_enhanced = enhance_image(img)
% Gamma矫正
gamma = 1.5;
img_gamma = imadjust(img, [], [], gamma);% 直方图均衡化
img_histeq = histeq(img_gamma);% 中值滤波
img_median = medfilt2(img_histeq, [3 3]);% 边缘锐化
img_sharpen = imsharpen(img_median, ‘Amount’, 1.5);img_enhanced = img_sharpen;
end -
肺质分割
src/image_processing/segment_lung.m
matlab
深色版本
function lung_mask = segment_lung(img)
% 阈值分割
threshold = graythresh(img);
lung_mask = imbinarize(img, threshold);% 形态学操作
se = strel(‘disk’, 5);
lung_mask = imopen(lung_mask, se);
lung_mask = imfill(lung_mask, ‘holes’);
end -
肺结节分割
src/image_processing/segment_nodule.m
matlab
深色版本
function nodule_mask = segment_nodule(img, lung_mask)
% 使用肺质掩膜
img_lung = img .* uint8(lung_mask);% 计算灰度特征
threshold = graythresh(img_lung);
nodule_mask = imbinarize(img_lung, threshold);% 形态学操作
se = strel(‘disk’, 3);
nodule_mask = imopen(nodule_mask, se);
nodule_mask = imfill(nodule_mask, ‘holes’);
end -
可视化标注文件
src/image_processing/visualize_annotations.m
matlab
深色版本
function visualize_annotations(img, file_path)
% 读取XML标注文件
annotations = read_xml(file_path);% 可视化标注
figure;
imshow(img, []);
hold on;
for i = 1:length(annotations)
annotation = annotations(i);
rectangle(‘Position’, annotation, ‘EdgeColor’, ‘r’, ‘LineWidth’, 2);
end
hold off;
end -
计算评价指标
src/utils/calculate_metrics.m
matlab
深色版本
function [iou, dice, precision] = calculate_metrics(gt_mask, pred_mask)
% 计算交并比(IoU)
intersection = sum(sum(gt_mask & pred_mask));
union = sum(sum(gt_mask | pred_mask));
iou = intersection / union;% 计算Dice系数
dice = 2 * intersection / (sum(sum(gt_mask)) + sum(sum(pred_mask)));% 计算精确率(Precision)
true_positives = sum(sum(gt_mask & pred_mask));
false_positives = sum(sum(~gt_mask & pred_mask));
precision = true_positives / (true_positives + false_positives);
end -
GUI人机界面
src/gui/PulmonaryNoduleSegmentation.fig
使用MATLAB的GUIDE工具创建一个简单的GUI界面,包含按钮和图像显示区域。
src/gui/PulmonaryNoduleSegmentation.m
matlab
深色版本
function varargout = PulmonaryNoduleSegmentation(varargin)
% PulmonaryNoduleSegmentation MATLAB code for PulmonaryNoduleSegmentation.fig
% PULMONARYNODULESEGMENTATION, by itself, creates a new PULMONARYNODULESEGMENTATION or raises the existing
% singleton*.
%
% H = PULMONARYNODULESEGMENTATION returns the handle to a new PULMONARYNODULESEGMENTATION or the handle to
% the existing singleton*.
%
% PULMONARYNODULESEGMENTATION(‘CALLBACK’,hObject,eventData,handles,…) calls the local
% function named CALLBACK in PULMONARYNODULESEGMENTATION.M with the given input arguments.
%
% PULMONARYNODULESEGMENTATION(‘Property’,‘Value’,…) creates a new PULMONARYNODULESEGMENTATION or raises the
% existing singleton*. Starting from the left, property value pairs are
% applied to the GUI before PulmonaryNoduleSegmentation_OpeningFcn gets called. An
% unrecognized property name or invalid value makes property application
% stop. All inputs are passed to PulmonaryNoduleSegmentation_OpeningFcn via varargin.
%
% *See GUI Options on GUIDE’s Tools menu. Choose “GUI allows only one
% instance to run (singleton)”.
%
% See also: GUIDE, GUIDATA, GUIHANDLES
% Edit the above text to modify the response to help PulmonaryNoduleSegmentation
% Last Modified by GUIDE v2.5 04-Nov-2023 12:00:00
% Begin initialization code - DO NOT EDIT
gui_Singleton = 1;
gui_State = struct('gui_Name', mfilename, ...
'gui_Singleton', gui_Singleton, ...
'gui_OpeningFcn', @PulmonaryNoduleSegmentation_OpeningFcn, ...
'gui_OutputFcn', @PulmonaryNoduleSegmentation_OutputFcn, ...
'gui_LayoutFcn', [] , ...
'gui_Callback', []);
if nargin && ischar(varargin{1})
gui_State.gui_Callback = str2func(varargin{1});
end
if nargout
[varargout{1:nargout}] = gui_mainfcn(gui_State, varargin{:});
else
gui_mainfcn(gui_State, varargin{:});
end
% End initialization code - DO NOT EDIT
% — Executes just before PulmonaryNoduleSegmentation is made visible.
function PulmonaryNoduleSegmentation_OpeningFcn(hObject, eventdata, handles, varargin)
% This function has no output args, see OutputFcn.
% hObject handle to figure
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
% varargin command line arguments to PulmonaryNoduleSegmentation (see VARARGIN)
% Choose default command line output for PulmonaryNoduleSegmentation
handles.output = hObject;
% Update handles structure
guidata(hObject, handles);
% UIWAIT makes PulmonaryNoduleSegmentation wait for user response (see UIRESUME)
% uiwait(handles.figure1);
% — Outputs from this function are returned to the command line.
function varargout = PulmonaryNoduleSegmentation_OutputFcn(hObject, eventdata, handles)
% varargout cell array for returning output args (see VARARGOUT);
% hObject handle to figure
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
% Get default command line output from handles structure
varargout{1} = handles.output;
% — Executes on button press in pushbutton1.
function pushbutton1_Callback(hObject, eventdata, handles)
% hObject handle to pushbutton1 (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
% 读取图像
[file_path, path] = uigetfile({'*.dcm'}, 'Select DICOM Image');
if isequal(file_path, 0)
return;
end
full_file_path = fullfile(path, file_path);
[img, info] = read_dicom(full_file_path);
axes(handles.axes1);
imshow(img, []);
title('Original Image');
% 绘制灰度直方图
figure;
imhist(img);
title('Gray Level Histogram');
% 图像增强
img_enhanced = enhance_image(img);
axes(handles.axes2);
imshow(img_enhanced, []);
title('Enhanced Image');
% 肺质分割
lung_mask = segment_lung(img_enhanced);
axes(handles.axes3);
imshow(lung_mask, []);
title('Lung Segmentation');
% 肺结节分割
nodule_mask = segment_nodule(img_enhanced, lung_mask);
axes(handles.axes4);
imshow(nodule_mask, []);
title('Nodule Segmentation');
% 可视化标注文件
[xml_file_path, xml_path] = uigetfile({'*.xml'}, 'Select XML Annotation File');
if isequal(xml_file_path, 0)
return;
end
full_xml_file_path = fullfile(xml_path, xml_file_path);
visualize_annotations(img, full_xml_file_path);
% 计算评价指标
gt_mask = read_xml(full_xml_file_path);
[iou, dice, precision] = calculate_metrics(gt_mask, nodule_mask);
set(handles.text1, 'String', sprintf('IoU: %.2f', iou));
set(handles.text2, 'String', sprintf('Dice: %.2f', dice));
set(handles.text3, 'String', sprintf('Precision: %.2f', precision));
- 主程序
src/main.m
matlab
深色版本
% 主程序
addpath(‘src/image_processing’);
addpath(‘src/utils’);
addpath(‘src/gui’);
% 打开GUI
PulmonaryNoduleSegmentation;
9. 读取XML标注文件
src/utils/read_xml.m
matlab
深色版本
function annotations = read_xml(file_path)
% 读取XML标注文件
doc = xmlread(file_path);
root = doc.getDocumentElement;
roi_list = root.getElementsByTagName(‘ROI’);
annotations = {};
for i = 0:roi_list.getLength-1
roi = roi_list.item(i);
x = str2double(roi.getAttribute('x'));
y = str2double(roi.getAttribute('y'));
width = str2double(roi.getAttribute('width'));
height = str2double(roi.getAttribute('height'));
annotations{end+1} = [x, y, width, height];
end
end
10. 运行项目
将数据文件(如LIDC-IDRI-0001和LIDC-IDRI-0002的DICOM图像和XML标注文件)放入data和labels目录。
运行main.m:
bash
深色版本
cd path/to/PulmonaryNoduleSegmentation
matlab -nodesktop -nosplash -r “run(‘src/main.m’)”
11. 代码说明
读取图像:read_dicom.m负责读取DICOM图像并显示,同时绘制灰度直方图。
图像增强:enhance_image.m对图像进行Gamma矫正、直方图均衡化、中值滤波和边缘锐化。
肺质分割:segment_lung.m基于阈值分割从原CT图像中分割出肺质。
肺结节分割:segment_nodule.m在肺质分割后,进行特征提取,计算灰度特征和形态学特征来分割出肺结节。
可视化标注文件:visualize_annotations.m读取医生的XML标注文件并可视化出医生的标注结果。
计算评价指标:calculate_metrics.m计算交并比(IoU)、Dice系数和精确率(Precision)。
GUI人机界面:PulmonaryNoduleSegmentation.fig和PulmonaryNoduleSegmentation.m提供了一个用户友好的界面,方便用户进行图像处理和结果显示。
12. 注意事项
数据集:项目中使用的参数是根据特定的两张图像设置的,因此只适用于压缩包中的这两张图像。替换成其他图像可能效果不佳。
MATLAB版本:需要MATLAB 2022b及以上版本。
希望这些代码和说明能帮助你完成肺结节分割项目,并成功实现功能。