如何在指定位置有效提取图像补丁?

use*_*593 3 matlab image-processing

我需要s x s x 3 从图像(3个通道)中提取大约指定2D位置的图像块.

如何在没有for循环的情况下有效地完成此操作?我知道我可以在(x,y)位置周围提取一个补丁:

apatch = I(y-s/2:y+s/2, x-s/2:x+s/2, :)
Run Code Online (Sandbox Code Playgroud)

我如何为许多补丁做到这一点?我知道我可以使用MATLAB的功能,blockproc但我无法指定位置.

ray*_*ica 6

您可以使用im2col图像处理工具箱将每个像素邻域转换为单个列.选择像素邻域使得每个块在列基础上被选择,这意味着通过首先遍历行来构造块,然后前进到下一列并且在那里获得邻域.

你这样称呼im2col:

B = im2col(A, [M N]);
Run Code Online (Sandbox Code Playgroud)

我假设您需要滑动/重叠邻域而不是明确的邻域,这是执行任何类型的图像过滤时通常使用的. A是你的图像,你想找到M x N转换为列的像素邻域. B将是每个邻域是单列并水平平铺在一起的输出.但是,您可能希望处理想要沿图像边界抓取像素邻域的情况.在这种情况下,您需要先填充图像.我们将假设在图像顶部和底部以及填充到图像左侧和右侧的列填充行M和行.因此,我们应该垫N允许填充更容易很奇怪.具体来说,你想确定有floor(M/2)floor(N/2)A首先使用padarray.让我们假设边界像素将被复制,这意味着填充的行和列将只是从顶部或底部行或左右列中抓取的那些,具体取决于我们需要填充的位置.因此:

Apad = padarray(A, floor([M N]/2), 'replicate');
Run Code Online (Sandbox Code Playgroud)

对于下一部分,如果要选择指定邻域,可以使用sub2ind将2D坐标转换为线性索引,以便选择正确的列以获得正确的像素块.但是,因为您有彩色图像,所以您需要im2col在每个颜色通道上执行.不幸的是,im2col仅适用于灰度图像,因此您必须为图像中的每个通道重复此操作.

因此,要准备好进行补丁采样,请执行以下操作:

B = arrayfun(@(x) im2col(Apad(:,:,x), [M N]), 1:size(A,3), 'uni', 0);
B = cat(3, B{:});
Run Code Online (Sandbox Code Playgroud)

上面的代码将创建一个3D版本im2col,其中每个3D切片将为im2col每个颜色通道生成.现在,我们可以使用sub2ind(x,y)坐标转换为线性索引,以便我们可以选择我们想要的像素邻域.因此,假设你的位置存储在矢量xy,你会做这样的事情:

%// Generate linear indices
ind = sub2ind([size(A,1) size(A,2)], y, x);

%// Select neighbourhoods
%// Should be shaped as a MN x len(ind) x 3 matrix
neigh = B(:,ind,:);

%// Create cell arrays for each patch
patches = arrayfun(@(x) reshape(B(:,x,:), [M N 3]), 1:numel(ind), 'uni', 0);
Run Code Online (Sandbox Code Playgroud)

patches将是一个单元格数组,其中每个元素在(x,y)您指定的每个位置包含所需的修补程序.因此,patches{1}补丁位于(x(1), y(1)),patches{2}补丁位于(x(2), y(2)),等等.为了您的复制和粘贴乐趣,这就是我们所拥有的:

%// Define image, M and N here
%//...
%//...

Apad = padarray(A, floor([M N]/2), 'replicate');
B = arrayfun(@(x) im2col(Apad(:,:,x), [M N]), 1:size(A,3), 'uni', 0);
B = cat(3, B{:});

ind = sub2ind([size(A,1) size(A,2)], y, x);
neigh = B(:,ind,:);
patches = arrayfun(@(x) reshape(neigh(:,x,:), [M N 3]), 1:numel(ind), 'uni', 0);
Run Code Online (Sandbox Code Playgroud)