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

Оптимизация кода

Recommended Posts

Добрый день !

Вот есть код :

#include "StdAfx.h"

#include <opencv2/opencv.hpp>

#include <opencv2/core/core_c.h>

#include <opencv2/core/core.hpp>

#include <opencv2/calib3d/calib3d.hpp>

#include <opencv2/features2d/features2d.hpp>

#include <opencv2/imgproc/imgproc_c.h>

#include <opencv2/imgproc/imgproc.hpp>

#include <opencv2/highgui/highgui_c.h>

#include <opencv2/highgui/highgui.hpp>

#include <opencv2/objdetect/objdetect.hpp>

#include <C:\videoInput0.1995\compiledLib\compiledByDevCpp\include\videoInput.h>

#include <process.h>

#include <stdio.h>

#include <vector>

#include <iostream>

using namespace cv;


# pragma comment(lib, "C:/videoInput0.1995/compiledLib/compiledByCW/videoInput.lib")





static CvMemStorage* storage = 0;

static CvHaarClassifierCascade* cascade = 0;




const char* cascade_name = "C:/OpenCV2.2/data/haarcascades/haarcascade_frontalface_default.xml";



double scale = 1;

CvSeq* contours = 0;

void detect_and_draw( IplImage* image);

void Init();

CvFont myFont;

char text_buf[20];


int _tmain(int argc, _TCHAR* argv[])

{

Init();

return 0;

}


void Init()

{

IplImage  *frame_copy = 0;

IplImage *image = 0;

int i;

const char* input_name = 0;



cvInitFont(&myFont, CV_FONT_HERSHEY_COMPLEX, 0.7, 1, 0, 1, 8);


//Загрузка базы данных, обученной на детектирование лиц в Фас

cascade = (CvHaarClassifierCascade*)cvLoad( cascade_name, 0, 0, 0 );




//Создание хранилища памяти

storage = cvCreateMemStorage(0);



cvNamedWindow( "result", 1 );



//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$

        // создание объекта videoInput

        videoInput VI;


        // получение списка доступных видеоустройств, возвращается число устройств

        int numDevices = VI.listDevices();

        int device1=0; // первое найденое видеоустройсво из списка


        // частота кадров

        VI.setIdealFramerate(device1, 15);


        // указываем разрешение

        VI.setupDevice(device1, 500, 400, VI_COMPOSITE);


        //VI.showSettingsWindow(device1); // показать окошко настроек камеры


        // создаём картинку нужного размера

        image = cvCreateImage(cvSize(VI.getWidth(device1),VI.getHeight(device1)), IPL_DEPTH_8U, 3);


        while(1){

                if (VI.isFrameNew(device1)){

                        // первый параметр - индекс видеоустройсва

                        // второй - указатель на буфер для сохранения данных

                        // третий - флаг, определяющий менять ли местами B и R -составляющий

                        // четвёртый - флаг, определяющий поворачивать картинку или нет

                        VI.getPixels(device1, (unsigned char *)image->imageData, false, true); // получение пикселей в BGR

						//


if( image )

 {

//Производим детектирование

detect_and_draw( image);

 }

              }


                char c = cvWaitKey(33);

                if (c == 27) { // ESC

                        break;

                }

        }

//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$

}




void detect_and_draw( IplImage* img )

{


static CvScalar colors[] =

{ {{0,0,255}}, {{0,128,255}}, {{0,255,255}}, {{0,255,0}}, {{255,128,0}}, {{255,255,0}}, {{255,0,0}}, {{255,0,255}}

};


IplImage *gray;


int i, j;


gray = cvCreateImage( cvSize(img->width,img->height), 8, 1 ); 



//cvCvtColor( img, gray, CV_BGR2GRAY ); 



cvClearMemStorage( storage );


if( cascade )

 {


double t = (double)cvGetTickCount();


CvSeq* faces = cvHaarDetectObjects( img, cascade, storage, 1.1, 2, 0|CV_HAAR_DO_CANNY_PRUNING,cvSize(30, 30) ); 


t = (double)cvGetTickCount() - t;


printf( "detection time = %gms\n", t/((double)cvGetTickFrequency()*1000.) );

sprintf(text_buf,"find faces:%d",faces->total);

cvPutText(img, text_buf, cvPoint(5,40), &myFont, cvScalar(255,255,255));

for( i = 0; i < (faces ? faces->total : 0); i++ )

    {


CvRect* r = (CvRect*)cvGetSeqElem( faces, i );


CvMat small_img_roi;


CvSeq* nested_objects;


CvPoint center;


CvScalar color = colors[i%8]; 


int radius;


center.x = cvRound((r->x + r->width*0.5)*scale);


center.y = cvRound((r->y + r->height*0.5)*scale);


radius = cvRound((r->width + r->height)*0.25*scale);


cvCircle( img, center, radius, color, 3, 8, 0 );



}}

cvShowImage( "result", img );

cvWaitKey(1);

cvReleaseImage( &gray );




}

