📄 facialfeaturedlg.cpp
字号:
return true;
}
void CFacialFeatureDlg::SetPixelValArray(RGBQUAD** target,int val)
{
for (int i=0; i<m_nBmpHeigh; i++)
for (int j=0; j<m_nBmpWidth; j++)
{
target[i][j].rgbBlue = val;
target[i][j].rgbGreen = val;
target[i][j].rgbRed = val;
}
}
void CFacialFeatureDlg::DrawCross(CDC *pDC, CPoint point, COLORREF crColor)
{
CPen pen,*oldPen;
pen.CreatePen(PS_SOLID,1,crColor);
oldPen = (CPen*)pDC->SelectObject(&pen);
pDC->MoveTo(point.x-7,point.y);
pDC->LineTo(point.x+7,point.y);
pDC->MoveTo(point.x,point.y-7);
pDC->LineTo(point.x,point.y+7);
pDC->SelectObject(oldPen);
pen.DeleteObject();
}
void CFacialFeatureDlg::OnFaceDetect()
{
// TODO: Add your control notification handler code here
LightCompensation();
ConverFromDib();
CvCapture* capture = 0;
CvHaarClassifierCascade* cascade =
cvLoadHaarClassifierCascade("<default_face_cascade>",
cvSize(ORIG_WIN_SIZE, ORIG_WIN_SIZE));
hid_cascade = cvCreateHidHaarClassifierCascade(cascade, 0, 0, 0, 1);
cvReleaseHaarClassifierCascade(&cascade);
storage = cvCreateMemStorage(0);
// IplImage* image = pDoc->m_Image->GetImage();
IplImage* temp = cvCreateImage(cvSize(image->width/2,image->height/2), 8, 3);
if(image)
{
cvFlip(image, image, 0);
image->origin = IPL_ORIGIN_BL;
int scale = 2;
CvPoint pt1, pt2;
cvPyrDown(image, temp, CV_GAUSSIAN_5x5 );
#ifdef WIN32
cvFlip(temp, temp, 0 );
#endif
cvClearMemStorage(storage);
if(hid_cascade)
{
CvSeq* faces = cvHaarDetectObjects( temp, hid_cascade, storage,
1.2, 2, CV_HAAR_DO_CANNY_PRUNING );
for(int i = 0; i < (faces ? faces->total : 0); i++ )
{
CvRect* r = (CvRect*)cvGetSeqElem( faces, i, 0 );
pt1.x = r->x * scale;
pt2.x = (r->x+r->width) * scale;
#ifdef WIN32
pt1.y = image->height - r->y * scale;
pt2.y = image->height - (r->y+r->height) * scale;
#else
pt1.y = r->y*scale;
pt2.y = (r->y+r->height) * scale;
#endif
//////////////////////////////////////////////////////////////////////////
// Display the faces in the image
{
CvRect region;
region.x = pt1.x;
region.y = r->y*scale;
region.width = r->width * scale;
region.height = r->height * scale;
///zzl
m_rFaceArea.top = pt1.y;
m_rFaceArea.bottom = pt2.y;
m_rFaceArea.left = pt1.x;
m_rFaceArea.right = pt2.x;
cvFlip(image, image, 0);
image->origin = IPL_ORIGIN_TL;
cvSetImageROI(image, region);
IplImage* image1 = cvCreateImage(cvSize(r->width*scale,
r->height*scale), image->depth, image->nChannels);
cvCopy(image, image1);
cvResetImageROI(image);
// cvNamedWindow("face", 1);
// cvShowImage("face", image1);
cvWaitKey(0);
cvDestroyWindow("face");
cvReleaseImage(&image1);
// Invalidate();
cvFlip(image, image, 0);
image->origin = IPL_ORIGIN_BL;
}
//////////////////////////////////////////////////////////////////////////
// cvRectangle( image, pt1, pt2, CV_RGB(255,255,0), 3 );
}
}
cvReleaseImage( &temp );
int top,bottom,left,right,nFaceWidth;
nFaceWidth = m_rFaceArea.right - m_rFaceArea.left;
top = m_nBmpHeigh - m_rFaceArea.top;
bottom = m_nBmpHeigh - m_rFaceArea.bottom;
left = m_rFaceArea.left + nFaceWidth/8;
right = m_rFaceArea.right - nFaceWidth/8;
m_rAdaFaceArea = CRect(left-nFaceWidth/8,top,right+nFaceWidth/8,bottom);
/*
for (int i=top; i<=bottom; i++)
{
m_tPixelOfRefBmpArray[i][left].rgbBlue = 0;
m_tPixelOfRefBmpArray[i][left].rgbGreen = 0;
m_tPixelOfRefBmpArray[i][left].rgbRed = 0;
m_tPixelOfRefBmpArray[i][right].rgbBlue = 0;
m_tPixelOfRefBmpArray[i][right].rgbGreen = 0;
m_tPixelOfRefBmpArray[i][right].rgbRed = 0;
m_tPixelOfRefBmpArray[i][(int)((m_rFaceArea.left +m_rFaceArea.right)/2)].rgbBlue = 0;
}
*/
/* for (j=left; j<=right; j++)
{
m_tPixelOfRefBmpArray[top - 5][j].rgbBlue = 0;
m_tPixelOfRefBmpArray[top - 5][j].rgbGreen = 0;
m_tPixelOfRefBmpArray[top - 5][j].rgbRed = 0;
m_tPixelOfRefBmpArray[bottom][j].rgbBlue = 0;
m_tPixelOfRefBmpArray[bottom][j].rgbGreen = 0;
m_tPixelOfRefBmpArray[bottom][j].rgbRed = 0;
// m_tPixelOfRefBmpArray[(int)(2*(m_rFaceArea.bottom - m_rFaceArea.top)/3) + m_rFaceArea.top][j].rgbRed = 0;
// m_tPixelOfRefBmpArray[(int)((m_rFaceArea.bottom - m_rFaceArea.top)/3) + m_rFaceArea.top][j].rgbGreen = 0;
}
*/
//重新调整脸部区域的参数,方便进行特征的检测与定位
CRect rect(left,top,right,bottom);
m_rFaceArea = rect;
m_bFaceOK = true;
m_bShowFace = true;
CreateBitMap();
}
// Invalidate();
}
void CFacialFeatureDlg::ConverFromDib()
{
CvSize ImgSize;
ImgSize.width = m_nBmpWidth;
ImgSize.height = m_nBmpHeigh;
image = cvCreateImage(ImgSize, IPL_DEPTH_8U, 3);
BYTE* IplImg = (BYTE*)(image->imageData);
for(int i = 0; i < m_nBmpHeigh; i++)
for(int j = 0; j < m_nBmpWidth; j++)
{
IplImg[3*(j + i*m_nBmpWidth)] = m_tPixelOfRefBmpArray[i][j].rgbBlue;
IplImg[3*(j + i*m_nBmpWidth) + 1] = m_tPixelOfRefBmpArray[i][j].rgbGreen;
IplImg[3*(j + i*m_nBmpWidth) + 2] = m_tPixelOfRefBmpArray[i][j].rgbRed;
}
}
void CFacialFeatureDlg::OnEyeCenter()
{
// TODO: Add your control notification handler code here
if (!(m_bFaceOK && m_bShowFace)) {
AfxMessageBox("Please detect face first!");
return;
}
int top,bottom,left,right,nFaceWidth;
nFaceWidth = m_rFaceArea.right - m_rFaceArea.left;
top = m_nBmpHeigh - m_rFaceArea.top;
bottom = m_nBmpHeigh - m_rFaceArea.bottom;
left = m_rFaceArea.left + nFaceWidth/8;
right = m_rFaceArea.right - nFaceWidth/8;
CPoint LeftEyeArea(-1,-1), RightEyeAre(-1,-1);
//人脸区域参数的进一步细化
int nLeft,nRight,nTop,nBottom;
nLeft = m_rFaceArea.left + 2;
nRight = m_rFaceArea.right - 2;
nBottom = m_rFaceArea.bottom -2;
nTop = m_rFaceArea.top + 2;
//眼睛参数的大致估计:三庭五眼
int nEyeWidth = 0.28*(nRight - nLeft);//0.28是一个经验数值,可以修改
int nEyeHeigh = nEyeWidth/3;
int nFaceCerH = (m_rFaceArea.right + m_rFaceArea.left)/2;
int nFaceCerV = (m_rFaceArea.bottom + m_rFaceArea.top)/2;
SetPixelValArray(m_tPixelOfRefBmpArray, 0);
//将人脸区域转换为灰度
for(int i=nTop; i<nBottom; i++)
{
for(int j=nLeft; j<nRight; j++)
{
m_tPixelOfRefBmpArray[i][j].rgbBlue = (unsigned char)(0.2989*m_tPixelOfOriBmpArray[i][j].rgbRed
+ 0.5870*m_tPixelOfOriBmpArray[i][j].rgbGreen
+ 0.1140*m_tPixelOfOriBmpArray[i][j].rgbBlue);
}
}
//在水平区域的1/2到1/3处、nLeft到face中线区域计算9×9区域的象素均值
//lefteye
int regionH = m_rFaceArea.top + (m_rFaceArea.bottom - m_rFaceArea.top)/3;
double Lcomval = 255.0;
for(int row=regionH+4; row<nFaceCerV-4; row++)
{
for(int col=nLeft+(nRight-nLeft)/8; col<nFaceCerH-(nRight-nLeft)/8; col++)
{
double meanpixel = 0;
for(int p=-4; p<=4; p++)
{
for(int q=-4;q<=4;q++)
{
meanpixel += m_tPixelOfRefBmpArray[row+p][col+q].rgbBlue;
}
}
meanpixel = meanpixel/81;
if (meanpixel<Lcomval)
{
Lcomval = meanpixel;
LeftEyeArea.x = col;
LeftEyeArea.y = row;
}
}
}
// righteye
double Rcomval = 255.0;
for(row=regionH+4; row<nFaceCerV-4; row++)
{
for(int col=nFaceCerH+(nRight-nLeft)/8; col<nRight-(nRight-nLeft)/8; col++)
{
double meanpixel = 0;
for(int p=-4; p<=4; p++)
{
for(int q=-4;q<=4;q++)
{
meanpixel += m_tPixelOfRefBmpArray[row+p][col+q].rgbBlue;
}
}
meanpixel = meanpixel/81;
if (meanpixel<Rcomval)
{
Rcomval = meanpixel;
RightEyeAre.x = col;
RightEyeAre.y = row;
}
}
}
//to detect eyecorners using canny
grayimg = cvCreateImage(cvSize(image->width,image->height), IPL_DEPTH_8U,1);
edgeimg = cvCreateImage(cvSize(image->width,image->height), IPL_DEPTH_8U, 1);
cvCvtColor(image,grayimg,CV_BGR2GRAY);
cvCanny(grayimg,edgeimg,0,128,3);//0,128是经验值,程序死掉的地方之一
cvFlip(edgeimg,edgeimg,0);
BYTE* IplEdge = (BYTE*)edgeimg->imageData;
SetPixelValArray(m_tPixelOfRefBmpArray,0);
float zzl = 0;
for(i=0; i<m_nBmpHeigh; i++)
{
for(INT j=0; j<m_nBmpWidth; j++)
m_tPixelOfRefBmpArray[i][j].rgbBlue = IplEdge[j + i*m_nBmpWidth];
}
//搜索角点
//左眼右眼角
bool findcornerLr = false;
// for(i=LeftEyeArea.x+nEyeWidth/2-2; i>LeftEyeArea.x-nEyeWidth/2; i--)
for(i=LeftEyeArea.x+1.1*nEyeHeigh; i>LeftEyeArea.x+nEyeHeigh/2; i--)
{
for(int j=LeftEyeArea.y+nEyeWidth/4; j>LeftEyeArea.y; j--)
{
if (m_tPixelOfRefBmpArray[j][i].rgbBlue == 255)
{
findcornerLr = true;
m_LeftEyeRightCorner.x=i;
m_LeftEyeRightCorner.y=j;
break;
}
}
if (findcornerLr) {m_bLeftEyeRightCornerOK = TRUE; break;}
}
//左眼左眼角
bool findcornerLl = false;
// for(i=LeftEyeArea.x-nEyeWidth/2+5; i<LeftEyeArea.x+nEyeWidth/2; i++)
for(i=LeftEyeArea.x-1.1*nEyeHeigh; i<LeftEyeArea.x+nEyeHeigh/2; i++)
{
for(int j=LeftEyeArea.y; j>LeftEyeArea.y-nEyeWidth/4; j--)
{
if (m_tPixelOfRefBmpArray[j][i].rgbBlue == 255)
{
findcornerLl = true;
m_LeftEyeLeftCorner.x=i;
m_LeftEyeLeftCorner.y=j+2;//2是一个经验值
break;
}
}
if (findcornerLl) {m_bLeftEyeLeftCornerOK = TRUE; break;}
}
//右眼左眼角
bool findcornerRl = false;
// for(i=RightEyeAre.x-nEyeWidth/2+2; i<RightEyeAre.x+nEyeWidth/2; i++)
for(i=RightEyeAre.x-1.1*nEyeHeigh; i<RightEyeAre.x-nEyeHeigh/2; i++)
{
for(int j=RightEyeAre.y+nEyeWidth/4; j>RightEyeAre.y; j--)
{
if (m_tPixelOfRefBmpArray[j][i].rgbBlue == 255)
{
findcornerRl = true;
m_RightEyeLeftCorner.x=i;
m_RightEyeLeftCorner.y=j;
break;
}
}
if (findcornerRl) {m_bRightEyeLeftCornerOK = TRUE; break;}
}
//右眼右眼角
bool findcornerRr = false;
// for(i=RightEyeAre.x+nEyeWidth/2-2; i>RightEyeAre.x-nEyeWidth/2; i--)
for(i=RightEyeAre.x+1.1*nEyeHeigh; i>RightEyeAre.x-nEyeHeigh/2; i--)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -