2 vùng có đường viền có nghĩa là trong một khu vực nhỏ nhất định phải có 3 màu hiện diện: đỏ, đen và xanh lục.
Vì vậy, một giải pháp rất không hiệu quả thể hiện chính nó: sử dụng Color pixelColor = myBitmap.GetPixel(x, y);
bạn có thể quét một khu vực cho 3 màu đó. Khu vực này phải lớn hơn chiều rộng của đường viền của khóa học.
Có rất nhiều phòng để tối ưu hóa (như đi các bước 50 pixel và giảm độ chính xác liên tục). Vì màu đen là màu ít được sử dụng nhất, trước tiên bạn sẽ tìm kiếm xung quanh các vùng màu đen.
này nên giải thích những gì tôi đã viết trong ý kiến khác nhau trong chủ đề này:
namespace Phobos.Graphics
{
public class BorderDetector
{
private Color region1Color = Color.FromArgb(222, 22, 46);
private Color region2Color = Color.FromArgb(11, 189, 63);
private Color borderColor = Color.FromArgb(11, 189, 63);
private List<Point> region1Points = new List<Point>();
private List<Point> region2Points = new List<Point>();
private List<Point> borderPoints = new List<Point>();
private Bitmap b;
private const int precision = 10;
private const int distanceTreshold = 25;
public long Miliseconds1 { get; set; }
public long Miliseconds2 { get; set; }
public BorderDetector(Bitmap b)
{
if (b == null) throw new ArgumentNullException("b");
this.b = b;
}
private void ScanBitmap()
{
Color c;
for (int x = precision; x < this.b.Width; x += BorderDetector.precision)
{
for (int y = precision; y < this.b.Height; y += BorderDetector.precision)
{
c = this.b.GetPixel(x, y);
if (c == region1Color) region1Points.Add(new Point(x, y));
else if (c == region2Color) region2Points.Add(new Point(x, y));
else if (c == borderColor) borderPoints.Add(new Point(x, y));
}
}
}
/// <summary>Returns a distance of two points (inaccurate but very fast).</summary>
private int GetDistance(Point p1, Point p2)
{
return Math.Abs(p1.X - p2.X) + Math.Abs(p1.Y - p2.Y);
}
/// <summary>Finds the closests 2 points among the points in the 2 sets.</summary>
private int FindClosestPoints(List<Point> r1Points, List<Point> r2Points, out Point foundR1, out Point foundR2)
{
int minDistance = Int32.MaxValue;
int distance = 0;
foundR1 = Point.Empty;
foundR2 = Point.Empty;
foreach (Point r1 in r1Points)
foreach (Point r2 in r2Points)
{
distance = this.GetDistance(r1, r2);
if (distance < minDistance)
{
foundR1 = r1;
foundR2 = r2;
minDistance = distance;
}
}
return minDistance;
}
public bool FindBorder()
{
Point r1;
Point r2;
Stopwatch watch = new Stopwatch();
watch.Start();
this.ScanBitmap();
watch.Stop();
this.Miliseconds1 = watch.ElapsedMilliseconds;
watch.Start();
int distance = this.FindClosestPoints(this.region1Points, this.region2Points, out r1, out r2);
watch.Stop();
this.Miliseconds2 = watch.ElapsedMilliseconds;
this.b.SetPixel(r1.X, r1.Y, Color.Green);
this.b.SetPixel(r2.X, r2.Y, Color.Red);
return (distance <= BorderDetector.distanceTreshold);
}
}
}
Nó rất đơn giản. Tìm kiếm theo cách này chỉ mất khoảng 2 + 4 ms (quét và tìm các điểm gần nhất).
Bạn cũng có thể thực hiện tìm kiếm đệ quy: đầu tiên với độ chính xác = 1000, sau đó độ chính xác = 100 và cuối cùng là độ chính xác = 10 cho hình ảnh lớn. FindClosestPoints thực tế sẽ cung cấp cho bạn một khu vực hình chữ nhật ước tính, nơi biên giới nên được đặt (thường là biên giới là như thế).
Sau đó, bạn có thể sử dụng phương pháp tiếp cận véc tơ mà tôi đã mô tả trong các nhận xét khác.
Tôi đang bối rối về những hạn chế trong giải pháp. Trong mã đã chỉnh sửa của bạn, bạn đang lưu trữ các hình dạng dưới dạng danh sách các pixel. Những thứ này có thể được đặt theo bất kỳ cách nào không? Chúng ta có thể biểu diễn các hình dạng trong một mảng 2 chiều với một offset không? Nếu chúng ta có thể làm những việc như thế thì giải pháp cho vấn đề trở nên nhanh hơn. – Yellowfog
Khoảng cách giữa 2 điểm là 'distance = Math.Sqrt (Math.Pow (Math.Abs (x1-x2), 2) + Math.Pow (Math.Abs (y1-y2), 2))'. Ngoài ra khi bạn tìm thấy 2 điểm khu vực có thể xảy ra là đường viền nằm ở đâu đó giữa chúng (không nhất định). Vì vậy, bạn có thể kiểm tra pixel bằng cách sử dụng véc tơ cho đến khi bạn đạt đến một đường viền (hoặc không thành công). –
Đó là thuật toán O (n^2), sẽ rất chậm khi hình dạng của bạn có kích thước đáng kể. Ngoài ra, sqrt là một hoạt động chậm. Nói chung nó cũng nhanh hơn để tạo khoảng cách cho khoảng cách của bạn và so sánh các giá trị bình phương. –