General Blockproc questions that aren't in the documentation

I have 4 question's regarding Blockproc.
1: When you take an image and break it up into smaller images (ROI's) to use blockproc, what is the exact order of the smaller images
In my image below, the yellow box is "top-left"
Q2: Also, is there away to show grid lines like above just to verify where blockproc has operated?
Q3: Is it possible to use blockproc and NOT operate on all the smaller images, i.e. just the images where the cyan circles are?
Q4: Can you combine functions so blockproc doesn't have to run twice, e.g.:
fun = @(block_struct) mean2(block_struct.data);
AVG = blockproc(IM2,[500 500],fun,'UseParallel',true);
fun2 = @(block_struct) std2(block_struct.data);
SD = blockproc(IM2,[500 500],fun2,'UseParallel',true)
Thanks
Jason

 Accepted Answer

1) The output placement is always deterministic (each block goes back to its original spatial position).
The order in which your function handle is invoked is typically that raster order (i.e. left to right), but is not something you should rely on if parallelization / internal scheduling is involved (e.g., if you use UseParallel or if MATLAB changes scheduling for performance). Therefore: rely on block_struct.location (and sizes) rather than a “counter” to infer order.
2) Of course you can add a border to each subimage:
I = imread('cameraman.tif');
bs = [64,64];
J = blockproc(I, bs, @(s) addBorderGray(s,128));
imshow(J);
function out = addBorderGray(block_struct, val)
out = block_struct.data;
out(1,:) = val; % top
out(end,:) = val; % bottom
out(:,1) = val; % left
out(:,end) = val; % right
end
3) of course: within the blockproc function you can add whatever image detection code you want... and also make decisions based on the results of that code. In your case: detect the cyan, the use IF to do something special with those subimages and ELSE to return other subimages unchanged.
4) Write your code in an Mfile, not an anonymous function, then you can combine as many operations as you want.

4 Comments

Thankyou Stephen, some followup comments.
1:Please could you expand on this.
Therefore: rely on block_struct.location (and sizes) rather than a “counter” to infer order.
Im basically after a heatmap of e..g the std2 values of each sub image, but the heatmap must map to exactly the same parts on the image
2: For the border, that a fantastic idea, however its not working straight off. My image is a 12 bit tif on a uiaxes.This is my code with your suggstion added. How do I get it to add onto the image currently on my uiaxes?
ax=app.UIAxes;
IM=getimage(ax);
[sy,sx]=size(IM);
% Image needs cropping to remove perimeter artefacts.
xl=415; xr=10656; yt=0; yb=0; % For TDI image crop %% xl=400; xr=10650; yt=0; yb=0; LAura: 450 & 5035
rect=[xl, yb, xr-xl,sy-yt-yb]; %[x, y, width, height]
rectangle(ax,'Position',rect, 'EdgeColor','y','LineWidth',1);
pause(0.1);
IM2=imcrop(IM,rect);
cla(ax,'reset'); %Clear
myImagesc(app, ax, IM2); cl=[0.15,0.15,0.2]; ax.Color=cl; drawnow;
fun = @(block_struct) mean2(block_struct.data);
I2 = blockproc(IM2,[500 500],fun,'UseParallel',true);
fun2 = @(block_struct) std2(block_struct.data);
SD = blockproc(IM2,[500 500],fun2,'UseParallel',true)
bs = [500,500];
J = blockproc(IM2, bs, @(s) addBorderGray(s,128));
4: Sorry, I don't follow this:
Write your code in an Mfile, not an anonymous function, then you can combine as many operations as you want.
"Im basically after a heatmap of e..g the std2 values of each sub image, but the heatmap must map to exactly the same parts on the image"
Blockproc does not randomly mix up the subimages, if that is what you concern is. Whatever operation/s you perform using blockproc will end up in the corresponding location in the output image. That is the whole point.
"How do I get it to add onto the image currently on my uiaxes?"
Replace the image data in the uiaxes.
"Sorry, I don't follow this:"
Place MEAN2, STD2, and whatever else you want in that function file.
Call that function file from blockproc.
Place MEAN2, STD2, and whatever else you want in that function file.
OK thanks, so like this:
[SD, mn] = myFun(app,block_struct)
SD = std2(block_struct.data);
mn = mean2(block_struct.data);
And then call it lke this:
bs=[500 500]
[SD,mn] = blockproc(IM2,bs,myFun,'UseParallel',true);
My main code is in a pushbutton callback, and myFun is a method in my app, hence the "app" argument
"And then call it lke this:"
No, blockproc only supports one output argument. But there is nothing stopping you from making your function return a vector or small matrix of results from any calculations. Then you would get a matrix which consists of those different results interlaced together, which can be retrieved using basic indexing:
I = imread('cameraman.tif');
bs = [64,64];
fh = @(bs) [mean2(bs.data),std2(bs.data)];
J = blockproc(I, bs, fh);
Jmean = J(:,1:2:end)
Jmean = 4×4
167.3821 153.7048 169.9453 159.2217 126.1189 32.4487 130.4160 155.5337 80.6594 50.1492 126.0491 132.7637 86.0100 86.2617 123.4392 119.4883
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
Jstd = J(:,2:2:end)
Jstd = 4×4
6.8601 61.9769 31.7836 6.5953 68.7267 46.5268 63.4436 9.8767 67.0647 63.4185 54.8252 40.0863 52.7884 59.6727 30.1970 21.3049
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
Checking "by hand":
mean2(I(1:64,1:64))
ans = 167.3821
std2(I(1:64,1:64))
ans = 6.8601

