Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Алгоритмы > Сравнить два лица.


Автор: galileopro 6.7.2009, 00:50
Нужно сравнить 2 фотографии людей, и сделать вывод: одинаковые люди изображены или нет.
Вот ради примера 2 фотографии: 
http://ipicture.ru/
http://ipicture.ru/
Это одна и та же актриса. Нужно установить сходство программно.
Пока у меня получилось лишь выделить лицо по цвету (OpenGL под C#  и  Tao):
Код
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Tao.OpenGl;

namespace OpenGLDemo
{
    public partial class MainForm : Form
    {
        public const int size = 200;
        public byte[, ,] Bits = new byte[size, size, 3];
        public byte[, ,] Bits2 = new byte[size, size, 3];
        public MainForm()
        {
            InitializeComponent();
            openGlControl.InitializeContexts();
            Init();
            Resize(openGlControl.Width, openGlControl.Height);
        }

        private void MainForm_Paint(object sender, PaintEventArgs e)
        {
            Draw();
        }

        private static bool Init()
        {
            Gl.glShadeModel(Gl.GL_SMOOTH);
            Gl.glClearDepth(1.0f);
            Gl.glEnable(Gl.GL_DEPTH_TEST);
            Gl.glDepthFunc(Gl.GL_LEQUAL);
            Gl.glEnable(Gl.GL_COLOR_MATERIAL);
            Gl.glEnable(Gl.GL_LIGHTING);
            Gl.glEnable(Gl.GL_LIGHT0);
            Gl.glHint(Gl.GL_PERSPECTIVE_CORRECTION_HINT, Gl.GL_NICEST);
            return true;
        }
        private static void Resize(int width, int height)
        {
            if (height == 0) height = 1;
            Gl.glViewport(0, 0, width, height);
            Gl.glMatrixMode(Gl.GL_MODELVIEW);
            Gl.glLoadIdentity();

        }
        private byte abs(int r)
        {
            if (r < 0) r = -r;
 return Convert.ToByte(r);
        }
        private byte max(int r, int g, int b)
        {
            int m = r;
            if (g > m) m =g;
            if (b > m) m = b;
            return Convert.ToByte(m);
        }
        private byte min(int r, int g, int b)
        {
            int m = r;
            if (g < m) m = g;
            if (b < m) m = b;
            return Convert.ToByte(m);
        }
        private void Draw()
        {           
            Gl.glClear(Gl.GL_COLOR_BUFFER_BIT | Gl.GL_DEPTH_BUFFER_BIT);           
            Gl.glEnable(Gl.GL_TEXTURE_2D);
            Bitmap bitmap = new Bitmap("photo1.bmp");
            for (int i = 0; i <= size-1; i++)
                for (int j = 0; j <= size-1; j++)
                    {
                        Bits[i, j, 0] = bitmap.GetPixel(i, j).R;
                        Bits[i, j, 1] = bitmap.GetPixel(i, j).G;
                        Bits[i, j, 2] = bitmap.GetPixel(i, j).B;
                        Bits2[i, j, 0] = bitmap.GetPixel(i, j).R;
                        Bits2[i, j, 1] = bitmap.GetPixel(i, j).G;
                        Bits2[i, j, 2] = bitmap.GetPixel(i, j).B;
                    }

            Gl.glTexImage2D(Gl.GL_TEXTURE_2D, 0,
                            Gl.GL_RGB, size, size, 0,
                            Gl.GL_RGB, Gl.GL_UNSIGNED_BYTE, @Bits);
            Gl.glTexParameteri(Gl.GL_TEXTURE_2D, Gl.GL_TEXTURE_MIN_FILTER, Gl.GL_LINEAR);
            Gl.glTexParameteri(Gl.GL_TEXTURE_2D, Gl.GL_TEXTURE_MAG_FILTER, Gl.GL_LINEAR);

            Gl.glPushMatrix();
            Gl.glRotated(-90, 0, 0, 1);
            Gl.glBegin(Gl.GL_QUADS);

            Gl.glTexCoord2d(0.0, 1.0);
            Gl.glVertex2f(0.0f, 1.0f);

            Gl.glTexCoord2d(0.0f, 0.0f);
            Gl.glVertex2f(0.0f, 0.0f);

            Gl.glTexCoord2d(1.0, 0.0f);
            Gl.glVertex2f(1.0f, 0.0f);

            Gl.glTexCoord2d(1.0f, 1.0f);
            Gl.glVertex2f(1.0f, 1.0f);
            Gl.glEnd();
            Gl.glPopMatrix();

            for (int i = 0; i <= size - 1; i++)
                for (int j = 0; j <= size - 1; j++)
                {
byte r=bitmap.GetPixel(i, j).R;
byte g=bitmap.GetPixel(i, j).G;
byte b=bitmap.GetPixel(i, j).B;
if (!((r > g) && (r > b) && (b > 20) && (r > 95) && (b > 20) && (abs(r - g) > 15) && (max(r,g,b)-min(r,g,b) > 15))) 
{
    Bits2[i, j, 0] = 0;
    Bits2[i, j, 1] = 0;
    Bits2[i, j, 2] = 0;
}
                }

            Gl.glTexImage2D(Gl.GL_TEXTURE_2D, 0,
                                        Gl.GL_RGB, size, size, 0,
                                        Gl.GL_RGB, Gl.GL_UNSIGNED_BYTE, @Bits2);
            Gl.glTexParameteri(Gl.GL_TEXTURE_2D, Gl.GL_TEXTURE_MIN_FILTER, Gl.GL_LINEAR);
            Gl.glTexParameteri(Gl.GL_TEXTURE_2D, Gl.GL_TEXTURE_MAG_FILTER, Gl.GL_LINEAR);
            Gl.glPushMatrix();
            Gl.glRotated(-90, 0, 0, 1);
             Gl.glTranslated(-1, -1, 0);
            Gl.glBegin(Gl.GL_QUADS);

            Gl.glTexCoord2d(0.0, 1.0);
            Gl.glVertex2f(0.0f, 1.0f);

            Gl.glTexCoord2d(0.0f, 0.0f);
            Gl.glVertex2f(0.0f, 0.0f);

            Gl.glTexCoord2d(1.0, 0.0f);
            Gl.glVertex2f(1.0f, 0.0f);

            Gl.glTexCoord2d(1.0f, 1.0f);
            Gl.glVertex2f(1.0f, 1.0f);
            Gl.glEnd();
            Gl.glPopMatrix();
         Gl.glFlush();
        }

Вот скрин:
http://ipicture.ru/
Но теперь нужно изменить ракурс изображения, чтобы можно было сравнить со второй фотографией. Нужно как-то "развернуть" лицо в "фас". Как это сделать пока не знаю. Если кто может - подскажите.

Автор: cardinal 6.7.2009, 00:54
galileopro, я бы сам по этим фоткам затруднился сказать один и тот же ли это человек...

Автор: galileopro 6.7.2009, 00:59
Одна вообще. Просто у меня кроме её портфолио больше нет на примете фотографий, чтобы ракурсы разные были. Если у кого есть, то дайте ссылку, я запущу программу с другими фотками и скину скрин.

Автор: cardinal 6.7.2009, 01:26
Цитата(galileopro @  5.7.2009,  22:50 Найти цитируемый пост)
Но теперь нужно изменить ракурс изображения, чтобы можно было сравнить со второй фотографией. 

Первая мысль: сделать голову объемной (исходя из теней), наложить текстуру и потом повернуть. Половина объекта будет без текстуры, но по крайней мере будет один ракурс...

Автор: galileopro 6.7.2009, 01:34
1) Как сделать её объемной исходя из теней сам щас пытаюсь понять. 
2) А как вычислять уголповорота? Я не могу никак определить базовые точки на лице, чтобы определить направление вектора нормали к плоскости лица.
Есть вот это http://www.iai.dn.ua/public/JournalAI_2004_2/Razdel1/37_Tukhtasinov.pdf
но там лицо в фас, а у меня нет, и поэтому гикстограмма яркости сильно искажена и по ней трудно определить линии глаз, нос, губы...

Автор: NightmareZ 6.7.2009, 01:36
Трындец. И здесь день эзотерики. Для тебя эта задача неразрешима. Можешь закрывать тему.

Автор: galileopro 6.7.2009, 01:48
Цитата(NightmareZ @  6.7.2009,  01:36 Найти цитируемый пост)
Трындец. И здесь день эзотерики. Для тебя эта задача неразрешима. Можешь закрывать тему.

Разрешима. А вообще: нехочешь помогать - не помогай.

Автор: Bitter 6.7.2009, 10:48
NightmareZ, а для тебя разрешима?

Автор: Dims 6.7.2009, 17:29
Насколько я знаю, эта задача вообще пока что неразрешима. 

Есть методы, например, путём вычисления собственных значений (алгоритм eigenfaces). Есть и другие. Но, думаю, все эти методы (1) позволяют лишь сравнивать лица в одном ракурсе и (2) требуют обучения программы.

В Вашем случае, будут две большие проблемы:

1) нужно восстановить 3-мерную модель лица; для этого нужно найти источник света, вычислить наклон поверхностей, учесть макияж и т.п.

