MATLAB flip definition of angles (or alternative angular metric) - matlab

I am doing work on symmetric images where I would like to define a symmetric (polar) coordinate space. Basically for the left image, I want 0 degrees to be defined along the right horizontal axis (as is the default). However, for the right image, I want 0 degrees to be defined along the left horizontal axis.
I know a phase shift of pi would do the trick. However, for comparison purposes, I am trying to keep the range of angles the same, [-pi : pi).
In the above color plot of the rotations in an object, note that they are both defined in the same direction. Ideally I'd like to see the colors of the right object flipped across its vertical axis.
I should note that these angles are calculated by taking the arctan(y/x) of the perimeter coordinates when measured from the centroid. Is there a different trig function that may result in the proper symmetry? I couldn't seem to come up with one while still claiming it was representative of direction.

Related

Can I compute contour orientation without using polygon area sign?

Most of the times, I determine contour orientation generating 2D points and computing the closed polygon area. Depending on the area value sign I can understand if the contour is oriented clockwise or not (see How to determine if a list of polygon points are in clockwise order?).
Would it be possible to do the same computations without generating 2D points? I mean, relying only on geometric curve properties?
We are interested in determining the orientation of contours like these ones without sampling them with 2D points.
EDIT: Some interesting solutions can be found here:
https://math.stackexchange.com/questions/423718/general-way-to-find-out-whether-a-curve-is-positively-oriented
Scientific paper: Determining the orientation of closed planar curves, DJ Filip (1990)
How are those geometric curves defined?
Do you have an angle for them? The radius doesn't matter, only the difference between entry-angle and exit-angle of each curve.
In that case, a trivial idea crossing my mind is to just sum up all the angles. If the result is positive, you know you had more curves towards the right meaning it's a clockwise contour. If it was negative, then more curves were leftwards -> anti-clockwise contour. (assuming that positive angels determine a right-curve and vica versa)
After thinking about this for awhile, for polygons that contain arcs I think there are three ways to do this.
One, is to break the arcs into line segments and then use the area formula as described above. The success of this approach seems to be tied to how close the interpolation of the arcs is as this could cause the polygon to intersect itself.
A quicker way than the above would be to do the interpolation of the arcs and then find a vertex in the corner (minimal Y, if tie minimal X) and use the sign of the cross product for that vertex. Positive CCW, negative CW. Again, this is still tied to the accuracy of the interpolation.
I think a better approach would be to find the midpoint of the arc and create two line segments, one from the beginning of the arc to the midpoint and another from the midpoint to the end of the arc and replace the arc with these line segments. Now you have a polygon with only line segments. Then you can add up all the normalized cross products of all the vertices. The sign will tell you the direction. Positive is counter-clockwise, negative is clockwise. In this case it doesn't matter if the polygon self-intersects.

How to find distance mid point of bezier curve?

I am making game in Unity engine, where car is moving along the bezier curve by percentage of bezier curve legth.
On this image you can see curve with 8 stop points (yellow spheres). Between each stop point is 20% gap of total distance.
On the image above everything is working correctly, but when I move handles, that the handles have different length problem occurs.
As you can see on image above, distances between stop points are not equal. It is because of my algorithm, because I am finding point of segment by multiplying segment length by interpolation (t). In short problem is that: if t=0.5 it is not in the 50% percent of the segment. As you can see on first image, stop points are in half of segment, but in the second image it is not in half of segment. This problem will be fixed, if there is some mathematical formula, how to find distance middle point.
As you can see on the image above, there are two mid points. T param mid point can be found by setting t to 0.5 (it is what i am doing now), but it is not half of the distance.
How can I find distance mid point (for cubic bezier curve, that have handles in different distance)?
You have correctly observed that the parameter value t=0.5 is generally not the point in the middle of the length. That is a good start but the difficulty lies in the mathematics beneath.
Denoting the components of your parametric curve by x(t) and y(t), the length of the curve
between t=0 (the beginning) and a chosen parameter value t = u is equal to
What you are trying to do is to find u such that l(u) is one half of l(1). This is sometimes possible but often difficult or impossible. So what can you do?
One possibility is to approximate the point you want. A straightforward way is to approximate your Bezier curve by a piecewise linear curve (simply by choosing many parameter values 0 = t_0 < t_1 < ... < t_n = 1 and connecting the values in these parameters by line segments). Now it is easy to compute the entire length (Pythagoras Theorem is your friend) as well as the middle point (walk along the piecewise linear curve the prescribed length). The more points you sample, the more precise you will be and the more time your computation will take, so there is a trade-off. Of course, you can use a more complicated numerical scheme for the approximation but that is beyond the scope of the answer.
The second possibility is to restrict yourself to a subclass of Bezier curves that will let you do what you want. These are called Pythagorean-Hodograph (shortly PH) curves. They have the extremely useful property that there exists a polynomial sigma(t) such that
This means that you can compute the integral above and search for the correct value of u. However, everything comes at a price and the price here is that you will have less freedom, where to put the control points (for me as a mathematician, a cubic Bézier curve has four control points; computer graphics people often speak of "handles" so you might have to translate into your terminology). For the cubic case you can find the conditions on slide 15 of this seminar talk by Vito Vitrih.
Denote:
the control points,
;
then the Bézier curve is a PH curve if and only if
.
It is up to you to figure out, if you can enforce this condition in your situation or if it is too restrictive for your application.