Sign in to comment.

More Answers (2)

You can use xline and yline in a for loop to overlay your red lines over the image. blockproc will not do that for you.
To do just certain block columns I'd probably just extract those columns into a new image and then process the whole image
threeColumns = grayImage(:, [col1:col2, col3:col4, col5:col6]);
though you can have blockproc "jump" or "overlap" blocks. See attached demos particularly the one that overlaps. Set the overlap to be positive instead of negative or vice versa so it jumps ahead rather than overlaps. I think you'll need two jump values, one for the rows of 0 and one for the columns of almost half the image width.
If you still need help, say so.

3 Comments

thankyou, I will try this first and see how I get on:
threeColumns = grayImage(:, [col1:col2, col3:col4, col5:col6]);
Also:
You can use xline and yline in a for loop to overlay your red lines over the image. blockproc will not do that for you.
this seems easy enough, but i need to know which corner of the image to start with
Start with row 1 and column 1
grayImage = imread('moon.tif');
imshow(grayImage);
[rows, columns] = size(grayImage)
rows = 537
columns = 358
stepWidth = 20;
for row = 1 : stepWidth : rows
yline(row, 'Color', 'r');
end
for col = 1 : stepWidth : columns
xline(col, 'Color', 'r');
end
Thankyou I.A. As i have 100s of images, I found this way was much faster:
k=1:numBlocksAcross;
axis(ax,'image');
xline(ax,k*blockSizeAcross,'r--'); drawnow;
k=1:numBlocksTall;
yline(ax,k*blockSizeDown,'r--'); drawnow;

Sign in to comment.

Is it also possible to "exclude" and sub images that aren't full size (i,e where the red crosses are)
(without rezising/imcrop the raw image)

8 Comments

"Is it also possible to "exclude" and sub images that aren't full size (i,e where the red crosses are)"
All blocks are processed ,but there is nothing stopping you from returning some kind of magic number which has a special meaning.
I = imread('cameraman.tif');
bs = [71,71];
% Just to show the block sizes on the image:
J = blockproc(I, bs, @(s) addBorderGray(s,128));
imshow(J);
For example, lets get the mean of all full-sized blocks and return NaN for all smaller blocks:
K = blockproc(I, bs, @(s) getMean(s,bs))
K = 4×4
168.1321 144.5818 170.4723 NaN 109.4805 42.7750 148.6983 NaN 66.8451 80.2162 120.4668 NaN NaN NaN NaN NaN
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
And, exactly as I wrote in my answer, you can check anything in that conditional: size, color, etc.
function out = getMean(s,bs)
if isequal(s.blockSize,bs)
out = mean2(s.data);
else
out = NaN;
end
end
function out = addBorderGray(s, val)
out = s.data;
out(1,:) = val; % top
out(end,:) = val; % bottom
out(:,1) = val; % left
out(:,end) = val; % right
end
Thankyou, thats great. One last question. How would i run a function of the form Myanalysis(app,IM) Would i call it in blockproc as Fun=app.Myanalysis(blocdata)
If you use PadPartialBlocks together with 'PadMethod', nan then taking the mean or std of a padded partial block will return nan (because mean or std of data that includes nan, results in nan). In that way you would not need special code to check the size.
3thanks Walter, thats a nice idea.
Using mean2 and std2 was just for illustration.
My real function actually takes the FFT of each sub image and performs a few more operations. So Im going to have to see whether having a sub image consisting of partial NaN's will return a NaN. Maybe theres a way where I can check for the presence of any NaN's in the sub image?
perhaps
anynan(Image)
Hi Walter, I've tried implementing your NaN idea, but it errors:
I2 = blockproc(IM2,bs,fun,'UseParallel',true,'PadPartialBlocks',NaN);
NaN values cannot be converted to logicals.
Error in blockprocInMemory (line 35)
if pad_partial_blocks && row_padding > 0
^^^^^^^^^^^^^^^^^^
Error in blockproc (line 251)
result_image = blockprocInMemory(source,fun,options);
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Error in HTS_TestSoftware/Button4Pushed (line 26121)
I2 = blockproc(IM2,bs,fun,'UseParallel',true,'PadPartialBlocks',NaN);
I would need to see the code for blockProcInMemory

Sign in to comment.

Products

Release

R2024b

Tags

Asked:

on 22 Jan 2026

Commented:

on 25 Jan 2026

Community Treasure Hunt

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

Start Hunting!