Эта задача будет сложна сама по себе, потому что данных наверняка недостаточно. То есть, алгоритм тоже должен быть обучаемый и после обучения он должен "знать" о том, что такое лицо в принципе, чтобы делать правильные предположения о том, как идёт 3d поверхность в неясных случаях.

2) Нужно сравнить две 3-мерные модели

Это тоже будет сложная задача, потому что модели не будут одинаковыми. Во-первых, из-за ошибок и искажений, возникших на предыдущем этапе, во-вторых, из-за того, что любое лицо немного меняется естественным образом и, наконец, из-за несоответствия масштабов.

То есть, алгоритм тоже должен будет много знать, чтобы правильно отделить важные отличия от второстепенных.

Автор: Pavia 6.7.2009, 19:12
Поповуду сравнения. Считается чтобы точно сравнить надо вычислить растояния между глазами носом и ртом.
Но в твоем случии придется еще востанавливать 3D.

1) Выделить овал лица.  Тут  предлогаю применить выделение границ. Советую найти реализацию Canny. В OpenCV уже есть.
Хотя тут можно и ручками сделать. Просто локальный максимум.

2) Предлогаю сделать так. При помоще градиента вычисляем наклон и высоту пикселей.  Это даст примерную 3D модель.

отдаю свою идею. 

