How to find the centerline line of 2-dimensional long region - algorithm

How to design a thinning algorithm to find the center-line of a 2-dimensional long region, for instance a river in a geological map? or is there any other method to find the center-line of an irregular 2-dimensional long region?
Thanks for any helpful answers.

Try to search for "Skeletonization". Roughly it's extraction of center lines from graphical objects. There are several algorithms for this:
gradually remove pixels which are not part of skeleton: http://cgm.cs.mcgill.ca/~godfried/teaching/projects97/azar/skeleton.html#define
sending wave from object borders to inside and looking for self-collisions
sending wave from some part of the object and looking for middle of wave front

[I made it a separate answer, because approach is too different]
This approach is applicable for rivers without branches:
Extract "left" and "right" border as sequences of pixel coordinates
Find correspondence between pixels from left and right borders (e.g. with dynamic programming)
Define centre line points as middle points between two corresponding left and right points
Edit:
By correspondence I mean sequence of pairs of pixels which goes continuously along both borders keeping distance between them minimal. "Continuously" means that we either do one step along both borders or one step along one of them.
Example of finding such sequence is described here: http://en.wikipedia.org/wiki/Levenshtein_distance

Related

Contour detection

I could not understand how contour detection algorithm works on a 2D graph generally. Do the Contour detection algorithms check all points in the space to find each contour line? Can someone explain intuitively?
A lot will depend on precisely what you application is. Are you after all the contour lines or just a single one? What is the data you start with - points arranged on a regular grid, random samples or perhaps a function you can evaluate at any given point. Information about how well the data behaves is also useful - does is have a few big peeks or is it very bumpy.
The main algorithms involve some form or zero-following, say we want to follow the zero contour. There are two main tasks finding an initial point and following round the contour.
For example consider that we have data arranged on a regular grid and have a starting point in one grid square. You can examine neighbouring squares and look at the sign of the function at the corners. If the corners are all positive or all negative we know the contour can not go through the square and we ignore that square. If the contour is nicely behaved there should be exactly two square with sign changes, choose one, move to that square and repeat. Eventually you will follow the contour back to the start or possibly an edge of your domain.
Finding starting points is trickier. You can look along the edges of your domain, or use some form of sampling.

How to find this kind of geometry in images

Suppose I have an image of a scene as depicted above. A sort of a pole with a blob on it next to possibly similar objects with no blobs.
How can I find the blob marked by the red circle (a binary image indicating which pixels belong to the blob).
Note that the pole together with the blob may be rotated arbitrarily and also size may vary.
Can you try to do it in below 4 steps?
Circle detection like: writing robust (color and size invariant) circle detection with opencv (based on Hough transform or other features)
Line detection, like: Finding location of rectangles in an image with OpenCV
Identify rectangle position by combining neighboring lines (For each line segment you have the start and end point position, you also know the direction of each line segment. So that you can figure out if two connecting line segments (whose endpoints are close) are orthogonal. Your goal is to find 3 such segments for each rectangle.)
Check the relative position of each circle and rectangle to see if any pair can form the knob shape.
One approach could be using Viola-Jones object detection framework.
Though the framework is mostly used for face detection - it is actually designed for generic objects you feed to the algorithm.
The algorithm basic idea is to feed samples of "good object" (what you are looking for) and "bad objects" to a machine learning algorithm - which generates patterns from the images as its features.
During Classification - using a sliding window the algorithm will search for a "match" to the object (the classifier returned a positive answer).
The algorithm uses supervised learning and thus requires a labeled set of examples (both positive and negative ones)
I'm sure there is some boundary-map algorithm in image processing to do this.
Otherwise, here is a quick fix: pick a pixel at the center of the
"undiscovered zone", which initially is the whole image.
trace the horizantal and vertical lines at 4 directions each ending at the
borders of the zone and find the value changes from 0 to 1 or the vice verse.
Trace each such value switch and complete the boundary of each figure (Step-A).
Do the same for the zones
that still are undiscovered: start at some center
point and skim thru the lines connecting the center to the image border or to a
pixel at the boundary of a known zone.
In Step-A, you can also check to see whether the boundary you traced is
a line or a curve. Whenever it is a curve, you need only two points on it--
points at some distance from one another for the accuracy of the calculation.
The lines perpendicular each to these two points of tangency
intersect at the center of the circle red in your figure.
You can segment the image. Then use only the pixels in the segments to contribute to a Hough-transform to find the circles.
Then you will only have segments with circle in them. You can use a modified hough transform to find rectangles. The 'best' rectangle and square combination will then be your match. This is very computationally intentsive.
Another approach, if you already have these binary pictures, is to transform to a (for example 256 bin) sample by taking the distance to the centroid compared to the distance travelled along the edge. If you start at the point furthest away from the centroid you have a fairly rotational robust featurevector.

