How to remove the for loop in the following MATLAB code? - performance

I need to perform the following computation in an image processing project. It is the logarthmic of the summation of H3. I've written the following code but this loop has a very high computation time. Is there any way to eliminate the for loop?
for k=1:i
for l=1:j
HA(i,j)=HA(i,j)+log2((H3(k,l)/probA).^q);
end;
end;
Thanks in advance!
EDIT:
for i=1:256
for j=1:240
probA = 0;
probC = 0;
subProbA = H3(1:i,1:j);
probA = sum(subProbA(:));
probC = 1-probA;
for k=1:i
for l=1:j
HA(i,j)=HA(i,j)+log2((H3(k,l)/probA).^q);
end;
end;
HA(i,j)=HA(i,j)/(1-q);
for k=i+1:256
for l=j+1:240
HC(i,j)=HC(i,j)+log2((H3(k,l)/probC).^q);
end;
end;
HC(i,j)=HC(i,j)/(1-q);
e1(i,j) = HA(i,j) + HC(i,j);
if e1(i) >= emax
emax = e1(i);
tt1 = i-1;
end;
end;
end;

Assuming the two loops are nested inside some other outer loops that are iterated with i and j (though using i and j as iterators are not the best practices) and also assuming that probA and q are scalars, try this -
HA(i,j) = sum(sum(log2((H3(1:i,1:j)./probA).^q)))
Using the above code snippet, yon can replace your actual code posted in the EDIT section with this -
for i=1:256
for j=1:240
subProbA = H3(1:i,1:j);
probA = sum(subProbA(:));
probC = 1-probA;
HA(i,j) = sum(sum(log2((subProbA./probA).^q)))./(1-q);
HC(i,j) = sum(sum(log2((subProbA./probC).^q)))./(1-q);
e1(i,j) = HA(i,j) + HC(i,j);
if e1(i) >= emax
emax = e1(i);
tt1 = i-1;
end
end
end
Note that in this code, probA = 0; and probC = 0; are removed as they are over-written anyway later in the original code.

