Is Matlabs function gradient necessary? - matlab

I stumbled over this by visualizing changes in data. In my opinion the gradient function in Matlab has a weakness for certain inputs. Let's say I have a matrix like a chessfield and compute the gradient:
matrix = repmat([1 5;5 1], 10, 10)
[Fx,Fy] = gradient(matrix);
In matrix we have a lot of changes in both direction. But because of the behaviour of gradient, Fx and Fy will only contain zeros except for the borders.
Is this behaviour wanted? Is it then not always better to use diff() and then achieving equal size of in- and output matrix with padding? Or in other words, when is it useful to use gradient() instead of diff()?

The documentation tells use that gradient uses central differences to compute the gradient at interior points, which explains the behaviour with your chessboard-pattern.
This function is intended for computing the gradient of a function that was evaluated on a regular grid. For the gradient to make sense, we assume that the function is differentiable. But a central difference (or any finite difference scheme) only makes sense if the function is sampled sufficiently densely, otherwise you will have issues like these.

Related

Mixture of 1D Gaussians fit to data in Matlab / Python

I have a discrete curve y=f(x). I know the locations and amplitudes of peaks. I want to approximate the curve by fitting a gaussian at each peak. How should I go about finding the optimized gaussian parameters ? I would like to know if there is any inbuilt function which will make my task simpler.
Edit
I have fixed mean of gaussians and tried to optimize on sigma using
lsqcurvefit() in matlab. MSE is less. However, I have an additional hard constraint that the value of approximate curve should be equal to the original function at the peaks. This constraint is not satisfied by my model. I am pasting current working code here. I would like to have a solution which obeys the hard constraint at peaks and approximately fits the curve at other points. The basic idea is that the approximate curve has fewer parameters but still closely resembles the original curve.
fun = #(x,xdata)myFun(x,xdata,pks,locs); %pks,locs are the peak locations and amplitudes already available
x0=w(1:6)*0.25; % my initial guess based on domain knowledge
[sigma resnorm] = lsqcurvefit(fun,x0,xdata,ydata); %xdata and ydata are the original curve data points
recons = myFun(sigma,xdata,pks,locs);
figure;plot(ydata,'r');hold on;plot(recons);
function f=myFun(sigma,xdata,a,c)
% a is constant , c is mean of individual gaussians
f=zeros(size(xdata));
for i = 1:6 %use 6 gaussians to approximate function
f = f + a(i) * exp(-(xdata-c(i)).^2 ./ (2*sigma(i)^2));
end
end
If you know your peak locations and amplitudes, then all you have left to do is find the width of each Gaussian. You can think of this as an optimization problem.
Say you have x and y, which are samples from the curve you want to approximate.
First, define a function g() that will construct the approximation for given values of the widths. g() takes a parameter vector sigma containing the width of each Gaussian. The locations and amplitudes of the Gaussians will be constrained to the values you already know. g() outputs the value of the sum-of-gaussians approximation at each point in x.
Now, define a loss function L(), which takes sigma as input. L(sigma) returns a scalar that measures the error--how badly the given approximation (using sigma) differs from the curve you're trying to approximate. The squared error is a common loss function for curve fitting:
L(sigma) = sum((y - g(sigma)) .^ 2)
The task now is to search over possible values of sigma, and find the choice that minimizes the error. This can be done using a variety of optimization routines.
If you have the Mathworks optimization toolbox, you can use the function lsqnonlin() (in this case you won't have to define L() yourself). The curve fitting toolbox is probably an alternative. Otherwise, you can use an open source optimization routine (check out cvxopt).
A couple things to note. You need to impose the constraint that all values in sigma are greater than zero. You can tell the optimization algorithm about this constraint. Also, you'll need to specify an initial guess for the parameters (i.e. sigma). In this case, you could probably choose something reasonable by looking at the curve in the vicinity of each peak. It may be the case (when the loss function is nonconvex) that the final solution is different, depending on the initial guess (i.e. you converge to a local minimum). There are many fancy techniques for dealing with this kind of situation, but a simple thing to do is to just try with multiple different initial guesses, and pick the best result.
Edited to add:
In python, you can use optimization routines in the scipy.optimize module, e.g. curve_fit().
Edit 2 (response to edited question):
If your Gaussians have much overlap with each other, then taking their sum may cause the height of the peaks to differ from your known values. In this case, you could take a weighted sum, and treat the weights as another parameter to optimize.
If you want the peak heights to be exactly equal to some specified values, you can enforce this constraint in the optimization problem. lsqcurvefit() won't be able to do it because it only handles bound constraints on the parameters. Take a look at fmincon().
you can use Expectation–Maximization algorithm for fitting Mixture of Gaussians on your data. it don't care about data dimension.
in documentation of MATLAB you can lookup gmdistribution.fit or fitgmdist.

Using matlab to obtain the vector fields and the angles made by the vector field on a closed curve?

Here is the given system I want to plot and obtain the vector field and the angles they make with the x axis. I want to find the index of a closed curve.
I know how to do this theoretically by choosing convenient points and see how the vector looks like at that point. Also I can always use
to compute the angles. However I am having trouble trying to code it. Please don't mark me down if the question is unclear. I am asking it the way I understand it. I am new to matlab. Can someone point me in the right direction please?
This is a pretty hard challenge for someone new to matlab, I would recommend taking on some smaller challenges first to get you used to matlab's conventions.
That said, Matlab is all about numerical solutions so, unless you want to go down the symbolic maths route (and in that case I would probably opt for Mathematica instead), your first task is to decide on the limits and granularity of your simulated space, then define them so you can apply your system of equations to it.
There are lots of ways of doing this - some more efficient - but for ease of understanding I propose this:
Define the axes individually first
xpts = -10:0.1:10;
ypts = -10:0.1:10;
tpts = 0:0.01:10;
The a:b:c syntax gives you the lower limit (a), the upper limit (c) and the spacing (b), so you'll get 201 points for the x. You could use the linspace notation if that suits you better, look it up by typing doc linspace into the matlab console.
Now you can create a grid of your coordinate points. You actually end up with three 3d matrices, one holding the x-coords of your space and the others holding the y and t. They look redundant, but it's worth it because you can use matrix operations on them.
[XX, YY, TT] = meshgrid(xpts, ypts, tpts);
From here on you can perform whatever operations you like on those matrices. So to compute x^2.y you could do
x2y = XX.^2 .* YY;
remembering that you'll get a 3d matrix out of it and all the slices in the third dimension (corresponding to t) will be the same.
Some notes
Matlab has a good builtin help system. You can type 'help functionname' to get a quick reminder in the console or 'doc functionname' to open the help browser for details and examples. They really are very good, they'll help enormously.
I used XX and YY because that's just my preference, but I avoid single-letter variable names as a general rule. You don't have to.
Matrix multiplication is the default so if you try to do XX*YY you won't get the answer you expect! To do element-wise multiplication use the .* operator instead. This will do a11 = b11*c11, a12 = b12*c12, ...
To raise each element of the matrix to a given power use .^rather than ^ for similar reasons. Likewise division.
You have to make sure your matrices are the correct size for your operations. To do elementwise operations on matrices they have to be the same size. To do matrix operations they have to follow the matrix rules on sizing, as will the output. You will find the size() function handy for debugging.
Plotting vector fields can be done with quiver. To plot the components separately you have more options: surf, contour and others. Look up the help docs and they will link to similar types. The plot family are mainly about lines so they aren't much help for fields without creative use of the markers, colours and alpha.
To plot the curve, or any other contour, you don't have to test the values of a matrix - it won't work well anyway because of the granularity - you can use the contour plot with specific contour values.
Solving systems of dynamic equations is completely possible, but you will be doing a numeric simulation and your results will again be subject to the granularity of your grid. If you have closed form solutions, like your phi expression, they may be easier to work with conceptually but harder to get working in matlab.
This kind of problem is tractable in matlab but it involves some non-basic uses which are pretty hard to follow until you've got your head round Matlab's syntax. I would advise to start with a 2d grid instead
[XX, YY] = meshgrid(xpts, ypts);
and compute some functions of that like x^2.y or x^2 - y^2. Get used to plotting them using quiver or plotting the coordinates separately in intensity maps or surfaces.

Implementation of Radon transform in Matlab, output size

Due to the nature of my problem, I want to evaluate the numerical implementations of the Radon transform in Matlab (i.e. different interpolation methods give different numerical values).
while trying to code my own Radon, and compare it to Matlab's output, I found out that my radon projection sizes are different than Matlab's.
So a bit of intuition of how I compute the amount if radon samples needed. Let's do the 2D case.
The idea is that the maximum size would be when the diagonal (in a rectangular shape at least) part is proyected in the radon transform, so diago=sqrt(size(I,1),size(I,2)). As we dont wan nothing out, n_r=ceil(diago). n_r should be the amount of discrete samples of the radon transform should be to ensure no data is left out.
I noticed that Matlab's radon output is always even, which makes sense as you would want a "ray" through the rotation center always. And I noticed that there are 2 zeros in the endpoints of the array in all cases.
So in that case, n_r=ceil(diago)+mod(ceil(diago)+1,2)+2;
However, it seems that I get small discrepancies with Matlab.
A MWE:
% Try: 255,256
pixels=256;
I=phantom('Modified Shepp-Logan',pixels);
rd=radon(I,pi/4);
size(rd,1)
s=size(I);
diagsize=sqrt(sum(s.^2));
n_r=ceil(diagsize)+mod(ceil(diagsize)+1,2)+2
rd=
367
n_r =
365
As Matlab's Radon transform is a function I can not look into, I wonder why could it be this discrepancy.
I took another look at the problem and I believe this is actually the right answer. From the "hidden documentation" of radon.m (type in edit radon.m and scroll to the bottom)
Grandfathered syntax
R = RADON(I,THETA,N) returns a Radon transform with the
projection computed at N points. R has N rows. If you do not
specify N, the number of points the projection is computed at
is:
2*ceil(norm(size(I)-floor((size(I)-1)/2)-1))+3
This number is sufficient to compute the projection at unit
intervals, even along the diagonal.
I did not try to rederive this formula, but I think this is what you're looking for.
This is a fairly specialized question, so I'll offer up an idea without being completely sure it is the answer to your specific question (normally I would pass and let someone else answer, but I'm not sure how many readers of stackoverflow have studied radon). I think what you might be overlooking is the floor function in the documentation for the radon function call. From the doc:
The radial coordinates returned in xp are the values along the x'-axis, which is
oriented at theta degrees counterclockwise from the x-axis. The origin of both
axes is the center pixel of the image, which is defined as
floor((size(I)+1)/2)
For example, in a 20-by-30 image, the center pixel is (10,15).
This gives different behavior for odd- or even-sized problems that you pass in. Hence, in your example ("Try: 255, 256"), you would need a different case for odd versus even, and this might involve (in effect) padding with a row and column of zeros.