Почему то сильно тормозит картинка,получаемая с веб камеры .

по умолчанию значение cvWaitKey(1) было 1000 .сейчас 1 и стало шустрее,но недостаточно.

+ время обнаружения порядка 500мс а если людей в кадре несколько то и более.

Как можно улучшить эти показатели?

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


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

Добавьте ключ CV_HAAR_FIND_BIGGEST_OBJECT, будет быстрее, правда искать будет только один объект.

Поставьте вместо cvSize(30, 30) например cvSize(150, 150), это тоже должно ускорить процесс.

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


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

Добавьте ключ CV_HAAR_FIND_BIGGEST_OBJECT, будет быстрее, правда искать будет только один объект.

Поставьте вместо cvSize(30, 30) например cvSize(150, 150), это тоже должно ускорить процесс.

спасибо за ответ!

это уже опробовал.

в первом случае не подходит так как надо искать и считать всех кто есть в кадре,а второе не подходит по причине того,что начинает пропускать лица ,которые дальше эмм..ну примерно метра ,2х от камеры.

Есть еще что то?или это плата за бесплатное пользование библиотеки?

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


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

есть варианты:

-использовать новый LBP каскад

-использовать GPU

-не искать на каждом кадре, а делать трекинг

-уменьшить разрешение изображения.

еще неплохо было бы, если вы написали ваше железо и сколько времени тратиться на детектирование.

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


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

есть варианты:

-использовать новый LBP каскад

-использовать GPU

-не искать на каждом кадре, а делать трекинг

-уменьшить разрешение изображения.

еще неплохо было бы, если вы написали ваше железо и сколько времени тратиться на детектирование.

благодарю за ответ!

1)LBP каскад есть уже обученный?подключать его так же как и Хааровский?

2)насколько я знаю по умолчанию используется лишь одно ядро процессора.

у меня их два.возможно есть смысл для начала его задействовать?

если знаете как,подскажите пожалуйста :)

3)то есть просто следить за найденным лицом?есть примеры гденть такого кода?сам боюсь не осилю с нуля

4)да у меня и так берется 500 на 400.уменьшать не вариант.хотелось бы наоборот увеличить...

CPU Intel Core 2 Duo P8400 по 2.3 Ггц на ядро

GPU Nvidia 9600M GT 512Mb

Диск SAMSUNG HM500JI 5400 об/мин

ОЗУ 3Гб ddr2

время детектирования если в кадре один человек и хорошее освещение то около 400мс.

если плохое ,то около 600.

ну и с появлением нескольких лиц в кадре где то плюс 200мс

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


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

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

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


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

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

спасибо за совет!

а как задействовать видеоядро?

кстате начал разбираться с этим и на сайте ссылка

пишет чел вот ,что :

"Чтобы сравнить производительность вычислений на видеокарте и на процессоре я написал несколько тестов производительности на базе Qt. Можете их скачать здесь. К моему удивлению, у меня видеокарта nvidia GeForce 9600M GS считает в разы медленнее чем процессор intel Centrino 2."

по сути это мое железо.может и не стоит мне связываться тогда с этим?

Изменено пользователем nikrubab

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


Ссылка на сообщение
Поделиться на других сайтах
1)LBP каскад есть уже обученный?подключать его так же как и Хааровский?

да

2)насколько я знаю по умолчанию используется лишь одно ядро процессора.

у меня их два.возможно есть смысл для начала его задействовать?

если знаете как,подскажите пожалуйста

по идее прям поверх не получится распараллелить.

можно было бы распараллелить по данным, т.е. там сканируется скользящим окном, ну так вот и распределить непересекающиеся окна между тредами, но это надо лезть внутрь.

т.е. тут можно распараллелить только между кадрами, по треду на кадр, а это по идее не очень полезно.

3)то есть просто следить за найденным лицом?есть примеры гденть такого кода?сам боюсь не осилю с нуля

на первом кадре ищете по всему кадру, на втором только вокруг прямоугольника который нашелся на первом кадре, если объект не нашелся, то повторяете всё с первого шага.

а как задействовать видеоядро?

https://developer.nvidia.com/cuda-gpus