Calculate angle of matrix with topography for each triangle

I have a matrix with data of a topography, let's say several hills. I want to have information of the angle of each data point to the vertical line. Here are two examples:
If I consider a place near the foot of the hill that is totally flat, I have a degree of 90° (90° to the vertical line).
If I am at the steepest point of the hill, I have a lower angle of let's say 50°.
To compute this I guess I have to to connect all the topography data so that (at least) three near pixels form triangle. After that I have to compute the angle(s) of this triangle.
Can I use a existing algorithm?
If your heightmap is a matrix A then you could approximate the the gradient components of every inner point (without the egdes) by
Xgrad = (A(2:end-1,3:end)-A(2:end-1,1:end-2))/2;
Ygrad = (A(3:end,2:end-1)-A(1:end-2,2:end-1))/2;
The angulars will then be
deg = (pi/2 - atan(sqrt(Xgrad.^2 + Ygrad.^2),1))/pi*180;
Depending on your heightmap, differentiating numerically can produce "fuzzy" results. Maybe you have to do some blur-filtering in order to produce smoother gradients.

How do I interpret the orientation of the gradient when using imgradient in MATLAB?

I am finding the gradient of an image. For now I am simply using a 5 x 5 image. I am more interested in finding the direction of the gradient but I am not getting the results manually on paper as I get them using MATLAB function imgradient. Please refer to the following images to know more about the input images and the Sobel filter that is used here to find the gradient of an image. One of the 3 x 3 sobel operator used here is the one that I get using the function
f1 = fspecial('sobel');
and the other one is obtained by just transposing the f1.
Please note that I am trying to find the direction of only one pixel here that is rounded by red color. Here in the first two cases my result matches with that i obtain using imgradient function but in the third case imgradient gives -135 degree whereas I am getting it to be -45. Please help me find the error.
Also please explain how to interpret the following gradient directions as shown in the follwing image.
Your calculations are correct but it is highly recommended that you don't use the atan(y/x) definition because this calculation is not cognizant of the quadrant that the angle of the gradient resides in. Doing atan(y/x) with your components would falsely report the angle to be -45 degrees when that isn't correct. You should use atan2 instead.
Now the internals of imgradient are quite straight forward. I'd like to point out that the angle reported by imgradient is assuming that the y coordinate is increasing from bottom to top. In addition, imgradient should report the angle of orientation that is pointing to the greatest rate of change. In the case of images, this points in the direction where we progress from dark pixels to light pixels.
First a call to imgradientxy is called and a call to fspecial('sobel') is made if you provide the sobel flag to imgradient. In fact, this portion of imgradientxy is what is important to remember (starting at line 75: MATLAB R2015a):
case 'sobel'
h = -fspecial('sobel'); %// Align mask correctly along the x- and y- axes
Gx = imfilter(I,h','replicate'); %'
if nargout > 1
Gy = imfilter(I,h,'replicate');
end
Notice that the negative of the output of fspecial is performed as well as the comment provided at that line. This is to ensure that the mask to detect horizontal edges (i.e. Gy) is y-down (as it is commonly known in computer graphics). Specifically, the origin of the image is at the top-left corner and not the bottom left.
This is a pictorial representation of how the coordinate system is laid out in y-down:
Source: Wikipedia - Rotation Matrix
As such, when finding the orientation there is an additional requirement to ensure that the angle of the orientation of the gradient is with respect to the y-up coordinate system which is what we're used to. Therefore when you are finding the angle of orientation of the gradient, you need to negate the y coordinate before calculating the angle so that the angle is with respect to the standard convention instead.
Pursuing the definition of the gradient that you seek is the conventional system of the y coordinate increasing from bottom to top. The negation is required and in fact if you examine the source code for imgradient, this is precisely what is being done at line 127 of the code (version R2015a):
Gdir = atan2(-Gy,Gx)*180/pi; %// Radians to degrees
You may be asking yourself why there is a need to negate the mask and again negate the y coordinate after to find the orientation. The reason why is because the modified mask is required to properly capture the magnitude of the gradient and so we negate the mask once and find the gradient magnitude and then we negate the y coordinate so that we can find the angle with respect to the conventional coordinate system.
In your case, given that Gx = 765 and Gy = -765, substituting these quantities into the above equation yields:
>> Gy = 765;
>> Gx = -765;
>> Gdir = atan2(-Gy,Gx)*180/pi
Gdir =
-135
This makes sense because the gradient direction corresponds to the direction towards the greatest rate of change. -135 degrees means that we're pointing to the south west which does make sense as we are progressing from dark pixels to light pixels.
Now if you consult your third example image, the angles reported by imgradient are indeed correct. Simply draw a line from the dark area to the light area and see what angle it makes with the x axis where it is aligned with the columns increasing towards the right. The first angle of +90 degrees makes sense as we are moving from bottom to top to follow the dark area and light. This is a similar situation with the situation where the image is reversed. The third situation is what we have seen before and the fourth situation is simply the third situation rotated by 180 degrees and so naturally the angle of orientation from dark to light is now +45 degrees as opposed to -135 degrees previously.

Arrange the vertices of a 3D convex polygonal plane in counter clockwise direction in MATLAB

I have a convex polygon in 3D. For simplicity, let it be a square with vertices, (0,0,0),(1,1,0),(1,1,1),(0,0,1).. I need to arrange these vertices in counter clockwise order. I found a solution here. It is suggested to determine the angle at the center of the polygon and sort them. I am not clear how is that going to work. Does anyone have a solution? I need a solution which is robust and even works when the vertices get very close.
A sample MATLAB code would be much appreciated!
This is actually quite a tedious problem so instead of actually doing it I am just going to explain how I would do it. First find the equation of the plane (you only need to use 3 points for this) and then find your rotation matrix. Then find your vectors in your new rotated space. After that is all said and done find which quadrant your point is in and if n > 1 in a particular quadrant then you must find the angle of each point (theta = arctan(y/x)). Then simply sort each quadrant by their angle (arguably you can just do separation by pi instead of quadrants (sort the points into when the y-component (post-rotation) is greater than zero).
Sorry I don't have time to actually test this but give it a go and feel free to post your code and I can help debug it if you like.
Luckily you have a convex polygon, so you can use the angle trick: find a point in the interior (e.g., find the midpoint of two non-adjacent points), and draw vectors to all the vertices. Choose one vector as a base, calculate the angles to the other vectors and order them. You can calculate the angles using the dot product: A · B = A B cos θ = |A||B| cos θ.
Below are the steps I followed.
The 3D planar polygon can be rotated to 2D plane using the known formulas. Use the one under the section Rotation matrix from axis and angle.
Then as indicated by #Glenn, an internal points needs to be calculated to find the angles. I take that internal point as the mean of the vertex locations.
Using the x-axis as the reference axis, the angle, on a 0 to 2pi scale, for each vertex can be calculated using atan2 function as explained here.
The non-negative angle measured counterclockwise from vector a to vector b, in the range [0,2pi], if a = [x1,y1] and b = [x2,y2], is given by:
angle = mod(atan2(y2-y1,x2-x1),2*pi);
Finally, sort the angles, [~,XI] = sort(angle);.
It's a long time since I used this, so I might be wrong, but I believe the command convhull does what you need - it returns the convex hull of a set of points (which, since you say your points are a convex set, should be the set of points themselves), arranged in counter-clockwise order.
Note that MathWorks recently delivered a new class DelaunayTri which is intended to superseded the functionality of convhull and other older computational geometry stuff. I believe it's more accurate, especially when the points get very close together. However I haven't tried it.
Hope that helps!
So here's another answer if you want to use convhull. Easily project your polygon into an axes plane by setting one coordinate zero. For example, in (0,0,0),(1,1,0),(1,1,1),(0,0,1) set y=0 to get (0,0),(1,0),(1,1),(0,1). Now your problem is 2D.
You might have to do some work to pick the right coordinate if your polygon's plane is orthogonal to some axis, if it is, pick that axis. The criterion is to make sure that your projected points don't end up on a line.