Great Circle Distance Problems (Spherical Vincenty Case and a simplified version) - matlab

%Great Circle Distnace -- Simplified
%% 12.18993,133.45898 %% point 1 (lat/long)
%% 14.34243,65.12750 %% point 2 (lat/long)
%%VARIABLES%%
phi_1=12.18993; %lat_1
phi_2=14.34243; %lat_2
gam_1=133.45898; %long_1
gam_2=65.12750; %long_2
delt_gam = abs(gam_1 - gam_2); %absoulte difference in longitudes
R_Earth = 6371000; %mean radius of the earth in meters, change to FT to get distance accordingly
%%Unsimplified Great-Circle Equation -- Breaking it up into numerator and
%%denominator sections to avoid more problems -- Spherical Case of the
%%Vincenty Formula
Numer_sec1= ((cos(phi_2))*(sin(delt_gam))^2);
Numer_sec2=(((((cos(phi_1))*(sin(phi_2)))+((sin(phi_1))*(cos(phi_2))*(delt_gam))))^2);
Denom_1= (((sin(phi_1))*(sin(phi_2)))+((cos(phi_1))*(cos(phi_2))*delt_gam));
delt_sig2=atan((sqrt(Numer_sec1+Numer_sec2))/(Denom_1));
delt_GC2=R_Earth*delt_sig2;
disp(delt_GC2)
Hey guys, so currently I'm trying to get my distance between two Lat/Long Points hammered out with the Spherical Case of the Vincenty formula in MatLab. I've been referencing http://en.wikipedia.org/wiki/Great-circle_distance
And from that have created the above MatLab code. I tried the first equation that was given (a more simplified version, but to no avail either), so I'm going with the Vincenty case. Given the two lat/long points (decimal format) that are listed at the beginning of the code I've yet to calculate the correct distance in between the two points with my program. I can't seem to find out what's going on, so I'm asking you guys if there's any way you could help me figure this out.
Thank you very much in advance, and I'll be looking at the post frequently so that I can help you help me by answering any questions you may have about my code thus far.
Based on this website: http://williams.best.vwh.net/gccalc.htm the distance should be 7381.56km.
The first answer below has reminded me that I have the mapping toolbox, yet I'm not sure how to interpret the results that I'm getting, so please check the commment that I posted below.
[ARCLEN, AZ] = distance(LAT1,LON1,LAT2,LON2)
this does in-fact work, but I'm not sure what I do with the arc-length or the azimuth that's produced.
Thank you and Happy New Year to all.

If you just want an answer for the WGS84 without programming up the
algorithm and without paying for the Mapping Toolbox, download the
Matlab package Geodesics on an ellipsoid of revolution. This
includes an improvement in the Mapping Toolbox function,
called geoddistance. To solve your problem
format long;
geoddistance(12.18993,133.45898,14.34243,65.12750)
->
7381566.23351761
The arguments to geoddistance are in degrees and the result is in
meters. This does the calculation for the WGS84 ellipsoid. If you want
to use a difference ellipsoid specify a 5th argument [a,e] (equatorial
radius, eccentricity). (For a sphere, set e = 0; if you want to specify a prolate ellipsoid, set e to a pure imaginary. Accurate answers are returned for |e| < 0.2.)
Incidentally many of the pictures of geodesics shown in the
Wikipedia article on ellipsoidal geodesics are drawn with this
package.

The default units for trigonometric functions in MATLAB are radians. You appear to be specifying your latitudes and longitudes in degrees. Either translate to radians or else use the sind() and cosd() functions.
Or, if you happen to have the mapping toolbox installed (Mathworks does charge extra for it, however), you can just use the distance() function. The distance() function should in principle actually be the superior way, if it is available to you, because it can accept an ellipsoidal Earth model.

Related

Understanding 3D distance outputs in matlab

