📄 facialfeaturedlg.cpp
字号:
{
for(int j=RightEyeAre.y; j>RightEyeAre.y-nEyeWidth/4; j--)
{
if (m_tPixelOfRefBmpArray[j][i].rgbBlue == 255)
{
findcornerRr = true;
m_RightEyeRightCorner.x=i;
m_RightEyeRightCorner.y=j+2;
break;
}
}
if (findcornerRr) {m_bRightEyeRightCornerOK = TRUE; break;}
}
m_LeftEye = LeftEyeArea;
m_RightEye = RightEyeAre;
m_bLeftEyeOK = TRUE;
m_bRightEyeOK = TRUE;
CopyBitMap(m_tPixelOfRefBmpArray,m_tPixelOfOriBmpArray);
CreateBitMap();
}
void CFacialFeatureDlg::OnMouthCenter()
{
// 嘴巴特征的鉴别:1、色度空间;2、边缘信息
if (!m_bLeftEyeOK)
{
AfxMessageBox("Please detect eyes first!");
return;
}
//眼睛的倾斜角度
/*
double tanEye;
if (m_RightEye.y == m_LeftEye.y) tanEye = 0;
else tanEye = double((m_RightEye.y - m_LeftEye.y))/(m_RightEye.x - m_LeftEye.x);
*/
//双眼的距离
int EyesDis = (m_RightEye.x - m_LeftEye.x)*(m_RightEye.x - m_LeftEye.x);
EyesDis += (m_RightEye.y - m_LeftEye.y)*(m_RightEye.y - m_LeftEye.y);
EyesDis = (int)sqrt(EyesDis);
//可能的嘴巴水平区域在脸的下部1/4处,竖直区域在双眼之间
int MouthUp = m_rFaceArea.bottom - (m_rFaceArea.bottom - m_rFaceArea.top)/4;
int MouthDown = m_rFaceArea.bottom;
int MouthLeft = m_LeftEye.x;
int MouthRight = m_RightEye.x;
//嘴巴区域的颜色空间
SetPixelValArray(m_tPixelOfRefBmpArray,0);
yuvimg = cvCreateImage(cvSize(image->width,image->height),IPL_DEPTH_8U,1);
IplImage* temp = cvCreateImage(cvSize(image->width,image->height),IPL_DEPTH_8U,1);;
cvFlip(yuvimg,yuvimg,0);
BYTE* IplYuv = (BYTE*)yuvimg->imageData;
BYTE* IplTemp = (BYTE*)temp->imageData;
double nThreshold = 0.25;
bool mouthCornerOK = true;
bool mouthR = false;
bool mouthL = false;
BYTE R,G,B;
double tempcolor,delta;
while (mouthCornerOK)
{
for(int i=MouthUp; i<MouthDown; i++)
{
for(int j=MouthLeft; j<MouthRight; j++)
{
R = m_tPixelOfOriBmpArray[i][j].rgbRed;
G = m_tPixelOfOriBmpArray[i][j].rgbGreen;
B = m_tPixelOfOriBmpArray[i][j].rgbBlue;
if((R==G) && (G==B)) temp = 0;
else tempcolor = 0.5*(2*R-G-B)/sqrt((R-G)*(R-G) +(R-B)*(G-B));
delta = acos(tempcolor);
if (delta < nThreshold)
{
m_tPixelOfRefBmpArray[i][j].rgbRed = 255;
}
else m_tPixelOfRefBmpArray[i][j].rgbRed = 0;
}
}
//对已经获得的嘴唇区域进行腐蚀等操作,以去除毛刺
for(int row=0; row<m_nBmpHeigh; row++)
{
for(int col=0; col<m_nBmpWidth; col++)
IplYuv[col + row*m_nBmpWidth] = m_tPixelOfRefBmpArray[row][col].rgbRed;
}
//使用下面这两个函数有时候会引起问题,导致程序的终止
//原因可能是应为m_tPixelOfRefBmpArray[row][col].rgbRed均为0所导致的?
cvDilate(yuvimg,temp,0,2);//死机的地方之一
cvErode(yuvimg,temp, 0, 2); //
for(row=0; row<m_nBmpHeigh; row++)
{
for(int col=0; col<m_nBmpWidth; col++)
m_tPixelOfRefBmpArray[row][col].rgbRed = IplTemp[col + row*m_nBmpWidth];
}
//在嘴唇区域内搜索两个嘴角
//left mouth corner
for(int j=MouthLeft; j<MouthRight; j++)
{
for(i=MouthDown; i>MouthUp; i--)
{
if (m_tPixelOfRefBmpArray[i][j].rgbRed == 255)
{
m_LeftMouthCorner.x = j;
m_LeftMouthCorner.y = i;
mouthL = true;
break;
}
}
if (mouthL) break;
}
//right corner
for(j=MouthRight; j>MouthLeft; j--)
{
for(i=MouthDown; i>MouthUp; i--)
{
if (m_tPixelOfRefBmpArray[i][j].rgbRed == 255)
{
m_RightMouthCorner.x = j;
m_RightMouthCorner.y = i;
mouthR = true;
break;
}
}
if (mouthR) break;
}
//适应不同光照下的阈值调节
if (nThreshold>=0.2 && nThreshold<=0.5 && (m_RightMouthCorner.x - m_LeftMouthCorner.x)<(m_RightEye.x - m_LeftEye.x)*0.5)
{
nThreshold += 0.05;
mouthR = false;
mouthL = false;
}
else if (nThreshold>0 && nThreshold<=0.2 && (m_RightMouthCorner.x - m_LeftMouthCorner.x)>0.8*(m_RightEye.x - m_LeftEye.x))
{
nThreshold -= 0.05;
mouthR = false;
mouthL = false;
}
else mouthCornerOK = false;
}
if (mouthR && mouthL )
{
m_MidMouth.x = (m_LeftMouthCorner.x + m_RightMouthCorner.x)/2;
m_MidMouth.y = (m_LeftMouthCorner.y + m_RightMouthCorner.y)/2;
m_bLeftMouthCornerOK = TRUE;
m_bRightMouthCornerOK = TRUE;
//m_bMidMouthOK = TRUE;
}
else
{
AfxMessageBox("can't detect mouth features!");
return;
}
//修正数值4
m_LeftMouthCorner.y -= 4;
m_LeftMouthCorner.x -= 4;
m_RightMouthCorner.y -= 4;
m_RightMouthCorner.x += 4;
CopyBitMap(m_tPixelOfRefBmpArray,m_tPixelOfOriBmpArray);
CreateBitMap();
cvReleaseImage(&yuvimg);
cvReleaseImage(&temp);
}
void CFacialFeatureDlg::OnNoseCenter()
{
if (!m_bLeftEyeOK)
{
AfxMessageBox("Please detect eyes first!");
return;
}
//眼睛,嘴巴和鼻孔的倾斜角度
double tanEye,tanMouth,tanNose;
if (m_RightEye.y == m_LeftEye.y) tanEye = 0;
else tanEye = double((m_RightEye.y - m_LeftEye.y))/(m_RightEye.x - m_LeftEye.x);
if (m_RightMouthCorner.y == m_LeftMouthCorner.y) tanMouth = 0;
else tanMouth = double((m_RightMouthCorner.y - m_LeftMouthCorner.y))/(m_RightMouthCorner.x - m_LeftMouthCorner.x);
// 确定鼻子的水平区域在1/2和1/3之间, 竖直在两眼之间
int NoseUp = (m_rFaceArea.bottom + m_rFaceArea.top)/2 + m_nBmpWidth/30;
int NoseDown = m_rFaceArea.bottom - (m_rFaceArea.bottom - m_rFaceArea.top)/3+ m_nBmpWidth/30;
int NoseLeft = m_LeftMouthCorner.x;
int NoseRight = m_RightMouthCorner.x;
//鼻子区域的gray空间
SetPixelValArray(m_tPixelOfRefBmpArray,0);
double threshold = 100;
double Y;
bool findnose = false;
while (!findnose)
{
for(int i=NoseUp; i<NoseDown; i++)
{
for(int j=NoseLeft; j<NoseRight; j++)
{
Y = 0.30*m_tPixelOfOriBmpArray[i][j].rgbRed+0.59*m_tPixelOfOriBmpArray[i][j].rgbGreen
+0.11*m_tPixelOfOriBmpArray[i][j].rgbBlue;
m_tPixelOfRefBmpArray[i][j].rgbBlue = 0.30*m_tPixelOfOriBmpArray[i][j].rgbRed+0.59*m_tPixelOfOriBmpArray[i][j].rgbGreen
+0.11*m_tPixelOfOriBmpArray[i][j].rgbBlue;//用于后面的调整
if(Y<threshold)
{
m_tPixelOfRefBmpArray[i][j].rgbRed = 255;
}
else m_tPixelOfRefBmpArray[i][j].rgbRed = 0;
}
}
//left nosestrill
bool noseL = false;
for(int j=NoseLeft; j<(m_LeftMouthCorner.x + m_RightMouthCorner.x)/2; j++)
{
for(i=NoseDown; i>NoseUp; i--)
{
if (m_tPixelOfRefBmpArray[i][j].rgbRed == 255)
{
m_LeftNostril.x = j;
m_LeftNostril.y = i;
noseL = true;
break;
}
}
if (noseL) break;
}
// right nostrill
bool noseR = false;
for(j=NoseRight; j>(m_LeftMouthCorner.x + m_RightMouthCorner.x)/2; j--)
{
for(i=NoseDown; i>NoseUp; i--)
{
if (m_tPixelOfRefBmpArray[i][j].rgbRed == 255)
{
m_RightNostril.x = j;
m_RightNostril.y = i;
noseR = true;
break;
}
}
if(noseR) break;
}
//only find left nostrill
if (noseL && !noseR)
{
m_RightNostril.y = m_LeftNostril.y;
m_RightNostril.x = m_LeftNostril.x + 0.6*(m_RightMouthCorner.x - m_LeftMouthCorner.x);
noseR = true;
findnose = true;
}
//only find right nostrill
if (noseR && !noseL)
{
m_LeftNostril.y = m_RightNostril.y;
m_LeftNostril.x = m_RightNostril.x - 0.6*(m_RightMouthCorner.x - m_LeftMouthCorner.x);
noseL = true;
findnose = true;
}
//both are not found
if (!noseR && !noseL)
{
threshold += 20;//调整阈值
// AfxMessageBox("cannt find nose feature, please try the other method!");
// return;
}
if (noseL && noseR)
{
if (m_RightNostril.y == m_LeftNostril.y) tanNose = 0;
else tanNose = double((m_RightNostril.y - m_LeftNostril.y))/(m_RightNostril.x - m_LeftNostril.x);
//修正鼻孔定的过于倾斜
if (fabs(tanNose - tanEye)>=0.1)
{
if (double(m_LeftMouthCorner.y - m_LeftNostril.y)/(m_LeftMouthCorner.y-m_LeftEye.y)<0.2
|| double(m_LeftNostril.y-m_LeftEye.y)/(m_LeftMouthCorner.y-m_LeftEye.y)<0.3)
{
m_LeftNostril.y = m_RightNostril.y;
m_LeftNostril.x = m_RightNostril.x - 0.6*(m_RightMouthCorner.x - m_LeftMouthCorner.x);
}
else if (double(m_RightMouthCorner.y - m_RightNostril.y)/(m_RightMouthCorner.y-m_RightEye.y)<0.2
|| double(m_RightNostril.y-m_RightEye.y)/(m_RightMouthCorner.y-m_RightEye.y)<0.3)
{
m_RightNostril.y = m_LeftNostril.y;
m_RightNostril.x = m_LeftNostril.x + 0.6*(m_RightMouthCorner.x - m_LeftMouthCorner.x);
}
else if ((m_RightMouthCorner.y - m_RightNostril.y)<(m_LeftMouthCorner.y - m_LeftNostril.y))
{
m_LeftNostril.y = m_RightNostril.y;
m_LeftNostril.x = m_RightNostril.x - 0.6*(m_RightMouthCorner.x - m_LeftMouthCorner.x);
}
else if ((m_RightMouthCorner.y - m_RightNostril.y)<(m_LeftMouthCorner.y - m_LeftNostril.y))
{
m_LeftNostril.y = m_RightNostril.y;
m_LeftNostril.x = m_RightNostril.x - 0.6*(m_RightMouthCorner.x - m_LeftMouthCorner.x);
}
}
m_bLeftNostrilOK = TRUE;
m_bRightNostrilOK = TRUE;
findnose = true;
}
}
//一般而言,鼻孔的位置会定在外边缘,向里可能5象素调整
double sumL1 = 0, sumR1 = 0, sumL2 = 0, sumR2 = 0;
for(int i=-3; i<=3; i++)
{
for(int j=-3; j<=3;j++)
{
sumL1 += m_tPixelOfRefBmpArray[m_LeftNostril.y+i][m_LeftNostril.x+j].rgbBlue;
sumL2 += m_tPixelOfRefBmpArray[m_RightNostril.y+i][m_RightNostril.x+j].rgbBlue;
sumR1 += m_tPixelOfRefBmpArray[m_LeftNostril.y+i][m_LeftNostril.x + 5 + j].rgbBlue;
sumR2 += m_tPixelOfRefBmpArray[m_RightNostril.y+i][m_RightNostril.x + 5 + j].rgbBlue;
}
}
if (sumL2<sumL1) m_LeftNostril.x += 5;
if (sumR2<sumR1) m_RightNostril.x -= 5;
//调整在人脸偏转情况下,定位在同一个鼻孔
if ((m_RightNostril.x - m_LeftNostril.x)<=18 )
{
if ((m_RightMouthCorner.x-(m_RightNostril.x-m_LeftNostril.x)/2)>(m_LeftNostril.x-(m_RightNostril.x-m_LeftNostril.x)/2))
m_LeftNostril.x = m_RightNostril.x - 0.6*(m_RightMouthCorner.x - m_LeftMouthCorner.x);
else
m_RightNostril.x = m_LeftNostril.x + 0.6*(m_RightMouthCorner.x - m_LeftMouthCorner.x);
}
//对于基本正面的图像,鼻孔的距离眼睛的高度大于距离嘴巴的高度
//一下属于强制措施,可以考虑改进
if ((double(m_LeftMouthCorner.y - m_LeftNostril.y)/(m_LeftMouthCorner.y-m_LeftEye.y)<0.2)
&& (double(m_RightMouthCorner.y - m_RightNostril.y)/(m_RightMouthCorner.y-m_RightEye.y)<0.2))
{
m_LeftNostril.x = m_LeftMouthCorner.x + 0.2*(m_RightNostril.x - m_LeftNostril.x);
m_LeftNostril.y = m_LeftMouthCorner.y - (m_LeftMouthCorner.y - m_LeftEye.y)/3;
m_RightNostril.x = m_RightNostril.x - 0.2*(m_RightNostril.x - m_LeftNostril.x);
m_RightNostril.y = m_LeftNostril.y;
}
if ((m_LeftMouthCorner.y - m_LeftNostril.y)>(m_LeftNostril.y-m_LeftEye.y)
&& (m_RightMouthCorner.y - m_RightNostril.y)>(m_RightNostril.y-m_RightEye.y))
{
m_LeftNostril.x = m_LeftMouthCorner.x + 0.2*(m_RightNostril.x - m_LeftNostril.x);
m_LeftNostril.y = m_LeftMouthCorner.y - (m_LeftMouthCorner.y - m_LeftEye.y)/3;
m_RightNostril.x = m_RightNostril.x - 0.2*(m_RightNostril.x - m_LeftNostril.x);
m_RightNostril.y = m_LeftNostril.y;
}
CopyBitMap(m_tPixelOfRefBmpArray,m_tPixelOfOriBmpArray);
CreateBitMap();
cvReleaseImage(&image);
cvReleaseImage(&grayimg);
cvReleaseImage(&edgeimg);
}
void CFacialFeatureDlg::LightCompensation()
{
//对图像进行亮度gamma校正
int sumWhitePixel = 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -