Weird Behaviour of Parallel Processing when Using BlockProc

Hello, I a trying to speed up some analysis of an image (4700 v 128 pixels) that needs breaking up into smaller regions (20x128 pixels) and for each region having a calculation done such as the standard deviation (std2)
I thought the combination of Blockproc and the parallel toolbox would be ideal for this.
However, when I run my analysis, I sometmes get a fast completion time of 0.25s, but other times I run it it can take upto 3s.
1: When I start up my matlab session, i start a parallel pool:
% For parallel Processing (init parpool here)
delete(gcp('nocreate')); % but delete any that are already running
c=parcluster('local');
numwks=c.NumWorkers;
ReportMessage(app,['Parallel processing: NumWorkers = ',num2str(numwks)]);
parpool('Processes',numwks);
p=gcp;
conn=p.Connected;
ReportMessage(app,['...Connected ',num2str(conn)]);
2: I then run my fucntion from a push button callback.
My function first gets an image off a uiaxes, crops it and then performs the blockproc.
% Fast Analysis (SD)
tstart=tic;
ax=app.UIAxes;
IM=getimage(ax);
[sy,sx]=size(IM);
xl=5950; xr=10680; yb=0; yt=0; dx=xr-xl; % This is for image cropping
rect=[xl, yb, xr-xl,sy-yt-yb]; %[x, y, width, height]
IM2=imcrop(IM,rect);
IM=IM2-min(IM2(:)); % Background subtract
[sy,sx]=size(IM);
ColSize=20; % Number of pixels in each ROI - 20 default
nCols=floor(sx/ColSize);
RowSize = 128;
%BlockProc with Parallel
bss = [RowSize,ColSize]; % Each blockproc region
fh = @(bs) std2(bs.data); % perform this on each block
J = blockproc(IM, bss, fh,'UseParallel',true);
sd=J'; % Column vector
ReportMessage(app,num2str(toc(tstart)));
Is there something I am doing wrong? Do I need to close and reopen the parpool everytime or something.
Also, if I want the fh function to be a functio that has more than 1 argument, how do I do the syntax.
For example, I have a function (that works fine by itself)
Brenner=fmeasure(Image,'BREN',[]); %Focus metric
And I have tried to call it into Blockproc via:
fh = @(bs) fmeasure(bs.data,'BREN',[]);
It doesn't work properly.

1 comentario

"Also, if I want the fh function to be a functio that has more than 1 argument, how do I do the syntax."
If you mean this function:
then it works without error using the syntax you showed:
im = rand(128,4700);
s1 = blockproc(im,[128,20],@(bs)fmeasure(bs.data,'BREN',[]))
s1 = 1×235
0.1589 0.1560 0.1617 0.1616 0.1503 0.1561 0.1550 0.1609 0.1597 0.1552 0.1595 0.1543 0.1585 0.1518 0.1560 0.1548 0.1673 0.1553 0.1623 0.1634 0.1598 0.1545 0.1561 0.1593 0.1552 0.1567 0.1624 0.1546 0.1563 0.1514
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>

Iniciar sesión para comentar.

 Respuesta aceptada

Stephen23
Stephen23 el 17 de Mzo. de 2026 a las 14:35
Editada: Stephen23 el 17 de Mzo. de 2026 a las 14:57
I doubt that your example is good use of the parallel toolbox. Parallel code can be slower than serial code due to high communication overhead, small task sizes, or data serialization. It may be inefficient when workers send data back to the client frequently or when the overhead of starting a parallel pool outweighs the computation time. And your example has a small task size.
"...analysis of an image (4700 v 128 pixels) that needs breaking up into smaller regions (20x128 pixels)..."
RESHAPE and STD would be simpler and likely faster:
im = rand(128,4700);
tic
jm = reshape(im,128,20,[]);
s0 = std(jm,0,[1,2]);
toc
Elapsed time is 0.027938 seconds.
tic
s1 = blockproc(im,[128,20],@(bs)std2(bs.data));
toc
Elapsed time is 0.105474 seconds.
isequal(s0(:),s1(:))
ans = logical
1
A FOR loop could be useful too:
for k = 1:size(jm,3)
m = jm(:,:,k);
% do whatever with m
end
... which can be trivially converted to a PARFOR:

