in reply to Interesting problem fitting points to a template (algorithm?)

Given there are probably going to be rotation and x-y registration issues it seems to me that reducing the problem from 2 dimensions to a single dimension vector may work very swell in practice. It is easier to explain in code but the guts of the idea is simple. No matter how rotated or displaced, any planar figure (and the points define such a figure) will have a constant geometric centroid. Each point will have a constant distance from this centriod in one dimensional space regardless of rotation or displacement. We can use this to generate a very useful vector. We can also make the matching as precise of fuzzy as desired.

use constant X => 0; use constant Y => 1; my @points1 = ( [1,1], [2,2], [3,3] ); # a line like / my @points2 = ( [2,1], [3,2], [4,3] ); # a line like / displaced + R my @points3 = ( [1,1], [2.41,1], [3.82,1]);# a line like - my @template = ( [1,3], [2,2], [3,1] ); # a line like \ my $vp1 = vector(\@points1,2); my $vp2 = vector(\@points2,2); my $vp3 = vector(\@points3,2); my $vt = vector(\@template,2); print "@$vp1\n@$vp2\n@$vp3\ntemplate\n@$vt\n"; sub vector { my ($points, $precision) = @_; $precision ||= 10; # calculate the geometric centroid my ( $cx, $cy ) = (0,0); for (@$points) { $cx += $_->[X]; $cy += $_->[Y]; } $cx /= @$points; $cy /= @$points; # map the 1 dimensional distance of all points from centroid # using simple pythagorean geometry my @vector = map{ sqrt(($cx-$_->[X])**2 + ($cy-$_->[Y])**2) } @$po +ints; # fuzzify to desired precision and sort to create finished vector my $template = "%.${precision}f"; @vector = map{ sprintf $template, $_ } sort { $a <=> $b } @vector; return \@vector; } __DATA__ 0.00 1.41 1.41 0.00 1.41 1.41 0.00 1.41 1.41 template 0.00 1.41 1.41

So in one dimensional space our vector tells us that the 3 lines all match the template. The effects of rotation and displacement have been removed. You can also deal with scaling simply by using normalisation.

Matching the single dimension vector against a template set can be achieved in many ways. Stringifying the vector at a reliable precision and using a hash lookup against the template vectors is an obvious method.

This vector process has some caveats. For any given 1 dimensional vector there are an infinite number of 2 dimensional shapes that map to it. For example a vector of 1,1,1,1 in 1 dimensional space can represent any number of rectangles or a square in 2 dimensional space.

C = centroid . . . . : C : C C . . . .

cheers

tachyon

Replies are listed 'Best First'.
Re^2: Interesting problem fitting points to a template (algorithm?)
by doowah2004 (Monk) on Oct 06, 2004 at 13:03 UTC
    I like this solution because it is simple and clever, but the three problems that I see (and I may be wrong) are as follows:

    1. I have seven vertices making up a 2d shape, this shape may have suffered rotational and translational displacement. I have a rough idea of the maximum displayment, so I look at a given size ROI around where the points would be with no displacement. After discriminating the noise for size of points I am usually left with 1-2 possible points (not bad), but I have seen as many as twelve. So looking at a worse case (but very possible), if I am left with 10 points in each ROI, then starting with one ROI and working through each set of points I have 10^7 possible geometric objects that roughly look like my template. lots of checks....

    2. The distance between the points in the ROI << then the distance to the calculated centroid, so I am concerned about the ability to consistantly choose the seven correct points and not seven almost true points (similar to what you were saying about infinite number of shapes containg the same centroid). In your example it only looks at rotational displacement, there will be translation displacement, but that is easily delt with looking at the relative distances from the points to the centroid....so still valid.

    3. What if the ROI contains points, but does not contain the True point?


    This does give me some thoughts that I will work through. I am going to take all of the suggestions, try to hash something out in the next couple of days, and repost what I have done.

    Cameron

      The method copes fine with 360 degrees of rotation or any ammount x-y translation (there is an even an example of that). This is simple a function of mapping from 2D to 1D space. In one dimensional space the concepts or rotation and x-y tranlation simply have no meaning.

      However the method shown relies on having *all* the points, no extra points and no missing points. This is because it is using the centriod to create the vector. A single missing or additional point will result in a different centroid, and vastly different vector.

      It is not clear what the real problem you are dealing with is. Curious? It seems now that missing and additional points are an issue. If so you can modify the method as follows.

      Without an accurate centroid we must choose one (or more) arbitrary points to use for our 2D->1D mapping. You could choose x_min, or y_min or any other arbitrary point but given templates with ~ 10 points I would just choose all of them in sequence, ie arbitratily declare each point the 'centroid' in turn and calculate the 1D distance mapping vector as before. Insert this data into some sort of easy lookup hash structure. You probably won't need the sort anymore which is O(logn) anyway. You now have all 10 possible 1D mappings of your template object from every possible point, thus rotation, translation, and added/missing points are not an issue. For any given point set you can rapidly check that sets correlation against all the templates in O(n) time.

      I will be interested to hear how you get on.

      cheers

      tachyon