【问题标题】:Matlab: crop image with a sliding window?Matlab:用滑动窗口裁剪图像?
【发布时间】:2015-05-30 20:24:55
【问题描述】:

有人知道如何在 Matlab 中使用滑动窗口裁剪图像吗? 例如我有一个 1000x500 像素的图像,我想从这个图像中裁剪 50x50 像素的块......当然我必须处理不均匀的分割,但没有必要有相同大小的块。

【问题讨论】:

  • 如果你没有找到使用 Matlab 的方法,它是一个简单的带有 ImageMagick 的单行程序,它安装在大多数 Linux 发行版上,可用于 OSX 和 Windows...convert -crop 50x50 in.png tile%d.png 和你的200 个图块将创建为 tile0.pngtile199.png。随意将任何png 更改为jpgtifbmp 或任何你需要的。
  • 我必须在matlab中找到一种方法;D这只是我必须解决的问题的一部分!谢谢...
  • 当您说“裁剪”时,您的意思是要提取 50x50 像素矩阵并将其保存在新矩阵中?或者您想保持图像大小为 1000x5000 并且仅将感兴趣区域之外的所有像素归零?并且滑动窗口是自身重叠,还是块状覆盖图像?
  • 根据 1000x500 像素的图像和 50x50 像素的块的示例......最好有 (1000x500 )/( 50x50 )=200 1000x500 像素的图像,全部为零每个块外的像素...

标签: image matlab image-processing crop sliding-window


【解决方案1】:

过去帮助我的一些细节与(i)在块处理时分割图像的方法和(ii)“不均匀分割”有关,如 OP 所述。

(i) 分割/处理图像的方法:

1.处理非重叠块:

使用默认参数 {'BorderSize',[0 0]},可以使用blockproc 处理,如下所示。

(i)-1 的示例:注意输出的阻塞性质。这里每个大小为 32 x 32 的非重叠块用于计算 std2(),输出 std2 值用于填充该特定块。输入和输出的大小为 32 x 32。

fun = @(block_struct) std2(block_struct.data) * ones(size(block_struct.data));
I2 = blockproc('moon.tif',[32 32],fun);
figure; subplot(1, 2, 1);
imshow('moon.tif'); title('input');
subplot(1,2, 2)
imshow(I2,[]); title('output'); 

输入输出图像:

(i)-2:处理重叠块:

使用参数{'BorderSize',[V H]}:在块的上方和下方添加V行,在块的左侧和右侧添加H列。处理的块有 (N + 2*V) 行和 (M + 2*H) 列。使用默认参数 {'TrimBorder',true},将输出的边框修剪为 N 行和 M 列的原始输入块大小。

(i)-2 的示例:下面使用 blockproc 的代码使用 {'BorderSize',[15 15]} 和 [N M] = [1 1]。这类似于使用自定义内核过滤图像的每个像素。所以处理单元的输入是一个大小为 (1 + 2*15) 行和 (1 + 2*15) 列的块。并且由于 {'TrimBorder',true} 默认情况下,31 行 x 31 列块的 std2 作为每个像素的输出提供。修剪边框后的输出大小为 1 x 1。因此,请注意,与前面的示例相比,此示例输出是“非阻塞”的。此代码需要更长的时间来处理所有像素。

fun = @(block_struct) std2(block_struct.data) * ones(size(block_struct.data));
I2 = blockproc('moon.tif',[1 1],fun,'BorderSize',[15 15]);
figure; subplot(1, 2, 1);
imshow('moon.tif'); title('input');
subplot(1,2, 2)
imshow(I2,[]); title('output');

输入输出图像:

(ii) “不均匀的划分”:

1.零/复制/对称填充:

零填充,以便整数倍的块(N 行 x M cols 大小)可以覆盖不均匀维度中的 [图像 + 边界零点]。这可以通过使用默认参数 {'PadMethod', 0} 和 {'PadPartialBlocks' , true} (默认为 false )来实现。如果零边界区域导致从边界块计算的值出现高度不连续性,则可以使用 {'PadMethod', 'replicate'} 或 {'PadMethod', 'symmetric'}。

