?? facedetectiondoc.cpp
字號:
// FaceDetectionDoc.cpp : implementation of the CFaceDetectionDoc class
//
#include "stdafx.h"
#include "FaceDetection.h"
#include "FaceDetectionDoc.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CFaceDetectionDoc
IMPLEMENT_DYNCREATE(CFaceDetectionDoc, CDocument)
BEGIN_MESSAGE_MAP(CFaceDetectionDoc, CDocument)
//{{AFX_MSG_MAP(CFaceDetectionDoc)
ON_COMMAND(ID_FILE_SAVE_AS, OnFileSaveAs)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CFaceDetectionDoc construction/destruction
CFaceDetectionDoc::CFaceDetectionDoc()
{
// TODO: add one-time construction code here
int i,j;
m_hDIB=NULL;
for( i=0; i<ImgRange; i++)
for ( j=0; j<ImgRange; j++)
{
emymapc[i][j] = false;
emymapl[i][j] = false;
//lab[i][j] = false;
}
for( i=0;i<ImgRange; i++)
for ( j=0; j<ImgRange; j++)
lab[i][j] = false;
}
CFaceDetectionDoc::~CFaceDetectionDoc()
{
}
BOOL CFaceDetectionDoc::OnNewDocument()
{
if (!CDocument::OnNewDocument())
return FALSE;
// TODO: add reinitialization code here
// (SDI documents will reuse this document)
return TRUE;
}
/////////////////////////////////////////////////////////////////////////////
// CFaceDetectionDoc serialization
void CFaceDetectionDoc::Serialize(CArchive& ar)
{
if (ar.IsStoring())
{
// TODO: add storing code here
}
else
{
// TODO: add loading code here
}
}
/////////////////////////////////////////////////////////////////////////////
// CFaceDetectionDoc diagnostics
#ifdef _DEBUG
void CFaceDetectionDoc::AssertValid() const
{
CDocument::AssertValid();
}
void CFaceDetectionDoc::Dump(CDumpContext& dc) const
{
CDocument::Dump(dc);
}
#endif //_DEBUG
/////////////////////////////////////////////////////////////////////////////
// CFaceDetectionDoc commands
BOOL CFaceDetectionDoc::OnOpenDocument(LPCTSTR lpszPathName)
{
if (!CDocument::OnOpenDocument(lpszPathName))
return FALSE;
CFile fileM;
CFileException feM;
m_hDIB = NULL;
if (!fileM.Open(lpszPathName, CFile::modeRead | CFile::shareDenyWrite, &feM))
{
// 失敗
ReportSaveLoadException(lpszPathName, &feM,FALSE, AFX_IDP_FAILED_TO_OPEN_DOC);
// 返回FALSE
return FALSE;
}
if (!fileM2.Open(lpszPathName, CFile::modeRead | CFile::shareDenyWrite, &feM))
{
// 失敗
ReportSaveLoadException(lpszPathName, &feM,FALSE, AFX_IDP_FAILED_TO_OPEN_DOC);
// 返回FALSE
return FALSE;
}
TRY
{
m_hDIB = ::ReadDIBFile(fileM);
}
CATCH (CFileException, eLoad)
{
// 讀取失敗
fileM.Abort();
// 恢復光標形狀
EndWaitCursor();
// 報告失敗
ReportSaveLoadException(lpszPathName, eLoad,
FALSE, AFX_IDP_FAILED_TO_OPEN_DOC);
// 設置DIB為空
m_hDIB = NULL;
fileM.Close();
// 返回FALSE
return FALSE;
}
END_CATCH
m_hDIBtemp=(HDIB)CopyHandle(m_hDIB);
//if(fileM.Read(&bmfHeaderMulspec,sizeof(BITMAPFILEHEADER)) != sizeof(BITMAPFILEHEADER))
//return FALSE;
fileM.Close();
// TODO: Add your specialized creation code here
return TRUE;
}
bool CFaceDetectionDoc::LightingCompensate()
{
LPBITMAPINFOHEADER lpbi;
lpbi = (LPBITMAPINFOHEADER)::GlobalLock((HGLOBAL) m_hDIB);//讀取頭文件
lLineBytesMulspec = WIDTHBYTES((lpbi->biWidth)*24);
::GlobalUnlock((HGLOBAL) m_hDIB);
int width,height;
LPBYTE lpData;
long wBytesPerLine;
LPSTR lpDIB = (LPSTR) ::GlobalLock((HGLOBAL) m_hDIB);
// 獲取DIB寬度
width= (int) ::DIBWidth(lpDIB);
// 獲取DIB高度
height= (int) ::DIBHeight(lpDIB);
::GlobalUnlock((HGLOBAL) m_hDIB);
lpData = (unsigned char*)::FindDIBBits(lpDIB);
//得到圖片每行的象素所占字節個數
wBytesPerLine = lLineBytesMulspec;
//比例系數
const float thresholdco = 0.05;
//象素個數的臨界常數
const int thresholdnum = 100;
//灰度級數組
int histogram[256];
for(int i =0;i<256;i++)
histogram[i] = 0;
//對于過于小的圖片的判斷
if(width*height*thresholdco < thresholdnum)
return false;
int colorr,colorg,colorb;
long lOffset;
//考察整個圖片
for( i=0;i<height;i++)
for(int j=0;j<width;j++)
{
//得到象素數據的偏移
lOffset = i*wBytesPerLine + j*3;
//得到rgb值
colorb = *(lpData+lOffset++);
colorg = *(lpData+lOffset++);
colorr = *(lpData+lOffset++);
//計算灰度值
int gray = (colorr * 299 + colorg * 587 + colorb * 114)/1000;
histogram[gray]++;
}
int calnum =0;
int total = width*height;
int num;
//下面的循環得到滿足系數thresholdco的臨界灰度級
for(i =0;i<256;i++)
{
if((float)calnum/total < thresholdco)
{
calnum+= histogram[255-i];
num = i;
}
else
break;
}
int averagegray = 0;
calnum =0;
//得到滿足條件的象素總的灰度值
for(i = 255;i>=255-num;i--)
{
averagegray += histogram[i]*i;
calnum += histogram[i];
}
averagegray /=calnum;
//得到光線補償的系數
float co = 255.0/(float)averagegray;
//下面的循環對圖象進行光線補償
for(i =0;i<height;i++)
for(int j=0;j<width;j++)
{
//得到數據便宜
lOffset =i*wBytesPerLine + j*3;
//得到藍色分量
colorb = *(lpData+lOffset);
//調整
colorb *=co;
//臨界判斷
if(colorb >255)
colorb = 255;
//保存
*(lpData+lOffset) = colorb;
//綠色分量
colorb = *(lpData+lOffset+1);
colorb *=co;
if(colorb >255)
colorb = 255;
*(lpData+lOffset+1) = colorb;
//紅色分量
colorb = *(lpData+lOffset+2);
colorb *=co;
if(colorb >255)
colorb = 255;
*(lpData+lOffset+2) = colorb;
}
return TRUE;
}
void CFaceDetectionDoc::RgbtoYcb(HDIB hDIB,LPBYTE lpYcb)
{
LPBITMAPINFOHEADER lpbi;
lpbi = (LPBITMAPINFOHEADER)::GlobalLock((HGLOBAL) hDIB);//讀取頭文件
lLineBytesMulspec = WIDTHBYTES((lpbi->biWidth)*24);
::GlobalUnlock((HGLOBAL)hDIB);
int width,height;
WORD wBytesPerLine;
LPBYTE lpData;
LPSTR lpDIB = (LPSTR) ::GlobalLock((HGLOBAL) hDIB);
// 獲取DIB寬度
width= (int) ::DIBWidth(lpDIB);
// 獲取DIB高度
height= (int) ::DIBHeight(lpDIB);
lpData = (unsigned char*)::FindDIBBits(lpDIB);
//得到圖象的基本信息
wBytesPerLine = lLineBytesMulspec;//得到圖片每行的象素所占字節個數
long lOffset;
//下面的循環實現從rgb到ycc的轉化
for(int i=0;i<height;i++)
for(int j=0;j<width;j++)
{
lOffset = i*wBytesPerLine + j*3; //得到象素數據的偏移
//得到rgb數值
int b = *(lpData + lOffset);
int g = *(lpData + lOffset+1);
int r = *(lpData + lOffset+2);
//計算得到y,cr,cb的數值
int Y = (257*r+504*g+98*b)/1000+16;
int Cr = (439*r-368*g-71*b)/1000+128;
int Cb = (-148*r-291*g+439*b)/1000+128;
//保存計算得到的數值
*(lpYcb+lOffset++) = Y;
*(lpYcb+lOffset++) = Cr;
*(lpYcb+lOffset++) = Cb;
}
::GlobalUnlock((HGLOBAL) hDIB);
}
//////////////*皮膚顏色建模*//////////////
int CFaceDetectionDoc::_Cb(int Y)
{
int Cb;
//如果亮度很小的情況
if(Y<Kl)
Cb = 108 + ((Kl-Y)*10)/(Kl-Ymin);
//亮度很大的情況
else if(Y>Kh)
Cb = 108 + ((Y-Kh)*10)/(Ymax - Kh);
else
Cb = -1;
return Cb;
}
int CFaceDetectionDoc::_Cr(int Y)
{
int Cr;
//亮度很小的情況
if(Y<Kl)
Cr = 154 - ((Kl-Y)*10)/(Kl-Ymin);
//亮度很大的情況
else if(Y>Kh)
Cr = 154 - ((Y-Kh)*22)/(Ymax - Kh);
else
Cr = -1;
return Cr;
}
int CFaceDetectionDoc::_WCr(int Y)
{
int WCr;
if(Y<Kl)
//亮度很小的情況
WCr = WLcr + ((Y-Ymin)*(Wcr-WLcr))/(Kl-Ymin);
else if(Y>Kh)
//亮度很大的情況
WCr = WHcr + ((Ymax-Y)*(Wcr-WHcr))/(Ymax-Kh);
else WCr = -1;
return WCr;
}
int CFaceDetectionDoc:: _WCb(int Y)
{
int WCb;
if(Y<Kl)
//亮度很小的情況
WCb = WLcb + ((Y-Ymin)*(Wcb-WLcb))/(Kl-Ymin);
else if(Y>Kh)
//亮度很大的情況
WCb = WHcb + ((Ymax-Y)*(Wcb-WHcb))/(Ymax-Kh);
else WCb = -1;
return WCb;
}
void CFaceDetectionDoc::YccTransform(LPBYTE lpYcc,WORD wBytesPerLine,int height,int width)
{
int Y,Cr,Cb;
long lOffset;
//下面的循環實現ycc色彩空間的非線性轉換
for(int i=0;i<height;i++)
for(int j=0;j<width;j++)
{
//得到數據偏移
lOffset = i*wBytesPerLine + j*3;
//得到y,Cr,Cb數值
Y = *(lpYcc+lOffset);
Cr = *(lpYcc+lOffset+1);
Cb = *(lpYcc+lOffset+2);
//如果y數值在兩個臨界值之間,保持不變
if(Y>=Kl && Y<=Kh)
continue;
//調用非線性轉換函數調整Cr,Cb的數值
Cr = (Cr-_Cr(Y))*(Wcr/_WCr(Y))+_Cr(Kh);
Cb = (Cb-_Cb(Y))*(Wcb/_WCb(Y))+_Cb(Kh);
*(lpYcc+lOffset+1) = Cr;
*(lpYcc+lOffset+2) = Cb;
}
}
void CFaceDetectionDoc::faceear(LPBYTE lpYcc, WORD wBytesPerLine, int height,int width, bool flag[ImgRange][ImgRange])
{
//初始化標志位
for (int i=0; i<ImgRange; i++)
for (int j=0; j<ImgRange; j++)
{
flag[i][j] = false;
}
long lOffset;
int Cr;
int Cb;
for (i=0; i<height; i++)
for (int j=0; j<width; j++)
{
//得到偏移
lOffset = i*wBytesPerLine + j*3;
//得到Cr,Cb數值
Cr = *(lpYcc+lOffset+1);
Cb = *(lpYcc+lOffset+2);
//人臉顏色建模
if(FaceModeling(Cr,Cb))
{
//修改標志位
flag[i][j] = true;
}
}
}
BOOL CFaceDetectionDoc::FaceModeling(int Cr,int Cb)
{
//Cb的系數常量
const float cx = 122.453;//114.38;
//cr的系數常量
const float cy = 158.442;//160.02;
//角度常量
const float theta = 2.53;
//x軸線和y軸線的兩個常量
const float ecx = 1.60;
const float ecy = 2.41;
//長軸
const float a = 25.39;
//短軸
const float b = 14.03;
//相似度常量
const float judge = 0.5;
//計算得到x軸數值
float x = cos(theta)*(Cb-cx)+sin(theta)*(Cr-cy);
//y軸數值
float y = -sin(theta)*(Cb -cx)+cos(theta)*(Cr-cy);
//計算離心率
float temp = pow(x-ecx,2)/pow(a,2)+pow(y-ecy,2)/pow(b,2);
//如果滿足要求返回真,否則假
if(fabs(temp-1.0)<judge)
return TRUE;
else
return FALSE;
}
void CFaceDetectionDoc::Skintone()
{
LPBITMAPINFOHEADER lpbi;
lpbi = (LPBITMAPINFOHEADER)::GlobalLock((HGLOBAL) m_hDIB);//讀取頭文件
lLineBytesMulspec = WIDTHBYTES((lpbi->biWidth)*24);
::GlobalUnlock((HGLOBAL) m_hDIB);
int width,height;
LPBYTE lpData;
long wBytesPerLine;
LPSTR lpDIB = (LPSTR) ::GlobalLock((HGLOBAL) m_hDIB);
// 獲取DIB寬度
width= (int) ::DIBWidth(lpDIB);
// 獲取DIB高度
height= (int) ::DIBHeight(lpDIB);
::GlobalUnlock((HGLOBAL) m_hDIB);
lpData = (unsigned char*)::FindDIBBits(lpDIB);
//得到圖片每行的象素所占字節個數
wBytesPerLine = lLineBytesMulspec;
lpYcc = new BYTE[wBytesPerLine * height];
RgbtoYcb(m_hDIB,lpYcc);
YccTransform(lpYcc, wBytesPerLine,height,width);
faceear(lpYcc,wBytesPerLine,height,width,flag);
lpData =(LPBYTE)::GlobalLock(lpDIB)+sizeof(BITMAPINFOHEADER);
for (int i=0; i<height; i++)
for (int j=0; j<width; j++)
{
long lOffset = i*wBytesPerLine + j*3;
if (flag[i][j] == true)
{
*(lpData + lOffset++) = 255;
*(lpData + lOffset++) = 255;
*(lpData + lOffset++) = 255;
}
else
{
*(lpData + lOffset++) = 0;
*(lpData + lOffset++) = 0;
*(lpData + lOffset++) = 0;
}
}
::GlobalUnlock(lpDIB);
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -