Given the image below, what algorithm might I use to detect whether regions one and two (identified by color) have a border?
http://img823.imageshack.us/img823/4477/borders.png
If there’s a C# example out there, that would be awesome, but I’m really just looking for any example code.
Edit: Using Jaro’s advice, I came up with the following…
public class Shape
{
private const int MAX_BORDER_DISTANCE = 15;
public List<Point> Pixels { get; set; }
public Shape()
{
Pixels = new List<Point>();
}
public bool SharesBorder(Shape other)
{
var shape1 = this;
var shape2 = other;
foreach (var pixel1 in shape1.Pixels)
{
foreach (var pixel2 in shape2.Pixels)
{
var xDistance = Math.Abs(pixel1.X - pixel2.X);
var yDistance = Math.Abs(pixel1.Y - pixel2.Y);
if (xDistance > 1 && yDistance > 1)
{
if (xDistance * yDistance < MAX_BORDER_DISTANCE)
return true;
}
else
{
if (xDistance < Math.Sqrt(MAX_BORDER_DISTANCE) &&
yDistance < Math.Sqrt(MAX_BORDER_DISTANCE))
return true;
}
}
}
return false;
}
// ...
}
Clicking on two shapes that do share a border returns fairly quickly, but very distance shapes or shapes with a large number of pixels take 3+ seconds at times. What options do I have for optimizing this?
2 regions having border means that within a certain small area there should be 3 colors present: red, black and green.
So a very ineffective solution presents itself:
using
Color pixelColor = myBitmap.GetPixel(x, y);you could scan an area for those 3 colors. The area must be larger than the width of the border of course.There is of course plenty room for optimizations (like going in 50 pixels steps and decreasing the precision continually).
Since black is the least used color, you would search around black areas first.
This should explain what I have written in various comments in this topic:
It is very simple. Searching this way only takes about 2 + 4 ms (scanning and finding the closest points).
You could also do the search recursively: first with precision = 1000, then precision = 100 and finally precision = 10 for large images.
FindClosestPoints will practically give you an estimated rectangual area where the border should be situated (usually borders are like that).
Then you could use the vector approach I have described in other comments.