Being neither great at math nor coding, I am trying to understand the output I am getting when I try to calculate the linear distance between pairs of 3D points. Essentially, I have the 3D points of a bird that is moving in a confined area towards a stationary reward. I would like to calculate the distance of the animal to the reward at each point. However, when looking online for the best way to do this, I tried several options and get different results that I'm not sure how to interpret.
Example data:
reward = [[0.381605200000000,6.00214980000000,0.596942400000000]];
animal_path = = [2.08638710671220,-1.06496059617432,0.774253689976102;2.06262715454806,-1.01019576900787,0.773933446776898;2.03912411242035,-0.954888684677576,0.773408777383975;2.01583648760496,-0.898935333316342,0.772602855030873];
distance1 = sqrt(sum(([animal_path]-[reward]).^2));
distance2 = norm(animal_path - reward);
distance3 = pdist2(animal_path, reward);
Distance 1 gives 3.33919107083497 13.9693378592353 0.353216791787775
Distance 2 gives 14.3672145652704
Distance 3 gives 7.27198528565078
7.21319284516199
7.15394253573951
7.09412041863743
Why do these all yield different values (and different numbers of values)? Distance 3 seems to make the most sense for my purposes, even though the values are too large for the dimensions of the animal enclosure, which should be something like 3 or 4 meters.
Can someone please explain this in simple terms and/or point me to something less technical and jargon-y than the Matlab pages?
There are many things mathematicians call distance. What you normally associate with distance is the eucledian distance. This is what you want in this situation. The length of the line between two points. Now to your problem. The Euclidean distance distance is also called norm (or 2-norm).
For two points you can use the norm function, which means with distance2 you are already close to a solution. The problem is only, you input all your points at once. This does not calculate the distance for each point, instead it calculates the norm of the matrix. Something of no interest for you. This means you have to call norm once for each row point on the path:
k=nan(size(animal_path,1),1)
for p=1:size(animal_path,1),
k(p)=norm(animal_path(p,:) - reward);
end
Alternatively you can follow the idea you had in distance1. The only mistake you made there, you calculated the sum for each column, where the sum of each row was needed. Simple fix, you can control this using the second input argument of sum:
distance1 = sqrt(sum((animal_path-reward).^2,2))

How is the reprojection error calculated in Matlab's triangulate function? Sadly, the documentation gives no mathematical formula

How is the reprojection error calculated in Matlab's triangulate function?
Sadly, the documentation gives no mathematical formula.
It only says: The vector contains the average reprojection error for each M world point.
What is the procedure/Matlab uses when calculating this error?
I searched SOF but found nothing on this IMHO important question.
UPDATE:
How can they use this error to filter out bad matches here : http://se.mathworks.com/help/vision/examples/sparse-3-d-reconstruction-from-two-views.html
AFAIK The reprojection error is calculated always in the same way (in the field of computer vision in general).
The reprojection is (as the name says) the error between the reprojected point in the camera and the original point.
So from 2 (or more) points in the camera you triangulate and get 3D points in the world system. Due to errors in the calibration of the cameras, the point will not be 100% accurate. What you do is take the result 3D point (P) and with the camera calibration parameters project it in the cameras again, obtaining new points (\hat{p}) near the original ones (p).
Then you calculate the euclidean distance between the original point and the "reprojected" one.
In case you want to know a bit more about the method used by Matlab, I'll enhance the bibliography they use giving you also the page number:
Multiple View Geometry in Computer Vision by Richard Hartley and
Andrew Zisserman (p312). Cambridge University Press, 2003.
But basically it is a least squares minimization, that has no geometrical interpretation.
You can find an explanation of reprojection errors in the context of camera calibration in the Camera Calibrator tutorial:
The reprojection errors returned by the triangulate function are essentially the same concept.
The way to use the reprojection errors to discard bad matches is shown in this example:
[points3D, reprojErrors] = triangulate(matchedPoints1, matchedPoints2, ...
cameraMatrix1, cameraMatrix2);
% Eliminate noisy points
validIdx = reprojErrors < 1;
points3D = points3D(validIdx, :);
This code excludes all 3D points for which the reprojection error was more than a pixel. You can also use validIdx to eliminate the corresponding 2D matches.
Above mentioned answers interpret re-projection error in a simplistic way as an actual reprojection in the camera. In more general sense, this error reflects the distance between a noisy image point and the point estimated from the model. One can imagine a tangental plane to some surface (model) in n-dimensional space where the noisy point is projected (hence it lands on the plane, not on the model!). n is not obligatory = 2 since a notion of a "point" can be generalized to, for example, concatenation of coordinates of two corresponding points for Homography.
It is important to understand that reprojection error is not a final answer. Overall_error^2 = reprojection_error^2 + estimation_error^2. The latter is the distance between estimation reprojected and true point on the model. More on this can be found in chapter 5 of Hatrtley andd Zisserman book Multiple View Geometry. They prove that reprojeciton error has a theoretical limit 0.6*sigma (for Homography estimation), where sigma is noise standard deviation.
They filter out bad matches by removing relevant indexes which have large re-projection errors.
This means that points that have large re-projection errors are the outliers.

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.

