Перейти к содержимому
Compvision.ru
al072

Увеличение скорости распознавания лиц

Recommended Posts

Всем добрый день! Подскажите плиз с помощью каких средств можно сократить время цикла распознавания лиц? Если быть точнее, то необходимо оптимизировать работу функции model->predict(); При добавлении более 100 лиц в модель, время затрачиваемое на определение лица и присваивание метки увеличивается кратно 1 лицо 1 мс, таким образом получается что если искать совпадение в модели которая имеет порядка 200 лиц, в среднем на один цикл распознавания затрачивается 150 мс, из-за этого видеопоток начинает тормозить.

1) подскажите какой метод наиболее эффективно использовать? TBB, OpenMP, GPU или есть чтото более оптимальное?

2) можно ли распараллелить работу функции model->predict()? Модель создается с помощью createLBPHFaceRecognizer().

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Можно CUDA или OpenCL использовать, это даст примерно 100-кратное ускорение. Но придется все делать ручками.

OpenMP, TBB максимум 3-4 раза.

  • Like 1

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Ну не так уж тут все страшно.

Базис можно считать по-старому (если память позволяет), ибо 1 раз нужно.

А для распознавания и нужно то умножить вектор на матрицу, и найти расстояния между многомерными точками и выбрать наименьшее.

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

  • Like 1

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

У меня простойноутбук hp pavillion dv5 с Intel (Hd) Graphics. На такой встроенной слабой видеокарте возможно будет использовать OpenCL или CUDA?

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

OpenCL не уверен, а CUDA нельзя.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Сначала надо написать марку процессора. Не что-то абстрактное типа "Intel (Hd) Graphics", а конкретно, с цифрами.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Тип ЦП    DualCore Intel Core i3 350M, 2266 MHz (17 x 133)

Тип видеопроцессора    Intel(R) HD Graphics (Core i3)

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

На таком OpenCL не заведётся, только начиная с Ivy bridge

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Nuzhny, понял. Как на счет TBB. Есть шансы?

Поддержка TBB в opencv 2.4.11 есть по умолчанию или необходимо както подключать TBB дополнительно?

Запустил конфигуратор CMake. и после конфигурации увидел поддержку OpenCL.

Other third-party libraries:

Use IPP: NO

Use Eigen: NO

Use TBB: YES (ver 4.4 interface 9002)

Use OpenMP: NO

Use GCD NO

Use Concurrency NO

Use C=: NO

Use Cuda: NO

Use OpenCL: YES

 

OpenCL:

Version: dynamic

Include path: C:/Program Files/OpenCV 2.4.1/opencv/sources/3rdparty/include/opencl/1.2

Use AMD FFT: NO

Use AMD BLAS: NO

Значит ли это что есть шанс завести OpenCL или данная информация не о чем не говорит?

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

TBB можно. Если  он используется в твоих алгоритмах, то ускорение будет.

OpenCL  без шансов.

  • Like 1

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Ok. Как убедиться что tbb подключен к библиотеке? Если 

cv::parallel_for_ , доступен в пространстве имен cv, значит библиотека собрана с поддержкой TBB? Проще говоря в скачанной с офф сайта библиотеке OpenCV 2.4.11 уже есть поддержка TBB?

Следующий вопрос каким образом распараллелить работу метода model->predict(newface,lables,distance); ?

Допустим есть класс который работает с TBB:

class Parallel_process : public cv::ParallelLoopBody
    {

    private:
    public:
        Parallel_process()

        virtual void operator()(const cv::Range& range) const
        {
            for(int i = range.start; i < range.end; i++)
            {
                
            }
        }
    };

Как с помощью этого кода распараллелить работу метода predict()? Спасибо.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Ну так у тебя же исходники есть, можешь в них посмотреть. Или просто запусти своё распознавание: если загружено только 1 ядро, то ничего не параллелится.

Я немного о другом говорил: TBB - это не какая-то волшебная штука, автоматически распараллеливающая код. Надо быть уверенным, что внутри функций из OpenCV, которые ты используешь, программисты использовали TBB.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Ок. Покопаю исходники метода predict().

То есть если в исходниках метод не распараллелен, мне необходимо править исходники  и перестраивать библиотеки и либы? Что тогда делает опция "WITH TBB" в CMake? Извиняюсь за кучу вопросов. Пока каша в голове.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

TBB и OpenMP примерно одно и то же, но мне кажется OpenMP попроще будет, хотя это дело вкуса.

Посмотрите здесь, неплохая стстейка: https://habrahabr.ru/company/intel/blog/85273/

Здесь поразвернутее но на англ. : http://bisqwit.iki.fi/story/howto/openmp/

Еще методичка на русском: http://ccfit.nsu.ru/arom/data/openmp.pdf

