Карта посещений

Счетчики

Реклама Google

 

Проекции изображения лица

Материал из CompVision

Перейти к: навигация, поиск

Проекция изображения лица

Пример иллюстрирует применение функций поиска лица на изображении, а так же работу с матрицам OpenCv (нахождение среднего по строкам и столбцам (суммируются интенсивности для изображения в серых тонах, и результат отображается на захваченном изображении ф-ция cvReduce) ).

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

Файлы проекта: Проект

Текст примера (Компилировался с в C++Builder6 OpenCV2.0):

//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
# define _STLP_NO_CSTD_FUNCTION_IMPORTS
//#define SKIP_INCLUDES
#define _FM_NO_REMAP
 
 
#include "cv.h"
#include "highgui.h"
 
#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
CvCapture* capture = 0;
// Описатель шрифта (см. дальше)
CvFont font;
 
IplImage *frame=0, *frame_copy = 0;
IplImage* gray=0;
 
 
static CvHaarClassifierCascade* cascade = 0;
// Заменяя эти файлы можно искать разные вещи
// см. директорию haarcascades/ там все понятно
// ищем лицо фронтально
const char* cascade_name ="haarcascades/haarcascade_frontalface_alt2.xml";
 
 
void ProcessFrame( IplImage* image );
 
#define WIDTHBYTES(bits) ((((bits) + 31) / 32) * 4)
//---------------------------------------------------------------------------
// Создание API шного битмапа из интеловского RGB изображения
//---------------------------------------------------------------------------
HBITMAP CreateRGBBitmap(IplImage* _Grab)
         {
char *App;
             LPBITMAPINFO lpbi = new BITMAPINFO;
             lpbi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
             lpbi->bmiHeader.biWidth = _Grab->width;
             lpbi->bmiHeader.biHeight =_Grab->height;
             lpbi->bmiHeader.biPlanes = 1;
             lpbi->bmiHeader.biBitCount = 24;
             lpbi->bmiHeader.biCompression = BI_RGB;
             lpbi->bmiHeader.biSizeImage = WIDTHBYTES((DWORD)_Grab->width * 8) * _Grab->height;
             lpbi->bmiHeader.biXPelsPerMeter = 0;
             lpbi->bmiHeader.biYPelsPerMeter = 0;
             lpbi->bmiHeader.biClrUsed = 0;
             lpbi->bmiHeader.biClrImportant = 0;
             void* pBits;
             HBITMAP hBitmap = CreateDIBSection(
                 NULL,
                 lpbi,
                 DIB_RGB_COLORS,
                 (void **)&pBits,
                 NULL,
                 0 );
             delete lpbi;
             if ( hBitmap )
App=(char*)pBits;
long int length=0;
if(_Grab->nChannels==1) // Серое или бинарное
  {
length = _Grab->width*(_Grab->height);
 
for (int i=0;i<_Grab->height;i++)
{
 for (int j=0;j<_Grab->width;j++)
 {
  App[_Grab->width*3*(_Grab->height-i-1)+j*3]=_Grab->imageData[_Grab->width*(i)+j];
  App[_Grab->width*3*(_Grab->height-i-1)+j*3+1]=_Grab->imageData[_Grab->width*(i)+j];
  App[_Grab->width*3*(_Grab->height-i-1)+j*3+2]=_Grab->imageData[_Grab->width*(i)+j];
 }
}
  }
if(_Grab->nChannels==3) // Цветное
  {
for (int i=0;i<_Grab->height;i++)
{
memcpy(App+_Grab->width*3*(_Grab->height-i-1),_Grab->imageData+_Grab->width*3*i,_Grab->width*3);           // Копируем память
}
 
  }
return hBitmap;
         }
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
// Функция вывода изображения на HANDLE оконного компонента
//---------------------------------------------------------------------------
void  APIDrawIpl(int x,int y,IplImage* _Grab,void *HANDLE)
{
HDC hMemDC,hDC;
hDC=GetDC(HANDLE);
hMemDC = CreateCompatibleDC(hDC);
HBITMAP Bitmap=CreateRGBBitmap(_Grab);
SelectObject(hMemDC,Bitmap);
BitBlt(hDC,x,y,_Grab->width,_Grab->height,hMemDC,0,0,SRCCOPY);
DeleteObject(Bitmap);
DeleteDC(hMemDC);
DeleteDC(hDC);
}
 
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
 
 
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
        : TForm(Owner)
{
cascade = (CvHaarClassifierCascade*)cvLoad( cascade_name, 0, 0, 0 );
    if( !cascade )
    {
      Close();
    }
capture = cvCaptureFromCAM(0);
 
Application->OnIdle = IdleLoop; // Поток обработки простоя
}
//---------------------------------------------------------------------------
 
