В этом примере показано, как применить геометрическое преобразование (деформирование) к заблокированному изображению.
Применение геометрического преобразования к изображению является ключевым шагом во многих приложениях обработки изображений, таких как регистрация изображений. Вы можете использовать imwarp
для деформации грубых изображений, которые помещаются в памяти. Для больших изображений с высоким разрешением, которые не помещаются в памяти, используйте заблокированное изображение. Установите пространственную ссылку на деформированное изображение, чтобы сохранить характеристики изображения, такие как границы пикселей.
Создайте заблокированное изображение с помощью измененной версии изображения «tumor_091.tif» из CAMELYON16 набора данных. Оригинальное изображение представляет собой обучающее изображение лимфатического узла, содержащего опухолевую ткань. Оригинальное изображение имеет восемь уровней разрешения, а лучшее - разрешение 53760 на 61440. Измененное изображение имеет только три уровня грубого разрешения. Пространственная привязка измененного изображения была скорректирована, чтобы обеспечить согласованное соотношение сторон и зарегистрировать функции на каждом уровне.
bim = blockedImage('tumor_091R.tif');
Создайте affine2d
объект, который хранит информацию об аффинном геометрическом преобразовании. Это преобразование применяет перемещение и сдвиг.
tform = affine2d([ 0.99 0.01 0 0.17 0.98 0 120 -30 1]);
Получите изображение на самом грубом уровне разрешения.
imCoarse = gather(bim);
Деформируйте грубое изображение при помощи imwarp
. Отобразите оригинальное изображение и деформированное изображение в монтаже.
imCoarseWarped = imwarp(imCoarse,tform); figure imshow(imCoarseWarped)
Перед применением геометрического преобразования к изображению на уровне тонкого разрешения вычислите пространственную привязку заблокированного изображения после деформации. Используйте эту пространственную ссылку при преобразовании блоков
Получите размер пикселя оригинального изображения из его пространственной справочной информации.
inPixelExtent = (bim.WorldEnd(1,:)-bim.WorldStart(1,:))./bim.Size(1,:);
Вычислите выходные горизонтальные и вертикальные пространственные пределы, когда преобразование применяется.
yWorldLimits = [bim.WorldStart(1,1), bim.WorldEnd(1,1)]; xWorldLimits = [bim.WorldStart(1,2), bim.WorldEnd(1,2)]; [xout, yout] = outputLimits(tform,xWorldLimits,yWorldLimits);
Вычислите размер выходного изображения, которое сохраняет размер пикселя. Укажите размер изображения в формате [numrows, numcols].
outImgSize = [ceil(diff(yout)/inPixelExtent(1)),...
ceil(diff(xout)/inPixelExtent(2))];
Сохраните пространственную ссылочную информацию деформированного изображения. Установите мировые пределы и размер изображения деформированного изображения.
outWorldStart = [yout(1),xout(1)]; outWorldEnd = [yout(2), xout(2)];
Вычислите соответствующие размерности выходного пикселя.
outPixelExtent = (outWorldEnd-outWorldStart)./outImgSize; halfPixWidth = outPixelExtent/2;
Создайте заблокированное изображение с возможностью записи путем определения выхода пространственной справочной информации. Задайте размер блока, достаточно большой, чтобы эффективно использовать память.
outBlockSize = [1024 1024 3]; bwarped = blockedImage([],[outImgSize 3],outBlockSize,uint8(0),... 'Mode','w',... 'WorldStart', [yout(1), xout(1)],... 'WorldEnd', [yout(2), xout(2)]);
Цикл через выходное изображение, по одному блоку за раз. Для каждого выходного блока:
Найдите координаты четырех углов выходного блока.
Обратное отображение этих координат назад на вход, чтобы получить входную (исходную) область.
Ознакомьтесь с содержимым входа области.
Создайте пространственную ссылку, описывающую входную область.
Вычислите содержимое блока выхода при помощи imwarp
.
Запишите выходной блок в выходное изображение при помощи setBlock
функция.
Если у вас есть Parallel Computing Toolbox™, то можно заменить внешний for
оператор со parfor
оператор, чтобы запустить цикл параллельно.
inYWorldLimits = [bim.WorldStart(1,1), bim.WorldEnd(1,1)]; inXWorldLimits = [bim.WorldStart(1,2), bim.WorldEnd(1,2)]; for rBlockInd = 1:bwarped.SizeInBlocks(1) for cBlockInd = 1:bwarped.SizeInBlocks(2) blockSub = [rBlockInd, cBlockInd 1]; % Center of top left pixel of this block in world units blockStartSub = blocksub2sub(bwarped, blockSub); blockStartWorld = sub2world(bwarped, blockStartSub); % Center of bottom right pixel of this block in world units blockEndSub = blockStartSub + outBlockSize - 1; blockEndWorld = sub2world(bwarped, blockEndSub); % Spatial reference which describes this block (Note: spatial % referencing is in x-y order, while blockStart etc are in y-x % order). Ensure to move the region outwards by half a pixel to % reference the outer edge of this block. outRegionRef = imref2d(fliplr(outBlockSize(1:2))); outRegionRef.YWorldLimits = [blockStartWorld(1)-halfPixWidth(1),... blockEndWorld(1)+halfPixWidth(1)]; outRegionRef.XWorldLimits = [blockStartWorld(2)-halfPixWidth(2),... blockEndWorld(2)+halfPixWidth(2)]; % Output bounding box in world coordinates outbbox = [ fliplr(blockStartWorld(1:2)) blockStartWorld(2) blockEndWorld(1) blockEndWorld(2) blockStartWorld(1) fliplr(blockEndWorld(1:2))]; % Get corresponding input region. Note: This region need NOT be % rectangular if the transformation includes shear inRegion = transformPointsInverse(tform,outbbox); % Clamp region to image extents inRegion(:,2) = max(inRegion(:,2),inYWorldLimits(1)); inRegion(:,2) = min(inRegion(:,2),inYWorldLimits(2)); inRegion(:,1) = max(inRegion(:,1),inXWorldLimits(1)); inRegion(:,1) = min(inRegion(:,1),inXWorldLimits(2)); % Find the corresponding input bounding box inbboxStart = [min(inRegion(:,1)) min(inRegion(:,2))]; inbboxEnd = [max(inRegion(:,1)) max(inRegion(:,2))]; % Move to y-x (row-col) order inbboxStart = fliplr(inbboxStart); inbboxEnd = fliplr(inbboxEnd); % Convert to pixel subscripts inbboxStartSub = world2sub(bim, [inbboxStart 1]); inbboxEndSub = world2sub(bim, [inbboxEnd 3]); % Read corresponding input region inputRegion = getRegion(bim,inbboxStartSub,inbboxEndSub); % Input region's spatial referencing inRegionRef = imref2d(size(inputRegion)); % Convert the actual region pixel's centers back to world % coordinates. inbboxStart = sub2world(bim, inbboxStartSub); inbboxEnd = sub2world(bim, inbboxEndSub); % Convert to pixel edges from pixel centers inRegionRef.YWorldLimits = [inbboxStart(1)-halfPixWidth(1),... inbboxEnd(1)+halfPixWidth(2)]; inRegionRef.XWorldLimits = [inbboxStart(2)-halfPixWidth(1),... inbboxEnd(2)+halfPixWidth(2)]; % Warp this block warpedBlock = imwarp(inputRegion,inRegionRef,tform,'OutputView',outRegionRef); % Set the block data in the output blocked image setBlock(bwarped,blockSub,warpedBlock); end end
Отобразите деформированное изображение.
bwarped.Mode = 'r';
figure
bigimageshow(bwarped)
affine2d
| bigimageshow
| blockedImage
| getRegion
| imref2d
| setBlock
| transformPointsInverse