Корреляция с обратной связью. 

Суть в том задем начальное приблежение. Ввиде поворотной матрицы. Примерно совподали лица после поворота. После считаем корреляцию. Пробуем поворачивать на некотоый угол alfa + и - смотрим где корреляция больше если +alfa  то прибовляем Если корреляция больше при в данной позиции в 0.  Пробуем поворачивать по другой оси beta. Если и в этом случии максимум при 0 то уменьшаем alfa и beta в неско раз к примеру в 2. 

И так до тех пор пока alfa и  beta не станут очень маленькими. 

Поповоду соовмещения по координатам, то корреляцию считать не как коэфициент, а как функцию.  Думаю будет точнее. Хотя можно поступить по аналогии с глами.

Для ускорения рассчета корреляции можно брать не все точки. 

По поводу начальных приблежений их можно как задать ручками так и вычислить припомощи статестических моментов. Но боюсь тут погрешность будет большая.


Автор: galileopro 6.7.2009, 19:14
Ясно. Я это и пытаюсь сделать, а именно: построить 2 3-х мерные модели лица. Уже кое что получилось. Выложу скоро код и скрин.
Цитата(Pavia @  6.7.2009,  19:12 Найти цитируемый пост)
При помоще градиента вычисляем наклон и высоту пикселей.  Это даст примерную 3D модель.

