does affine transformation change neighbourhood - affinetransform

I have a set of 100 points.
I am considering 4 closest neighbour of each point.
Using three (non-collinear) points as basis among these four, I get affine coordinate of the fourth point.
This way I create database for 100 points.
There are 100 x 4C3 x 3 records. Each having an affine coordinate.
Now, I did affine transformation on all 100 points.
Specifically ,
If a point is (x,y)
It becomes new_x = x+2y+5
It becomes new_y = 3x+4y+6
I have observed that closest neighbours of all points got changed.
Actually some points had 1 or 2 neighbours as before, but rest changed.As a result affine coordinate matching did not work.
Note that I am calculating closest neighbour using euclidean distance i.e sqrt((x2-x1)2+(y2-y1)2).
When I think about affine transformation - I feel rotation,scaling and translation won't change neighbours but shearing maybe can.
Is my transformation not affine ?
Can you suggest a better way to get neighbours ?
Thanks.

Related

Optimizing computation of distance to triangle using barycentric coordinates

Building on the discussions here and here. I'm trying to compute the shortest distance between a 3D line and a 3D triangle.
I'm using barycentric coordinates to determine whether or not the point is inside the triangle. So given a triangle defined by vertices UVW and a line defined by point AB, I first compute the intersection of line AB with the plane defined by UVW. Let's call this intersection P and assume I've already done the checks to verify whether or not the point actually intersects the plane at all.
I then compute barycentric coordinates (S,T) such that S is defined along the edge UV and T is defined along the edge UW. Naturally, if 0≤S and 0≤T and S+T≤1 then P is on the triangle (or its edge) and my distance to the triangle is obviously zero.
If that's not true then P is outside the triangle and I need to compute the distance. The guidance of from the first link says to project point P onto all three edges to get three candidate points. Adding those points to the three triangle's vertices, you then have six points to test against.
Isn't it easier than that, though? If T<0, then don't you already know that UV is the closest edge and you only have to test against the projection of P onto that line? Similarly, if S<0 then UW would be the closest edge. If T>0 and S>0 then VW is the closest edge.
Thus based on the signs of S and T you already know the closest edge and only have to compute the distance from P to its projection onto that edge. If the projection isn't inside the triangle, then the closest point is either vertex. Thus your computations are about 1/3 of the proposed methods.
Am I missing something here, or is this a valid optimization? I'm fairly new to barycentric coordinates and their attributes.
It turns out that the problem of closest distance from a point and from a line are very similar and can both be reduced to a pure 2D problem.
Distance from a point
By Pythagoras, the squared distance from a point to a point of the triangle is the sum of the squared distance to the plane of support of the triangle and the squared distance of the projection of the point to that plane.
The latter distance is precisely the distance from the normal line to the triangle.
Distance from a line
Looking in the direction of the line, you see the projected triangle and the line is reduced to a single point. The requested 3D distance is equal to the 2D distance seen on the projection.
To obtain the desired coordinates, you use an auxiliary coordinate frame such that Z is in the direction of the line (and XY is a perpendicular plane); for convenience, choose the origin of the new frame to be on the line. Then by just ignoring Z, you get a planar problem in XY. The change of coordinates is an affine tranformation.
Point vs. triangle
Consider the three triangles formed by the origin (projection of the point/line) and a pair of triangle vertices (taken in cyclic order). The signed area of these triangles is a mere 2x2 determinant.
If the three areas have the same sign, the point is inside. Otherwise, the signs tell you where you are among the six surrounding regions, either past an edge or past a vertex.
On the upper figure, the point is inside (three positive areas). On the other figure, it is outside of the top-right edge (one negative area). Also note that dividing an area by the length of the corresponding side, you get the distance to the side. (Factor 2 omitted.)
The total work is
compute the affine frame;
convert the coordinates of the 3 or 4 points;
compute the three signed areas;
if inside, you are done;
otherwise, if in an edge region, compute a distance to a line and two distances to points;
otherwise you are in a vertex region, compute two distances to lines and one distance to vertex.