29 comentarios

Jason
Jason hace 20 minutos
Editada: Jason hace 15 minutos
Oh wow thats amazing. I did a time comparison on your S0 and S1 and get much faster times when using S0 (i.e. the reshape)
Elapsed time is 0.018587 seconds.
Elapsed time is 0.166048 seconds.
why is that, I thought Blockproc was the ultimate - obviously not.!
Could it be the use of std rather than std2?
Also, is there anything obviously wrong with my parallel toolbox approach - why do i sometimes see fast and other times slow.
Stephen23
Stephen23 hace 12 minutos
Editada: Stephen23 hace 8 minutos
"why is that, I thought Blockproc was the ultimate - obviously not.!"
BLOCKPROC splits up data, calls functions repeatedly, works with relatively complex data types, and would have to have a lot of input/error handling. Based on that alone I would assume that it is not very fast. Convenient perhaps, but not fast.
"Could it be the use of std rather than std2?"
I doubt it. It is understanding how data is stored, avoiding splitting data up, avoiding calling functions lots of times, avoiding parallel toolbox for small tasks, using RESHAPE to make data convenient to access, maximising speed by performing multiple operations with single (inbuilt, highly optimised) function calls by using their options, and various other things that one learns. These are the native and natural ways to use MATLAB efficiently.
When a user comes onto this forum as writes "my code is slow and I tried to speed it up using the parallel toolbox" then they have usually misunderstood MATLAB as well as what parallel processing requires and when to apply it.
Thankyou!
Sorry, one last question, how do I get the sd values from here into a column vector (without using loops)?
s0 = std(jm,0,[1,2]);
[sy,sx,sz]=size(s0)
idx=(1:sz)'
figure
sd=s0(:,:,idx)
plot(sd)
This didn't work
im = rand(128,4700);
jm = reshape(im,128,20,[]);
s0 = std(jm,0,[1,2]);
size(s0)
ans = 1×3
1 1 235
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
sd = s0(:)
sd = 235×1
0.2883 0.2886 0.2886 0.2895 0.2908 0.2870 0.2869 0.2890 0.2892 0.2878 0.2852 0.2828 0.2901 0.2901 0.2901
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
hold on
plot(sd)
plot(1/sqrt(12)*ones(size(sd)))
hold off
Jason
Jason hace alrededor de 6 horas
Editada: Jason hace alrededor de 2 horas
thankyou
Btw, where does this come from?
plot(1/sqrt(12)*ones(size(sd)))
Jason
Jason hace alrededor de 3 horas
Editada: Jason hace alrededor de 3 horas
Actually, im really sorry but Im still running into an error using the reshape approach
My actual image is 4730 pixels wide (not 4700) and 128 pixels high.
I want each sub region to be 20 pixels wide and 128 pixels high like in the picture below
I tried this:
[sy,sx]=size(IM);
nRows=floor(sy/128);
nCols=floor(sx/20);
jm = reshape(IM,nRows,nCols,[]); % reshape = rows, then cols
Error using reshape
Product of known dimensions, 236, not divisible into total number of elements, 605568.
Torsten
Torsten hace alrededor de 1 hora
Editada: Torsten hace alrededor de 1 hora
You must take nRows and nCols such that their product gives 4730.
factor(4730)
ans = 1×4
2 5 11 43
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
Thus nRows = 2, nCols = 5*11*43 or nRows = 2*5, nCols = 11*43 or nRows = 5*11, nCols = 2*43 or ... is allowed.
Or you must cut some part of the image.
Jason
Jason hace alrededor de 1 hora
OK, thankyou.
Stephen23
Stephen23 hace alrededor de 6 horas
Editada: Stephen23 hace alrededor de 3 horas
The error message states:
"Product of known dimensions, 236, not divisible into total number of elements, 605568."
Note that the function RESHAPE simply changes the dimension sizes of an array, without adding or removing any data.
Now consider your image, whch contains NP many pixels (where NP does not match your comment):
im = rand(128,4730);
sz = size(im);
np = prod(sz)
np = 605440
Now lets look at what you attempted with those NP pixels:
[sy,sx] = size(im);
nRows = floor(sy/128)
nRows = 1
nCols = floor(sx/20)
nCols = 236
So you attempted to reshape NP elements into an array with 1 row, 236 columns, and some unknown number of pages. But is NP divisble by 1 and 236 ? Well, 1 is trivial, but 236 lets check if there is any remainder:
mod(np,nCols)
ans = 100
Nope, the number of rows and columns that you attempted to reshape IM into will not work because they cannot evenly divide the number of pixels of IM. That is the cause of the error: RESHAPE cannot create the size array that you requested, because it would require either inventing more data or removing it, which RESHAPE does not do.
Also note that your concept of how to specify the number of rows and columns is unlikely to help you, as should be clear when you perform some basic sanity check, e.g. by asking yourself "why am I reshaping all of the pixels into one row?". You should be counting pixels.
Jason
Jason hace alrededor de 2 horas
Editada: Jason hace alrededor de 2 horas
Thankyou for an excellent explanation (and toTorsten).
Ive decided to crop my image so its exactly divisible.
I love how the std you showed uses pages. If i wanted to calculate the Brenner metric instead of the std, how would I do that. It seens std allows for "paging" but its not obvious how the fmeasure function allows for it.
Just to add, you've blown me away with your example being so much faster than blockproc.
Stephen23
Stephen23 hace alrededor de 3 horas
Editada: Stephen23 hace alrededor de 2 horas
"If i wanted to calculate the Brenner metric instead of the std, how would I do that. It seens std allows for "paging" but its not obvious how the fmeasure function allows for it."
I would skip FMEASURE entirely. If speed is important to you then I would start with a simple FOR loop, which is likely to give reasonable speed, give you a good baseline, and be easy to implement:
im = rand(128,4700);
tic
rn = 128;
cn = 20;
jm = reshape(im,rn,cn,[]);
pn = size(jm,3);
b0 = nan(pn,1);
for k = 1:pn
m = jm(:,:,k);
a = m(3:end,:)-m(1:end-2,:);
b = m(:,3:end)-m(:,1:end-2);
a(rn,1) = 0;
b(1,cn) = 0;
b0(k) = mean2(max(a,b).^2);
end
toc
Elapsed time is 0.014675 seconds.
b0
b0 = 235×1
0.1600 0.1487 0.1606 0.1542 0.1573 0.1644 0.1561 0.1576 0.1584 0.1644 0.1544 0.1584 0.1542 0.1596 0.1567
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
"where does this come from?"
It is the expected standard deviation of a continuous uniform distribution U(a,b) between a=0 and b=1. The variance of the uniform distribution is which for those a & b gives . The standard deviation is therefore just the square root of that.
Jason
Jason hace alrededor de 2 horas
Editada: Jason hace alrededor de 2 horas
Wow! Could I ask 1. Why do you suggest not using fmeasure? 2. Could you explain your FOR loop please and what that end metric actually is? Thankyoy
Stephen23
Stephen23 hace alrededor de 12 horas
Editada: Stephen23 hace alrededor de 12 horas
1) because a) inline code tends to be slightly faster than calling a function (as explained here), b) the code for Brenner's metric is fairly simple (just a few lines), c) you can avoid third-party code dependency, d) you may be able to improve/tailor the implementation, e) you learn something about writing code.... and maybe some other reasons. One code-writing rule-of-thumb is do not reinvent the wheel, but this is balanced aginst other rules-of-thumb, such that if you have different priorities (e.g. speed) then tighter coupling actually becomes more useful. In this case there really is nothing stopping you from replacing the entire content of the FOR-loop with an FMEASURE call (which then gets called multiple times).
2) Which part of the loop? The loop preallocates an output vector b0 with NaNs:
then loops over each page of the RESHAPEd image data, storing it in the temporary variable m. Each m is a matrix with size 128x20, which AFAICT is the subimage that you want to process. To calculate Brenner's metric I just looked at the code in FMEASURE, tweaked it, and checked it with an AI tool (btw, you can also look inside FMEASURE). The end metric is Brenner's metric. The metric value is stored in the preallocated vector, there is a vector of them because you have multiple subimages.
But you should not take my word for it: check everything yourself! You can check the size of m yourself using SIZE. You can perform a sanity check on the content of a subimage by extracting the last subimage yourself:
w = im(:,end-19:end);
isequal(m,w)
ans = logical
1
You can perform a sanity check on the metric by comparing the last metric with the output from FMEASURE:
b1 = fmeasure(m,'BREN',[])
b1 = 0.1605
isequal(b0(end),b1)
ans = logical
1
You can learn more about FOR loops here:
You can practice FOR loops here:
Thankyou again. I have taken your advice and performed a sanity check, but am getting a different value using fmeasure (quite a large difference too)
im = rand(128,4700);
% Reshape Way
t1=tic;
rn = 128;
cn = 20;
jm = reshape(im,rn,cn,[]);
pn = size(jm,3);
b0 = nan(pn,1);
for k = 1:pn
m = jm(:,:,k);
a = m(3:end,:)-m(1:end-2,:);
b = m(:,3:end)-m(:,1:end-2);
a(rn,1) = 0;
b(1,cn) = 0;
b0(k) = mean2(max(a,b).^2);
end
tend1=toc(t1);
ReportMessage(app,['Reshape: in ',num2str(tend1),' s']); % my own function
% Now fmeasure way
t2=tic;
rn = 128;
cn = 20;
jm = reshape(im,rn,cn,[]);
for k = 1:pn
m = jm(:,:,k);
FM(k)=fmeasure(m,'BREN',[]); %Focus metric
end
tend2=toc(t2);
ReportMessage(app,['Brenner: in ',num2str(tend2),' s']);
disp(' Reshape:')
head(b0(:))
disp(' Fmeasure:')
FM=FM';
head(FM(:))
size(b0)
size(FM)
And here is the output:
Reshape:
0.1589
0.1504
0.1602
0.1537
0.1655
0.1584
0.1565
0.1558
Fmeasure:
0.4994
0.4920
0.4837
0.5001
0.4974
0.4898
0.4979
0.4873
ans =
235 1
ans =
235 1
Stephen23
Stephen23 hace alrededor de 9 horas
Editada: Stephen23 hace alrededor de 9 horas
Using this function here:
and running on this forum I get:
im = rand(128,4700);
% reshape
rn = 128;
cn = 20;
jm = reshape(im,rn,cn,[]);
pn = size(jm,3);
b0 = nan(pn,1);
for k = 1:pn
m = jm(:,:,k);
a = m(3:end,:)-m(1:end-2,:);
b = m(:,3:end)-m(:,1:end-2);
a(rn,1) = 0;
b(1,cn) = 0;
b0(k) = mean2(max(a,b).^2);
end
% fmeasure
b1 = nan(pn,1);
for k = 1:pn
m = jm(:,:,k);
b1(k) = fmeasure(m,'BREN',[]);
end
% comparison:
b0
b0 = 235×1
0.1556 0.1557 0.1571 0.1562 0.1526 0.1576 0.1575 0.1608 0.1640 0.1650 0.1478 0.1568 0.1575 0.1584 0.1592
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
b1
b1 = 235×1
0.1556 0.1557 0.1571 0.1562 0.1526 0.1576 0.1575 0.1608 0.1640 0.1650 0.1478 0.1568 0.1575 0.1584 0.1592
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
isequal(b0,b1)
ans = logical
1
Hi, Im using exactly the same fmeasure, and here is the "Bren" part. This has foxed me!
case 'BREN' % Brenner's (Santos97)
[M N] = size(Image);
DH = Image;
DV = Image;
DH(1:M-2,:) = diff(Image,2,1);
DV(:,1:N-2) = diff(Image,2,2);
FM = max(DH, DV);
FM = FM.^2;
FM = mean2(FM);
Stephen23
Stephen23 hace alrededor de 9 horas
Editada: Stephen23 hace alrededor de 8 horas
It occured to me that you might be providing integer class image data for your actual data, in which case convert it to DOUBLE before running the FOR loop, for example:
jm = reshape(double(im),rn,cn,[]);
I just did some reading about Brenner's metric, and it seems that the implementation in FMEASURE is flawed due to its MAX after squaring. It should square the values before the MAX (or adding them, or whatever).
Consider this carefully-picked example:
im = [10,0,10; 0,0,0; 5,0,5]
im = 3×3
10 0 10 0 0 0 5 0 5
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
fmeasure(im,'BREN',[]) % ZERO !!!!
ans = 0
This occurs because the MAX silently ignores large negative values:
% DH(:,1) = Image(:,3) - Image(:,1)
DH(:,1) = [10-10, 0-0, 5-5] = [0, 0, 0] % First col only; rest stay 0
% → DH is all zeros
% DV(1,:) = Image(3,:) - Image(1,:)
DV(1,:) = [5-10, 0-0, 5-10] = [-5, 0, -5] % First row only; rest stay 0
% → DV has real, significant gradients — but NEGATIVE
FM = max(DH, DV)
= max(0, -5) = 0 % ← the bug! -5 gets silently ignored
FM = mean2(0.^2) = 0
To avoid this square the values before the MAX:
a = im(3:end,:)-im(1:end-2,:);
b = im(:,3:end)-im(:,1:end-2);
a(3,1) = 0;
b(1,3) = 0;
mean2(max(a,b).^2) % wrong!
ans = 0
mean2(max(a.^2,b.^2)) % right!
ans = 5.5556
Some other divergences of FMEASURE from Santos et al:
  • it does not implement the gradient threshold v,
  • it uses MEAN2 in place of summation.