first derivative by gradient of image by kernel

Let's say For each pixel, the gradient ∇g= [∂f/∂x, ∂f/∂y]. Then the first derivative should be measured by two operators like 1/2[1,0,1;0,0,0;-1,0,-1] & 1/2[-1,0,1;0,0,0;-1,0,-1]
then:
[i,j]=gradient(im);
filt1=[1,0,1;0,0,0;-1,0,-1];
filt2=[-1,0,1;0,0,0;-1,0,-1];
ii=(1./2).*(conv2(filt1,i));
jj=(1./2).*(conv2(filt2,j));
G_x=conv2(ii,im);
G_y=conv2(jj,im);
Is it correct or I should first multiply 1/2 to the operators, and then convolve them?
since associativity (with scalars) is a quality of convolutions the order of the multiplication should not play any rolle.
On the other hand your filters don't seem to me like they perform a differentiation. The classical filter for the discrete differentiation would be a Sobel that looks something like this:
[1,0,-1
2,0,-2
1,0,-1]
and
[1,2,1
0,0,0
-1,-2,-1]
For the purposes of optimizing the computation, it helps to apply the scaling of 1/2 directly to the filter kernels
filt1 = filt1/2;
Otherwise, if done afterward, N^2 additional multiplications have to be done to the NxN image pixels, instead of just 9 multiplications to a 3x3 kernel.
Beyond that, I agree with McMa. Your computations don't look anything like a differentiation. In fact, you already apply gradient() in the very first line, so I don't understand what more you need.
I'd be inclined to use the imgradient and imgradientxy functions in MATLAB. If you want directional gradients, use imgradientxy and if you want gradient magnitude and direction components, use imgradient.
You can choose to have derivatives computed using Sobel,Prewitt or Roberts gradient kernels or using central or intermediate differences.
Here's an example:
[Gx,Gy] = imgradientxy(im,'Sobel');
Instead if you want to continue using conv2, you can get gradient kernels using the fspecial function.
kernelx = fspecial('sobel');
kernely = kernelx';

