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);
Related
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.
To calculate an enhancement function for an input image I have written the following piece of code:
Ig = rgb2gray(imread('test.png'));
N = numel(Ig);
meanTotal = mean2(Ig);
[row,cal] = size(Ig);
IgTransformed = Ig;
n = 3;
a = 1;
b = 1;
c = 1;
k = 1;
for ii=2:row-1
for jj=2:cal-1
window = Ig(ii-1:ii+1,jj-1:jj+1);
IgTransformed(ii,jj) = ((k*meanTotal)/(std2(window) + b))*abs(Ig(ii,jj)-c*mean2(window)) + mean2(window).^a;
end
end
How can I reduce the calculation time?
Obviously, one of the factors is the small window (3x3) that should be made in the loop each time.
Here you go -
Igd = double(Ig);
std2v = colfilt(Igd, [3 3], 'sliding', #std);
mean2v = conv2(Igd,ones(3),'same')/9;
Ig_out = uint8((k*meanTotal)./(std2v + b).*abs(Igd-cal*mean2v) + mean2v.^a);
This will change the boundary elements too, which if not desired could be set back to the original ones with few additional steps, like so -
Ig_out(:,[1 end]) = Ig(:,[1 end])
Ig_out([1 end],:) = Ig([1 end],:)
I have a equation that used to compute sigma, in which i is index from 1 to N,* denotes convolution operation, Omega is image domain.
I want to implement it by matlab code. Currently, I have three options to implement the above equation. Could you look at my equation and said to me which one is correct? I spend so much time to see what is differnent amongs methods but I could not find. Thanks in advance
The different between Method 1 and Method 2 that is method 1 compute the sigma after loop but Method 2 computes it in loop.
sigma(1:row,1:col,1:dim) = nu/d;
Does it give same result?
===========Matlab code==============
Method 1
nu = 0;
d = 0;
I2 = I.^2;
[row,col] = size(I);
for i = 1:N
KuI2 = conv2(u(:,:,i).*I2,k,'same');
bc = b.*(c(:,:,i));
bcKuI = -2*bc.*conv2(u(:,:,i).*I,k,'same');
bc2Ku = bc.^2.*conv2(u(:,:,i),k,'same');
nu = nu + sum(sum(KuI2+bcKuI+bc2Ku));
ku = conv2(u(:,:,i),k,'same');
d = d + sum(sum(ku));
end
d = d + (d==0)*eps;
sigma(1:row,1:col,1:dim) = nu/d;
Method 2:
I2 = I.^2;
[row,col] = size(I);
for i = 1:dim
KuI2 = conv2(u(:,:,i).*I2,k,'same');
bc = b.*(c(:,:,i));
bcKuI = -2*bc.*conv2(u(:,:,i).*I,k,'same');
bc2Ku = bc.^2.*conv2(u(:,:,i),k,'same');
nu = sum(sum(KuI2+bcKuI+bc2Ku));
ku = conv2(u(:,:,i),k,'same');
d = sum(sum(ku));
d = d + (d==0)*eps;
sigma(1:row,1:col,i) = nu/d;
end
Method 3:
I2 = I.^2;
[row,col] = size(I);
for i = 1:dim
KuI2 = conv2(u(:,:,i).*I2,k,'same');
bc = b.*(c(:,:,i));
bcKuI = -2*bc.*conv2(u(:,:,i).*I,k,'same');
bc2Ku = bc.^2.*conv2(u(:,:,i),k,'same');
ku = conv2(u(:,:,i),k,'same');
d = ku + (ku==0)*eps;
sigma(:,:,i) = (KuI2+bcKuI+bc2Ku)./d;
end
sigma = sigma + (sigma==0).*eps;
I think that Method 1 is assume that sigma1=sigma2=...sigman because you were computed out of loop function
sigma(1:row,1:col,1:dim) = nu/d;
where nu and d are cumulative sum for each iteration.
While, the Method 2 shown that sigma1 !=sigma 2 !=..sigman because each sigma is calculated in loop function
Hope it help
I'm trying to develop the adaptive unsharp algorithm described by Polesel et al. in the article "Image Enhancement via Adaptive Unsharp Masking" (link to the article). The core of the algorithm is the minimization of a cost function defined as:
J(m,n) = E[e(m,n)^2] = E[(gd(m,n)-gy(m,n))^2]
where E[] is the statistical expectation and gy(m,n) is:
gy(m,n) = gx(m,n) + lambda1(m,n)*gzx(m,n) + lambda2(m,n)*gzy(m,n);
I want to find lambda1 and lambda2 for each pixel in order to minimize the cost function in each pixel.
Here the code that I wrote so far:
function [ o_sharpened_image ] = AdaptativeUnsharpMask( i_image , t1, t2)
%ADAPTATIVEUNSHARPMASK Summary of this function goes here
% Detailed explanation goes here
if isa(i_image,'dip_image')
i_image = dip_array(i_image);
end
if ~isfloat(i_image)
i_image = im2double(i_image);
end
adh = 4;
adl = 3;
g = [-1 -1 -1; -1 8 -1; -1 -1 -1];
dim = size(i_image);
lambda_x = 0.5*ones(dim);
lambda_y = 0.5*ones(dim);
z_x = conv2(i_image,[-1 2 -1],'same');
z_y = conv2(i_image,[-1; 2; -1],'same');
g_x = conv2(i_image,g,'same');
g_zx = conv2(z_x,g,'same');
g_zy = conv2(z_y,g,'same');
a = ones(dim);
variance_map = colfilt(i_image,[3 3],'sliding',#var);
a(variance_map >= t1 & variance_map < t2) = adh;
a(variance_map >= t2) = adl;
g_d = a.*g_x;
lambda = [lambda_x lambda_y];
lambda0 = lambda;
lambda_min = lsqnonlin(#(lambda) UnsharpCostFunction(lambda,g_d,g_zx,g_zy),lambda0);
o_sharpened_image = i_image + lambda_min(:,1:size(i_image,2)).*z_x + lambda_min(:,size(i_image,2)+1:end).*z_y;
end
Here the code of the cost function:
function [ J ] = UnsharpCostFunction( i_lambda, i_gd, i_gzx, i_gzy )
%UNSHARPCOSTFUNCTION Summary of this function goes herek
gy = i_gd + i_lambda(:,1:size(i_gd,2)).*i_gzx + i_lambda(:,size(i_gd,2)+1:end).*i_gzy;
J = mean((i_gd(:) - gy(:)).^2);
end
For each iteration I print on the command window the value of the J function and it is always the same. What am I doing wrong?
Thank you.
I want to write a fast MATLAB code where I need to write a for loop and I need to solve an ordinary differential equation each time.Is there any way to vectorize the code?
Following is the part of the code:
tspan=0:0.01:20;
dw=rand(p,1);
M0=repmat([0 0 1],p,1)';
for p=1:ns
[t,M(:,:,p)]=ode45(#(t,M) testfun(t,M,dw(p)),tspan,M0(:,p));
end
where
function dM=testfun(t,M,w1)
M_x=M(1);
M_y=M(2);
M_z=M(3);
dM=[w1*M_y;-w1*M_x+w1*M_z-2*w1*M_y;-w1*M_y-(1-M_z)];
Try this and let me know how it works.
right hand side of the ODE system:
function dM = testfun(t,M,w1)
dM = zeros(length(M), 1);
M_x = M(1:3:end, 1);
M_y = M(2:3:end, 1);
M_z = M(3:3:end, 1);
dM(1:3:end) = (w1.*M_y)';
dM(2:3:end) = (-w1.*M_x - 2*w1.*M_y + w1.*M_z)';
dM(3:3:end) = (-w1.*M_y - (1-M_z))';
end
main program:
clear all
clc
ns = input('Please tell me how many time you need to integrate the ODE system: ');
tspan = 0:0.01:20;
dw = rand(ns,1);
M0 = repmat([0; 0; 1], 1, ns);
[t, my_M] = ode45(#(t,my_M) testfun(t,my_M,dw), tspan, M0);
s = size(my_M);
for i = 1:ns
M(:, 1:s(2)/ns, i) = my_M(:, s(2)/ns*(i-1)+1:s(2)/ns*i);
end