В этом примере показано, как создать помеченное блокированное изображение, состоящее из категориальных меток.
Существует несколько способов задать категориальные данные о метке для изображения. Этот пример показывает два подхода. Один подход использует многоугольные объекты ROI, которые хранят координаты контуров опухоли и нормальной ткани. Другой подход использует маску, чтобы указать на бинарную сегментацию изображения в ткань и фон. Пример комбинирует информацию в координатах многоугольника и представлениях маски, чтобы создать одно помеченное блокированное изображение.
Создайте блокированное изображение с помощью модифицированной версии изображения от набора данных CAMELYON16, учебного изображения лимфатического узла, содержащего ткань опухоли. Модифицированное изображение имеет три крупных уровня разрешения. Пространственная ссылка была настроена, чтобы осуществить сопоставимое соотношение сторон и указать функции на каждом уровне.
bim = blockedImage('tumor_091R.tif');
Получите пространственную ссылку и пиксельную степень блокированного изображения на желаемом уровне на выходе.
pixelExtent = bim.Size(1,:)./(bim.WorldEnd(1,:) - bim.WorldStart(1,:));
Набор данных CAMELYON16 обеспечивает метки опухоли и нормальных областей в виде набора координат, задающих вручную аннотируемые контуры области относительно самого прекрасного уровня разрешения. Когда пиксели существуют в контурах и нормальной области и области опухоли, правильная метка для тех пикселей является нормальной тканью.
Загрузите данные о метке для блокированного изображения. Этот пример использует модифицированную версию меток изображения "tumor_091.tif" от набора данных CAMELYON16. Исходные метки хранятся в формате XML. Модифицированные метки передискретизируются и сохранены как файл MAT.
roiPoints = load('labelledROIs.mat')
roiPoints = struct with fields:
cancerRegions: {[344×2 double] [53×2 double] [539×2 double] [247×2 double] [37×2 double] [161×2 double]}
nonCancerRegions: {[46×2 double]}
Создайте многоугольные объекты ROI, которые хранят координаты контуров опухоли и нормальных контуров ткани.
tumorPolys = cellfun(@(position) images.roi.Polygon( ... 'Position',position,'Visible','on','Color','r'), ... roiPoints.cancerRegions); normalPolys = cellfun(@(position) images.roi.Polygon( ... 'Position',position,'Visible','on','Color','g'), ... roiPoints.nonCancerRegions);
Отобразите изображение, наложенное с аннотируемыми ROI. ROI имеют ту же систему координат, как изображение, таким образом изменяя уровни разрешения отображенного изображения все еще представляет ROI точно.
figure h = bigimageshow(bim); set(tumorPolys,'Parent',gca); set(normalPolys,'Parent',gca); title(['Resolution Level:' num2str(h.ResolutionLevel)]);
Увеличьте масштаб к одному ROI.
xlim([3940 4290])
ylim([2680 3010])
title(['Resolution Level:' num2str(h.ResolutionLevel)]);
Создайте маску на самом грубом уровне разрешения для запятнанной области, которая включает и опухоль и нормальную ткань. Маской является 1
TRUE
) для пикселей, полутоновое значение которых меньше 130. Заполните маленькие отверстия в маске путем выполнения морфологического закрытия с помощью bwmorph
функция.
tissueMask = apply(bim, ... @(bs)bwmorph(rgb2gray(bs.Data)<130,'close'),"Level",3); bigimageshow(tissueMask);
Объедините информацию в координатах многоугольника и представлениях маски, чтобы создать одно помеченное блокированное изображение.
Чтобы сохранить помеченное изображение, создайте writeable блокированное изображение с категориальным типом данных. Укажите, что необходимые имена классов и соответствующий числовой пиксель помечают Значения идентификаторов. Присвойте метку 0 'Фоновому' классу.
blockSize = [512 512]; destination = []; % Save the result 'in memory' sizeOfLabeled = bim.Size(1,1:2); % Labelled image is MxN (2D) labelIDs = [0,1,2]; labelClasses = ["Background","Normal","Tumor"]; initialvalue = categorical(NaN, labelIDs, labelClasses); bLabeled = blockedImage(destination,sizeOfLabeled,blockSize,initialvalue,... 'WorldStart', bim.WorldStart(1,1:2),... 'WorldEnd', bim.WorldEnd(1,1:2),... 'Mode','w')
bLabeled = blockedImage with properties: Read only properties Source: [] Adapter: [1×1 images.blocked.InMemory] Size: [5000 5358] SizeInBlocks: [10 11] ClassUnderlying: "categorical" BlockSize: [512 512] Settable properties InitialValue: <undefined>
Цикл посредством каждого выхода блокировал изображение, один блок за один раз. Определите метку каждого блока, затем установите пиксельные данные блока соответственно.
Чтобы определить метку каждого блока, начните с маски всей ткани. Пиксельные значения 0
в маске соответствуют фону, который совпадает с пиксельной меткой ID 'Фонового' класса. Пиксельные значения 1
в маске соответствуют всей ткани, которая совпадает с пиксельной меткой ID класса 'Normal'. Преобразуйте координаты многоугольника ткани опухоли к маске при помощи poly2mask
функция, затем замените те пиксели на пиксельную метку ID класса 'Опухоли', 2
.
Если у вас есть Parallel Computing Toolbox™, то можно запустить цикл параллельно, заменив for
оператор с parfor
оператор.
for cInd = 1:bLabeled.SizeInBlocks(2) for rInd = 1:bLabeled.SizeInBlocks(1) blockSub = [rInd, cInd]; blockStart = bLabeled.blocksub2sub(blockSub); blockEnd = blockStart + bLabeled.BlockSize - 1; % Clamp to image end blockEnd = min(blockEnd, bLabeled.Size); % Read the corresponding region from the tissue mask. Since the % mask is at a different level, convert coordinates to world and % back. blockStartEndInWorld = bLabeled.sub2world([blockStart; blockEnd]); blockStartEndMaskSub = tissueMask.world2sub(blockStartEndInWorld); maskBlock = getRegion(tissueMask, blockStartEndMaskSub(1,:), blockStartEndMaskSub(2,:)); % Scale up the mask region maskBlock = imresize(maskBlock, [blockEnd-blockStart+1]); % Find the pixel coordinates of healthy tissue then convert the % polygon coordinates to a mask. roiBlock = false(size(maskBlock)); xyStart = fliplr(blockStart); for ind = 1:numel(roiPoints.cancerRegions) vertices = roiPoints.cancerRegions{ind}; % Transform coordinates to local block pixel locations vertices = (vertices-xyStart); isTumor = poly2mask(vertices(:,1),vertices(:,2), ... size(roiBlock,1), size(roiBlock,2)); roiBlock = roiBlock|isTumor; end % Some healthy tissue ROIs are enclosed within a tumor ROI. Find % the pixel coordinates of healthy tissue then convert the polygon % coordinates to a mask. for ind = 1:numel(roiPoints.nonCancerRegions) vertices = roiPoints.nonCancerRegions{ind}; % Transform coordinates to local block pixel locations vertices = (vertices-xyStart); isHealthy = poly2mask(vertices(:,1),vertices(:,2), ... size(roiBlock,1), size(roiBlock,2)); roiBlock = roiBlock & ~isHealthy; end % Set the value of pixels in tumor regions as the corresponding % pixel label ID, |2|. blockNumeric = uint8(maskBlock); blockNumeric(roiBlock) = 2; % Create a categorical image from the block data. blockCategorical = categorical(blockNumeric,... labelIDs, labelClasses); % Set the block of the categorical blocked image as the categorical % block image. setBlock(bLabeled, blockSub ,blockCategorical); end end bLabeled.Mode = 'r';
Отобразите данные изображения, затем отобразите помеченные данные изображения в тех же осях. Три метки (нормальный, опухоль и фон) появляются в трех различных цветах. Сделайте метки частично прозрачными так, чтобы можно было отличить содержимое изображения внизу.
figure hbim = bigimageshow(bim); hla = axes; hbl = bigimageshow(bLabeled,'Parent',hla); hbl.AlphaData = 0.7; hla.Visible = 'off';
Увеличьте масштаб к ROI. Увеличьте прозрачность метки так, чтобы можно было более ясно отличить содержимое изображения внизу.
linkaxes(findall(gcf,'Type','axes'));
xlim([3940 4290]) ylim([2680 3010]) hbl.AlphaData = 0.5;
Для большинства наборов данных можно создать метки однажды и затем снова использовать метки для нескольких сеансов обучения. Помеченное блокированное изображение, bLabeled
, поддерживается временными файлами, которые не существуют через сеансы MATLAB®. Чтобы снова использовать метки на различном сеансе MATLAB, запишите bLabeled
к персистентному местоположению.
imageDir = 'Labels'; if exist(imageDir,'dir') rmdir('Labels','s'); end labelDir = fullfile(imageDir,'labelled'); write(bLabeled,labelDir);
На новой сессии MATLAB можно перезагрузить помеченное блокированное изображение путем создания нового blockedImage
объект. При загрузке помеченного блокированного изображения необходимо также задать 'Classes'
, 'PixelLabelIDs'
, и 'UndefinedID'
.
bLabeled = blockedImage(labelDir);
bigimageshow
| blockedImage
| blockedImageDatastore