2.假设图像中有一个“活动区域”用于块处理

对于处理每个像素的情况,如情况 (i)-2,我们可以假设沿图像外围的所有边都有一个 floor(block_size/2) 像素的边界区域,用作“虚拟”地区。用于块处理的 Active 区域包含在 Dummy 区域中。

类似的东西用于成像传感器,其中位于活动像素成像阵列外围的虚拟像素允许像所有活动区域像素的颜色插值这样的操作。由于颜色插值通常需要 5x5 像素掩码来插值像素的颜色值,因此可以使用 2 个像素的边界虚拟外围。

假设 MATLAB 索引,区域 ( floor(block_size/2) + 1 ) 到 ( Input_Image_Rows - floor(block_size)/2) ) 行由 ( floor(block_size/2) + 1 ) 到 ( Input_ImageCols - floor(block_size )/2) ) 列被视为活动区域(假设边为方形块,block_size),其对每个像素进行块处理,如 (i)-2 中所示。

假设方块大小为 5 x 5,如下所示:

block_size  = 5;
buffer_size = floor(block_size/2);
for i = (buffer_size+1):(image_rows-buffer_size)
    for j = (buffer_size+1):(image_cols-buffer_size)
        ...  % block processing for each pixel Image(i,j)
    end
end

Matlab 版本:R2013a

【讨论】:

    【解决方案2】:

    我会先研究一下函数blockproc,看看它是否能做你想做的事。


    如果您确定要将图像手动裁剪成块,则可以使用此脚本。它既将裁剪后的图像写入 .png 文件,又将裁剪后的图像保存在 3D 数组的页面中。您可以根据需要进行修改。

    此脚本假定图像可以被块大小整除。如果不是,则需要用零填充它。

    [rowstmp,colstmp]= size(myImage);
    block_height     = 50;
    block_width      = 50;
    
    blocks_per_row   = rows/block_height;
    blocks_per_col   = cols/block_width;
    number_of_blocks = blocks_per_row*blocks_per_col;
    
    %// pad image with zeros if needed
    if ~(mod(rowstmp-1,block_height)==0)
        rows = ceil(rowstmp/block_height)*block_height;
    end
    if ~(mod(colstmp-1,block_width)==0)
        cols = ceil(colstmp/block_width)*block_width;
    end
    Im = uint8(zeros(rows,cols));
    Im(1:rowstmp,1:colstmp) = myImage;
    
    %// make sure these image have type uint8 so they save properly
    cropped_image    = uint8(zeros(rows,cols));
    img_stack        = uint8(zeros(rows,cols,number_of_blocks));
    
    %// loop over the image blocks
    for i = 1:blocks_per_row
        for j = 1:blocks_per_col
            %// get the cropped image from the original image
            idxI = 1+(i-1)*block_height:i*block_height;
            idxJ = 1+(j-1)*block_width :j*block_width;
            cropped_image(idxI,idxJ) = Im(idxI,idxJ);
    
            %//imshow(cropped_image)
    
            %// write the cropped image to the current folder
            filename = sprintf('block_row%d_col%d.png',i,j);
            imwrite(cropped_image,filename);
            cropped_image(idxI,idxJ) = 0;
    
            %// keep all the blocks in a 3D array if we want to use them later
            img_stack(:,:,(i-1)*blocks_per_col+j);
        end
    end
    

    【讨论】:

    • 非常感谢您提供的答案....但是按照要求处理不均匀的划分是基本的...您有什么想法吗?
    • @Kevin 我不清楚您所说的“不均匀除法”是什么意思。正如图像宽度/高度不是块大小的偶数倍?我可以添加零填充来解决这个问题吗?
    • @Kevin 我在顶部附近添加了几行来解决这个问题。
    猜你喜欢
    • 2014-06-02
    • 1970-01-01
    • 2014-09-08
    • 1970-01-01
    • 2013-04-20
    • 2016-12-05
    • 2012-02-12
    • 1970-01-01
    相关资源
    最近更新 更多