How can I compute the diameter of the circle that circumscribes an irregular object?

I want a function to compute and get the diameter of the circle that circumscribes the object. Is there a built-in function in MATLAB to do this? Otherwise, what can I do?
Try this algorithm:
Compute the average x and average y for every point in the irregular object. This is done by taking the x and y component for every point and add them into the total x and total y and then divide by the number of points. This average x and average y point algorithm gives you a non-weighted center of the object.
Use that center point to compute the distance for every point in the irregular object again. Keeping the largest distance as the radius of the object.
Use the center point and the radius to compute the circumference.
I am submitting proof that the distance between the 2 points that are furthest apart in the object fails with a simple triangle. See image below. Also, the big-O notation for computing the two points that are the furthest apart is x^2. The big-O for this algorithm is 2x. The diameter of the circle in the image would be computed as 20; distance between -10,0 and 10,0. A circle of diameter 20 will not encompass the point # 0,-11. Any movement of the circle would automatically remove at least one of the two points used to compute the diameter of the circle because both points are on tangents.
Suppose M is a mask in BW, just do :
[b_x,b_y] = find(bwperim(M)== 1)
Check this function bwperim

Euclidean distance two pixels, each belonging to different images

I'm trying to implement Naive Bayes Nearest Neighbor (NBNN) for image classification. In the algorithm it asks for the Euclidean distance between two pixels belonging to different images.
I have 1) a set of m-images in a m-by-40,000 matrix (where 40,000 is the number of pixels in one image) and 2) another set of n-images in a n-by-40,000 matrix.
1) is the training set and 2) is the validation set.
In order for me to apply NBNN, from my understanding, I need to find the Euclidean distance between each pixels of 2) to the corresponding pixels of 1).
My question is, given two grey scale values, one from 1) and the other from 2), how would I find the Euclidean distance between them in order to apply k-NN?
Let x, y be two gray-scale 200-by-200 images. Pixels levels are x1,x2,...x40000 and y1, y2,...y40000.
The euclidean distance between x and y is d(x,y)=sqrt(sum_i((xi-yi)^2))
I will refer to the notation and definition given at wikipedia
You have 1d-data, thus p=(p1) and q=(q1). e(p,q)=sqrt((p1-q1)^2)=abs(p1-q1)
For the 1d-case, the euclidean distance is the absolute difference of the grey values.

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.

Principal direction in a binary image

As shown in image, there is a binary polygonal image. I want to find the principal direction in the image with respect to X-axis. I have shown the principal direction and X-axis with blue line. This can be done using PCA but my problem is such a small rectangle will have around 1000 pixels and I have to find Principal directions for around 100 polygons (polygon can be of arbitrary shape).
One approach that I have thought is:
Project that rectangle onto a line which is oriented at degrees at an interval (say) 5 degrees. The projection which has the maximum variance is the desired projection axis, and thus that is the desired angle. But this also falls under a greedy approach and thus will take time. Is there a smarter approach?
Also, if anybody could explain the exact procedure to do this using PCA, it would be helpful. I know the steps:
1. Take the covariance matrix.
2. Get the top eigenvector corresponding to largest eigenvalue -> that will be the principal direction.
But I am confused in the following statement which I often read everywhere:
A column vector: [0.5 0.5] is the first principal component and it gives the direction of the maximum variance. So can do I exactly calculate the angle by which I should rotate the data so that it will become parallel to X-axis.
Compute the eigenvector associated with the highest eigen value. Call that v. Normalize v. v = v/norm(v);
Compute angle between that and the horizontal direction: angle=acos(sum(v.*[1,0]))
Rotate by -angle, transformation matrix T = [cos(-angle) -sin(-angle); sin(-angle) cos(-angle)], multiply all points by that matrix. Do that for all polygons.