Вообще, много литературы по этой теме, почитайте, хотя бы для общего развития.

Сможете параллелить свои программы даже если параллельный код не встроен в функции библиотеки.

  • Like 1

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
3 hours ago, al072 said:

Ок. Покопаю исходники метода predict().

То есть если в исходниках метод не распараллелен, мне необходимо править исходники  и перестраивать библиотеки и либы? Что тогда делает опция "WITH TBB" в CMake? Извиняюсь за кучу вопросов. Пока каша в голове.

Некоторые части OpenCV распараллелены с помощью TBB, а некоторые нет. Насколько это будет влиять на конкретную задачу судить трудно, только практикой проверять. Допустим, поиск лица Хааром не будет распараллелен, а PCA будет. Во сколько раз получится ускорение? А хз, пока не запустишь, не узнаешь.

  • Like 1

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Всем спасибо. Буду читать изучать тестировать. Результат сообщу.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

В исходниках функции predict() не нашел никакого параллельного кода. Перестроил проект с флагом /openmp и добавил заголовок #include <omp.h>.

Далее сравнил результаты работы функции:

Для 150 лиц время работы составило: 20-25 милисекунд
model->predict(preprocessedFace, label, confidence); 
Для 150 лиц время работы составило: 60-65 милисекунд
#pragma omp parallel
{
    model->predict(preprocessedFace, label, confidence); 
}

То есть с использованием openMP стало еще хуже. В чем может быть проблема? Что делаю не так?

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

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

и скорее всего она решается с использованием потоков

Возможно есть еще возможность как то приостанавливать видео на время обработки? Или как сказал Nuzhny в п.1 По крайней мере можно попробовать тот же predict вынести в отдельный поток.

#pragma omp parallel

это не магическая команда которая делает код быстрее, сам код должен быть написал с использованием openmp.

 

А теперь идём далее, даже если мы хотим распараллелить PCA, то построение базиса делается через SVD(который насколько я знаю не параллелиться) или через EIG насчёт этого не знаю(но думаю тоже нет), тем более там вроде как есть трюк с левыми\правыми eigenvalue и даже если лиц много, то всё все равно сведется к размеру изображения, т.е. размерности вытянутого в вектор изображения. Возможно всякие iterative\aproximate варианты быстрее, но это уже не классический PCA.

Вообщем всё построение базиса ложится на BLAS\LAPACK.

Предсказание делается как проецирование на базис(BLAS) и потом поиск KNN(и по сути можно ускорить только это).

 

Теперь по поводу реализации cv::FaceRecognize

https://github.com/bytefish/libfacerec/blob/0342be1453ea7689f40b3c1b9e2253446627f2f1/include/facerec.hpp

У него есть 3 реализации: EigenFace (наш через PCA), FisherFace, LBPHFace.

Нам нужна void Eigenfaces::predict(InputArray _src, int &minClass, double &minDist)

https://github.com/bytefish/libfacerec/blob/0342be1453ea7689f40b3c1b9e2253446627f2f1/src/facerec.cpp

внутри у нас project into PCA subspace

и 2 этапа

1. subspaceProject - проекция на наш базис.

смотрим Mat libfacerec::subspaceProject(InputArray _W, InputArray _mean, InputArray _src)

https://github.com/bytefish/libfacerec/blob/0342be1453ea7689f40b3c1b9e2253446627f2f1/src/subspace.cpp

Внутри мы видим (Y = (X-mean)*W) вычитание из каждой строки среднего и использованиe gemm для перемножения матриц. p.s. gemm быстрее перемножения 2-х Mat?

2.Тупо поиск по ближайшему евклидову расстоянию.

 

Если вы хотите "добавить в базу еще 1 человека" вам надо не перестраивая базис добавить в _projections только что посчитанный вектор q.

 

 

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

В первую очередь спасибо за потраченное время на развернутый ответ!

1) С проблемой "плывет изображение" наконец удалось разобраться. Решение отписал в соответствующей ветке;

2) С openMP я понял что не все так просто как хотелось бы. Думал добавлю параллельные директивы и все залетает, но не тут то было.

3) Вместо  EigenFace , в данный момент использую LBPH, на мой взгляд он более стабильно определяет дистанцию. Каким образом можно обновлять базис для LPBH? По такому же принципу как и Eigen?

4) Застрял на реализации ThreadPool. Может ктонибудь помочь разобраться как из основного потока DWORD WINAPI ThreadMain запускать отдельный поток для обработки predict()? И как синхронизировать эти потоки?

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
5 hours ago, al072 said:

4) Застрял на реализации ThreadPool. Может ктонибудь помочь разобраться как из основного потока DWORD WINAPI ThreadMain запускать отдельный поток для обработки predict()? И как синхронизировать эти потоки?

