首页 > 解决方案 > 图像分割的Blockproc和for循环方法

问题描述

我正在学习如何将图像拆分为 8x8 的重叠块并重叠 4 个像素。

使用 blockproc(),我可以很容易地做到这一点:

T = dctmtx(8);
dct = @(block_struct) T * block_struct.data * T';
B1 = blockproc(I, [4 4], dct, 'BorderSize',[2 2], 'TrimBorder', false, 'PadPartialBlocks',true)

但问题是 blockproc() 需要一个函数才能在这种情况下工作,它的“dct”在创建的每个块上执行。

相反,我正在尝试使用for 循环分割图像,而没有任何功能。

将不胜感激这方面的一些帮助。

**编辑我尝试编写 for 循环方法,但我不确定它是否正确,因为它不像 blockproc 方法那样使用边框。

%% Read in image file
camera = imread('cameraman.tif');
camera = im2double(camera);
[hor,ver,color] = size(camera); %256x256 image
imshow(camera)

%% Set the specifications of the blocks
rblock = 8; %each block will occupy 8 pixels 
cblock = 8;
xpix = 4; %this will be our jump in the for loop
cpix = 4;

%% Compute how many blocks in row and column

whole_row = numel(1:rblock-xpix:(hor-(rblock-1))); 
whole_col = numel(1:cblock-cpix:(ver-(cblock-1)));

%% Create a cell array to store the blocked images
ca = cell(whole_row*whole_col,1); 
ca = reshape(ca, whole_row,whole_col); %reshape to 63x63

%% Scan through the image and extract each blocks
ind = 1;
for row = 1: rblock-xpix: (hor-(rblock-1))
    for col = 1: cblock-cpix : (ver-(cblock-1))
        row1 = row;
        row2 = row1 + rblock-1;

        col1 = col;
        col2 = col1 + cblock-1;

        ca{ind} = camera(row1:row2, col1:col2,:);
        ind = ind + 1;
    end
end

%% View the block images
ind = 1;
numPlotsR = size(ca,1); % 63
numPlotsC = size(ca,2); % 63

set(gcf,'units','normalized','outerposition',[0 0 1 1]);
drawnow;

for r =1: numPlotsR
    for c = 1: numPlotsC
        subplot(numPlotsR, numPlotsC, ind);
        rgbBlock = ca{c,r};
        imshow(rgbBlock)
        ind = ind + 1;
    end
end

标签: imagematlabimage-processing

解决方案


在选择块时,您的循环运行良好。您正在使用线性索引将块放置在单元格数组中,而您正在以“错误”的顺序进行操作。您现在正在用图像中的一行块填充元胞数组的列。转置元胞数组,或使用以下循环:

%% Create a cell array to store the blocked images
ca = cell(whole_row, whole_col);  % no need for reshape

%% Scan through the image and extract each blocks
row_start_indices = 1: rblock-xpix: (hor-(rblock-1))
col_start_indices = 1: cblock-cpix : (ver-(cblock-1))
for ri = 1:numel(row_start_indices);
    for ci = 1:numel(col_start_indices)
        row1 = row_start_indices(ri);
        row2 = row1 + rblock-1;

        col1 = col_start_indices(ci);
        col2 = col1 + cblock-1;

        ca{ri,ci} = camera(row1:row2, col1:col2,:);
    end
end

正如您所指出的,上面的结果与blockproc. 这与blockproc从图像中采样的方式有关。您指定一个 4×4 块,边界为 2 个像素,这意味着从图像中获取的第一个块是左上角的前 4×4 像素,每个方向有两个额外像素的边界。您指定PadPartialBlocks为 true,因此左上角将用零填充,因为没有可用于边框的图像数据。

因此,要使结果匹配,您可以填充图像,以便 for 循环采用与以下相同的块blockproc

%% Read in image file
camera = imread('cameraman.tif');
camera = im2double(camera);

%% use blockproc
T = eye(8); % create transformation that does not transform
dct = @(block_struct) T * block_struct.data * T';
B1 = blockproc(camera, [4 4], dct, 'BorderSize',[2 2], 'TrimBorder', false, 'PadPartialBlocks',false);

% pad image, and get new dimensions
pad_size = 2;
camera = padarray(camera, [pad_size pad_size]); % pad 2 pixel wide border in all directions
[hor,ver,color] = size(camera); %256x256 + something image

%% Set the specifications of the blocks
rblock = 8; %each block will occupy 8 pixels 
cblock = 8;
xpix = 4; %this will be our jump in the for loop
cpix = 4;

%% Compute how many blocks in row and column
whole_row = numel(1:rblock-xpix:(hor-(rblock-1))); 
whole_col = numel(1:cblock-cpix:(ver-(cblock-1)));

%% Create a cell array to store the blocked images
ca = cell(whole_row, whole_col);  % no need for reshape

%% Scan through the image and extract each blocks
row_start_indices = 1: rblock-xpix: (hor-(rblock-1));
col_start_indices = 1: cblock-cpix : (ver-(cblock-1));
for ri = 1:numel(row_start_indices);
    for ci = 1:numel(col_start_indices)
        row1 = row_start_indices(ri);
        row2 = row1 + rblock-1;

        col1 = col_start_indices(ci);
        col2 = col1 + cblock-1;

        ca{ri,ci} = camera(row1:row2, col1:col2,:);
    end
end

% convert the cell array to a matrix
camera2 = cell2mat(ca);

% compare resutls of blockproc and for-loop:
isEqual = all(all(camera2==B1));

% get rid of the border:
img_out = camera2(pad_size+1:end-pad_size, pad_size+1:end-pad_size);

推荐阅读