Как раз так я и начал строить. Ты не обижайся, просто нечто похожее я накопал в Интернете. Проблема возникает с шумами, с тем, что изображение иногда подвергают изменениям, после фотографирования (серпия, визуальные эффекты, это все дает большие погрешности).
Вообще уже кой чего получилось, но модели очень непохожи за счет случайных факторов.
Если лицо в "фас" то 3D модель построить легче. А вот если повернуто, то может кто-то знает, как направить свет в фас, а не так как на фотографии. Я по теням вычислил вектор источника светпа, и он направлен сбоку, а это влечет большие трудности.
Задача:
Переделать http://ipicture.ru/
так, чтобы свет был в лицо актрисе направлен, а не произвольно. Надо позарез.

Автор: cardinal 6.7.2009, 19:56
Цитата(galileopro @  6.7.2009,  17:14 Найти цитируемый пост)
Вообще уже кой чего получилось, но модели очень непохожи за счет случайных факторов.

Я думаю, что погрешность будет все равно очень большая. Но она и в жизни такая же (метод: на глаз)...

Автор: galileopro 6.7.2009, 20:08
Придумал:
Надо сначала "отключить" старый источник света, то есть яркость равнораспределить(получится какое-то полутоновое изображение), а потом с помощью OpenGL вроде можно установить новій источник света(по направлени лица, а для єтого енужно вічислить расположение глаз и носа, через 3 точки проводим 2 вектора, и их векторное пр-е - єто направляющий вектор лица(он перпендикулярен плоскости лица). Только как устанавливается источник света в OpenGl - это еще мне надо изучать.
Ах да , а потом делаем GetPixels() и вуаля, вот новая фотка, а свет уже в фас.

Дело в том, что я хочу по яркости пикселей постороить саму модель. Ведь выпуклые части лица при свете в фас осветятся наилучшим образом, а вогнутые плохо, и тогда яркость пиксела - это характеристика его местоположения в 3D модели

Автор: cardinal 6.7.2009, 22:15
Цитата(galileopro @  6.7.2009,  18:08 Найти цитируемый пост)
и тогда яркость пиксела - это характеристика его местоположения в 3D модели

но как уже сказали есть нюансы...
Цитата(Dims @  6.7.2009,  15:29 Найти цитируемый пост)
учесть макияж


Автор: galileopro 7.7.2009, 00:55
Вот все думаю, поможет ли моя идея направить свет в "фас". Пока я попробовал просто построить 3D по яркости пикселов и получилось вот єто:
Код

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Tao.OpenGl;

namespace OpenGLDemo
{
    public partial class MainForm : Form
    {
        public const int size = 200;
        public byte[, ,] Bits = new byte[size, size, 3];
        public byte[, ,] Bits2 = new byte[size, size, 3];
        public bool[,] flag = new bool[2,1];
        Bitmap bitmap = new Bitmap("photo1.bmp");
        public MainForm()
        {
            InitializeComponent();
            openGlControl.InitializeContexts();
            Init();
            Resize(openGlControl.Width, openGlControl.Height);
        }

        private void MainForm_Paint(object sender, PaintEventArgs e)
        {
            Draw();
        }

        private static bool Init()
        {
            Gl.glShadeModel(Gl.GL_SMOOTH);
            Gl.glClearDepth(1.0f);
            Gl.glEnable(Gl.GL_DEPTH_TEST);
            Gl.glDepthFunc(Gl.GL_LEQUAL);
            Gl.glEnable(Gl.GL_COLOR_MATERIAL);
            Gl.glEnable(Gl.GL_LIGHTING);
            Gl.glEnable(Gl.GL_LIGHT0);
            Gl.glHint(Gl.GL_PERSPECTIVE_CORRECTION_HINT, Gl.GL_NICEST);
            return true;
        }
        private static void Resize(int width, int height)
        {
            if (height == 0) height = 1;
            Gl.glViewport(0, 0, width, height);
            Gl.glMatrixMode(Gl.GL_MODELVIEW);
            Gl.glLoadIdentity();

        }
        private void Koga(Bitmap bitmap)
        {

            for (int i = 0; i <= size - 1; i++)
                for (int j = 0; j <= size - 1; j++)
                {
                    //R > 95 и G > 40 и B > 20 и max(R,G,B)-min(R,G,B) > 15 и |R - G| > 15 и R > G и R > B.
                    byte r = bitmap.GetPixel(i, j).R;
                    byte g = bitmap.GetPixel(i, j).G;
                    byte b = bitmap.GetPixel(i, j).B;
                    if (!((r > g) && (r > b) && (b > 20) && (r > 95) && (b > 20) && (abs(r - g) > 15) && (max(r, g, b) - min(r, g, b) > 15)))
                    {
                        Bits[i, j, 0] = 0;
                        Bits[i, j, 1] = 0;
                        Bits[i, j, 2] = 0;
                    }

                }
        }
        private byte abs(int r)
        {
            if (r < 0) r = -r;
 return Convert.ToByte(r);
        }
        private double absd(double d)
        {
            if (d < 0) d = -d;
            return d;
        }
        private byte max(int r, int g, int b)
        {
            int m = r;
            if (g > m) m =g;
            if (b > m) m = b;
            return Convert.ToByte(m);
        }
        private byte min(int r, int g, int b)
        {
            int m = r;
            if (g < m) m = g;
            if (b < m) m = b;
            return Convert.ToByte(m);
        }                                         
        }
        private void Draw()
        {           
            Gl.glClear(Gl.GL_COLOR_BUFFER_BIT | Gl.GL_DEPTH_BUFFER_BIT);
               Gl.glEnable(Gl.GL_TEXTURE_2D);
                
                for (int i = 0; i <= size-1; i++)
                    for (int j = 0; j <= size-1; j++)
                        {
                            Bits[i, j, 0] = bitmap.GetPixel(i, j).R;
                            Bits[i, j, 1] = bitmap.GetPixel(i, j).G;
                            Bits[i, j, 2] = bitmap.GetPixel(i, j).B;

                         
                            Bits2[i, j, 0] = bitmap.GetPixel(i, j).R;
                            Bits2[i, j, 1] = bitmap.GetPixel(i, j).G;
                            Bits2[i, j, 2] = bitmap.GetPixel(i, j).B;

                        }

                Koga(bitmap);
                             
    for (int i = 0; i < 199; i++)
        for (int j = 0; j < 199; j++)
    {
Gl.glPushMatrix();
Gl.glColor3d(Convert.ToDouble(Bits[i, j, 0])/50, Convert.ToDouble(Bits[i, j, 1])/50, Convert.ToDouble(Bits[i, j, 2])/50);
Gl.glTranslated(Convert.ToDouble(i) / 200, 1 - Convert.ToDouble(j) / 200, Convert.ToDouble(0.3*Bits[i, j, 0] + 0.59*Bits[i, j, 1] + 0.11*Bits[i, j, 2]) / 255);
Glu.GLUquadric q = Glu.gluNewQuadric();
Glu.gluSphere(q,0.01, 5, 5);
Glu.gluDeleteQuadric(q);
Gl.glPopMatrix();    
    }

Gl.glFlush();
        }


        private void button1_Click_1(object sender, EventArgs e)
        {
Gl.glRotated(90, 0, 1, 0);
Draw();
openGlControl.Refresh();
        }
    }  
}

