Reputation: 1335
I have a binary image, lets say 512x512px. I want to calculate pair correlation g(x). So far I'm doing it in as primitive as inefective way, line by line:
function Cr = pairCorr(image)
domains = imread(image); % read image
domains(domains>0) = 1; % make sure its binary by setting 1 to values > 0
size = length(domains(:, 1)); % image size
for i=1:size
line = domains(:, i); % take one line...
for j=1:size % and for each distance...
s = line(1:end-size+j);
Cr(i, j) = mean(s); %...calculate Cr as mean
end
end
Cr = mean(Cr); % average all lines
Any idea how to do it a bit faster? Thanks!
Upvotes: 1
Views: 1548
Reputation: 45752
Your code (from the loops on) seems to be to be the same as
Cr = mean(bsxfun(@rdivide, cumsum(domains), (1:n)'));
where my n
is your size
. Don't use size as a variable name in matlab as it's a very useful function. For example you went length(domains(:,1))
but you could have gone size(domains, 2)
What is my code doing:
cumsum(domains)
finds a cumulative sum down each column. So that's like doing your for j=1:size s = line(1:end-size+j); Cr(i, j) = mean(s); end
in one shot for the whole matrix. But with sum
instead of mean
. So to convert a vector of cumulative sums to means we must divide each element by the column number. So we want to divide by the vector 1:n. bsxfun
allows us to perform an operation on each slice of a dimension of a matrix. So in the 2D case on each column it allows to divide (that's the @rdivide
) by another constant column, i.e. (1:n)'
.
Here is a test showing equivalence:
n = 512;
A = rand(n);
A(A > 0.5) = 1;
A(A <= 0.5) = 0
tic
Cr1 = mean(bsxfun(@rdivide, cumsum(A)', (1:n)));
toc
tic
for i=1:n
line = A(:, i);
for j=1:n
s = line(1:end-n+j);
Cr2(i, j) = mean(s);
end
end
Cr2 = mean(Cr2)
toc
mean(mean(Cr1 == Cr2))
Results:
Elapsed time is 0.016396 seconds.
Elapsed time is 75.2006 seconds.
So although this is only for 1 run it gives you a speed up of like 4500 which is pretty good I think
Upvotes: 1