image - 图像分割的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
解决方案
在选择块时,您的循环运行良好。您正在使用线性索引将块放置在单元格数组中,而您正在以“错误”的顺序进行操作。您现在正在用图像中的一行块填充元胞数组的列。转置元胞数组,或使用以下循环:
%% 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);
推荐阅读
- linux - 如何将字典或 JSON 传递给 Invoke-AzVMRunCommand - 参数?
- javascript - 如何在 rxjs 的地图中展开可观察对象?
- sql - SQL查询:获取每个月的总值
- javascript - 从 blob 流中获取文件名和长度
- unreal-engine4 - UE4 蓝图:无法让玩家“死亡”在客户端上复制,只能在服务器上复制
- jquery - 在javascript中修改wordpress插件功能
- javascript - 我如何要求一个字段为(A 和 B),或(A),或(B),或(A 和 C),或(C)
- linux - 将目录中的文件与其他文件中的内容进行比较
- cron - 如何每月安排多天的 Cron 作业?
- excel - 如何以自定义格式导出文件名?