算法/想法 1
您可以将图像划分为正方形,如本示例所示:
使用此逻辑,您只需每 20 个像素检查一次。一旦您知道第一个点在哪里,您就会知道每个其他点都必须位于同一水平线上(在您提供的示例中)。
一个示例算法看起来与此类似(请注意,它需要进一步改进):
Bitmap myBitmap = new Bitmap ("input.png");
int skipX = 12;
int skipY = 12;
int detectedDots = 0;
for (int x = 0; x < myBitmap.Width; x += skipX) {
for (int y = 0; y < myBitmap.Height; y += skipY) {
Color pixelColor = myBitmap.GetPixel (x, y);
if (pixelColor.R + pixelColor.G + pixelColor.B == 0) {
myBitmap.SetPixel (x, y, Color.Red);
detectedDots++;
}
}
}
myBitmap.Save ("output.png");
Console.WriteLine (detectedDots + " dots detected");
我添加了一个输出,以便您检查检测到哪些点(所有点都包含红色像素)。
进一步的改进是找到一个点的中心。之后,您应该知道宽度(和高度),并且可以从左上角的第一个点开始,偏移点宽度。
算法 2
第二种算法分析每个像素,并且更容易实现。一旦有黑色像素,它就会检查之前在同一垂直或水平线上是否有黑色像素,并在这种情况下跳过,直到没有黑色像素在线。
进一步的改进是存储第一个点的高度并使sn-p中间的条件更漂亮。
Stopwatch watch = new Stopwatch(); watch.Start();
Bitmap myBitmap = new Bitmap ("input.png");
int dotsDetected = 0;
List<int> xFound = new List<int>();
for (int x = 0; x < myBitmap.Width; x++) {
bool yFound = false;
bool dotFound = false;
for (int y = 0; y < myBitmap.Height; y++) {
Color pixelColor = myBitmap.GetPixel (x, y);
if (pixelColor.R + pixelColor.G + pixelColor.B == 0) {
dotFound = true;
if (yFound)
continue;
if (xFound.Contains (y)
|| xFound.Contains (y + 1)
|| xFound.Contains (y + 2)
|| xFound.Contains (y + 3)
|| xFound.Contains (y + 4)
|| xFound.Contains (y - 1)
|| xFound.Contains (y - 2)
|| xFound.Contains (y - 3)
|| xFound.Contains (y - 4)) {
yFound = true;
continue;
}
xFound.Add (y);
//myBitmap.SetPixel (x, y, Color.Red);
dotsDetected++;
yFound = true;
} else
yFound = false;
}
if(!dotFound) //no dot found in this line
xFound.Clear();
}
//myBitmap.Save ("output.png");
watch.Stop();
Console.WriteLine("Picture analyzed in " + watch.Elapsed.TotalSeconds.ToString("#,##0.0000"));
Console.WriteLine (dotsDetected + " dots detected");