exponenta event banner

Создание блокированного изображения с метками из 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]}

Создайте полигональные объекты окупаемости инвестиций, в которых хранятся координаты границ опухоли и нормальных границ ткани.

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)]);

Увеличьте изображение одной окупаемости инвестиций.

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);

Создание комбинированного блокированного изображения с метками

Объедините информацию в координатах полигона и представлениях маски, чтобы создать одно блокированное изображение с метками.

Чтобы сохранить помеченное изображение, создайте записываемое заблокированное изображение с категориальным типом данных. Укажите требуемые имена классов и соответствующие числовые значения идентификатора метки пикселя. Присвойте метку 0 классу «Background».

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 в маске соответствуют фону, который соответствует идентификатору метки пикселя класса «Background». Пиксельные значения 1 в маске соответствуют всем тканям, что соответствует идентификатору метки пикселя класса «Normal». Преобразование координат многоугольника опухолевой ткани в маску с помощью poly2mask функция, затем замените эти пикселы идентификатором метки пикселя класса «Опухоль», 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';

Увеличьте изображение окупаемости инвестиций. Увеличьте прозрачность метки, чтобы можно было более четко различать содержимое изображения под ней.

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);

См. также

| |

Связанные темы