How to smooth hand drawn lines? - math

So I am using Kinect with Unity.
With the Kinect, we detect a hand gesture and when it is active we draw a line on the screen that follows where ever the hand is going. Every update the location is stored as the newest (and last) point in a line. However the lines can often look very choppy.
Here is a general picture that shows what I want to achieve:
With the red being the original line, and the purple being the new smoothed line. If the user suddenly stops and turns direction, we think we want it to not exactly do that but instead have a rapid turn or a loop.
My current solution is using Cubic Bezier, and only using points that are X distance away from each other (with Y points being placed between the two points using Cubic Bezier). However there are two problems with this, amongst others:
1) It often doesn't preserve the curves to the distance outwards the user drew them, for example if the user suddenly stop a line and reverse the direction there is a pretty good chance the line won't extend to point where the user reversed the direction.
2) There is also a chance that the selected "good" point is actually a "bad" random jump point.
So I've thought about other solutions. One including limiting the max angle between points (with 0 degrees being a straight line). However if the point has an angle beyond the limit the math behind lowering the angle while still following the drawn line as best possible seems complicated. But maybe it's not. Either way I'm not sure what to do and looking for help.
Keep in mind this needs to be done in real time as the user is drawing the line.

You can try the Ramer-Douglas-Peucker algorithm to simplify your curve:
https://en.wikipedia.org/wiki/Ramer%E2%80%93Douglas%E2%80%93Peucker_algorithm
It's a simple algorithm, and parameterization is reasonably intuitive. You may use it as a preprocessing step or maybe after one or more other algorithms. In any case it's a good algorithm to have in your toolbox.
Using angles to reject "jump" points may be tricky, as you've seen. One option is to compare the total length of N line segments to the straight-line distance between the extreme end points of that chain of N line segments. You can threshold the ratio of (totalLength/straightLineLength) to identify line segments to be rejected. This would be a quick calculation, and it's easy to understand.
If you want to take line segment lengths and segment-to-segment angles into consideration, you could treat the line segments as vectors and compute the cross product. If you imagine the two vectors as defining a parallelogram, and if knowing the area of the parallegram would be a method to accept/reject a point, then the cross product is another simple and quick calculation.
https://www.math.ucdavis.edu/~daddel/linear_algebra_appl/Applications/Determinant/Determinant/node4.html
If you only have a few dozen points, you could randomly eliminate one point at a time, generate your spline fits, and then calculate the point-to-spline distances for all the original points. Given all those point-to-spline distances you can generate a metric (e.g. mean distance) that you'd like to minimize: the best fit would result from eliminating points (Pn, Pn+k, ...) resulting in a spline fit quality S. This technique wouldn't scale well with more points, but it might be worth a try if you break each chain of line segments into groups of maybe half a dozen segments each.
Although it's overkill for this problem, I'll mention that Euler curves can be good fits to "natural" curves. What's nice about Euler curves is that you can generate an Euler curve fit by two points in space and the tangents at those two points in space. The code gets hairy, but Euler curves (a.k.a. aesthetic curves, if I remember correctly) can generate better and/or more useful fits to natural curves than Bezier nth degree splines.
https://en.wikipedia.org/wiki/Euler_spiral

Related

segmenting lat/long data graph into lines/vectors

I have lat/lng data of multirotor UAV flights. There are alot of datapoints (~13k per flight) and I wish to find line segments from the data. They give me flight speed and direction. I know that most of the flights are guided missons meaning a point is given to fly to. However the exact points are unknown to me.
Here is a graph of a single flight lat/lng shifted to near (0,0) so they are visible on the same time-series graph.
I attempted to generate similar data, but there are several constraints and it may take more time to solve than working on the segmenting.
The graphs start and end nearly always at the same point.
Horisontal lines mean the UAV is stationary. These segments are expected.
Beginning and and end are always stationary for takeoff and landing.
There is some level of noise in the lines for the gps accuracy tho seemingly not that much.
Alot of data points.
The number of segments is unknown.
The noise I could calculate given the segments and least squares method to the line. Currently I'm thinking of sampling the data (to decimate it a little) and constructing lines. Merging the lines with smaller angle than x (dependant on the noise) and finding the intersection points of the lines left.
Another thought is to try and look at this problem in the frequency domain. The corners should be quite high frequency. Maybe I could make a custom filter kernel that would enable me to use a window function and win in efficency.
EDIT: Rewrote the question for more clarity and less rambling.

Convert curved line between two points to straight connection

I have the two points p1 and p2 and the line l (black). The line is made of 100+ internal points arranged in an array starting from p1 and ending in p2.
Now, I would like to convert the curved line to a "straight" line like the red line on the above illustration. I am, however, a little unsure how to do this.
So far, my idea is to iterate the line with a fixed distance (e.g. take all points from start and 100 pixels forward), calculate the curve of the line, if it exceeds a threshold, make the straigt line change direction, then iterate the next part and so on. I'm not sure this would work as intended.
Another idea would to make a greedy algorith trying to minimize the distance between the black and red line. This could, however, result in small steps which I would like to avoid. The steps might be avoided by making turns costly.
Are there any algorithms about this particular problem, or how would you solve it?
Search for the phrase polygonal chain simplification and you'll see there is quite a literature on this topic.
Here is one reference that could lead you to others:
Buzer, Lilian. "Optimal simplification of polygonal chains for subpixel-accurate rendering." Computational Geometry 42.1 (2009): 45-59.

