Как я могу найти изображение шаблона в другом изображении? Kinect и AForge предпочтительнее

Я скопировал образец AForge отсюда: http://www.aforgenet.com/framework/features/template_matching.html И надеялся, что он будет работать с двумя растровыми изображениями в качестве источников, как в следующем коде:

    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-веб-камеры, где PlanarImage отформатирован как Bitmap (метод откуда-то скопирован, но до сих пор работал)

 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 известный объект, в моем случае — резиновую утку.

Заранее спасибо.


person nico    schedule 23.01.2012    source источник
comment
Хорошо, ответ здесь таков, что он хочет Format24bppRgb-Bitmaps. Тем не менее, результат все равно дерьмовый. Сотни совпадений с одинаковым положением и размером.   -  person nico    schedule 06.02.2012
comment
У меня была такая же проблема с низкой производительностью, пока я не переключился на openCV и Emgu Wrapper. . Поскольку исходный плакат запрашивает более быстрое решение и не получил ответа, я предоставляю ссылку, которая позволит выполнить требуемую задачу за долю времени по сравнению с AForge. Aforge медленный, потому что это итеративный метод (грубая сила). Код плакатов даже медленнее, чем AForge. библиотека openCV выполнит требуемую задачу очень быстро, [используя сравнение на основе математических функций](docs.opencv.org/2.4/doc/tutorials/img   -  person Hakan Usakli    schedule 05.06.2019


Ответы (2)


вот решение, использующее 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);
person Mandah Mr.    schedule 25.02.2012
comment
Я тоже нашел этот пример, так как это только что объяснено на сайте aforge. он просто не сделал хорошую работу. почти каждый результат был неправильным. и 5 сек? на каждый кадр уходило несколько минут. так.. нет, мне не помогает. Я сам читал документацию. Но теперь я просто ввел какой-то другой алгоритм для другой информации, и у меня 10 кадров в секунду. - person nico; 26.02.2012
comment
@nico, да, это с сайта, я думал, что это более простой подход к вашим 4 циклическим операторам FOR выше. Итак, как вы решили и получили 10 кадров в секунду? И извините, если это не поможет вам, это не должно помогать всем, просто новичкам, таким как я, может быть полезно. - person Mandah Mr.; 27.02.2012
comment
Я просто использовал 2 другие функции объекта. Что касается вашей проблемы: просто сделайте цветовой фильтр и перед сопоставлением убедитесь, что в области сопоставления цвет соответствует требованиям (если ваш объект заполнен красным, просто попробуйте, если средняя точка соответствует красному). моей второй особенностью была глубина через kinect. только если обе функции соответствуют требованиям, пусть мой медленный алгоритм работает с этими позициями (а не с любой позицией, как я ее опубликовал). Интересные ссылки для вас: codeproject.com/Articles/9727/Image -Processing-Lab-in-C и aforgenet.com/articles/shape_checker - person nico; 28.02.2012

Итак, я только что реализовал это сам. Но это так медленно, поэтому, если у кого-то есть идеи по улучшению, не стесняйтесь критиковать мой код:

    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;
    }
person nico    schedule 04.02.2012
comment
для дальнейшего использования, пожалуйста, не используйте нецензурные слова в любом контенте, который вы публикуете на StackOverlfow. Ваш ответ будет отредактирован, чтобы удалить нецензурную брань. - person Jason Evans; 01.02.2013