В этом примере показано, как применить геометрическое преобразование (деформирующееся) к большому изображению.
Применение геометрического преобразования к изображению является ключевым шагом во многих приложениях для обработки изображений как регистрация изображений. Можно использовать imwarp
деформировать крупные изображения, которые умещаются в памяти. Для больших изображений с высоким разрешением, которые не умещаются в памяти, блоки деформации изображения. Установите пространственную ссылку деформированного изображения сохранять характеристики изображения, такие как пиксельные степени.
Создайте bigimage
использование модифицированной версии изображения "tumor_091.tif" от набора данных CAMELYON16. Оригинальное изображение является учебным изображением лимфатического узла, содержащего ткань опухоли. Оригинальное изображение имеет восемь уровней разрешения, и самый прекрасный уровень имеет разрешение 53760 61440. Модифицированное изображение имеет только три крупных уровня разрешения. Пространственная ссылка модифицированного изображения была настроена, чтобы осуществить сопоставимое соотношение сторон и указать функции на каждом уровне.
bim = bigimage('tumor_091R.tif');
Создайте affine2d
объект, который хранит информацию об аффинном геометрическом преобразовании. Это преобразование применяет перевод и сдвиг.
tform = affine2d([ 0.99 0.01 0 0.17 0.98 0 120 -30 1]);
Получите изображение на самом грубом уровне разрешения.
imCoarse = getFullLevel(bim);
Деформируйте крупное изображение при помощи imwarp
. Отобразите оригинальное изображение и деформированное изображение в монтаже.
imCoarseWarped = imwarp(imCoarse,tform); montage({imCoarse,imCoarseWarped})
Прежде, чем применить геометрическое преобразование к изображению на уровне высокого разрешения, вычислите пространственную ссылку большого изображения после деформирования. Используйте эту пространственную ссылку при преобразовании блоков
Получите пиксельную степень оригинального изображения от его пространственной информации о ссылке.
srcLevel = bim.FinestResolutionLevel; inRef = bim.SpatialReferencing(srcLevel); inPixelExtent = [inRef.PixelExtentInWorldX,inRef.PixelExtentInWorldY];
Вычислите выходную горизонталь и вертикальные пространственные пределы, когда преобразование будет применено.
[xout,yout] = outputLimits(tform,inRef.XWorldLimits,inRef.YWorldLimits);
Вычислите размер выходного изображения, которое сохраняет пиксельную степень. Задайте размер изображения в формате [numrows, numcols].
outImgSize = [ceil(diff(yout)/inPixelExtent(2)),ceil(diff(xout)/inPixelExtent(1))];
Создайте imref2d
объект, который хранит пространственную информацию ссылки деформированного изображения. Установите мировые пределы и размер изображения деформированного изображения.
outRef = imref2d(outImgSize,xout,yout)
outRef = imref2d with properties: XWorldLimits: [120.5800 6275] YWorldLimits: [-29.5050 4.9241e+03] ImageSize: [4954 6155] PixelExtentInWorldX: 0.9999 PixelExtentInWorldY: 0.9999 ImageExtentInWorldX: 6.1544e+03 ImageExtentInWorldY: 4.9536e+03 XIntrinsicLimits: [0.5000 6.1555e+03] YIntrinsicLimits: [0.5000 4.9545e+03]
Задайте источник выхода как левый верхний пиксель.
outOrigin = [xout(1),yout(1)];
Вычислите соответствующие размерности выходного пикселя.
outPixelExtent = [outRef.PixelExtentInWorldX,outRef.PixelExtentInWorldY]; halfPixWidth = outPixelExtent/2;
Создайте перезаписываемый bigimage
путем указывания выхода пространственная информация ссылки. Задайте размер блока, который является достаточно большим, чтобы использовать память эффективно.
outBlockSize = [1024 1024]; bwarped = bigimage(outRef,bim.Channels,bim.ClassUnderlying, ... 'BlockSize',outBlockSize);
Цикл через выходное изображение, один блок за один раз. Для каждого выходного блока:
Найдите координаты четырех углов выходного блока.
Обратная карта эти координаты назад к входу, чтобы получить вход (источник) область.
Считайте содержимое входной области.
Создайте пространственную ссылку, описывающую входную область.
Вычислите выходное содержимое блока при помощи imwarp
.
Запишите выходной блок в выходное изображение при помощи setBlock
функция.
Если у вас есть Parallel Computing Toolbox™, то можно заменить внешний for
оператор с parfor
оператор, чтобы запустить цикл параллельно.
colStarts = 1:outBlockSize(2):outRef.ImageSize(2); for cInd = 1:numel(colStarts) colStart = colStarts(cInd); for rStart = 1:outBlockSize(1):outRef.ImageSize(1) % Center of top left pixel of this block in world units xyStart = [colStart,rStart].* outPixelExtent; xyStart = xyStart + outOrigin; % Center of bottom right pixel of this block in world units bsize = fliplr(bwarped.BlockSize); % (r,c) -> (x,y) xyEnd = ([colStart,rStart] + (bsize-1)).*outPixelExtent; xyEnd = xyEnd + outOrigin; % Output bounding box outbbox = [xyStart xyStart(1) xyEnd(2) xyEnd(1) xyStart(2) xyEnd]; % Corresponding spatial reference which describes this rectangle outRegionRef = imref2d(bsize); outRegionRef.XWorldLimits = [xyStart(1)-halfPixWidth(1),xyEnd(1)+halfPixWidth(1)]; outRegionRef.YWorldLimits = [xyStart(2)-halfPixWidth(2),xyEnd(2)+halfPixWidth(2)]; % Get corresponding input region. The region is not rectangular if the transformation % includes shear inRegion = transformPointsInverse(tform,outbbox); % Clamp to image extents (working with pixel centers) xcenterLims = inRef.XWorldLimits + [halfPixWidth(1)-halfPixWidth(1)]; ycenterLims = inRef.YWorldLimits + [halfPixWidth(2)-halfPixWidth(2)]; inRegion(:,1) = max(inRegion(:,1),xcenterLims(1)); inRegion(:,1) = min(inRegion(:,1),xcenterLims(2)); inRegion(:,2) = max(inRegion(:,2),ycenterLims(1)); inRegion(:,2) = min(inRegion(:,2),ycenterLims(2)); % Find the input bounding box (still using pixel centers) inbboxStart = [min(inRegion(:,1)) min(inRegion(:,2))]; inbboxEnd = [max(inRegion(:,1)) max(inRegion(:,2))]; % Read corresponding input region inputRegion = getRegion(bim,srcLevel,inbboxStart,inbboxEnd); % Input region's spatial referencing inRegionRef = imref2d(size(inputRegion)); % Convert to pixel edges from pixel centers inRegionRef.XWorldLimits = [inbboxStart(1)-halfPixWidth(1),inbboxEnd(1)+halfPixWidth(2)]; inRegionRef.YWorldLimits = [inbboxStart(2)-halfPixWidth(1),inbboxEnd(2)+halfPixWidth(2)]; warpedBlock = imwarp(inputRegion,inRegionRef,tform,'OutputView',outRegionRef); % Set the block data in the output bigimage setBlock(bwarped,1,xyStart,warpedBlock); end end
Отобразите деформированное изображение.
bigimageshow(bwarped)
affine2d
| bigimage
| bigimageshow
| getRegion
| imref2d
| setBlock
| transformPointsInverse