http://ipicture.ru/
http://ipicture.ru/
Жуткий бред. Можно попытаться смоделировать полигонами. Может будет лучше, но вообще что-то плохо.
Сделал процедуру для выравнивания яркости вот теперь думаю, если выровнять яркость, потом расположить прямо перед лицом её источник света, то модель улучшится? Судя по предварительному результату - неясно.

Автор: _Y_ 9.7.2009, 15:49
Я бы выделял отдельные черты лица (глаза, рот, и т.п.) и считал соотношения размеров элементов и расстояний, лежащих в одной плоскости. Например, соотношение между расстоянием между глазами и шириной рта должно быть достаточно надежной характеристикой. Потом сравнивал бы эти характерискики для разных фотографий. По-моему на этом и основывается автоматическое распознавание лиц, а не на моделировании всего лица.  Но я не специалист - просто читал где-то-что-то про автоматизацию отлова террористов в аэропортах.

ИМХО если решишь задачу с достоверностью результата близкой к достоверности зрительного сравнения фотографий, то много лет сможешь питаться, разъезжая по миру с лекцией "Как мне удалось это сделать". smile  Удачи!

Автор: galileopro 9.7.2009, 19:57
Цитата(_Y_ @  9.7.2009,  15:49 Найти цитируемый пост)
Я бы выделял отдельные черты лица (глаза, рот, и т.п.) и считал соотношения размеров элементов и расстояний, лежащих в одной плоскости.