Assuming that q is scalar value, this code removes all the four for loops. Also in your given code you are calculating the maximum value of e1 only along the first column. If that is so then you should put in out of the second loop
height = 256;
width = 240;
a = repmat((1:height)',1,width);
b = repmat(1:width,height,1);
probA = arrayfun(#(ii,jj)(sum(sum(H3(1:ii,1:jj)))),a,repmat(1:width,height,1));
probC = 1 - probA;
HA = arrayfun(#(ii,jj)(sum(sum(log2((H3(1:ii,1:jj)/probA(ii,jj)).^q)))/(1-q)),a,b);
HC = arrayfun(#(ii,jj)(sum(sum(log2((H3(ii+1:height,jj+1:width)/probC(ii,jj)).^q)))/(1-q)),a,b);
e1 = HA + HC;
[emax tt_temp] = max(e1(:,1));
tt1 = tt_temp - 1;

Related

I have a problem with a function in matlab

I'm depveloping a function in matlab, but I have the following problem.
When I assign the codigo variable to my function, matlab show me the next message
Error using ContLetrasTexto>shannon
Too many output arguments.
Error in ContLetrasTexto (line 111)
codigos = shannon(1, length(vectorprobabilidad), vectorprobabilidad, codigos);
My code is the following
% create the cell array of codes
codigos = cell(size(letra));
% call the recursive encoder function
codigos = shannon(1, length(vectorprobabilidad), vectorprobabilidad, codigos);
%Método shannon-Fano%
function shannon(inicio, fin, p, codes)
shannon_inicial = inicio;
shannon_final = fin;
suma_arriba = p(inicio);
suma_fin = p(fin);
while(shannon_inicial ~= shannon_final-1)
if (suma_arriba > suma_fin)
shannon_final = shannon_final - 1;
suma_fin = suma_fin + p(shannon_final);
else
shannon_inicial = shannon_inicial + 1;
suma_arriba = suma_arriba + p(shannon_inicial);
end;
end;
for i = inicio:shannon_inicial
p(i) = 0;
end;
for j = shannon_final:fin
p(j) = 1;
end;
if(shannon_inicial-inicio+1 > 1)
shannon(inicio,shannon_inicial,p,codes);
end;
if(fin-shannon_final+1 > 1)
shannon(shannon_final,fin,p,codes);
end;
end
I'll be grateful for your help

a program to apply the following transformation function to a grayscale image

I want to apply following transformation function to a grayscale image, i know how to apply it to the following function,
my question is how do i apply a program to the following transformation function,
code so far,
clear;
pollen = imread('Fig3.10(b).jpg');
u = double(pollen);
[nx ny] = size(u)
nshades = 256;
r1 = 80; s1 = 10; % Transformation by piecewise linear function.
r2 = 140; s2 = 245;
for i = 1:nx
for j = 1:ny
if (u(i,j)< r1)
uspread(i,j) = ((s1-0)/(r1-0))*u(i,j)
end
if ((u(i,j)>=r1) & (u(i,j)<= r2))
uspread(i,j) = ((s2 - s1)/(r2 - r1))*(u(i,j) - r1)+ s1;
end
if (u(i,j)>r2)
uspread(i,j) = ((255 - s2)/(255 - r2))*(u(i,j) - r2) + s2;
end
end
end
hist= zeros(nshades,1);
for i=1:nx
for j=1:ny
for k=0:nshades-1
if uspread(i,j)==k
hist(k+1)=hist(k+1)+1;
end
end
end
end
plot(hist);
pollenspreadmat = uint8(uspread);
imwrite(pollenspreadmat, 'pollenspread.jpg');
Thanks in advance
The figure says that for any intensities that are between A and B, they should be set to C. All you have to do is modify your two for loops so that for any values between A and B, set the output location to C. I'll also assume the range is inclusive. You can simply remove the first and last if conditions and use the middle one:
for i = 1:nx
for j = 1:ny
if ((u(i,j)>=r1) && (u(i,j)<= r2))
uspread(i,j) = C;
end
end
end
C is a constant that you would set yourself. Usually for segmentation, this result is very high to distinguish the foreground from the background. You have a uint8 image here, so C = 255; would work.
However, I would recommend you achieve a more vectorized solution. Avoid for loops and use logical indexing instead:
uspread = u;
uspread(u >= r1 & u <= r2) = C;

Faster matrix recursion in Matlab

The matrix-recursion of the n x n matrices Y_t looks like this:
Y_{t} = A + \sum_{i=1}^{p} B_{i} * Y_{t-i}
A and B are given.
This is my attempt, but it runs slowly:
Y = zeros(n,n,T); %Going to fill the 3rd dimension for Y_t, t=1:T
Y(:,:,1:p) = initializingY
for t=(p+1):T
Y(:,:,t) = A;
for i=1:p
Y(:,:,t) = Y(:,:,t) + B(:,:,i)*Y(:,:,t-i);
end
end
Can you think of a more efficient way to do this?
You can kill the inner loop with matrix-multiplication after some reshaping & permuting, like so -
Y = zeros(n,n,T);
%// Y(:,:,1:p) = initializingY
for t=(p+1):T
Br = reshape(B(:,:,1:p),n,[]);
Yr = reshape(permute(Y(:,:,t-(1:p)),[1 3 2]),[],n);
Y(:,:,t) = A + Br*Yr;
end
Short of using clever mathematical tricks to reduce the number of operations, the best shot is to optimize the memory access. That is: avoid subsrefing, increase the locality of your code, reduce the cache misses by manipulating short arrays instead of large ones.
n = 50;
T = 1000;
p = 10;
Y = zeros(n,n,T);
B = zeros(n,n,p);
A = rand(n);
for t = 1:p
Y(:,:,t) = rand(n);
B(:,:,t) = rand(n);
end
fprintf('Original attempt: '); tic;
for t=(p+1):T
Y(:,:,t) = A;
for k=1:p
Y(:,:,t) = Y(:,:,t) + B(:,:,k)*Y(:,:,t-k);
end;
end;
toc;
%'This solution was taken from Divakar'
fprintf('Using reshaping: '); tic;
Br = reshape(B(:,:,1:p),n,[]);
for t=(p+1):T
Yr = reshape(permute(Y(:,:,t-(1:p)),[1 3 2]),[],n);
Y(:,:,t) = A + Br*Yr;
end;
toc;
%'proposed solution'
Y = cell(1,T);
B = cell(1,p);
A = rand(n);
for t = 1:p
Y{t} = rand(n);
B{t} = rand(n);
end
fprintf('Using cells: '); tic;
for t=(p+1):T
U = A;
for k=1:p
U = U + B{k}*Y{t-k};
end;
Y{t} = U;
end;
toc;
For setups given in my example I get a two-fold speed increase for a decent machine (i5 + 4Gb, MATLAB R2012a). I am curious how well it does on your machine.

Matlab: How to convert nested far loop into parfor

I am having problems with the following loop, since it is taking too much time. Hence, I would like to use parallel processing, specifically parfor function.
P = numel(scaleX); % quite BIG number
sz = P;
start = 1;
sqrL = 10; % sqr len
e = 200;
A = false(sz, sz);
for m = sz-sqrL/2:(-1)*sqrL:start
for n = M(m):-sqrL:1
temp = [scaleX(m), scaleY(m); scaleX(n), scaleY(n)];
d = pdist(temp, 'euclidean');
if d < e
A(m, n) = 1;
end
end
end
Can anyone, please, help me to convert the outer 'far' loop into 'parfor' in this code?

Simple Speed-up of code

It is known that MATLAB works slow with for loop. I have tried to vectorize the following code without success. Perhaps I am wrong with the implementation.
for I = NS2:-1:1
A = 0;
for J=1:8
A = A + KS2(J,I)*FA(J);
end
S2 = S2 + ( SS2(1,I)*sin(A) + SS2(2,I)*cos(A) );
end
where:
FA = matrix 1x8
KS2 = matrix 8x25
SS2 = matrix 2x25
A = scalar
S2 = scalar
I try to improve it in this way:
A = 0;
J = 1:8;
for I = NS2:-1:1
A = FA(1,J)*KS2(J,I);
S2 = S2 + ( SS2(1,I)*sin(A) + SS2(2,I)*cos(A) );
end
However, the runtime for this improvement is similar to the original code.
Try this instead (no loops):
A = (FA*KS2).'; %'# A is now 25-by-1
S2 = SS2(1,:)*sin(A) + SS2(2,:)*cos(A);

Resources