What does imresizemex do in Matlab imresize function? - matlab

I was trying to create an image resize code using C to do exactly what imresize.m in Matlab does. I stuck at the line calling imresizemex in imresize.m. It seems that imresizemex is a compiled machine code that can only be called in Matlab (I found it as imresizemex.mexw64 file in a Matlab private folder, no source code available). I also tried to call it in C, but failed. Does anyone know where to find the source code for imresizemex? Thanks a lot!

I think I figured it out ^ ^. It does the weighted multiplication and sum part of the cubic convolution interpolation. Here's my Matlab code replacing imresizemex. Although almost 6 seconds slower, it produces exactly the same result.
function outimg=reducesize(inimg, weights,indices,dim)
% reduce first dimension
reduce1=zeros(dim(1),size(inimg,2));
weight1=weights{1};
index1=indices{1};
for i=1:size(inimg,2)
for j=1:dim(1)
w11=weight1(j,:);
ind11=index1(j,:);
B=double(inimg(ind11,i));
v=w11.*B';
reduce1(j,i)=sum(v);
end
end
% reduce second dimension
reduce2=zeros(dim(1),dim(2));
weight2=weights{2};
index2=indices{2};
for i=1:dim(1)
for j=1:dim(2)
w22=weight2(j,:);
ind22=index2(j,:);
B=reduce1(i,ind22);
v=w22.*B;
reduce2(i,j)=sum(v);
end
end
outimg=round(reduce2);

Related

Unexpected length of array and plotting error as a result