Проблема в том, что если ракурс изменен, то эти осонвные точки уже будут не в одной плоскости. Поэтому я и восстанавливаю 3D. А сравнивать разумеется будем по основным элементам. Спасибо за совет.

Автор: dereyly 10.7.2009, 13:05
Здравствуй, сложной задачей ты занимаешься, но надеюсь у тебя все получится... Вот есть пару ссылок работы 2х комерческих программ: 
http://www.youtube.com/watch?v=nice6NYb_WA
http://www.seeingmachines.com/product/faceapi/

Автор: _Y_ 10.7.2009, 13:10
Цитата(galileopro @ 9.7.2009,  19:57)
если ракурс изменен, то эти осонвные точки уже будут не в одной плоскости

Мне кажется там хитрость в том, что сравниваются только те характеристические соотношения, которые можно определить на обеих фотографиях. Остальные же просто игнорируются. Ну и, понятно, таких соотношений должно быть много, чтобы статистически исключить шум.

Кстати, если человек ни разу не попадал под трактор, линия рта и линия глаз у него параллельны и, соответственно, всегда лежат в одной плоскости smile  Это просто пример, конечно.

Автор: _Y_ 11.7.2009, 12:48
Я вот еще подумал. Для выбора характеристических признаков можно покопаться в принципах сборки милицейских фотороботов.

Автор: dereyly 12.7.2009, 01:00
Цитата(_Y_ @ 11.7.2009,  12:48)
Я вот еще подумал. Для выбора характеристических признаков можно покопаться в принципах сборки милицейских фотороботов.

Идея интересная вот только, как их БД вскрыть, так как обычно формат элементов находится во внутреннем представлении.

Автор: galileopro 12.7.2009, 22:28
А можно ли попытаться не строить 3 Д с нуля, а сделать базу из 3Д моделей лиц, а потом надожить фото как текстуру? А по фотографии определить какая из доступных моделей подходит лучше всего и еще сделать модели так, чтобы можно было изменять полноту лица, расстояние между бровями и другие параметры?

Автор: DRUID3 13.7.2009, 09:09
Цитата(galileopro @  12.7.2009,  21:28 Найти цитируемый пост)
А можно ли попытаться не строить 3 Д с нуля, а сделать базу из 3Д моделей лиц, а потом надожить фото как текстуру? А по фотографии определить какая из доступных моделей подходит лучше всего и еще сделать модели так, чтобы можно было изменять полноту лица, расстояние между бровями и другие параметры? 

Если при этом правильно организовать хранение этих самых моделей - в виде дерева - то поиск по базе можно будет заметно ускорить...

Добавлено через 2 минуты и 33 секунды
Цитата(_Y_ @  11.7.2009,  11:48 Найти цитируемый пост)
Я вот еще подумал. Для выбора характеристических признаков можно покопаться в принципах сборки милицейских фотороботов. 

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

