?? facedetectiondoc.cpp
字號:
eye1count++;
//把當(dāng)前點(diǎn)改成白色
*(lpData + lOffset++) = 255;
*(lpData + lOffset++) = 255;
*(lpData + lOffset++) = 255;
}
//如果當(dāng)前象素的數(shù)值為2
else if(*(lpData + lOffset) == 2)
{
//眼睛2的橫坐標(biāo)和縱坐標(biāo)加上當(dāng)前點(diǎn)的坐標(biāo)值
eye2.x +=j;
eye2.y +=i;
//象素點(diǎn)個(gè)數(shù)加一
eye2count++;
//把當(dāng)前點(diǎn)設(shè)置為白色
*(lpData + lOffset++) = 255;
*(lpData + lOffset++) = 255;
*(lpData + lOffset++) = 255;
}
}
//計(jì)算眼睛的中心點(diǎn)坐標(biāo)
eye1.x /=eye1count;
eye1.y /=eye1count;
eye2.x /=eye2count;
eye2.y /=eye2count;
//把中心點(diǎn)設(shè)置為綠色
lOffset = eye1.y*wBytesPerLine + eye1.x*3;
*(lpData + lOffset++) = 0;
*(lpData + lOffset++) = 255;
*(lpData + lOffset++) = 0;
lOffset = eye2.y*wBytesPerLine + eye2.x*3;
*(lpData + lOffset++) = 0;
*(lpData + lOffset++) = 255;
*(lpData + lOffset++) = 0;
::GlobalUnlock((HGLOBAL) m_hDIB);
}
void CFaceDetectionDoc::FunctionMouseMap(LPBYTE lpRgb, const LPBYTE lpYcc, WORD wBytesPerLine, CRect faceLocation)
{
//下面的循環(huán)在人臉的區(qū)域內(nèi)實(shí)現(xiàn)嘴巴的匹配
for (int i=faceLocation.top; i<faceLocation.bottom; i++)
for (int j=faceLocation.left; j<faceLocation.right; j++)
{
//得到偏移
long lOffset = i*wBytesPerLine + j*3;
//得到cr,cb的數(shù)值
int cr = *(lpYcc+lOffset+1);
int cb = *(lpYcc+lOffset+2);
//標(biāo)志
bool lab;
int mapm;
//根據(jù)cr的數(shù)值設(shè)定標(biāo)志
cr = cr-157;//143;
if(cr <-6 || cr>6)
{
cr = 0;
}
cr *=cr;
if(cr>16)
lab = true;
else
lab = false;
//根據(jù)cb的時(shí)值設(shè)定標(biāo)志
cb= cb-118;//120;
if(cb<-5 || cb >5)
{
cb = 0;
if(lab = true)
lab = false;
}
//如果cr,cb兩項(xiàng)數(shù)值都在設(shè)定的范圍之內(nèi),則設(shè)定顏色位白色,否則黑色
if(lab)
mapm = 255;
else
mapm = 0;
*(lpRgb + lOffset++) = mapm;
*(lpRgb + lOffset++) = mapm;
*(lpRgb + lOffset++) = mapm;
}
}
void CFaceDetectionDoc::MouseMap()
{
LPBYTE lpYcc2;
LPBITMAPINFOHEADER lpbi;
lpbi = (LPBITMAPINFOHEADER)::GlobalLock((HGLOBAL) m_hDIB);//讀取頭文件
lLineBytesMulspec = WIDTHBYTES((lpbi->biWidth)*24);
::GlobalUnlock((HGLOBAL) m_hDIB);
int width,height;
long wBytesPerLine;
LPSTR lpDIB = (LPSTR) ::GlobalLock((HGLOBAL) m_hDIB);
// 獲取DIB寬度
width= (int) ::DIBWidth(lpDIB);
// 獲取DIB高度
height= (int) ::DIBHeight(lpDIB);
//得到圖片每行的象素所占字節(jié)個(gè)數(shù)
wBytesPerLine = lLineBytesMulspec;
LPBYTE lpData;
long lOffset;
lpData = (unsigned char*)::FindDIBBits(lpDIB);
lpYcc2 = new BYTE[wBytesPerLine * height];
RgbtoYcb(m_hDIBtemp,lpYcc2);
FunctionMouseMap(lpData,lpYcc2,wBytesPerLine,CRect(0,0,width-1,height-1));
::GlobalUnlock((HGLOBAL) m_hDIB);
}
void CFaceDetectionDoc::DeleteScatePoint()
{
LPBITMAPINFOHEADER lpbi;
lpbi = (LPBITMAPINFOHEADER)::GlobalLock((HGLOBAL) m_hDIB);//讀取頭文件
lLineBytesMulspec = WIDTHBYTES((lpbi->biWidth)*24);
::GlobalUnlock((HGLOBAL) m_hDIB);
int width,height;
long wBytesPerLine;
LPSTR lpDIB = (LPSTR) ::GlobalLock((HGLOBAL) m_hDIB);
// 獲取DIB寬度
width= (int) ::DIBWidth(lpDIB);
// 獲取DIB高度
height= (int) ::DIBHeight(lpDIB);
//得到圖片每行的象素所占字節(jié)個(gè)數(shù)
wBytesPerLine = lLineBytesMulspec;
LPBYTE lpData;
long lOffset;
lpData = (unsigned char*)::FindDIBBits(lpDIB);
for (int i=0; i<height; i++)
for(int j=0; j<width; j++)
{
//得到偏移
lOffset =i*wBytesPerLine + j*3;
//如果當(dāng)前點(diǎn)為白色點(diǎn)
if(*(lpData + lOffset) == 255)
{
//設(shè)定判斷數(shù)組
for(int ii = 0;ii<ImgRange;ii++)
for (int jj=0; jj<ImgRange; jj++)
this->lab[ii][jj] = false;
//設(shè)定判斷長度
lenth=0;
//判斷是否為離散點(diǎn)
bool judge = IsScaterPoint(j, i, width,height,lpData,wBytesPerLine,3,lab);
if(!judge)
{
//是離散點(diǎn)則把該點(diǎn)設(shè)置為黑色
*(lpData + lOffset++) = 0;
*(lpData + lOffset++) = 0;
*(lpData + lOffset++) = 0;
}
}
}
::GlobalUnlock((HGLOBAL) m_hDIB);
}
BOOL CFaceDetectionDoc::IsScaterPoint(int x, int y, int width, int height, LPBYTE lpData,WORD wBytesPerLine, int threshold,bool lab[m_HEIGHT][m_WIDTH])
{
long lOffset;
//得到數(shù)據(jù)的偏移
lOffset = y*wBytesPerLine + x*3;
//判斷該點(diǎn)是否為白色以及是否計(jì)算過了
if(*(lpData+lOffset) == 255 && lab[y][x] == false)
{
//鏈長度加一
lenth++;
//更改標(biāo)志位
lab[y][x] = true;
//如果鏈長度達(dá)到臨界值則返回真
if(lenth >= threshold)
return true;
//對右邊點(diǎn)的邊界判斷以及標(biāo)志位判斷
if(x+1<width && lab[y][x+1] == false)
{
//遞歸調(diào)用本函數(shù),對右邊的點(diǎn)進(jìn)行判斷
IsScaterPoint(x+1,y,width,height,lpData,wBytesPerLine,threshold,lab);
if(lenth>=threshold)
return true;
}
//處理左邊的點(diǎn)
if(x-1>=0 && lab[y][x-1] == false)
{
(IsScaterPoint(x-1,y,width,height,lpData,wBytesPerLine,threshold,lab));
if(lenth>=threshold)
return true;
}
//處理上面的點(diǎn)
if(y-1>=0 && lab[y-1][x]==false)
{
(IsScaterPoint(x,y-1,width,height,lpData,wBytesPerLine,threshold,lab));
if(lenth>=threshold)
return true;
}
//處理下面的點(diǎn)
if(y+1<height && lab[y+1][x]==false)
{ (IsScaterPoint(x,y+1,width,height,lpData,wBytesPerLine,threshold,lab));
if(lenth>=threshold)
return true;
}
//處理右下的點(diǎn)
if(y+1<height && x+1 <width && lab[y+1][x+1]==false)
{ (IsScaterPoint(x+1,y+1,width,height,lpData,wBytesPerLine,threshold,lab));
if(lenth>=threshold)
return true;
}
//處理左下的點(diǎn)
if(y+1<height && x-1 >=0 && lab[y+1][x-1]==false)
{ (IsScaterPoint(x-1,y+1,width,height,lpData,wBytesPerLine,threshold,lab));
if(lenth>=threshold)
return true;
}
//處理左上的點(diǎn)
if(y-1>=0 && x-1 >=0 &&lab[y-1][x-1]==false)
{ (IsScaterPoint(x-1,y-1,width,height,lpData,wBytesPerLine,threshold,lab));
if(lenth>=threshold)
return true;
}
//處理右上的點(diǎn)
if(y-1<height && x+1<width && lab[y+1][x]==false)
{ (IsScaterPoint(x+1,y-1,width,height,lpData,wBytesPerLine,threshold,lab));
if(lenth>=threshold)
return true;
}
}
//如果遞歸結(jié)束,長度達(dá)不到臨界值,返回假
return false;
}
void CFaceDetectionDoc::MouthCenter(CPoint &mouthLocation)
{
LPBITMAPINFOHEADER lpbi;
lpbi = (LPBITMAPINFOHEADER)::GlobalLock((HGLOBAL) m_hDIB);//讀取頭文件
lLineBytesMulspec = WIDTHBYTES((lpbi->biWidth)*24);
::GlobalUnlock((HGLOBAL) m_hDIB);
int width,height;
long wBytesPerLine;
LPSTR lpDIB = (LPSTR) ::GlobalLock((HGLOBAL) m_hDIB);
// 獲取DIB寬度
width= (int) ::DIBWidth(lpDIB);
// 獲取DIB高度
height= (int) ::DIBHeight(lpDIB);
//得到圖片每行的象素所占字節(jié)個(gè)數(shù)
wBytesPerLine = lLineBytesMulspec;
LPBYTE lpData;
long lOffset;
lpData = (unsigned char*)::FindDIBBits(lpDIB);
//下面的三個(gè)變量用來累計(jì)嘴巴區(qū)域的象素的x,y和象素點(diǎn)數(shù)
int xnum = 0 ;
int ynum = 0 ;
int count = 0;
CRect faceLocation(0,0,width-1,height-1);
for (int i=faceLocation.top; i<faceLocation.bottom; i++)
for (int j=faceLocation.left; j<faceLocation.right; j++)
{
lOffset = i*wBytesPerLine + j*3;
//白色點(diǎn)
if(*(lpData + lOffset) == 255)
{
//x值加
xnum +=j;
//y值加
ynum +=i;
//點(diǎn)數(shù)加
count++;
}
}
//得到中心點(diǎn)位置
mouthLocation.x = xnum/count;
mouthLocation.y = ynum/count;
//把中心點(diǎn)設(shè)置位綠色
lOffset = mouthLocation.y*wBytesPerLine + mouthLocation.x*3;
*(lpData + lOffset++) =0;
*(lpData + lOffset++) =255;
*(lpData + lOffset++) =0;
::GlobalUnlock((HGLOBAL) m_hDIB);
}
void CFaceDetectionDoc::EllipseFace(CPoint mouth, CPoint eye1, CPoint eye2,CRect faceLocation)
{
LPBITMAPINFOHEADER lpbi;
lpbi = (LPBITMAPINFOHEADER)::GlobalLock((HGLOBAL) m_hDIBtemp);//讀取頭文件
lLineBytesMulspec = WIDTHBYTES((lpbi->biWidth)*24);
::GlobalUnlock((HGLOBAL) m_hDIBtemp);
int width,height;
long wBytesPerLine;
LPSTR lpDIB = (LPSTR) ::GlobalLock((HGLOBAL) m_hDIBtemp);
// 獲取DIB寬度
width= (int) ::DIBWidth(lpDIB);
// 獲取DIB高度
height= (int) ::DIBHeight(lpDIB);
//得到圖片每行的象素所占字節(jié)個(gè)數(shù)
wBytesPerLine = lLineBytesMulspec;
LPBYTE lpData;
long lOffset;
lpData = (unsigned char*)::FindDIBBits(lpDIB);
//用dda算法畫三角形
DdaLine(mouth,eye1,lpData,wBytesPerLine);
DdaLine(mouth,eye2,lpData,wBytesPerLine);
DdaLine(eye1,eye2,lpData,wBytesPerLine);
/*
//橢圓的中心點(diǎn)和兩個(gè)焦點(diǎn)坐標(biāo)
int ellipsecenter_x;
int ellipsecenter_y;
int ellipseFocusTop_x;
int ellipseFocusTop_y;
int ellipseFocusBottom_x;
int ellipseFocusBottom_y;
//根據(jù)眼睛和嘴巴的坐標(biāo)計(jì)算橢圓的中心點(diǎn)坐標(biāo)
ellipsecenter_x = (eye1.x + eye2.x + mouth.x )/3;
ellipsecenter_y = (eye1.y + eye2.y)/2 -abs(eye2.x - eye1.x)/2;
//上面的焦點(diǎn)
ellipseFocusTop_x = ellipsecenter_x;
ellipseFocusBottom_x = ellipsecenter_x;
//下面的焦點(diǎn)
ellipseFocusTop_y = ellipsecenter_y + (eye1.y +eye2.y)/2 -mouth.y;
ellipseFocusBottom_y = ellipsecenter_y - ((eye1.y +eye2.y)/2 -mouth.y)+2;
//長軸
int a = (eye1.x-eye2.x)*2-2;
for (int i=0; i<height; i++)
for (int j=0; j<width; j++)
{
//得到一個(gè)點(diǎn)到兩個(gè)焦點(diǎn)的距離和
int lenth = sqrt(pow(j-ellipseFocusTop_x,2)+pow(i-ellipseFocusTop_y,2))
+sqrt(pow(j-ellipseFocusBottom_x,2)+ pow(i-ellipseFocusBottom_y,2));
//判斷距離和與長軸的關(guān)系
if(lenth<2*a+2 && lenth >2*a-2)
{
//把點(diǎn)設(shè)置為綠色
lOffset =i*wBytesPerLine + j*3;
*(lpData + lOffset++) = 0;
*(lpData + lOffset++) = 255;
*(lpData + lOffset++) = 0;
}
}*/
for (int j=faceLocation[0].top; j<faceLocation[0].bottom; j++)
{
//把得到的人臉區(qū)域用綠色矩形標(biāo)注,處理豎直的兩條邊
lOffset = j*wBytesPerLine + faceLocation[0].left*3;
*(lpData + lOffset++) = 0;
*(lpData + lOffset++) = 255;
*(lpData + lOffset++) = 0;
lOffset = j*wBytesPerLine + faceLocation[0].right*3;
*(lpData + lOffset++) = 0;
*(lpData + lOffset++) = 255;
*(lpData + lOffset++) = 0;
}
for (j=faceLocation[0].left; j<faceLocation[0].right; j++)
{
//處理水平的兩天矩形邊
lOffset = faceLocation[0].top*wBytesPerLine + j*3;
*(lpData + lOffset++) = 0;
*(lpData + lOffset++) = 255;
*(lpData + lOffset++) = 0;
lOffset = faceLocation[0].bottom*wBytesPerLine + j*3;
*(lpData + lOffset++) = 0;
*(lpData + lOffset++) = 255;
*(lpData + lOffset++) = 0;
}
::GlobalUnlock((HGLOBAL) m_hDIBtemp);
m_hDIB = (HDIB)CopyHandle(m_hDIBtemp);
}
void CFaceDetectionDoc::DdaLine(CPoint from, CPoint end, LPBYTE lpData, WORD wBytesPerLine)
{
//x,y的增量
float delta_x;
float delta_y;
//x,y的坐標(biāo)
float x;
float y;
//x,y上的差值
int dx;
int dy;
//總的步長
int steps;
int k;
//得到x,y的差值
dx = end.x - from.x;
dy = end.y - from.y;
//判斷x,y上的差值大小,確定步長
if(abs(dx) > abs(dy))
{
steps = abs(dx);
}
else
{
steps = abs(dy);
}
//得到每次增量的大小
delta_x = (float)dx / (float)steps;
delta_y = (float)dy / (float)steps;
//設(shè)定x,y的起點(diǎn)
x = (float)from.x;
y = (float)from.y;
//設(shè)定初始點(diǎn)的顏色為綠色
long lOffset = y*wBytesPerLine + x*3;
*(lpData + lOffset++) = 0;
*(lpData + lOffset++) = 255;
*(lpData + lOffset++) = 0;
//根據(jù)計(jì)算得到的步長,把直線上的點(diǎn)填充成綠色
for (k=1;k<=steps; k++)
{
//x,y分別加上各自的增量
x+=delta_x;
y+=delta_y;
//設(shè)置點(diǎn)的顏色
lOffset = y*wBytesPerLine + x*3;
*(lpData + lOffset++) = 0;
*(lpData + lOffset++) = 255;
*(lpData + lOffset++) = 0;
}
}
void CFaceDetectionDoc::OnFileSaveAs(LPCTSTR lpszPathName)
{
CFile file;
if(!file.Open(lpszPathName, CFile::modeCreate |// 打開文件
CFile::modeReadWrite | CFile::shareExclusive))
{
return;// 返回FALSE
}
BOOL bSuccess = FALSE;
bSuccess = ::SaveDIB(m_hDIB, file); // 保存圖象
file.Close();// 關(guān)閉文件
SetModifiedFlag(FALSE);// 重置脹標(biāo)記為FALSE
if (!bSuccess)
{
AfxMessageBox("保存BMP圖象時(shí)出錯(cuò)");// 提示出錯(cuò)
}
}
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -