How to use multilinear functions with Matlab? - 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.)

Related

Is Matlabs function gradient necessary?

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.

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.

Vertical line fit using polyfit

Its just a basic question. I am fitting lines to scatter points using polyfit.
I have some cases where my scatter points have same X values and polyfit cant fit a line to it. There has to be something that can handle this situation. After all, its just a line fit.
I can try swapping X and Y and then fir a line. Any easier method because I have lots of sets of scatter points and want a general method to check lines.
Main goal is to find good-fit lines and drop non-linear features.
First of all, this happens due to the method of fitting that you are using. When doing polyfit, you are using the least-squares method on Y distance from the line.
(source: une.edu.au)
Obviously, it will not work for vertical lines. By the way, even when you have something close to vertical lines, you might get numerically unstable results.
There are 2 solutions:
Swap x and y, as you said, if you know that the line is almost vertical. Afterwards, compute the inverse linear function.
Use least-squares on perpendicular distance from the line, instead of vertical (See image below) (more explanation in here)
(from MathWorld - A Wolfram Web Resource: wolfram.com)
Polyfit uses linear ordinary least-squares approximation and will not allow repeated abscissa as the resulting Vandermonde matrix will be rank deficient. I would suggest trying to find something of a more statistical nature.
If you wish to research Andreys method it usually goes by the names Total least squares or Orthogonal distance regression http://en.wikipedia.org/wiki/Total_least_squares
I would tentatively also put forward the possibility of detecting when you have simultaneous x values, then rotating your data about the origin, fitting the line and then transform the line back. I could not say how poorly this would perform and only you could decide if it was an option based on your accuracy requirements.

Griddata with 'cubic' Interpolation Method Returns NaN

I found that if I use griddata Method with Cubic Interpolation method, for certain values of x, y, it will return NaN. One post says that this is because the x and y data are very near to convex hull.
Any idea how to fix this?
Edit: Note that I can't make sure that my inputs are monotonously increasing ( thus, gridfit doesn't work). The reason is because I would have to mesh my area ( which could be an irregular polygon in 2D), get all the points before generating the coressponding Z values for each points. My code is as follows:
function ZI=Interpolate3D(scatteredData, boundary)
%scatteredData is the scattered points, boundary is the area that I want to generate 3D surface.
% Given the boundaries, generate mesh first
[element,points]= GenMesh(boundary);
ZI = griddata(scatteredData(:,1),scatteredData(:,2),scatteredData(:,3),points(:,1),points(:,2), 'cubic',{'QJ'});
If your points are outside of the convex hull, you CANNOT get a result other than NaN from griddata using the cubic option. If the point is right on the line, then a NaN may result, depending upon what happens in the least significant bits of the computation.
The issue is that the cubic method uses a triangulation. If your point is outside of the convex hull, then the triangulation fails on that point.
Of course, you CAN use the -v4 method, but there are tremendously good reasons why it has largely been superceded. It uses a distance based interpolation method, where for n data points, a full nxn matrix must be generated. Then a system of equations is solved using that matrix. This will be quite slow for even moderately large problems.
The virtue of the -v4 method is it will extrapolate smoothly without producing nans. This is why it was left in there.
For larger problems where you need a smooth result, and you still wish to extrapolate outside of the convex hull, you can use my gridfit tool. It does do smoothing though, not pure interpolation.
All such methods have tradeoffs that you must resolve for your particular problem.
Since the release of Matlab R2013a you can use scatteredInterpolant instead of griddata.
This has several advantages:
Matlab can perform interpolation as well as extrapolation on a scatteredInterpolant object. You can specify a point outside the convex hull of your scattered data and will still not get a NaN.
Once created, the scatteredInterpolant object can be evaluated multiple times, thus saving computational time compared to calling griddata several times.
On the down side: While you can specify the interpolation and extrapolation methods, cubic is not available but only linear, nearest and natural.
Using scatteredInterpolant your code could look like
F = scatteredInterpolant(scatteredData(:,1),scatteredData(:,2),scatteredData(:,3));
ZI=F(points(:,1),points(:,2));
Are you sure you want cubic interpolation? For some input data the calculated z-nodes could have extreme large values!
I always use -v4 option like the post in your link mentions. You can also play with options used in Qhull via delaunayn, some (but not all) are {'Qt','Qbb','Qc'} http://www.qhull.org/html/qhull.htm