По собственному опыту: лучше взять boost и не париться с чистым WinAPI (много лет  писал на нём, перечитывал Рихтера и Руссиновича).

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

LBPH::train

https://github.com/bytefish/libfacerec/blob/0342be1453ea7689f40b3c1b9e2253446627f2f1/src/facerec.cpp

идет вычисление LBP из него spartial histogram и кладется в _histograms, т.е. базис не строится и на него проецировать не надо, просто вычисляются фичи.

p.s. а что LBPH работает лучше всего?

кстати можно делать PCA не на базе пикселей изображения, а на базе LBP, не факт что будет лучше, но сжать вектор фич получится.

 

 

по поводу потоков что то такое (код не смотрел)

http://stackoverflow.com/questions/27661353/opencv-camera-capture-from-within-a-thread

Если есть современный компилятор >VS2010, gcc>4.6 то можно использвать std::thread, если нет то тогда boost.

 

  • Like 1

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
7 часов назад, mrgloom said:

LBPH::train

https://github.com/bytefish/libfacerec/blob/0342be1453ea7689f40b3c1b9e2253446627f2f1/src/facerec.cpp

идет вычисление LBP из него spartial histogram и кладется в _histograms, т.е. базис не строится и на него проецировать не надо, просто вычисляются фичи.

p.s. а что LBPH работает лучше всего?

кстати можно делать PCA не на базе пикселей изображения, а на базе LBP, не факт что будет лучше, но сжать вектор фич получится.

 

 

по поводу потоков что то такое (код не смотрел)

http://stackoverflow.com/questions/27661353/opencv-camera-capture-from-within-a-thread

Если есть современный компилятор >VS2010, gcc>4.6 то можно использвать std::thread, если нет то тогда boost.

 

Тестировал Eigen,Fisher, LBPH на 10 людях (по 30 лиц на каждого). Пробовал разные настройки threshold, при различной освещенностью, самый стабильный результат определения добился с помощью LPBH. А у вас какие результаты? какими алгоритмами пользуетесь?

Я использую VS2010, #include <thread> такого хидера я не нашел, если я правильно понимаю то std::thread в VS2010 не доступен? То есть данная библиотека доступна начиная с VS2012 (поправьте если я не прав). 

Посмотрел код по ссылке на stackoverflow, думаю что-то подобное мне и нужно. Для того чтобы не было тормозов необходимо обрабатывать загрузку фреймов, обработку и определение в разных threads. То есть я так понимаю нужен threads pool который должен параллельно запускать 3 threads и синхронизировать их работу. Пытался реализовать этот механизм с помощью DWORD WINAPI, но не хватает познаний в многопоточном программировании. С boost раньше не работал, но надеюсь там будет проще это реализовать.. 

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

http://stackoverflow.com/questions/19857263/how-to-activate-c11-standard-in-visual-studio-2010

https://habrahabr.ru/post/173639/

Пишут что C++11 частично реализован в VS2010, и согласно таблицы сравнения версий. thread поддерживается начиная с 2012/2013.

Вообщем boost мне в руки))

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Господа, подскажите плиз как правильнее реализовать работу потоков и оптимизировать работу программы. Имеется 4 основных процесса:

1) Получение изображения с камеры (занимает 2-3 миллисекунды); Полученное изображение записывается в cv::Mat Frame;

2) Обработка изображения (занимает 45 миллисекунд); Обработанное изображение записывается в cv::Mat processedFrame;

3) Распознавание занимает (от 5 - 40 миллисекунд в зависимости от колличества лиц и меток в базисе);

4) Вывод изображения на форму занимает (2 миллисекунды).

Если запускать все четыре процесса паралленьно каждый в своем потоке, то получается что возникает необходимость синхронизировать 1,2,3,4 потоки последовательно, и смысл в многопоточности теряется. То есть пока не завершен 1 процесс получения кадра, нет смысла запускать 2 процесс обработки этого кадра, пока кадр не обработан, нет смысла выполнять функцию 3 распознавания и соответственно выводить изображение на форму 4.

Подскажите каким образом можно оптимизировать работу потоков и как добиться сокращения времени работы цикла начиная от получения изображения до вывода его на форму?

То есть изначально все четыре процесса 1,2,3,4 я запускал в одном потоке и это занимало 50-150 миллисекунд в зависимости от количества лиц и меток.

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Создайте учётную запись или войдите для комментирования

Вы должны быть пользователем, чтобы оставить комментарий

Создать учётную запись

Зарегистрируйтесь для создания учётной записи. Это просто!

Зарегистрировать учётную запись

Войти

Уже зарегистрированы? Войдите здесь.

Войти сейчас


  • Сейчас на странице   0 пользователей

    Нет пользователей, просматривающих эту страницу

×