【问题标题】:C# native Image template matchC#原生图像模板匹配
【发布时间】:2015-06-04 23:21:15
【问题描述】:

我在这里遇到了一点性能问题。 我的图像处理教授让我在没有任何库的情况下进行模板匹配,所以我在 c# 中完成了......它完美地完成了这项工作,但是非常非常非常慢 要在 500x500 的图像中找到 80x80 的模板,这需要几分钟,并且使用的 CPU 不超过 20%

我做错了吗?

这是我的代码,所有图像都是灰色的。

    public Task<Point[]> MatchImage(Bitmap orig, Bitmap template, int limit = 30)
    {
        Task<Point[]> tsk = 
        new Task<Point[]>(() =>
        {
            Point p;
            List<Point> l = new List<Point>();
            int oh = orig.Height, ow = orig.Width;
            int th = template.Height, tw = template.Width;

            for (int x = 0; x < oh - th; x++)
                for (int y = 0; y < ow - tw; y++)
                {
                    p = new Point(x, y);
                    if (sumBitArea(orig, template, p) <= limit)
                        l.Add(p);
                }
                return l.ToArray();
        });

        tsk.Start();
        return tsk;
    }


    /// <summary>
    /// Soma os pixels de uma determinada imagem
    /// PS PARA USAR MANDE A IMAGEM RECORTADA !
    /// SE MANDAR INTEIRA VAI RETORNAR O VALOR TOTAL.
    /// USEM A GRAPHCS E UM RECTANGLE !
    /// </summary>
    /// <param name="image">treixo da imagem original</param>
    /// <param name="template">imagem template</param>
    /// <param name="p">ponto inicial de referencia</param>
    /// <returns>o valor da soma</returns>
    private int sumBitArea(Bitmap image, Bitmap template, Point p)
    {
        int value = 0;

        int height = p.X + template.Height;
        int width = p.Y + template.Width;

        for (int x = p.X, xt = 0; x < height; x++, xt++)
            for (int y = p.Y, yt = 0; y < width; y++,yt++)
            {
                int tmp = Math.Abs(image.GetPixel(y, x).R - template.GetPixel(yt, xt).R);
                value += tmp;
            }

        return value;
    }

解决方案 - 解决锁定位

这里是解决方案代码

    public Task<Point[]> MatchImage(Bitmap orig, Bitmap template, int limit = 30)
    {
        Task<Point[]> tsk =
        new Task<Point[]>(() =>
        {
            BitmapData lockedOrig = orig.LockBits(
               new Rectangle(0, 0, orig.Width, orig.Height),
               ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb);

            //bloqueando a leitura da memoria em que a imagem nova sera colocada
            BitmapData lockedTemplate = template.LockBits(
               new Rectangle(0, 0, template.Width, template.Height),
               ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb);

            Point p;
            List<Point> l = new List<Point>();
            int oh = orig.Height, ow = orig.Width;
            int th = template.Height, tw = template.Width;

            for (int y = 0; y < oh - th; y++)
            {
                for (int x = 0; x < ow - tw; x++)
                {
                    p = new Point(x, y);
                    if (sumBitArea(lockedOrig, lockedTemplate, p) <= limit)
                        l.Add(p);
                }
            }

            orig.UnlockBits(lockedOrig);
            template.UnlockBits(lockedTemplate);
            return l.ToArray();
        });

        tsk.Start();
        return tsk;
    }

    unsafe private int sumBitArea(BitmapData image, BitmapData template, Point p)
    {
        int value = 0;
        int pixelSize = 3;

        int height = p.Y + template.Height;
        int width = p.X + template.Width;
        int x = p.X, xt = 0;
        int y = p.Y, yt = 0;
        byte* tRow;
        byte* oRow;

        for (yt = 0 ; y < height; y++, yt++)
        {
            //criando um ponteiro para a imagem original
            oRow = (byte*)image.Scan0 + (y * image.Stride);

            //criando um ponteiro para a nova imagem
            tRow = (byte*)template.Scan0 + (yt * template.Stride);

            for (xt = 0; x < width; x++, xt++)
            {
                int tmp = Math.Abs((byte)oRow[x * pixelSize + 2] - (byte)tRow[xt * pixelSize + 2]);
                value += tmp;
            }
        }
        return value;
    }

【问题讨论】:

  • 您是否尝试过锁定位或使用FastBitmap 实现?您应该能够找到大量像这样的实现。它应该加速多次获取像素。您只需要妥善处理它。
  • 哇,它立即做到了! TX @NikolaDavidovic 我会更新回答

标签: c# performance image-processing native template-matching


【解决方案1】:

您是否尝试过锁定位或使用 FastBitmap 实现?您应该能够找到大量像这样的实现。它应该加速多次获取像素。您只需要妥善处理它。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-04-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-03
    • 1970-01-01
    • 2013-04-08
    相关资源
    最近更新 更多