So I guess that adds another point to the list: f) because random code from the internet is not always reliable: you always need to check it thoroughly.
"This has foxed me!"
Step-by-step debugging: print critical values from each approach, work backwards until you pinpoint where they diverge.
Torsten
Torsten hace alrededor de 8 horas
It occured to me that you might be providing integer class image data
im = rand(128,4700);
?
Jason
Jason hace alrededor de 3 horas
Editada: Jason hace alrededor de 3 horas
Hmm, So I see the error you have pointed out with the Brenner calculation in the fmeasure function.
But 2 things bug me:
1: How come in your example above, you get the same values for b0 and b1?
im = rand(128,4700);
% reshape
rn = 128;
cn = 20;
jm = reshape(im,rn,cn,[]);
pn = size(jm,3);
b0 = nan(pn,1);
for k = 1:pn
m = jm(:,:,k);
a = m(3:end,:)-m(1:end-2,:);
b = m(:,3:end)-m(:,1:end-2);
a(rn,1) = 0;
b(1,cn) = 0;
b0(k) = mean2(max(a,b).^2);
end
% fmeasure
b1 = nan(pn,1);
for k = 1:pn
m = jm(:,:,k);
b1(k) = fmeasure(m,'BREN',[]);
end
% comparison:
b0
2: I spent all day trying to track down why Im not getting the same values as you but can't see anything wrong.
im = rand(128,4700);
% Reshape Way
rn = 128;
cn = 20;
jm = reshape(double(im),rn,cn,[]);
pn = size(jm,3);
b0 = nan(pn,1);
for k = 1:pn
m = jm(:,:,k);
a = m(3:end,:)-m(1:end-2,:);
b = m(:,3:end)-m(:,1:end-2);
a(rn,1) = 0;
b(1,cn) = 0;
b0(k) = mean2(max(a,b).^2);
end
% Now fmeasure way
rn = 128;
cn = 20;
jm = reshape(im,rn,cn,[]);
b1 = nan(pn,1);
for k = 1:pn
m = jm(:,:,k);
b1(k)=fmeasure((m),'BREN',[]); %Focus metric
end
disp(' Reshape:')
head(b0)
disp(' Fmeasure:')
head(b1)
Reshape:
0.1586
0.1559
0.1567
0.1555
0.1621
0.1543
0.1642
0.1622
Fmeasure:
0.7821
0.7611
0.7665
0.7806
0.7833
0.7503
0.7840
0.7819
Your implementation looks different from Brenner's row version:
function fm = brenner_measure(img)
% Brenner's formula: sum of squared differences 2 pixels apart
diffs = (img(1:end-2, :) - img(3:end, :)).^2;
fm = mean(diffs(:));
end
When you come across negative row and/or column differences your method can break down.
You may try to replace
b0(k) = mean2(max(a,b).^2);
with
b0(k) = mean2(max([a,b,0]).^2);
% or if you want to get upper bound
b0(k) = mean2(max([a,-a,b,-b]).^2);
and compare results
Jason
Jason hace alrededor de 2 horas
Editada: Jason hace alrededor de 2 horas
Thanks Nick, so I did as you suggested
(Are you saying the formula that Stephen kindly gave me is wrong)?
% Stephen's Brenner
for k = 1:pn
m = jm(:,:,k);
a = m(3:end,:)-m(1:end-2,:);
b = m(:,3:end)-m(:,1:end-2);
a(rn,1) = 0;
b(1,cn) = 0;
% b0(k) = mean2(max(a,b).^2); % Stephen's Original formula
b0(k) = mean2(max([a,b,0]).^2); % Nick's suggestion
end
Error using horzcat
Dimensions of arrays being concatenated are not consistent.
Error in HTS_TestSoftware/TestingButtonPushed (line 28012)
b0(k) = mean2(max([a,b,0]).^2);
Stephen23
Stephen23 hace alrededor de 1 hora
Editada: Stephen23 hace 37 minutos
"(Are you saying the formula that Stephen kindly gave me is wrong)?"
I did not give you any formula! Exactly as I wrote in this comment here, I copied the algorithm from FMEASURE. And FMEASURE quotes Santos et al., which I also downloaded. You can find it here:
You selected FMEASURE (which uses Santos et al's algorithm, although perhaps with some bugs), which my code exactly replicates (as demonstrated here).
"Your implementation looks different from Brenner's row version"
Of course it looks different, because it is different! Santos et al explicitly stated their text: "The first three functions (, , ) were slightly modified to consider both the horizontal and the vertical gradients". Brenner only considered the horizontal gradients, not the horiztonal gradients. But Santos et al stated that they modified this algorithm!
If you do not even know what algorithm you are using, how do you expect to verify its output?
Have you read Santos et al's paper yet?
"You may try to replace b0(k) = mean2(max(a,b).^2); with b0(k) = mean2(max([a,b,0]).^2);"
No, that won't work because it attempts to concatenate arrays with incompatible sizes. It also attempts to implement something quite different from what Santos et al specified.
" I spent all day trying to track down why Im not getting the same values as you but can't see anything wrong."
You will not find anything by looking all day at some code hoping to see something "wrong". That is not how debugging works.
You need to debug. I already explained an initial approach here.
One obvious start is to compare intermediate values. Have you done that? It should take about two minutes.
Hi Stephen, OK thanks.
BTW, I have already showed above which "Brenner" algo Im using from the fmeasure function
case 'BREN' % Brenner's (Santos97)
[M N] = size(Image);
DH = Image;
DV = Image;
DH(1:M-2,:) = diff(Image,2,1);
DV(:,1:N-2) = diff(Image,2,2);
FM = max(DH, DV);
FM = FM.^2;
FM = mean2(FM);
Im sorry if i incorrectly suggested "your" Brenner formula. What I mean't was after you kindly showed how to use reshape with std function, I asked how to also incorportate the fmeasure "Brenner" formula
You did mention to skip it and gve me what i assumed was something similar (and I just called it Stephen's Brenner)
"If i wanted to calculate the Brenner metric instead of the std, how would I do that. It seens std allows for "paging" but its not obvious how the fmeasure function allows for it."
I would skip FMEASURE entirely. If speed is important to you then I would start with a simple FOR loop, which is likely to give reasonable speed, give you a good baseline, and be easy to implement:
im = rand(128,4700);
tic
rn = 128;
cn = 20;
jm = reshape(im,rn,cn,[]);
pn = size(jm,3);
b0 = nan(pn,1);
for k = 1:pn
m = jm(:,:,k);
a = m(3:end,:)-m(1:end-2,:);
b = m(:,3:end)-m(:,1:end-2);
a(rn,1) = 0;
b(1,cn) = 0;
b0(k) = mean2(max(a,b).^2);
end
toc
Stephen23
Stephen23 hace alrededor de 2 horas
Editada: Stephen23 hace alrededor de 2 horas
@Jason: please run your code in this forum. Then I can help you to debug it.
"How come in your example above, you get the same values for b0 and b1?"
Because the code inside FOR-loop simply replicates that of FMEASURE.
sorry for sloppy comment — only idea, the code was not correct, just illustration…
a few details follow
for k = 1:pn
m = jm(:,:,k);
a = abs(m(3:end,2:end-1)-m(1:end-2,2:end-1)); % get absolute values
b = abs(m(2:end-1,3:end)-m(2:end-1,1:end-2)); % the same for columns
% a(rn,1) = 0;
% b(1,cn) = 0;
b0(k) = mean2(max(a,b).^2); % now it is correct, but not Brenner
% b0(k) = mean2(max([a,b,0]).^2); — my fault, was careless :
% were not scalar type
end
The original Brenner resembles function brenner_measure() in my previous post
Note that Nicks code discards data without warning. It also has the wrong denominator inside MEAN2.
Consider an image which has gradient only in the first row:
format long G
rn = 3;
cn = 3;
m = [0,4,8; 4,4,4; 4,4,4]
m = 3×3
0 4 8 4 4 4 4 4 4
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
0) Inline code, fixed FMEASURE bug:
a = m(3:end,:)-m(1:end-2,:);
b = m(:,3:end)-m(:,1:end-2);
a(rn,1) = 0;
b(1,cn) = 0;
fm0 = mean2(max(a.^2,b.^2))
fm0 =
8.88888888888889
1) inline code, same bug as FMEASURE:
fm1 = mean2(max(a,b).^2)
fm1 =
7.11111111111111
2) FMEASURE
fm2 = fmeasure(m,'BREN',[])
fm2 =
7.11111111111111
3) Not like anything else:
a = abs(m(3:end,2:end-1)-m(1:end-2,2:end-1)); % get absolute values
b = abs(m(2:end-1,3:end)-m(2:end-1,1:end-2)); % the same for columns
fm3 = mean2(max(a,b).^2)
fm3 =
0
So even though there is a valid gradient Nick's code does not detect it. The incorrect denominator is slightly more subtle, but is left as an exercise.
@Jason: please run your code in this forum. Then I can help you to debug it. "How come in your example above, you get the same values for b0 and b1?" Because the code inside FOR-loop simply replicates that of FMEASURE. How do I run my code in this forum? Ive never done that before
Stephen23
Stephen23 hace 11 minutos
Editada: Stephen23 hace 10 minutos
"How do I run my code in this forum? Ive never done that before"
Write the code in the message:
Optionally upload Mfiles:
Then click the RUN button:

Iniciar sesión para comentar.

Más respuestas (0)

Preguntada:

el 17 de Mzo. de 2026 a las 14:24

Editada:

hace 22 minutos

Community Treasure Hunt

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

Start Hunting!

Translated by