Packing arbitrary polygons within an arbitrary boundary

I was wondering if anybody could point me to the best algorithm/heuristic which will fit my particular polygon packing problem. I am given a single polygon as a boundary (convex or concave may also contain holes) and a single "fill" polygon (may also be convex or concave, does not contain holes) and I need to fill the boundary polygon with a specified number of fill polygons. (I'm working in 2D).
Many of the polygon packing heuristics I've found assume that the boundary and/or filling polygons will be rectangular and also that the filling polygons will be of different sizes. In my case, the filling polygons may be non-rectangular, but all will be exactly the same.
Maybe this is a particular type of packing problem? If somebody has a definition for this type of polygon packing I'll gladly google away, but so far I've not found anything which is similar enough to be of great use.
Thanks.
The question you ask is very hard. To put this in perspective, the (much) simpler case where you're packing the interior of your bounded polygon with non-overlapping disks is already hard, and disks are the simplest possible "packing shape" (with any other shape you have to consider orientation as well as size and center location).
In fact, I think it's an open problem in computational geometry to determine for an arbitrary integer N and arbitrary bounded polygonal region (in the Euclidean plane), what is the "optimal" (in the sense of covering the greatest percentage of the polygon interior) packing of N inscribed non-overlapping disks, where you are free to choose the radius and center location of each disk. I'm sure the "best" answer is known for certain special polygonal shapes (like rectangles, circles, and triangles), but for arbitrary shapes your best "heuristic" is probably:
Start your shape counter at N.
Add the largest "packing shape" you can fit completely inside the polygonal boundary without overlapping any other packing shapes.
Decrement your shape counter.
If your shape counter is > 0, go to step 2.
I say "probably" because "largest first" isn't always the best way to pack things into a confined space. You can dig into that particular flavor of craziness by reading about the bin packing problem and knapsack problem.
EDIT: Step 2 by itself is hard. A reasonable strategy would be to pick an arbitrary point on the interior of the polygon as the center and "inflate" the disk until it touches either the boundary or another disk (or both), and then "slide" the disk while continuing to inflate it so that it remains inside the boundary without overlapping any other disks until it is "trapped" - with at least 2 points of contact with the boundary and/or other disks. But it isn't easy to formalize this "sliding process". And even if you get the sliding process right, this strategy doesn't guarantee that you'll find the biggest "inscribable disk" - your "locally maximal" disk could be trapped in a "lobe" of the interior which is connected by a narrow "neck" of free space to a larger "lobe" where a larger disk would fit.
Thanks for the replies, my requirements were such that I was able to further simplify the problem by not having to deal with orientation and I then even further simplified by only really worrying about the bounding box of the fill element. With these two simplifications the problem became much easier and I used a stripe like filling algorithm in conjunction with a spatial hash grid (since there were existing elements I was not allowed to fill over).
With this approach I simply divided the fill area into stripes and created a spatial hash grid to register existing elements within the fill area. I created a second spatial hash grid to register the fill area (since my stripes were not guaranteed to be within the bounding area, this made checking if my fill element was in the fill area a little faster since I could just query the grid and if all grids where my fill element were to be placed, were full, I knew the fill element was inside the fill area). After that, I iterated over each stripe and placed a fill element where the hash grids would allow. This is certainly not an optimal solution, but it ended up being all that was required for my particular situation and pretty fast as well. I found the required information about creating a spatial hash grid from here. I got the idea for filling by stripes from this article.
This type of problem is very complex to solve geometrically.
If you can accept a good solution instead of the 100% optimal
solution then you can to solve it with a raster algorithm.
You draw (rasterize) the boundary polygon into one in-memory
image and the fill polygon into another in-memory image.
You can then more easily search for a place where the fill polygon will
fit in the boundary polygon by overlaying the two images with
various (X, Y) offsets for the fill polygon and checking
the pixel values.
When you find a place that the fill polygon fits,
you clear the pixels in the boundary polygon and repeat
until there are no more places where the fill polygon fits.
The keywords to google search for are: rasterization, overlay, algorithm
If your fill polygon is the shape of a jigsaw piece, many algorithms will miss the interlocking alignment. (I don't know what to suggest in that case)
One approach to the general problem that works well when the boundary is much larger than
the fill pieces is to tile an infinite plane with the pieces in the best way you can, and then look for the optimum alignment of the boundary on this plane.

What is an efficient algorithm for finding the number of shapes in a binary image?

For a binary image, I am interested in a way to efficiently count the number of individual shapes present in the image. Also as an adjacent question, how can one fit each shape that is present in the image in a square?
Pseudocode is most welcome.
I can't answer the second half, but if the first half defines a "shape" as contiguous pixels of a certain color, here's what I do. Maintain an array for the whole image, indicating which pixels have been "seen". (A bool[,] would do the trick, in C#-speak.)
Then begin iterating over each pixel. If it's been seen already, skip it.
Otherwise, if it's not yet been seen and it's the "non-shape" color, mark it seen and move on.
Otherwise, it hasn't been seen and is a shape. From here, spider out in each of the four compass directions. If you reach a seen pixel, stop and turn back (this prevents an infinite loop from occurring). If the pixel is the non-shape color, mark the pixel seen and stop immediately. Otherwise, the pixel is a shape color. Mark it seen and add it to whatever "shape definition" data you are building up.
Once this process completes, you have discovered one shape. Store it somewhere, and continue searching. All of the pixels in that shape should now be marked seen, and will no longer be considered by the algorithm.
This algorithm for shape-discovery once a shape-color pixel has been located is inherently recursive, and for large shapes may overflow the stack. It may be appropriate to use a heap-based stack implementation to perform the entire shape search.
(If you consider diagonally-adjacent pixels enough to link two shapes into one, simply search all eight adjacent pixels instead of just the four horizontally- and vertically-adjacent ones.)
One possible notion of "shape" is connected components. In that case, a union-find algorithm will give you want you want: http://en.wikipedia.org/wiki/Connected_Component_Labeling. If you also want the X and Y extents, union-find can be extended to keep track of those.
Do Blobing of the image data, you will get each shape with all pixels and extents [RECT of the shape]
If your image has a shape inside shape, then blobing will treat both as individual shapes.
If you need code send me mail, will be happy to share.

What is an efficient way to find a non-colliding rectangle nearest to a location

For a 2D game I am working on, I am using y axis sorting in a simple rectangle-based collision detection. This is working fine, and now I want to find the nearest empty rectangle at a given location with a given size, efficiently. How can I do this? Is there an algorithm?
I could think of a simple brute force grid test (with each grid the size of the empty space we're looking for) but obviously this is slow and not even a complete test.
Consider using quad-trees to store your rectangles.
See http://en.wikipedia.org/wiki/Quadtree for more information.
If you're already using axis sorting, then presumably you've computed a list of your rectangles sorted by their positions.
Perhaps I am misunderstanding, but could you not just look at the two rectangles before and after the rectangle in question, and decide which one is closer? If you're talking about finding the closest rectangle to an arbitrary point, then you could simply walk through the list until you find the first rectangle with a greater position than your arbitrary point, and use that rectangle and the one before it as the two to compare.

Resources