【问题标题】:How can I find a template image in another image? Kinect and AForge preferred如何在另一个图像中找到模板图像?首选 Kinect 和 AForge
【发布时间】:2022-02-25 03:02:40
【问题描述】:

我从这里复制了 AForge-Sample: http://www.aforgenet.com/framework/features/template_matching.html 并希望它可以使用 2 个位图作为源,如下代码所示:

    Bitmap findTemplate (Bitmap sourceImage, Bitmap template)
    {

    // create template matching algorithm's instance
    // (set similarity threshold to x.y%, 1.0f = 100%)
    ExhaustiveTemplateMatching tm = new ExhaustiveTemplateMatching( 0.4f );
    // find all matchings with specified above similarity
    TemplateMatch[] matchings = tm.ProcessImage( sourceImage, template ); **// "Unsupported pixel format of the source or template image." as error message**
    // highlight found matchings
    BitmapData data = sourceImage.LockBits(
        new Rectangle( 0, 0, sourceImage.Width, sourceImage.Height ),
        ImageLockMode.ReadWrite, sourceImage.PixelFormat );
    foreach ( TemplateMatch m in matchings )
    {
        AForge.Imaging.Drawing.Rectangle( data, m.Rectangle, System.Drawing.Color.White );
        // do something else with matching
    }
    sourceImage.UnlockBits( data );
    return sourceImage;
    }

但是当调用 TemplateMatch[] matchings = tm.P.... 时,它给出了上面提到的错误。 模板是这样生成的:

Bitmap templatebitmap=(Bitmap)AForge.Imaging.Image.FromFile("template.jpg");

源是使用 kinect-webcam 生成的,其中 PlanarImage 被格式化为位图(从某处复制的方法,但它一直在工作)

 Bitmap PImageToBitmap(PlanarImage PImage)
        {
            Bitmap bmap = new Bitmap(
              PImage.Width,
              PImage.Height,
              System.Drawing.Imaging.PixelFormat.Format32bppRgb);
            BitmapData bmapdata = bmap.LockBits(
              new Rectangle(0, 0, PImage.Width,
                                   PImage.Height),
              ImageLockMode.WriteOnly,
              bmap.PixelFormat);
            IntPtr ptr = bmapdata.Scan0;
            Marshal.Copy(PImage.Bits,
                         0,
                         ptr,
                         PImage.Width *
                            PImage.BytesPerPixel *
                                 PImage.Height);
            bmap.UnlockBits(bmapdata);
            return bmap;
        }

那么,有人可以帮助我吗,我的错误可能在哪里? 或者也许有人知道将模板与 Kinect 匹配的更好方法? 总体工作是用 kinect 检测已知物体,在我的例子中是一只橡皮鸭。

谢谢你。