How to find the nearest points to given coordinates with MATLAB?

I need to solve a minimization problem with Matlab and I'm wondering which is the easiest solution. All the potential solutions that I've been thinking in require lot of programming effort.
Suppose that I have a lat/long coordinate point (A,B), what I need is to search for the nearest point to this one in a map of lat/lon coordinates.
In particular, the latitude and longitude arrays are two matrices of 2030x1354 elements (1km distance) and the idea is to find the unique indexes in those matrices that minimize the distance to the coordinates (A,B), i.e., to find the closest values to the given coordinates (A,B).
Any help would be very appreciated.
Thanks!
This is always a fun one :)
First off: Mohsen Nosratinia's answer is OK, as long as
you don't need to know the actual distance
you can guarantee with absolute certainty that you will never go near the polar regions
and will never go near the ±180° meridian
For a given latitude, -180° and +180° longitude are actually the same point, so simply looking at differences between angles is not sufficient. This will be more of a problem in the polar regions, since large longitude differences there will have less of an impact on the actual distance.
Spherical coordinates are very useful and practical for purposes of navigation, mapping, and that sort of thing. For spatial computations however, like the on-surface distances you are trying to compute, spherical coordinates are actually pretty cumbersome to work with.
Although it is possible to do such calculations using the angles directly, I personally don't consider it very practical: you often have to have a strong background in spherical trigonometry, and considerable experience to know its many pitfalls -- very often there are instabilities or "special points" you need to work around (the poles, for example), quadrant ambiguities you need to consider because of trig functions you've introduced, etc.
I've learned to do all this in university, but I also learned that the spherical trig approach often introduces complexity that mathematically speaking is not strictly required, in other words, the spherical trig is not the simplest representation of the underlying problem.
For example, your distance problem is pretty trivial if you convert your latitudes and longitudes to 3D Cartesian X,Y,Z coordinates, and then find the distances through the simple formula
distance (a, b) = R · arccos( a/|a| · b/|b| )
where a and b are two such Cartesian vectors on the sphere. Note that |a| = |b| = R, with R = 6371 the radius of Earth.
In MATLAB code:
% Some example coordinates (degrees are assumed)
lon = 360*rand(2030, 1354);
lat = 180*rand(2030, 1354) - 90;
% Your point of interest
P = [4, 54];
% Radius of Earth
RE = 6371;
% Convert the array of lat/lon coordinates to Cartesian vectors
% NOTE: sph2cart expects radians
% NOTE: use radius 1, so we don't have to normalize the vectors
[X,Y,Z] = sph2cart( lon*pi/180, lat*pi/180, 1);
% Same for your point of interest
[xP,yP,zP] = sph2cart(P(1)*pi/180, P(2)*pi/180, 1);
% The minimum distance, and the linear index where that distance was found
% NOTE: force the dot product into the interval [-1 +1]. This prevents
% slight overshoots due to numerical artifacts
dotProd = xP*X(:) + yP*Y(:) + zP*Z(:);
[minDist, index] = min( RE*acos( min(max(-1,dotProd),1) ) );
% Convert that linear index to 2D subscripts
[ii,jj] = ind2sub(size(lon), index)
If you insist on skipping the conversion to Cartesian and use lat/lon directly, you'll have to use the Haversine formula, as outlined on this website for example, which is also the method used by distance() from the mapping toolbox.
Now, all of this is valid for the whole Earth, provided you find the smooth spherical Earth accurate enough an approximation. If you want to include the Earth's oblateness or some higher order shape model (or God forbid, distances including terrain), you need to do far more complicated stuff. But I don't think that is your goal here :)
PS - I wouldn't be surprised that if you would write everything out that I did, you'll probably re-discover the Haversine formula. I just prefer to be able to calculate something as simple as distances along the sphere from first principles alone, rather than from some black box formula you had implanted in your head sometime long ago :)
Let Lat and Long denote latitude and longitude matrices, then
dist2=sum(bsxfun(#minus, cat(3,A,B), cat(3,Lat,Long)).^2,3);
[I,J]=find(dist2==min(dist2(:)));
I and J contain the indices in A and B that correspond to nearest point. Note that if there are multiple answers, I and J will not be scalar values, but vectors.

Detect incorrect points in a homogeneous surface

In my project i have hige surfaces of 20.000 points computed by a algorithm. This algorithm, sometimes, has an error, computing 1 or more points in an small area incorrectly.
This error can not be solved in the algorithm, but needs to be detected afterwards.
The error can be seen in the next figure:
As you can see, there is a point wrongly computed that not only breaks the full homogeneous surface, but also destroys the aestetics of the plot (wich is also important in the project.)
Sometimes it can be more than a point, in general no more than 5 or 6. The error is allways the Z axis, so no need to check X and Y
I have been squeezing my mind to find a bit "generic" algorithm to detect this poitns.
I thougth that maybe taking patches of surface and meaning the Z, then detecting the points out of the variance... but I dont think it will work allways.
Any ideas?
NOTE: I dont want someone to write code for me, just an idea.
PD: relevant code for the avobe image:
[x,y] = meshgrid([-2:.07:2]);
Z = x.*exp(-x.^2-y.^2);
subplot(1,2,1)
surf(x,y,Z,gradient(Z))
subplot(1,2,2)
Z(35,35)=Z(35,35)+0.3;
surf(x,y,Z,gradient(Z))
The standard trick is to use a Laplacian, looking for the largest outliers. (This is not unlike what Mohsen posed for an answer, but is actually a bit easier.) You could even probably do it with conv2, so it would be pretty efficient.
I could offer a few ways to implement the idea. A simple one is to use my gridfit tool, found on the File Exchange. (Gridfit essentially uses a Laplacian for its smoothing operation.) Fit the surface with all points included, then look for the single point that was perturbed the most by the fit. Exclude it, then rerun the fit, again looking for the largest outlier. (With gridfit, you can use weights to give points a zero weight, a simple way to exclude a point or list of points.) When the largest perturbation that was needed is small enough, you can decide to stop the process. A nice thing is gridfit will also impute new values for the outliers, filling in all of the holes.
A second approach is to use the Laplacian directly, in more of a filtering approach. Here, you simply compute a value at each point that is the average of each neighbor to the left, right, above, and below. The single value that is most largely in disagreement with its computed average is replaced with a new value. Or, you can use a weighted average of the new value with the old one there. Again, iterate until the process does not generate anything larger than some tolerance. (This is the basis of an old outlier detection and correction scheme that I recall from the Fortran IMSL libraries, but probably dates back to roughly 30 years ago.)
Since your functions seems to vary smoothly these abrupt changes can be detected by looking into the derivatives. You can
Take the derivative in one direction
Calculate mean and standard deviation of derivative
Find the points by looking for points that are further from mean by certain multiple of standard deviation.
Here is the code
U=diff(Z);
V=(U-mean(U(:)))/std(U(:));
surf(x(2:end,:),y(2:end,:),V)
V=[zeros(1,size(V,2)); V];
V(abs(V)<10)=0;
V=sign(V);
W=cumsum(V);
[I,J]=find(W);
outliers = [I, J];
For your example you get this plot for V with a peak at around 21.7 while second peak is at around 1.9528, so maybe a threshold of 10 is ok.
and running the code returns
outliers =
35 35
The need for cumsum is for the cases that you have a patch of points next to each other that are incorrect.