c# - 如何检测图像中的黑色子弹?

标签 c# c#-4.0 image-processing emgucv aforge

给定下图,如何使用 C#、EmguCV 或 AForge 检测此图像中的黑色子弹(90 颗子弹)?

enter image description here

我尝试使用 GetPixel(x,y) 方法,但它只逐个像素地检查,速度非常慢,我需要检测的是子弹而不是像素。

最佳答案

算法/想法 1 您可以将图像分成正方形,如本示例所示: enter image description here

使用此逻辑,您只需检查每 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 第二种算法分析每个像素并且更容易实现。一旦有黑色像素,它就会检查之前在同一垂直或水平线上是否有黑色像素,并在这种情况下跳过,直到没有黑色像素在线。

进一步的改进是存储第一个点的高度并使代码段中间的条件更加美观。

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");

Performance

关于c# - 如何检测图像中的黑色子弹?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30944998/

相关文章:

c#-4.0 - 如何使用 Office.Interop.Excel 进行交替行着色?

image-processing - 如何将两个不同尺寸的图像的光谱相乘?

javascript - 如何使用 JavaScript 修复图像透视变形和旋转?

c# - 在C#中实现单例可继承类

c# - 拦截按钮点击页面加载

c# - 使用 Jet 读取 CSV 文件 - 制表符分隔不起作用!

c#-4.0 - YouTube数据API LiveChatId帮助

image-processing - KITTI Stereo 2015 数据集使用的两个彩色相机的外部参数和内部参数是多少

c# - 使用 LINQ 将元素附加到集合

c# - 如何检查数字字符串是否在运行序列中