Автор: _Y_ 13.7.2009, 09:44
Цитата(DRUID3 @ 13.7.2009,  09:09)
Цитата(_Y_ @  11.7.2009,  11:48 Найти цитируемый пост)
Для выбора характеристических признаков можно покопаться в принципах сборки милицейских фотороботов.
 А Вы в состоянии написать программу эффективно работающую с изображениями фоторобота? Они сделаны для восприятия человека...

Извиняюсь, я, видимо, недостаточно ясно выразил свою мысль. Она не в том, чтобы програмно собирать фоторобота. Я просто предлагал покапаться в принципах его сборки. Для того, чтобы понять какие признаки могут быть характеристическими, а какие нет. А уж описывать эти признаки придется самому и именно в удобной для компьютерной обработки форме.

Автор: galileopro 13.7.2009, 14:48
Вот есть программа, она делает 3Д модель лица по 3-м фотографиям: в фас, левый профиль, правый профиль. Называется FaceGen Modeller 3.1.2. Скачать можно тут, но учтите, что Демо-версия не сохраняет модель(посмотреть можно, а воспользоваться - нет).  http://www.facegen.com/
Если есть эти 3 фотки, то можно сделать 3Д по ним, а потом просто развернуть модель в нужный ракурс, наложить текстуру, применить фильтры (ну чтобы 2 сравниваемых изображения обладали более-менее одинаковыми свойствами), а потом сравнить эти 2 фотки (уже в одинаковых ракурсах). Для сравнения проще всего попиксельное, но можно и нейросеть обучить, можно и основные елементы выделить, кому как, я бы использовал нейросеть, так как когда-то я с ними сталкивался, а вот как выделить основные елементы лица если угол поворота более 20-25 градусов я так и не разобрал. Ну это еще можно почитать.
Основной неодстаток проги - то, что у меня, по крайней мере, она моделила 3Д но текстуру не наложила, то есть модель сгенерировала очень похожую на фотки, но цвет кожи, волосы, макияж, и все остальное благополучно отбросила, получился этакий Вин Дизель, но черты лица такие, как на фотках.
Пришлость экспортировать модель из проги в 3Д макс и там уже наложить текстуру. Потом я по теням определил насколько нужно изменить ракурс (насколько повернуть по Ох Оу Oz) и сравнил попиксельно (дало 86.324% сходства) и методом нейросетей (91.454%). Нейросеть делал сам, пользовался 
http://depositfiles.com/files/urhq14jpd
http://www.basegroup.ru/library/analysis/neural/math/
http://masters.donntu.edu.ua/2007/kita/mikhalets/ind/index.htm
http://daily.sec.ru/dailypblshow.cfm?rid=5&pid=4425
И еще много чем. Вообще довольно геморно получается, но единственное понятно: по одной фотографии восстановить 3Д не получится. Или получится с большими погрешностями. Думаю  нужно попробовать написать прогу, которая хотя бы по 3-м фоткам (фас, левый профиль, правый профиль) восстановила 3Д и изменила нужным образом ракурс, наложила текстуру и сравнила полученные изображения. Причем мне понравился метод FaceGen Modeller 3.1.2 там ты на фотки накладываешь сетку из основных точек - вроде это результативнее, чем тратить машинное время на определение их внутри программы. Хотя можно и так.
Итак, господа форумчане, хочу услышать отзыв. smile

Автор: DRUID3 13.7.2009, 21:07
galileopro
Ну вобщем-то интересно...Но... Но я думал мы обсуждаем несколько иное. У ментов есть систем где вводится фотка (понятное дело никаких 3-х ракурсов в помине нет) а с телекамер(например в аэропорту) непрерывно сканируется изображение на совпадение. И ежу понятно - масштаб совершенно иной, угол захвата и падения освещения - произвольный... Системы - реальные, "принятые на вооружение", для работы достаточно одноядерного процессора ~3GHz (не знаю правда плавающая точка там или фиксированная)...