How to use multilinear functions with Matlab?

Multilinear function is such that it is linear with respect to each variable. For example, x1+x2x1-x4x3 is a multilinear function. Working with them requires proper data-structure and algrorihms for fast assignment, factorization and basic aritmetics.
Does there exist some library for processing multilinear function in Matlab?
No, not that much so.
For example, interp2 an interpn have 'linear' methods, which are effectively as you describe. But that is about the limit of what is supplied. And there is nothing for more general functions of this form.
Anyway, this class of functions has some significant limitations. For example, as applied to color image processing, they are often a terribly poor choice because of what they do to neutrals in your image. Other functional forms are strongly preferred there.
Of course, there is always the symbolic toolbox for operations such as factorization, etc., but that tool is not a speed demon.
Edit: (other functional forms)
I'll use a bilinear form as the example. This is the scheme that is employed by tools like Photoshop when bilinear interpolation is chosen. Within the square region between a group of four pixels, we have the form
f(x,y) = f_00*(1-x)*(1-y) + f_10*x*(1-y) + f_01*(1-x)*y + f_11*x*y
where x and y vary over the unit square [0,1]X[0,1]. I've written it here as a function parameterized by the values of our function at the four corners of the square. Of course, those values are given in image interpolation as the pixel values at those locations.
As has been said, the bilinear interpolant is indeed linear in x and in y. If you hold either x or y fixed, then the function is linear in the other variable.
An interesting question is what happens along the diagonal of the unit square? Thus, as we follow the path between points (0,0) and (1,1). Since x = y along this path, substitute x for y in that expression, and expand.
f(x,x) = f_00*(1-x)*(1-x) + f_10*x*(1-x) + f_01*(1-x)*x + f_11*x*x
= (f_11 + f_00 - f_10 - f_01)*x^2 + (f_10 + f_01 - 2*f_00)*x + f_00
So we end up with a quadratic polynomial along the main diagonal. Likewise, had we followed the other diagonal, it too would have been quadratic in form. So despite the "linear" nature of this beast, it is not truly linear along any linear path. It is only linear along paths that are parallel to the axes of the interpolation variables.
In three dimensions, which is where we really care about this behavior for color space interpolation, that main diagonal will now show a cubic behavior along that path, despite that "linear" name for the function.
Why are these diagonals important? What happens along the diagonal? If our mapping takes colors from an RGB color space to some other space, then the neutrals in your image live along the path R=G=B. This is the diagonal of the cube. The problem is when you interpolate an image with a neutral gradient, you will see a gradient in the result after color space conversion that moves from neutral to some non-neutral color as the gradient moves along the diagonal through one cube after another. Sadly, the human eye is very able to see differences from neutrality, so this behavior is critically important. (By the way, this is what happens inside the guts of your color ink jet printer, so people do care about it.)
The alternative chosen is to dissect the unit square into a pair of triangles, with the shared edge along that main diagonal. Linear interpolation now works inside a triangle, and along that edge, the interpolant is purely a function of the endpoints of that shared edge.
In three dimensions, the same thing happens, except we use a dissection of the unit cube into SIX tetrahedra, all of which share the main diagonal of the cube. The difference is indeed critically important, with a dramatic reduction in the deviation of your neutral gradients from neutrality. As it turns out, the eye is NOT so perceptive to deviations along other gradients, so the loss along other paths does not hurt nearly so much. It is neutrals that are crucial, and the colors we must reproduce as accurately as possible.
So IF you do color space interpolation using mappings defined by what are commonly called 3-d lookup tables, this is the agreed way to do that interpolation (agreed upon by the ICC, an acronym for the International Color Consortium.)