Why does blockproc return empty?

The blockproc documentation says that the block function can return a vector. Mine does so and prodcues non-empty output, as demonstrated below. However, the final output B returned by blockproc is empty. Why, and how does one obtain meaningful vector-valued output from blockproc?
A=reshape(1:4,2,2)
A = 2×2
1 3 2 4
B=blockproc(A,[2,2],@blockfun,'BorderSize',[1,1])
out = 16×1
0 0 0 0 0 1 2 0 0 3
B = 14×0 empty double matrix
function out=blockfun(S)
out=S.data(:)
end

 Accepted Answer

You can't specify a bordersize with a 2x2 matrix. There is nothing left after you chop those off your input matrix. It appears the border size is implemented AFTER blockproc. So while the output is a column vector inside blockproc, upon return to the main program, when it chops off the first and last row and column, you have nothing left since your output was only a single column. Hence it's empty. Get rid of the BorderSize option if your matrix is that small. Use it only for larger matrixes.
A = reshape(1:4,2,2)
A = 2×2
1 3 2 4
B = blockproc(A, [2,2], @blockfun)
out = 4×1
1 2 3 4
B = 4×1
1 2 3 4
function out = blockfun(S)
out = S.data(:)
end

6 Comments

You can't specify a bordersize with a 2x2 matrix.
Even if I increase A from 2x2 to 30x30, I get an empty result:
A=rand(30);
B=blockproc(A,[2,2],@blockfun,'BorderSize',[1,1])
B = 210×0 empty double matrix
function out=blockfun(S)
out=S.data(:);
end
So while the output is a column vector inside blockproc, upon return to the main program, when it chops off the first and last row and column, you have nothing left since your output was only a single column.
That part is true, but it can be suppressed with TrimBorder=false,
A=reshape(1:4,2,2);
B=blockproc(A,[2,2],@blockfun,'BorderSize',[1,1],'TrimBorder',0)
B = 16×1
0 0 0 0 0 1 2 0 0 3
function out=blockfun(S)
out=S.data(:);
end
I'm confused about a few things, hopefully someone can clarify.
I modified the example to process a 4 x 4 image, using 2 x 2 blocks, with the simple goal of returning the original image. The goal was met, but I have some questions on how it got there.
Define the image
A=reshape(1:16,4,4)
A = 4×4
1 5 9 13 2 6 10 14 3 7 11 15 4 8 12 16
Call blockproc and output some information on the way:
B = blockproc(A,[2,2],@blockfun,'BorderSize',[1,1],'PadMethod',100)
S = struct with fields:
border: [1 1] blockSize: [2 2] data: [4×4 double] imageSize: [4 4] location: [1 1]
data = 4×4
100 100 100 100 100 1 5 9 100 2 6 10 100 3 7 11
S = struct with fields:
border: [1 1] blockSize: [2 2] data: [4×4 double] imageSize: [4 4] location: [1 3]
data = 4×4
100 100 100 100 5 9 13 100 6 10 14 100 7 11 15 100
S = struct with fields:
border: [1 1] blockSize: [2 2] data: [4×4 double] imageSize: [4 4] location: [3 1]
data = 4×4
100 2 6 10 100 3 7 11 100 4 8 12 100 100 100 100
S = struct with fields:
border: [1 1] blockSize: [2 2] data: [4×4 double] imageSize: [4 4] location: [3 3]
data = 4×4
6 10 14 100 7 11 15 100 8 12 16 100 100 100 100 100
B = 4×4
1 5 9 13 2 6 10 14 3 7 11 15 4 8 12 16
Question 1: the data field of the block_struct input to blockfun has size 4 x 4. Apparently, that's the size of the block with borders added. The doc page blockproc says that the data field is size m x n. But the parameters m and n specify the Block Size (second input argument to blockproc), which in this case is 2 x 2. Is the doc page using m and n to mean different things in different places? Also, the doc page says that the data field is "block data," not "block and border data." What is the data field really supposed to be?
Question 2: My reading of the doc page is that the elements of the borders around the 2 x 2 block should all be 100 based on PadMethod. Assuming that the data field is the block and borders, it looks like image data is being grabbed and inserted in the block borders. Am I misunderstanding something?
Question 3: The doc page says that PadMethod defines the "Method used to pad the image boundary," Shouldn't that say "block boundary"?
Edit: I guess the way it works is that PadMethod does pad the image boundary, and the Border around each block is then pulled form the padded image. But then, what does this mean: "The function pads blocks with borders extending beyond the image edges with zeros." Aren't the borders extending beyond the image padded based on PadMethod?
function out = blockfun(S)
S
data = S.data
out = S.data;
end
@Paul I don't ever see any need in my work for padding or borders so I never use those options.
Normally when you do block processing you want a single value returned for one block. So if you do that a 4x4 matrix with 2x2 blocks would return a 2x2 output image. You can have it return the original size if you use ones() as shown in the attached demos. In my overlapping demo I use BorderSize and it says that it's how much the block "backs up" after jumping to the next block location.
This function is new to me and certainly seems useful for general processing of ... blocks of matrices. Kind of like a block matrix version of arrayfun. Simple 2D example to diagonalize each 2 x 2 block.
A = reshape(1:16,4,4);
size(A)
ans = 1×2
4 4
B = blockproc(A,[2 2],@(S) diag(diag(S.data)))
B = 4×4
1 0 9 0 0 6 0 14 3 0 11 0 0 8 0 16
I don't ever see any need in my work for padding or borders so I never use those options.
Strange. In my experience, blockproc is extraordinarily slow and there are often much faster options. That's why I created this FEX submission (see demo below). The only instances I can imagine it being useful is when you do need a border on your blocks.
A=rand(4000);
bsz=[4,4]; %blocksize
msk=eye(4);
fun=@(s)s.data.*msk;
tic;
out1=blockproc(A,bsz,fun);
toc
Elapsed time is 5.224310 seconds.
tic;
tmp= blkReshape(A,bsz,1,1,[]).*msk ;
out2=blkReshape(tmp,bsz, blkSize(A,bsz));
toc
Elapsed time is 0.149759 seconds.
Error=max(abs(out1-out2),[],'all')
Error =
0

Sign in to comment.

More Answers (0)

Products

Release

R2022a

Tags

Asked:

on 24 Dec 2022

Edited:

on 25 Dec 2022

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!