Вобщем, как верно подметил Dims...
Цитата(Dims @  6.7.2009,  16:29 Найти цитируемый пост)
1) нужно восстановить 3-мерную модель лица; для этого нужно найти источник света, вычислить наклон поверхностей, учесть макияж и т.п.

Именно. Причем точно так же придется делать и для эталона(образцовой фотографии) и для сканируемой... Построить модель в виде графа. Причем поиск производить по сильно упрощенной модели(то же расстояние глаза-нос-рот). Если есть вхождение в диапазон совпадений - усложнять модель и снова сканировать и т.д. Если камера будет высокого разрешения - можно будет еще сравнивать расцветку полигонов(образованных ребрами графа) тем же вейвлет-преобразованием Добеши, например... Почему вейвлет? опять же, можно останавливаться на произвольном уровне детализации при несовпадении...

Цитата(Dims @  6.7.2009,  16:29 Найти цитируемый пост)
2) Нужно сравнить две 3-мерные модели

Это тоже будет сложная задача, потому что модели не будут одинаковыми. Во-первых, из-за ошибок и искажений, возникших на предыдущем этапе, во-вторых, из-за того, что любое лицо немного меняется естественным образом и, наконец, из-за несоответствия масштабов.

Да... с масштабами будет нелегко, и даже не знаю как правильно. Наверное нужно модель в виде графа сводить к какой-то общей величине. Толи общей сумме весов ребер, то ли к общему объему занимаемому 3-D моделью. Что менее ресурсоемко...

Добавлено через 6 минут и 59 секунд
Да, еще хотел добавить что нестОит сюда пока тянуть никаких нейронных сетей... Блин, это какая-то новая эпидемия... Нейронные сети это основа физической машины нашего мозга, а отнюдь не ИИ вообще, основа искусственного интеллекта - математика... Вот эти самые НС между задачей и ее моделью, как Java между конкретной архитектурой процессора и ленью программиста общим командным интерфейсом... Т.е. можно но быстрее и правильнее без них...
 Тем более что их смешали уже и с сетями Вольтерии(которые вообще не из этой степи) и мноигим чем еще... Слово очень модное, почти как нанотехнологии...

Добавлено через 8 минут и 56 секунд
Кстати, достойная задача для CUDA...

Автор: galileopro 13.7.2009, 22:06
Ясно. Просто хотелось побыстрее получить результат.
Цитата(DRUID3 @  13.7.2009,  21:07 Найти цитируемый пост)
масштаб совершенно иной, угол захвата и падения освещения - произвольный...

Сейчас пытаюсь реализовать такое:
1) Определить местоположение лица.
Здесь я пробовал так:
Выделяю кожу по цвету 
 if (!((r > g) && (r > b) && (b > 20) && (r > 95) && (b > 20) && (abs(r - g) > 15) && (max(r,g,b)-min(r,g,b) > 15)))
беру  Лапласиан и выделяю контуры,
d2f = 4*z5 - (z2 + z4 + z6 + z8) 
Здеся как и советуется в http://masters.donntu.edu.ua/2007/kita/mikhalets/ind/index.htm с сглаживающей Гаусовской функцией, потом нахожу замкнутый контур, который приближенно имеет форму эллипса или на него можно наложить 2 параболы.
2) Преобразую в бинарное, и определяю расстояние между ушами, потом на линии ушей делая квадратик как сказано в http://www.iai.dn.ua/public/JournalAI_2004_2/Razdel1/37_Tukhtasinov.pdf и масштабирую под другой масштаб (оба изображения под один, равный максимальному размеру из 2-х данных)
3) Нахожу источник света по теням и областям высокой яркости (здесь тоже свертки из http://masters.donntu.edu.ua/2007/kita/mikhalets/ind/index.htm). Тут проблема такая: хотелось бы максимально выровнять яркость по направлению источника света.
4) Наклон поверхностей - метод градиентного спуска, и это действительно, как упоминалось, дает приближенную 3D модель.
5)Построить модель в виде графа. Сейчас это и делаю. Как получится - напишу.
Спасибо за помощь.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)