I wanted to plot the load voltage across the resistor in series with a diode using matlab. This is a rather simple example involving piecewise functions, however I ran into an unexpected error.
t=[0:0.001:10]
vs=4*sin(pi * t)
for i =1:length(vs)
if(vs(i)<=0.7)
v(i)=0;
else
v(i)=vs(i)-0.7;
end
end
plot(t,v)
t is the time, vs is the source voltage, and v is the load voltage. Now, running this gave me an error saying "error, t and v are of different sizes..". Using length() I found out that while t and vs are of lengths 10001, v is somehow of length 1000001.
This is truly baffling to me. How can v and vs possibly differ in size? every element of vs was mapped to an element of v, and yet the size of v comes out to be about 100 times the size of vs.
Being new to matlab, I still am not very comfortable with not explicitly declaring the array v before using it in the for loop. However, I went through with it, because the example I worked on prior to this, used the same thing and it worked without any problems. We simply had a plot a piecewise function:
x=[-2 : 0.00001 : 20];
for i=1: length(x)
if(x(i)>=-2 && x(i)<0)
y(i)=sqrt(x(i)^2+1);
else if(x(i)>=0 && x(i)<10)
y(i)=3*x(i)+1;
else
y(i)=9*sin(5*x(i)-50);
end
end
end
plot(x,y)
This code worked flawlessly, and in my opinion the initial code is fundamentally doing the same thing, so again, I'm clueless as to why it failed.
The original code works if you initialise v to be of the same size as t (and therefore, vs), but still, I want to know why the code involving x,y worked (where y wasn't initialised) and the code involving (t,v) failed.
Also, my friend copy pasted the entire code into the command window of matlab 2016, and it worked. (and I'm using the 2021 version).
Its good practice to initialize variables before entering a loop. It will help avoid undefinied behaviour when you run the script multiple times. If you run the script with different lengths for t, it would fail the second run. One solution would be:
t=0:0.001:10;
vs=4*sin(pi * t);
v=nan(size(t));
for i =1:length(vs)
if(vs(i)<=0.7)
v(i)=0;
else
v(i)=vs(i)-0.7;
end
end
figure;
plot(t,v);
You could also avoid the for loop and use matrix operations instead:
t=0:0.001:10;
vs=4*sin(pi * t);
v=vs-0.7;
v(vs<=0.7)=0;
figure;
plot(t,v);

How to improve the speed of this code with double loops in Matlab? Is it possible?

Dear community of stack overflow. Is it possible to improve the speed of this code in Matlab? Can I use vectorization? Note that I have to use in every loop the "vpasolve" or "fsolve" function.
Here is the code which calls the function with a double loop:
for i=1:1000
for j=1:1000
SilA(i,j)=SolW(i,j);
end
end
Here is the function which is called by the above code. Can I vectorize the input of w, xi and make the code run faster?
function [ffw] = SolW(w,xi)
format long e;
z=0;mm=0.46;sop=80;
epit=0.1;voP=80.;
rho=2.1;aposC=0.1;aposD=0.1;
parEh=0.2*10^6;parEv=0.2*10^6;parGv=0.074*10^6;
parpos=0.35;hp=0.2;Ep=30*10^6;
parposV=0.20;ll=0.15;dd=2*ll;
C11=(parEh*(parEv-parEh*parpos^2)/((1+parpos)*(parEv-parEv*parpos-2*parEh*parpos^2)))*(1+2*1i*aposD);
C13=(parEh*parEv*parpos/((parEv-parEv*parpos-2*parEh*parpos^2)))*(1+2*1i*aposD);
C33=((1-parpos)*parEv^2/(parEv-parEv*parpos-2*parEh*parpos^2))*(1+2*1i*aposD);
C44=parGv*(1+2*1i*aposD);
DD=(Ep*hp^3)/(12*(1-parposV^2));
a1=C44;
a2=C33;
c1=(C13+C44)*1i*xi;
c2=(C13+C44)*1i*xi;
b1=rho*w^2-C11*xi^2;
b2=rho*w^2-C44*xi^2;
syms xr
rsol=vpasolve((a1*xr+b1).*(a2*xr+b2)-c1*c2*xr==0,xr);
rsol=eval(rsol);
r=[-sqrt(rsol)];
r1=r(1,:);
r2=r(2,:);
Fdf1=sop*sqrt(2*pi/(1i*epit*xi))*exp(1i*(xi*voP+w)^2/(2*epit*xi));
BC11=C44*(r1-1i*xi*c2*r1/(a2*r1^2+b2));
BC21=(C13*1i*xi)-((C33*c2*r1^2)/(a2*r1^2+b2))+(DD*xi^4-mm*w^2+1i*aposC*w)*c2*r1/(a2*r1^2+b2);
BC12=C44*(r2-1i*xi*c2*r2/(a2*r2^2+b2));
BC22=(C13*1i*xi)-((C33*c2*r2^2)/(a2*r2^2+b2))+(DD*xi^4-mm*w^2+1i*aposC*w)*c2*r2/(a2*r2^2+b2);
syms As1 As2;
try
[Ass1,Ass2]=vpasolve(BC11*As1+BC12*As2==0,BC21*As1+BC22*As2+Fdf1==0,As1,As2);
A1=eval(Ass1);
A2=eval(Ass2);
catch
A1=0.0;
A2=0.0;
end
Bn1=-(c2*r1/(a2*r1^2+b2))*A1;
Bn2=-(c2*r2/(a2*r2^2+b2))*A2;
ffw=Bn1*exp(r1*z)+Bn2*exp(r2*z);
end
Everything in your function but the calls to vpasolve, and try.... can be vectorize.
First, all this does not depend on w or xi, so could be computed once only:
format long e;
z=0;mm=0.46;sop=80;
epit=0.1;voP=80.;
rho=2.1;aposC=0.1;aposD=0.1;
parEh=0.2*10^6;parEv=0.2*10^6;parGv=0.074*10^6;
parpos=0.35;hp=0.2;Ep=30*10^6;
parposV=0.20;ll=0.15;dd=2*ll;
C11=(parEh*(parEv-parEh*parpos^2)/((1+parpos)*(parEv-parEv*parpos-2*parEh*parpos^2)))*(1+2*1i*aposD);
C13=(parEh*parEv*parpos/((parEv-parEv*parpos-2*parEh*parpos^2)))*(1+2*1i*aposD);
C33=((1-parpos)*parEv^2/(parEv-parEv*parpos-2*parEh*parpos^2))*(1+2*1i*aposD);
C44=parGv*(1+2*1i*aposD);
DD=(Ep*hp^3)/(12*(1-parposV^2));
a1=C44;
a2=C33;
From what I know, eval is slow, and I'm pretty sure that you don't need it:
rsol=eval(rsol);
Here is an example of vectorization. You should first generate all indices combination using meshgrid, and then use the . to noticed matlab to use element wise operations:
[I, J] = meshgrid(1:1000, 1:1000)
c1=(C13+C44)*1i.*xi;
c2=(C13+C44)*1i.*xi;
b1=rho.*w.^2 - C11.*xi.^2;
b2=rho.*w.^2-C44.*xi.^2;
But you won't be able to vectorize vpasolve, and try.... litteraly, without changing it to something else. vpasolve is probably the bottleneck of you computation (verify this using matlab profiler), so optimizing as proposed above will probably not reduce your computation time much.
Then you have several solutions:
use parfor if you have access to it to parallelize your computations, which depending on your architecture, could give you a 4x speedup or so.
it may be possible to linearize your equations and solve them all in one operation. Anyway, using a linear solver will be probably much faster than using vpasolve. This will probably give you the fastest speedup (guessing factor 10 -100 ?)
because you have continuous data, you could reduce the number of steps, if you dare loosing precision.
Hope this helps
In the above program everything can be vectorized as #beesleep said above.
For example:
[I, J] = meshgrid(1:1000, 1:1000)
c1=(C13+C44)*1i.*xi;
c2=(C13+C44)*1i.*xi;
b1=rho.*w.^2 - C11.*xi.^2;
b2=rho.*w.^2-C44.*xi.^2;
The vpasolve part ,i.e.,
syms xr
rsol=vpasolve((a1*xr+b1).*(a2*xr+b2)-c1*c2*xr==0,xr);
rsol=eval(rsol);
r=[-sqrt(rsol)];
r1=r(1,:);
r2=r(2,:);
can also be vectorized by using fsolve as it is shown here:
fun=#(Xr) (a1.*Xr+b1).*(a2.*Xr+b2)-c1.*c2.*Xr
x01=-ones(2*Nxi);
x02=ones(2*Nxi);
options.Algorithm= 'trust-region-reflective'
options.JacobPattern=speye(4*Nxi^2);
options.PrecondBandWidth=0;
[rsol1]=fsolve(fun,x01,options);
[rsol2]=fsolve(fun,x02,options);
The other part, i.e,
syms As1 As2;
try
[Ass1,Ass2]=vpasolve(BC11*As1+BC12*As2==0,BC21*As1+BC22*As2+Fdf1==0,As1,As2);
A1=eval(Ass1);
A2=eval(Ass2);
catch
A1=0.0;
A2=0.0;
end
since contains linear equations and in each row has two dependent equations can be solved as it is shown here:
funAB1=#(As1) BC11.*As1+BC12.*((-Fdf2-BC21.*As1)./BC22);
x0AB=ones(2*Nxi)+1i*ones(2*Nxi);
options.Algorithm= 'trust-region-reflective';
options.JacobPattern=speye(4*Nxi^2);
options.PrecondBandWidth=0;
[A1]=fsolve(funAB1,x0AB,options);
A2=((-Fdf2-BC21.*A1)./BC22);
However, both can also be solved analytically, i.e.,
AAr=a1.*a2;
BBr=a1.*b2+b1.*a2-c1.*c2;
CCr=b1.*b2;
Xr1=(-BBr+sqrt(BBr^.2-4.*AAr.*CCr))./(2.*AAr);
Xr2=(-BBr-sqrt(BBr^.2-4.*AAr.*CCr))./(2.*AAr);
r1=-sqrt(Xr1(:,:));
r2=-sqrt(Xr2(:,:));

Using MATLAB pcg to Solve Inexactly

I am using MATLAB's PCG subroutine to solve a system of linear equations. However, I don't want it to solve exactly. I want it to run for only 20 iterations and if it doesn't converge, I want it to return the value at the 20th iteration.
What MATLAB (My version is the latest one) is doing however is returning a zero vector if it doesn't find an acceptable solution by 20 iterations. Is there any way to override this without changing the source code of pcg.m?
I have a code which I wrote which does that (I just copied from Wikipedia) but obviously, it is not close to how robust MATLAB's version is.
function [x] = conjgrad(A,b,x)
r=b-A*x;
p=r;
rsold=r'*r;
for i=1:20
Ap=A*p;
alpha=rsold/(p'*Ap);
x=x+alpha*p;
r=r-alpha*Ap;
rsnew=r'*r;
if sqrt(rsnew)<1e-10
break;
end
p=r+rsnew/rsold*p;
rsold=rsnew;
end

Solving Bessel Function using Runge Kutta

I'm working on an assignment for a class of mine and I'm supposed to write a code using a program of my choice (I've chosen Matlab) to solve the Bessel function differential equation using the 4th order Runge-Kutta method. For reference the Bessel function DE is:
x^2*(J_n)''+x*(J_n)'+(x^2-n^2)*J_n=0.
I'm able to separate this into two coupled first order DEs by:
(J_n)'=Z_n and
(Z_n)'+(1/x)*Z_n+[(x^2-n^2)/x^2]*J_n=0.
I have no experience with Matlab nor any other programming language before this assignment. I know Matlab has the 'ode45' command but I'm supposed to write the code myself, not rely on Matlab's commands. So far I've been working on the n=0 case for the Bessel function but I keep getting an error when I try and plot the function. The current error I have says: "Undefined function or method 'J' for input arguments of type 'double'." But I don't know how to fix this error nor if my code is even correct. Could someone tell me where I've gone wrong or what is the correct way to write this code?
h=0.01; %step size
J_0(1)=1; %initial condition for J_0
Z_0(1)=1; %initial condition for Z_0-This value should be zero
%but Matlab gives me an error. To fix this, I input
%Z_0(1)-1 to use the correct value for Z_0(1).
x(1)=0.001; %first value of x
dZ(Z_0,J_0)=(-1/x)*(Z_0-1)-J_0;
for i=[1:1:10]
dZ1=(-1/x)*(Z_0-1)-J_0;
dJ1=(Z_0(1)-1)*h;
dZ2=(-1/x)*(Z_0-1+0.5*h)-(J_0+0.5*h*dJ1);
dJ2=((Z_0(1)-1)+dZ1)*h;
dZ3=(-1/x)*(Z_0-1+0.5*h)-(J_0+0.5*h*dJ2);
dJ3=((Z_0(1)-1)+dZ1+dZ2)*h;
dZ4=(-1/x)*(Z_0-1+h)-(J_0+h*dJ3);
dJ4=((Z_0(1)-1)+dZ1+dZ2+dZ3)*h;
J(i+1)=J(i)+(h/6)*(dJ1+2*dJ2+2*dJ3+dJ4);
end
plot(J_0);
Thanks in advance for any help
Your problem is on the line:
J(i+1)=J(i)+(h/6)*(dJ1+2*dJ2+2*dJ3+dJ4);
In the right-hand side of your assignment operator you use the variable J that is never set before i is taking the value 1. Looks like a typo to me (should it be J_0 instead?)
Also, don't forget your index i when computing your dJ and dZ stuff in the for loop.

Effcient way to do FFT shift in matlab (without using fftshift function)

http://www.mathworks.com/help/techdoc/ref/fftshift.html
If you check that link - thats what I want to do in the first picture - swap quadrants of a matrix.
However, I cant seem to think of a good way to do this without having several loops to pull out the relevant sub-matrices.
I need it to work with MxN matrices, where M and N can be any combination of even and odd.
Thanks
The following should work
sz = ceil(size(A)/2)
A = A([sz(1)+1:end, 1:sz(1)], [sz(2)+1:end, 1:sz(2)])
That only works for 2d matrices, but can be easily generalized to the Nd case.
If you enter type fftshift.m at MATLAB's command line, you'll see the source code for MATLAB's implementation of the function (use edit fftshift.m if you want to view it in the editor with syntax highlighting). I'm not posting the code here, as it is copyrighted. However, you can try it on your machine and re-implement the same in C. Its up to you to figure out the license terms etc, if you're into any of that.