Метод сравнения растровых изображений на iPhone (unity3d)

Каким будет лучший способ сравнить 2 растровых изображения и получить корреляцию между 2 (0 полностью отличается, а 1 точно такое же) в Unity3d на iPhone? Я использую C#, так как в документации сказано, что использование Boo или UnityScript увеличит размер приложения.

Мне нужно что-то похожее на методы идентификации по отпечатку пальца, но не такое точное. Поскольку это предназначено для работы на iPhone, производительность здесь является большой проблемой.

Примеры изображений:

http://img25.imageshack.us/img25/303/294906.jpg http://img138.imageshack.us/img138/842/40248741fireworkexplosi.jpg

Для них я ожидаю иметь коэффициент корреляции около 0,5, поскольку они похожи, но различаются по цвету. Существует ряд различных параметров сравнения, но основными из них являются цвет и форма.

Любая помощь будет оценена.


person Daniel Rodriguez    schedule 07.12.2009    source источник
comment
вы ищете, какая доля пикселей одинакова на обоих изображениях? или вы хотите что-то более сложное, что будет распознавать сходство, даже если одно изображение было перемещено относительно другого? что это за образы?   -  person David Maymudes    schedule 07.12.2009
comment
Мне нужно что-то более сложное, что будет распознавать сходство. Изображения представляют собой абстрактные узоры цветов. Спасибо.   -  person Daniel Rodriguez    schedule 07.12.2009
comment
любое решение, вероятно, будет специфичным для деталей того, на что похожи ваши изображения и что считается похожим ... возможно, вы можете опубликовать несколько примеров изображений?   -  person David Maymudes    schedule 07.12.2009
comment
Добавил примеры изображений, спасибо.   -  person Daniel Rodriguez    schedule 08.12.2009


Ответы (1)


Чтобы ответить (вроде как) на мой собственный вопрос, после нескольких дней гугления я нашел это. Основная идея заключается в тестировании изображений со смещением/поворотом, поиском доминирующего цвета и так далее. Пока это лучшая информация, которую я смог найти, так что я попробую.

Предложенный там код выглядит так:

using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;

namespace BitmapSimilarity
{
    public interface IBitmapCompare
    {
        double GetSimilarity(Bitmap a, Bitmap b);
    }

    class BitmapCompare: IBitmapCompare
    {
        public struct RGBdata
        {
            public int r;
            public int g;
            public int b;

            public int GetLargest()
            {
                if(r>b)
                {
                    if(r>g)
                    {
                        return 1;
                    }
                    else
                    {
                        return 2;
                    }
                }
                else
                {
                    return 3;
                }
            }
        }

        private RGBdata ProcessBitmap(Bitmap a)
        {
            BitmapData bmpData = a.LockBits(new Rectangle(0,0,a.Width,a.Height),ImageLockMode.ReadOnly,PixelFormat.Format24bppRgb);
            IntPtr ptr = bmpData.Scan0;
            RGBdata data = new RGBdata();

            unsafe
            {
                byte* p = (byte*)(void*)ptr;
                int offset = bmpData.Stride - a.Width * 3;
                int width = a.Width * 3;

                for (int y = 0; y < a.Height; ++y)
                {
                    for (int x = 0; x < width; ++x)
                    {
                        data.r += p[0];             //gets red values
                        data.g += p[1];             //gets green values
                        data.b += p[2];             //gets blue values
                        ++p;
                    }
                    p += offset;
                }
            }
            a.UnlockBits(bmpData);
            return data;
        }

        public double GetSimilarity(Bitmap a, Bitmap b)
        {
            RGBdata dataA = ProcessBitmap(a);
            RGBdata dataB = ProcessBitmap(b);
            double result = 0;
            int averageA = 0;
            int averageB = 0;
            int maxA = 0;
            int maxB = 0;

            maxA = ((a.Width * 3) * a.Height);
            maxB = ((b.Width * 3) * b.Height);

            switch (dataA.GetLargest())            //Find dominant color to compare
            {
                case 1:
                    {
                        averageA = Math.Abs(dataA.r / maxA);
                        averageB = Math.Abs(dataB.r / maxB);
                        result = (averageA - averageB) / 2;
                        break;
                    }
                case 2:
                    {
                        averageA = Math.Abs(dataA.g / maxA);
                        averageB = Math.Abs(dataB.g / maxB);
                        result = (averageA - averageB) / 2;
                        break;
                    }
                case 3:
                    {
                        averageA = Math.Abs(dataA.b / maxA);
                        averageB = Math.Abs(dataB.b / maxB);
                        result = (averageA - averageB) / 2;
                        break;
                    }
            }

            result = Math.Abs((result + 100) / 100);

            if (result > 1.0)
            {
                result -= 1.0;
            }

            return result;
        }
    }

    class Program
    {
        static BitmapCompare SimpleCompare;
        static Bitmap searchImage;

        static private void Line()
        {
            for (int x = 0; x < Console.BufferWidth; x++)
            {
                Console.Write("*");
            }
        }

        static void CheckDirectory(string directory,double percentage,Bitmap sImage)
        {
            DirectoryInfo dir = new DirectoryInfo(directory);
            FileInfo[] files = null;
            try
            {
                files = dir.GetFiles("*.jpg");
            }
            catch (DirectoryNotFoundException)
            {
                Console.WriteLine("Bad directory specified");
                return;
            }

            double sim = 0;

            foreach (FileInfo f in files)
            {
                sim = Math.Round(SimpleCompare.GetSimilarity(sImage, new Bitmap(f.FullName)),3);
                if (sim >= percentage)
                {
                    Console.WriteLine(f.Name);
                    Console.WriteLine("Match of: {0}", sim);
                    Line(); 
                }
            }
        }

        static void Main(string[] args)
        {
            SimpleCompare = new BitmapCompare();
            Console.Write("Enter path to search image: ");
            try
            {
                searchImage = new Bitmap(Console.ReadLine());
            }
            catch (ArgumentException)
            {
                Console.WriteLine("Bad file");
                return;
            }

            Console.Write("Enter directory to scan: ");
            string dir = Console.ReadLine();
            Line();
            CheckDirectory(dir, 0.95 , searchImage);        //Display only images that match by 95%
        }
    }
}
person Daniel Rodriguez    schedule 09.12.2009