Jump to content
Compvision.ru
al072

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

Recommended Posts

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

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

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

Share this post


Link to post
Share on other sites

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

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

  • Like 1

Share this post


Link to post
Share on other sites

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

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

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

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

  • Like 1

Share this post


Link to post
Share on other sites

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

Share this post


Link to post
Share on other sites

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

Share this post


Link to post
Share on other sites

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

Share this post


Link to post
Share on other sites

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

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

 

Share this post


Link to post
Share on other sites

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

Share this post


Link to post
Share on other sites

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 или данная информация не о чем не говорит?

Share this post


Link to post
Share on other sites

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

OpenCL  без шансов.

  • Like 1

Share this post


Link to post
Share on other sites

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()? Спасибо.

Share this post


Link to post
Share on other sites

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

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

Share this post


Link to post
Share on other sites

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

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

Share this post


Link to post
Share on other sites

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

Share this post


Link to post
Share on other sites
3 hours ago, al072 said:

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

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

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

  • Like 1

Share this post


Link to post
Share on other sites

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

Share this post


Link to post
Share on other sites

В исходниках функции 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 стало еще хуже. В чем может быть проблема? Что делаю не так?

Share this post


Link to post
Share on other sites

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

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

Возможно есть еще возможность как то приостанавливать видео на время обработки? Или как сказал 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.

 

 

 

 

Share this post


Link to post
Share on other sites

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

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

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

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

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

 

Share this post


Link to post
Share on other sites
5 hours ago, al072 said:

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

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

Share this post


Link to post
Share on other sites

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

Share this post


Link to post
Share on other sites
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 просьба поделитесь.. 

Share this post


Link to post
Share on other sites

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 мне в руки))

Share this post


Link to post
Share on other sites

Господа, подскажите плиз как правильнее реализовать работу потоков и оптимизировать работу программы. Имеется 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 процесса каждый в своем потоке, но скорость вывода изображения на форму от этого не меняется, более того появляется еще больше геморроя с синхронизацией работы потоков.. 

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now


  • Recently Browsing   0 members

    No registered users viewing this page.

×