void __fastcall TForm1::IdleLoop(TObject*, bool& done)
{
    done = false;// Поток обработки простоя
    if( capture )
    {
// Даем приказ на захват кадра
            if( !cvGrabFrame( capture ))
                goto skip;
// Если удачно - получаем кадр
            frame = cvRetrieveFrame( capture );
            if( !frame )
// Если захват не удался - пропускаем дальнейшее 
                goto skip;
 
//*********************************************************
// Если стерли то что ниже - это надо раскомментировать
//            if( !frame_copy )
//                frame_copy = cvCreateImage( cvSize(frame->width,frame->height),
//                                            IPL_DEPTH_8U, frame->nChannels );
// Делаем копию кадра, иначе может пропасть.
//            cvCopy( frame, frame_copy, 0 );
// Если стерли то что ниже - это надо раскомментировать
//*********************************************************
 
//*********************************************************
// Если не нужно подгонять размер кадра - это можно стереть
// Выделяем память под копию кадра
            if( !frame_copy )
                frame_copy = cvCreateImage( cvSize(640,480),
                                            IPL_DEPTH_8U, frame->nChannels );
// Масштабируем под заданный размер
cvResize( frame, frame_copy, CV_INTER_LINEAR );
// Если не нужно подгонять размер кадра - это можно стереть
//*********************************************************
// Выделяем память под серую копию кадра
            if( !gray )
                gray = cvCreateImage( cvSize(frame_copy->width,frame_copy->height),
                                            IPL_DEPTH_8U,1);
// Обработка полученного кадра
            ProcessFrame( frame_copy );
    }
skip:;
 
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormClose(TObject *Sender, TCloseAction &Action)
{
cvReleaseImage( &frame_copy );
cvReleaseImage( &gray );
cvReleaseCapture( &capture );
}
//---------------------------------------------------------------------------
void ProcessFrame( IplImage* Grab )
{
static CvMemStorage* storage = 0;
storage = cvCreateMemStorage(0);
CvMemStorage* storage_cd = cvCreateMemStorage(0);
cvCvtColor(Grab, gray, CV_BGR2GRAY);      // Получаем серый цвет
// Необходимо удалить белый бордюр
cvRectangle(gray, cvPoint(0,0), cvPoint(gray->width-1,gray->height-1),CV_RGB(0,0,0));
 
//---------------------------------------------------------------------------
//----------------------Поиск лица-------------------------------------------
    if( cascade )
    {
 
// Это собственоо главная функция
// параметры см. в документации
        CvSeq* faces = cvHaarDetectObjects( gray, cascade, storage,
                                            1.2, 2, 0
                                            |CV_HAAR_FIND_BIGGEST_OBJECT
                                            //|CV_HAAR_DO_ROUGH_SEARCH
                                            |CV_HAAR_DO_CANNY_PRUNING
                                            //|CV_HAAR_SCALE_IMAGE
                                             );
// Обводим все лица в кадре
 
        for(int i = 0; i < (faces ? faces->total : 0); i++ )
        {
            CvRect* r = (CvRect*)cvGetSeqElem( faces, i );
            CvMat gray_roi;
            CvPoint center;
            int radius;
//------------------------------------------------------
//----------------------Обработка области лица----------
//------------------------------------------------------
cvRectangle(Grab, cvPoint(r->x,r->y), cvPoint(r->x+r->width,r->y+r->height),CV_RGB(0,255,0));
        cvSetImageROI(gray,*r);
         //--- Определили прямоугольник лица
CvMat MV,MH;
double *VertSumS;
double *HorSumS;
 
VertSumS=new double[r->height];
HorSumS=new double[r->width];
 
cvInitMatHeader( &MV,r->height,1, CV_64FC1, VertSumS );
cvInitMatHeader( &MH,1,r->width,CV_64FC1, HorSumS );
 
cvReduce(gray, &MV,1,CV_REDUCE_AVG); // Среднее по строкам
cvReduce(gray, &MH,0,CV_REDUCE_AVG); // Среднее по столбцам
 
for (int i=0;i<r->height ;i++)
{
double v=cvGetReal2D(&MV,i,0)*0.5;
cvLine( Grab, cvPoint(r->x,r->y+i), cvPoint(r->x-v,r->y+i), CV_RGB(100,0,0), 1, 8 );
}
 
for (i=0;i<r->width ;i++)
{
double v=cvGetReal2D(&MH,0,i)*0.5;
cvLine( Grab, cvPoint(r->x+i,r->y), cvPoint(r->x+i,r->y-v), CV_RGB(0,100,0), 1, 8 );
}
 
delete [] VertSumS;
delete [] HorSumS;
//--- Сбросили прямоугольник лица
        cvResetImageROI(gray);
       }
    }
//----------------------Поиск лица-------------------------------------------
//---------------------------------------------------------------------------
 
 
APIDrawIpl(10,10,Grab,Form1->Handle);          // Рисуем результат
cvReleaseMemStorage(&storage);
}
 
Последние посты форума