не знаю какое compute capability требуется в opencv, но у 9600M GT 1.1 (так что может не взлететь + ноутбучные видеокарты вроде как слабые, но попробовать всё равно думаю стоит)

Для использования надо поставить CUDA драйвера и Cuda Toolkit(не помню точно, но там всё в куче вроде), использовать готовые бинарники OpenCV или собрать из исходников с поддержкой GPU.

и использовать

gpu::CascadeClassifier_GPU

Cascade classifier class used for object detection. Supports HAAR and LBP cascades

кстати говоря

The GPU module is designed as a host-level API. This means that if you have pre-compiled OpenCV GPU binaries, you are not required to have the CUDA Toolkit installed or write any extra code to make use of the GPU.

так что лучше использовать готовые бинарники меньше мороки.

и еще

This means that for devices with CC 1.3 and 2.0 binary images are ready to run. For all newer platforms, the PTX code for 1.3 is JIT’ed to a binary image. For devices with CC 1.1 and 1.2, the PTX for 1.1 is JIT’ed. For devices with CC 1.0, no code is available and the functions throw Exception. For platforms where JIT compilation is performed first, the run is slow.

http://docs.opencv.org/modules/gpu/doc/introduction.html

  • Like 1

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


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

"Чтобы сравнить производительность вычислений на видеокарте и на процессоре я написал несколько тестов производительности на базе Qt. Можете их скачать здесь. К моему удивлению, у меня видеокарта nvidia GeForce 9600M GS считает в разы медленнее чем процессор intel Centrino 2."

не знаю как на вашем железе но вот у себя протестировал дефолтный поиск лица и глаз хааром. cpu core i5 3ГГц против gforce gt 635m. разница 20 раз. В использовании GPU есть такой момент: перегон в видеопамять изображение, инициализация вычисления все это относительно долго. Так что если вы банально вычитаете изображения то потери времени на все эти дела будет больше времени выигранном на самом параллельность вычислении. По этому у автора и результат такой противоречивый получился.

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


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

Доброго дня!

подскажите пожалуйста ресурс,где можно почитать про то как работать с GPU в opencv ?

iskees можете показать код программы с помощью которой вы тестировали?

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

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


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

Вот кусок моего кода детектора лиц на GPU:

#define  _CRT_SECURE_NO_DEPRECATE
#include <stdio.h>
#include <direct.h>
#include "fstream"
#include "iostream"
#include <vector>
#include "opencv2/core/core.hpp"
#include "opencv2/core/gpumat.hpp"
#include "opencv2/core/opengl_interop.hpp"
#include "opencv2/gpu/gpu.hpp"
#include "opencv2/ml/ml.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/contrib/contrib.hpp"
#include "opencv2/video/tracking.hpp"
#include "opencv2/imgproc/imgproc.hpp"

//#include "cuda_runtime.h"
//#include "device_launch_parameters.h"

using namespace std;
using namespace cv;
using namespace cv::gpu;


//cudaError_t VoterKernelHelper(const DevMem2Df src, PtrStepf dst);
cv::gpu::CascadeClassifier_GPU cascade_gpu;

//-------------------------------------------------------------------------------------------------------------
vector<Rect> detect_faces(Mat& image)
{
vector<Rect> res;
bool findLargestObject = true;
bool filterRects = true;
int detections_num;
Mat faces_downloaded;
Mat im(image.size(),CV_8UC1);
GpuMat facesBuf_gpu;
if(image.channels()==3)
{
cvtColor(image,im,CV_BGR2GRAY);
}
else
{
image.copyTo(im);
}
GpuMat gray_gpu(im);

cascade_gpu.visualizeInPlace = false;
cascade_gpu.findLargestObject = findLargestObject;
detections_num = cascade_gpu.detectMultiScale(gray_gpu, facesBuf_gpu, 1.2,(filterRects || findLargestObject) ? 4 : 0,Size(image.cols/4,image.rows/4));


if(detections_num==0){return res;}

facesBuf_gpu.colRange(0, detections_num).download(faces_downloaded);
Rect *faceRects = faces_downloaded.ptr<Rect>();

for(int i=0;i<detections_num;i++)
{
res.push_back(faceRects[i]);
}
gray_gpu.release();
facesBuf_gpu.release();
return res;
}
//-----------------------------------------------------------------------------------------------------------------

void main()
{
...
cascade_gpu.load("haarcascade_frontalface_alt2.xml");
...
rects=detect_faces(img);
...
for(int ir=0;ir<rects.size();ir++)
{
rectangle(frame,rects[ir],Scalar(255,255,0));
}
}
[/code]

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


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

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

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

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

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

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

Войти

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

Войти сейчас


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

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

×