【问题讨论】:

  • 好的,这里的答案是,它需要 Format24bppRgb-Bitmaps。尽管如此,结果还是很糟糕。数百个具有相同位置和大小的匹配项。
  • 在切换到 openCV 和 Emgu Wrapper 之前,我遇到了同样的性能缓慢问题。由于原始发帖人要求更快的解决方案并且没有收到回复,因此我提供了一个链接,与 AForge 相比,该链接将在更短的时间内完成所需的任务。 Aforge 很慢,因为它是一种迭代(蛮力)方法。海报代码甚至比 AForge 还要慢。 openCV 库将非常快速地完成所需的任务,[使用基于数学函数的比较](docs.opencv.org/2.4/doc/tutorials/img

标签: c# bitmap pattern-matching kinect aforge


【解决方案1】:

这是使用 AForge 的解决方案 但它很慢,大约需要 5 秒,但它有效 像往常一样,你需要引入 AForge 框架下载并安装它。 指定使用 AForge 命名空间

并复制粘贴以使其工作

System.Drawing.Bitmap sourceImage = (Bitmap)Bitmap.FromFile(@"C:\SavedBMPs\1.jpg");
System.Drawing.Bitmap template = (Bitmap)Bitmap.FromFile(@"C:\SavedBMPs\2.jpg");
// create template matching algorithm's instance
// (set similarity threshold to 92.5%)

ExhaustiveTemplateMatching tm = new ExhaustiveTemplateMatching(0.921f);
// find all matchings with specified above similarity

TemplateMatch[] matchings = tm.ProcessImage(sourceImage, template);
// highlight found matchings

BitmapData data = sourceImage.LockBits(
    new Rectangle(0, 0, sourceImage.Width, sourceImage.Height),
    ImageLockMode.ReadWrite, sourceImage.PixelFormat);
foreach (TemplateMatch m in matchings)
{

        Drawing.Rectangle(data, m.Rectangle, Color.White);

    MessageBox.Show(m.Rectangle.Location.ToString());
    // do something else with matching
}
sourceImage.UnlockBits(data);

【讨论】:

  • 我也找到了这个例子,因为这只是在 aforge 网站上解释的。它根本没有做好。几乎每个结果都是错误的。和 5 秒?每一帧都需要几分钟。所以..不,对我没有帮助。我自己阅读了文档。但是现在,我只是在其他信息上引入了一些其他算法,我有 10fps。
  • @nico,是的,它来自该站点,我认为这是对上面的 4 个循环 FOR 语句更简单的方法。那么你是如何解决并获得 10fps 的呢?很抱歉,如果它对您没有帮助,它不必对每个人都有帮助,只是像我这样的新手可能会觉得它有用。
  • 我只是使用了该对象的 2 个其他功能。关于您的问题:只需做一个颜色过滤器,在匹配之前验证,如果在匹配区域中颜色符合要求(如果您的对象被填充为红色,只需尝试,如果中间点符合“红色”)。我的第二个功能是通过 kinect 的深度。仅当两个功能都满足要求时,才让我的慢速算法在这些位置上运行(而不是在我发布的任何位置上运行)。有趣的链接:codeproject.com/Articles/9727/Image-Processing-Lab-in-C 和 aforgenet.com/articles/shape_checker
【解决方案2】:

所以,我只是自己实现了它。但它太慢了——所以如果有人有改进的想法,请随时批评我的代码:

    public class Position
    {
        public int bestRow { get; set; }
        public int bestCol { get; set; }
        public double bestSAD { get; set; }
        public Position(int row, int col, double sad)
        {
            bestRow = row;
            bestCol = col;
            bestSAD = sad;
        }
    }

    Position element_position = new Position(0, 0, double.PositiveInfinity);
    Position ownSearch(Bitmap search, Bitmap template) {
        Position position = new Position(0,0,double.PositiveInfinity);
        double minSAD = double.PositiveInfinity;


        // loop through the search image
        for (int x = 0; x <= search.PhysicalDimension.Width - template.PhysicalDimension.Width; x++)
        {
            for (int y = 0; y <= search.PhysicalDimension.Height - template.PhysicalDimension.Height; y++)
            {
                position_label2.Content = "Running: X=" + x + "  Y=" + y;
                double SAD = 0.0;

                // loop through the template image
                for (int i = 0; i < template.PhysicalDimension.Width; i++)
                {
                    for (int j = 0; j < template.PhysicalDimension.Height; j++)
                    {
                        int r = Math.Abs(search.GetPixel(x + i, y + j).R - template.GetPixel(i, j).R);

                        int g = Math.Abs(search.GetPixel(x + i, y + j).G - template.GetPixel(i, j).G);

                        int b = Math.Abs(search.GetPixel(x + i, y + j).B - template.GetPixel(i, j).B);

                        int a = template.GetPixel(i, j).A;

                        SAD = SAD + ((r + g + b)*a/255 );

                    }
                }
                // save the best found position 
                if (minSAD > SAD)
                {
                    minSAD = SAD;
                    // give me VALUE_MAX
                    position.bestRow = x;
                    position.bestCol = y;
                    position.bestSAD = SAD;
                }
            }
        }
        return position;
    }

【讨论】:

  • 为了将来参考,请不要在您发布在 StackOverlfow 上的任何内容中使用脏话。您的答案将被编辑以删除脏话。
猜你喜欢
  • 2011-01-29
  • 2013-04-06
  • 1970-01-01
  • 2012-11-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-08-31
  • 2022-08-13
相关资源
最近更新 更多