5

Blockproc is a really useful function for "gridding" an image in MATLAB. It's pretty well documented, and it even comes complete with a tutorial page. However, when you want some sort of overlap between blocks, things get trickier. The Mathworks forums have some explanations, including this one and this one, and there's an attempt at an explanation here (Question #1), but nobody really explains anywhere why certain flags need to be set with other ones. Can someone please explain what the purpose of the 'BorderSize' parameter is? It seems that when 'Trim Borders' is set to false, the 'BorderSize' parameter does exactly what the documentation says (and what you'd expect):

'BorderSize': A two-element vector, [V H], specifying the amount of border pixels to add to each block. The function adds V rows above and below each block and H columns left and right of each block. The size of each resulting block will be: [M + 2*V, N + 2*H]

By default, the function automatically removes the border from the result of fun. See the 'TrimBorder' parameter for more information. The function pads blocks with borders extending beyond the image edges with zeros.

But when you read the 'TrimBorder' details, it doesn't clear up much:

'TrimBorder': A logical scalar. When set to true, the blockproc function trims off border pixels from the output of the user function, fun. The function removes V rows from the top and bottom of the output of fun, and H columns from the left and right edges. The 'BorderSize' parameter defines V and H. The default is true, meaning that the blockproc function automatically removes borders from the fun output.

Why would I want to include a 'BorderSize' (i.e. overlap tiles) but not apply it to the output? Is this just a poorly explained flag: 'TrimBorder' must be off in order to use 'BorderSize', or is there something bigger I'm missing? I guess the gist of my confusion is: when would I want 'TrimBorder' set to false?

Examples:

% Non-overlapping
A = ones(10);
B = blockproc(A, [2,2], @(x)sum(sum(x.data)));
% B = 
% [ 4 4 4 4 4 ]
% [ 4 4 4 4 4 ]
% [ 4 4 4 4 4 ]
% [ 4 4 4 4 4 ]
% [ 4 4 4 4 4 ]

% GOOD Overlapping--one-pixel border
B = blockproc(A, [2,2], @(x)sum(sum(x.data)), 'BorderSize', [1,1], 'TrimBorder', false);
% B =
% [ 9  12 12 12 9  ]
% [ 12 16 16 16 12 ]
% [ 12 16 16 16 12 ]
% [ 12 16 16 16 12 ]
% [ 9  12 12 12 9  ]

% BAD Overlapping--one-pixel border
B = blockproc(A, [2,2], @(x)sum(sum(x.data)), 'BorderSize', [1,1]);
% B = []
Community
  • 1
  • 1
marcman
  • 3,233
  • 4
  • 36
  • 71

2 Answers2

5

Why would I want to include a 'BorderSize' (i.e. overlap tiles) but not apply it to the output?

Consider all the workflows where you want to apply a function fun on each block of size MxN in an image, but for the result to be valid you actually need the border pixels around the MxN block. (filtering, morphology, any function where a single output pixel value depends on a mxn surrounding neighborhood). i.e you need (M+m, N+n) block of input to compute one MxN output block.

Simple (aka madeup) example:

h = fspecial('gaussian', 3);
im = imread('peppers.png');
B1 = blockproc(im, [20 20], @(bs)imfilter(bs.data,h));
imshowpair(im, B1,'montage');

enter image description here

Notice the grid lines? In this particular case, you would just call imfilter on the full image. But blockproc lets you work with images which are larger than your physical memory. So for this discussion, imagine im is a huge tiff file.

For this workflow - if you just used BorderSize to include the 3 pixels border around each 20x20 block and did not trim the output border:

h = fspecial('gaussian');
im = imread('peppers.png');
B1 = blockproc(im, [20 20], @(bs)imfilter(bs.data,h), 'BorderSize', [3 3], 'TrimBorder', false);
imshowpair(im, B1,'montage');

enter image description here

So - you really need to trim the border (the default)

h = fspecial('gaussian');
im = imread('peppers.png');
B1 = blockproc(im, [20 20], @(bs)imfilter(bs.data,h), 'BorderSize', [3 3], 'TrimBorder', true);
imshowpair(im, B1,'montage');

enter image description here

Note - I used IMFILTER as an example. For small images, one would use IMFITLER directly. Only for images that are large would one consider using IMFITLER in BLOCPROC.

Ashish Uthama
  • 1,331
  • 1
  • 9
  • 14
  • This is a great answer. In general if your output block from your block function is supposed to be the same size at the input block, you're going to probably want to trim your borders. If your block function is fundamentally changing the data coming out (as in your case, where you are taking in a whole block and returning a scalar value) you likely will NOT want to trim the borders. There's no real magic happening. If TrimBorder is set to true then after your block function returns the output it will be "trimmed" by the border size. In your case your entire output was "trimmed" away. – brendan Jan 14 '16 at 21:26
  • This is a very detailed answer, thank you! Can you explain the behavior in my "bad" example though? Why did leaving 'TrimBorder' on result in an empty matrix output? – marcman Jan 15 '16 at 18:55
  • Sorry, I missed addressing that. Its essentially what @brendan said above - TrimBorder=true will attempt to 'remove' the Bordersize ([1 1]) from the output of your function, which is already a scalar, hence the actual output is []! – Ashish Uthama Jan 18 '16 at 01:25
0

Just in case you are looking for getting an overlapping block and saving it-

    function cropSaveBlock(bs,ii) 
   subBlockRegion =(bs.data(:,:));
   fileName = [strrep(num2str(bs.location,ii),' ','_') '.jpg'];
   imwrite(subBlockRegion, fileName);
   end
    a = imread('cameraman.tif');

ii=[1-whatever u want file name] %[1:20] if your image has 20 resulting blocks

aa=blockproc(a, [257 257], @(bs)cropSaveBlock(bs,ii),'BorderSize', [10 10 ])

%Here, the bordersize is x, y 10 ,10-of the whole image a- not of the blocks

h612
  • 544
  • 2
  • 11