Maximum number of points that lie on the same straight straight line in a 2D plane

I am trying to solve a programming interview question that requires one to find the maximum number of points that lie on the same straight straight line in a 2D plane. I have looked up the solutions on the web. All of them discuss a O(N^2) solution using hashing such as the one at this link: Here
I understand the part where common gradient is used to check for co-linear points since that is a common mathematical technique. However, the solution points out that one must beware of vertical lines and overlapping points. I am not sure how these points can cause problems? Can't I just store the gradient of vertical lines as infinity (a large number)?
Hint:
Three distinct points are collinear if
x_1*(y_2-y_3)+x_2*(y_3-y_1)+x_3*(y_1-y_2) = 0
No need to check for slopes or anything else. You need need to eliminate duplicate points from the set before the search begins though.
So pick a pair of points, and find all other points that are collinear and store them in a list of lines. For the remainder points do the same and then compare which lines have the most points.
The first time around you have n-2 tests. The second time around you have n-4 tests because there is no point on revisiting the first two points. Next time n-6 etc, for a total of n/2 tests. At worst case this results in (n/2)*(n/2-1) operations which is O(n^2) complexity.
PS. Who ever decided the canonical answer is using slopes knows very little about planar geometry. People invented homogeneous coordinates for points and lines in a plane for the exact reason of having to represent vertical lines and other degenerate situations.

Approximate a list of points with a short list of Bézier curves

I have a list of (x, y) points. I know how to make a list of Bézier curves which pass through all of those points and have a continuous first (and second, though less important) derivative. However, the list that I end up with is far too long. I would prefer to approximate the points I have if it lets me cut down on the number of curves I have. I would like to be able to pass a parameter of either how close an approximation I get or a maximum number of curves, preferably the former.
The reason I want this is that the end result will have a graphical UI where users can edit the Bézier curves, and it isn't critical that the curves pass through each point exactly, as long as they are close. More curves makes it harder to edit.
EDIT:
Some more information about the purpose of this. I'm trying to make image editing software. When someone loads a bitmap, I want to be able to trace a center line. Potrace is what I would use to trace the outline of a shape, but it won't work for tracing strokes. I've been able to identify lots of points along the center line, and I want to turn this data into a list of connected Bézier curves. The reason I don't want to make a Bézier spline is that there will be too many control points for this to be easy to edit. "Too many" is not an easy-to-define term, but I would like to be able to pass a parameter to limit the number of curves. Either a function that minimizes how far the curves are from the points based on a maximum number of curves or a function that minimizes the number of curves based on a maximum deviation from the points.
Several approaches exist for achieving what you want to do:
1) Use RDP algorithm to reduce the number of points, then create a list of Bezier curves passing thru the remaining points.
2) Use curve fitting algorithms (for example, Schneider algorithm) to produce multiple Bezier curves that are connected with G1 (tangent) continuity. Check out Schneider algorithm implementation in this link.
3) Use least square fitting with B-spline to produce a single B-spline curve.
From implementation point of view, approach 1 is probably the easiest one for you as you already know how to create Bezier curves interpolating a list of points. Approach 3 will be much more difficult to implement and you probably will have to convert the B-spline curve into Bezier curves so as to use them at the UI level. Please refer to this SO article for detailed discussion.

quality analysis of fitted pyramid

sorry for posting this in programing site, but there might be many programming people who are professional in geometry, 3d geometry... so allow this.
I have been given best fitted planes with the original point data. I want to model a pyramid for this data as the data represent a pyramid. My approach of this modeling is
Finding the intersection lines (e.g. AB, CD,..etc) for each pair of adjacent plane
Then, finding the pyramid top (T) by intersecting the previously found lines as these lines don’t pass through a single point
Intersecting the available side planes with a desired horizontal plane to get the basement
In figure – black triangles are original best fitted triangles; red
and blue triangles are model triangles
I want to show that the points are well fitted for the pyramid model
than that it fitted for the given best fitted planes. (Assume original
planes are updated as shown)
Actually step 2 is done using weighted least square process. Each intersection line is assigned with a weight. Weight is proportional to the angle between normal vectors of corresponding planes. in this step, I tried to find the point which is closest to all the intersection lines i.e. point T. according to the weights, line positions might change with respect to the influence of high weight line. That mean, original planes could change little bit. So I want to show that these new positions of planes are well fitted for the original point data than original planes.
Any idea to show this? I am thinking to use RMSE and show before and after RMSE. But again I think I should use weighted RMSE as all the planes refereeing to the point T are influenced so that I should cope this as a global case rather than looking individual planes….. But I can’t figure out a way to show this. Or maybe I should use some other measure…
So, I am confused and no idea to show this.. Please help me…
If you are given the best-fit planes, why not intersect the three of them to get a single unambiguous T, then determine the lines AT, BT, and CT?
This is not a rhetorical question, by the way. Your actual question seems to be for reassurance that your procedure yields "well-fitted" results, but you have not explained or described what kind of fit you're looking for!
Unfortunately, without this information, your question cannot be answered as asked. If you describe your goals, we may be able to help you achieve them -- or, if you have not yet articulated them for yourself, that exercise may be enough to let you answer your own question...
That said, I will mention that the only difference between the planes you started with and the planes your procedure ends up with should be due to floating point error. This is because, geometrically speaking, all three lines should intersect at the same point as the planes that generated them.

Resources