📄 facedemodlg.cpp
字号:
// FaceDemoDlg.cpp : implementation file
//
#include "stdafx.h"
#include "FaceDemo.h"
#include "FaceDemoDlg.h"
#include <afxpriv2.h>
#include <malloc.h>
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
#define WM_CAPFACEMESSAGE WM_USER+2101
HWND g_cfHwnd;
/////////////////////////////////////////////////////////////////////////////
// CAboutDlg dialog used for App About
CString g_csPath;
typedef struct _YUV_FRAME_
{
unsigned char *y;
unsigned char *u;
unsigned char *v;
}YUV_FRAME;
YUV_FRAME yuvTemp;
typedef struct
{
YUV_FRAME pBmpBuff;//用于截取yuv数据的内存
CTime time;//抓取时间
IPicture *iPic;//用于显示的bmp数据
int nChannel;
CRect sRect;//显示范围
int w;
int h;
}BMP,*PBMP;
BMP bpInfo[12];
typedef struct
{
BOOL bDetectNow;//是否已经在检测
int nPicType;//0-YUV,1-jpeg图像
int nFrameInterval;//检测帧间隔
int nJpegQuality;//jpeg图像质量
BOOL bSaveFile;//是否存盘
}FACEDETECTPARAM;
FACEDETECTPARAM fdParam[4];
static int nFaceW = 0;
//读取图像文件用于显示
void LoadPictureFromFile(CString strBmpFileName,int index)
{
if(strBmpFileName)
{
CFile file;
if (!file.Open(strBmpFileName, CFile::modeRead|CFile::shareDenyWrite))
{
return;
}
CArchive ar(&file, CArchive::load | CArchive::bNoFlushOnDelete);
CArchiveStream arcstream(&ar);
if (bpInfo[index].iPic)
{
bpInfo[index].iPic->Release();
}
HRESULT hr = OleLoadPicture((IStream*)&arcstream, 0, FALSE, IID_IPicture, (void**)&bpInfo[index].iPic);
// ASSERT(SUCCEEDED(hr) && bpInfo[index].iPic);
if(!SUCCEEDED(hr))
{
TRACE("LOAD PICTURE ERR\n!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
bpInfo[index].iPic=NULL;
}
file.Close();
}else
{
if (bpInfo[index].iPic)
{
bpInfo[index].iPic->Release();
bpInfo[index].iPic = NULL;
}
}
}
/* 从yuv数据中读取人脸信息
nChannel:通道号
pImage为原始图像地址
FACE_INFO 为图像中的人脸位置信息(矩形)
w:原始图像宽度
h:原始图像高度
*/
void FGetYUVFace(int nChannel,char * pImage,FACE_INFO * pFaceInfo,UINT w,UINT h)
{
CFaceDemoDlg*dlgmain=(CFaceDemoDlg*)AfxGetMainWnd();
WaitForSingleObject(dlgmain->m_muShowPic,INFINITE);
int dw,dh;
int x,y,fw,fh;
char *Y,*U,*V,*yd,*ud,*vd;
/*
!!注意:由于当前版本的人脸检测基于CIF图像,而返回的图像是2CIF,因此水平方向的x和width应该放大一倍。
这部分以后会完善!
未压缩格式时,先将人脸存储为BMP格式的临时文件,然后从文件中加载图像显示。
*/
x = pFaceInfo->x * 2;
y = pFaceInfo->y;
fw = pFaceInfo->width * 2;
fh = pFaceInfo->height;
Y = pImage;
U = pImage + w * h;
V = pImage + w * h * 5 / 4;
yd = (char *)bpInfo[nFaceW].pBmpBuff.y;
ud = (char *)(bpInfo[nFaceW].pBmpBuff.y + (fw * fh));
vd = (char *)(bpInfo[nFaceW].pBmpBuff.y + (fw * fh * 5 / 4));
for(int i=y;i< (y + fh);i++)
{
//从原始图像中取出局部的人脸图像
memcpy(yd,Y + i * w + x,fw);
yd += fw;
//原始图像是420格式,UV数据每隔一行取一行
if(!(i & 1))
{
memcpy(ud,U + i * w / 4 + x / 2,fw / 2);
memcpy(vd,V + i * w / 4 + x / 2,fw / 2);
ud += fw / 2;
vd += fw / 2;
}
}
bpInfo[nFaceW].time = CTime::GetCurrentTime();
dw = pFaceInfo->width * 2;
dh = pFaceInfo->height;
char csFileName[200];
if(dlgmain->m_bSaveFile)
{
sprintf(csFileName,"%s\\%02d%02d%d.bmp",dlgmain->m_csPath,bpInfo[nFaceW].time.GetMonth(),bpInfo[nFaceW].time.GetDay(),GetTickCount());
}else
{
sprintf(csFileName,"%stempbmp.bmp",g_csPath);
}
//设置要显示的图像区域,此时存储的是人脸局部图像,因此要显示全部图像内容。
bpInfo[nFaceW].sRect.left = 0;
bpInfo[nFaceW].sRect.top = 0;
bpInfo[nFaceW].sRect.right = dw;
bpInfo[nFaceW].sRect.bottom = dh;
bpInfo[nFaceW].w = dw;
bpInfo[nFaceW].h = dh;
//将人脸的局部图像(YUV格式)转换到BMP格式并写入文件
HW_ConvertToBmpFile(bpInfo[nFaceW].pBmpBuff.y,dw * dh * 3 / 2,dw,dh,csFileName,0);
//加载BMP文件
LoadPictureFromFile(csFileName,nFaceW);
ReleaseMutex(dlgmain->m_muShowPic);
bpInfo[nFaceW].nChannel = nChannel;
//显示图像
SendMessage(g_cfHwnd,WM_CAPFACEMESSAGE, 0, nFaceW);
nFaceW ++;
if(nFaceW >= 12)
nFaceW = 0;
}
/* 从jpeg文件中读取人脸信息
nChannel:通道号
csFileName:jpeg文件名
FACE_INFO:为图像中的人脸位置信息(矩形)
w:原始图像宽度
h:原始图像高度
*/
void FGetJpegFace(int nChannel,char * csFileName,FACE_INFO *pFaceInfo,UINT w,UINT h)
{
CFaceDemoDlg*dlgmain=(CFaceDemoDlg*)AfxGetMainWnd();
WaitForSingleObject(dlgmain->m_muShowPic,INFINITE);
//设置要显示的图像区域,此时文件中存储的是包含全部人脸的大图像,要显示的人脸只是其中的一部分。
bpInfo[nFaceW].time = CTime::GetCurrentTime();
bpInfo[nFaceW].sRect.left = pFaceInfo->x * 2; //人脸的x和width要乘2
bpInfo[nFaceW].sRect.top = pFaceInfo->y ;
bpInfo[nFaceW].sRect.right = pFaceInfo->width * 2 + pFaceInfo->x * 2;
bpInfo[nFaceW].sRect.bottom = pFaceInfo->height + pFaceInfo->y;
bpInfo[nFaceW].h = h;
bpInfo[nFaceW].w = w;
TRACE("x=%d,y=%d,w=%d,h=%d\n",pFaceInfo->x * 2,pFaceInfo->y , pFaceInfo->width * 2 ,pFaceInfo->height);
//加载图像
LoadPictureFromFile(csFileName,nFaceW);
bpInfo[nFaceW].nChannel = nChannel;
ReleaseMutex(dlgmain->m_muShowPic);
SendMessage(g_cfHwnd,WM_CAPFACEMESSAGE, 0, nFaceW);
nFaceW ++;
if(nFaceW >= 12)
nFaceW = 0;
}
//回调函数
void FaceDetectionCallback(UINT nChannel,UINT nFaceCount,FACE_INFO *pFaceInfo,char *pImage,UINT len,UINT w,UINT h)
{
CFaceDemoDlg*dlgmain=(CFaceDemoDlg*)AfxGetMainWnd();
UINT i;
if(fdParam[nChannel].nPicType == 0)
{
//未压缩格式,原始图像,直接处理
for(i=0;i<nFaceCount;i++)
{
FGetYUVFace(nChannel,pImage,pFaceInfo,w,h);
pFaceInfo++;
}
}
else
{
//图像已经压缩为JPEG格式,先存储到文件
char csFileName[200];
FILE * f;
if(fdParam[nChannel].bSaveFile)
{
sprintf(csFileName,"%s\\ch%02d_%02d%02d%d.jpg",dlgmain->m_csPath,nChannel,bpInfo[nFaceW].time.GetMonth(),bpInfo[nFaceW].time.GetDay(),GetTickCount());
}else
{
sprintf(csFileName,"%stempjpg.jpg",g_csPath);
}
f=fopen(csFileName,"wb");
fwrite(pImage,1,len,f);
fclose(f);
for(i=0;i<nFaceCount;i++)
{
FGetJpegFace(nChannel,csFileName,pFaceInfo,w,h);
pFaceInfo++;
}
}
}
class CAboutDlg : public CDialog
{
public:
CAboutDlg();
// Dialog Data
//{{AFX_DATA(CAboutDlg)
enum { IDD = IDD_ABOUTBOX };
//}}AFX_DATA
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CAboutDlg)
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
//}}AFX_VIRTUAL
// Implementation
protected:
//{{AFX_MSG(CAboutDlg)
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
//{{AFX_DATA_INIT(CAboutDlg)
//}}AFX_DATA_INIT
}
void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CAboutDlg)
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
//{{AFX_MSG_MAP(CAboutDlg)
// No message handlers
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CFaceDemoDlg dialog
CFaceDemoDlg::CFaceDemoDlg(CWnd* pParent /*=NULL*/)
: CDialog(CFaceDemoDlg::IDD, pParent)
{
//{{AFX_DATA_INIT(CFaceDemoDlg)
m_csTime1 = _T("");
m_csTime10 = _T("");
m_csTime11 = _T("");
m_csTime2 = _T("");
m_csTime4 = _T("");
m_csTime3 = _T("");
m_csTime6 = _T("");
m_csTime7 = _T("");
m_csTime8 = _T("");
m_csTime9 = _T("");
m_csTime0 = _T("");
m_bSaveFile = FALSE;
m_nJpegQuality = 50;
m_nFrameInterval = 10;
m_csChan1 = _T("");
m_csChan10 = _T("");
m_csChan11 = _T("");
m_csChan12 = _T("");
m_csChan2 = _T("");
m_csChan3 = _T("");
m_csChan4 = _T("");
m_csChan5 = _T("");
m_csChan6 = _T("");
m_csChan7 = _T("");
m_csChan8 = _T("");
m_csChan9 = _T("");
m_nChannel=0;
m_bInited=FALSE;
m_bStartCap=FALSE;
m_bColorFace=TRUE;
m_nType = 0;
m_csTime5 = _T("");
//}}AFX_DATA_INIT
// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}
void CFaceDemoDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CFaceDemoDlg)
DDX_Control(pDX, IDC_PIC_TIME9, m_edTime9);
DDX_Control(pDX, IDC_PIC_TIME8, m_edTime8);
DDX_Control(pDX, IDC_PIC_TIME7, m_edTime7);
DDX_Control(pDX, IDC_PIC_TIME6, m_edTime6);
DDX_Control(pDX, IDC_PIC_TIME5, m_edTime5);
DDX_Control(pDX, IDC_PIC_TIME4, m_edTime4);
DDX_Control(pDX, IDC_PIC_TIME3, m_edTime3);
DDX_Control(pDX, IDC_PIC_TIME2, m_edTime2);
DDX_Control(pDX, IDC_PIC_TIME11, m_edTime11);
DDX_Control(pDX, IDC_PIC_TIME10, m_edTime10);
DDX_Control(pDX, IDC_PIC_TIME1, m_edTime1);
DDX_Control(pDX, IDC_PIC_TIME0, m_edTime0);
DDX_Control(pDX, IDC_PIC_CHAN9, m_edChan9);
DDX_Control(pDX, IDC_PIC_CHAN8, m_edChan8);
DDX_Control(pDX, IDC_PIC_CHAN7, m_edChan7);
DDX_Control(pDX, IDC_PIC_CHAN6, m_edChan6);
DDX_Control(pDX, IDC_PIC_CHAN5, m_edChan5);
DDX_Control(pDX, IDC_PIC_CHAN4, m_edChan4);
DDX_Control(pDX, IDC_PIC_CHAN3, m_edChan3);
DDX_Control(pDX, IDC_PIC_CHAN2, m_edChan2);
DDX_Control(pDX, IDC_PIC_CHAN12, m_edChan12);
DDX_Control(pDX, IDC_PIC_CHAN11, m_edChan11);
DDX_Control(pDX, IDC_PIC_CHAN10, m_edChan10);
DDX_Control(pDX, IDC_PIC_CHAN1, m_edChan1);
DDX_Control(pDX, IDC_COMBO_MODE, m_cmbType);
DDX_Text(pDX, IDC_PIC_TIME1, m_csTime1);
DDX_Text(pDX, IDC_PIC_TIME10, m_csTime10);
DDX_Text(pDX, IDC_PIC_TIME11, m_csTime11);
DDX_Text(pDX, IDC_PIC_TIME2, m_csTime2);
DDX_Text(pDX, IDC_PIC_TIME4, m_csTime4);
DDX_Text(pDX, IDC_PIC_TIME3, m_csTime3);
DDX_Text(pDX, IDC_PIC_TIME6, m_csTime6);
DDX_Text(pDX, IDC_PIC_TIME7, m_csTime7);
DDX_Text(pDX, IDC_PIC_TIME8, m_csTime8);
DDX_Text(pDX, IDC_PIC_TIME9, m_csTime9);
DDX_Text(pDX, IDC_PIC_TIME0, m_csTime0);
DDX_Check(pDX, IDC_CHECK_FILE, m_bSaveFile);
DDX_Text(pDX, IDC_JPEG_QUALITY, m_nJpegQuality);
DDX_Text(pDX, IDC_FRAME_INTERVAL, m_nFrameInterval);
DDX_Text(pDX, IDC_PIC_CHAN1, m_csChan1);
DDX_Text(pDX, IDC_PIC_CHAN10, m_csChan10);
DDX_Text(pDX, IDC_PIC_CHAN11, m_csChan11);
DDX_Text(pDX, IDC_PIC_CHAN12, m_csChan12);
DDX_Text(pDX, IDC_PIC_CHAN2, m_csChan2);
DDX_Text(pDX, IDC_PIC_CHAN3, m_csChan3);
DDX_Text(pDX, IDC_PIC_CHAN4, m_csChan4);
DDX_Text(pDX, IDC_PIC_CHAN5, m_csChan5);
DDX_Text(pDX, IDC_PIC_CHAN6, m_csChan6);
DDX_Text(pDX, IDC_PIC_CHAN7, m_csChan7);
DDX_Text(pDX, IDC_PIC_CHAN8, m_csChan8);
DDX_Text(pDX, IDC_PIC_CHAN9, m_csChan9);
DDX_Text(pDX, IDC_PIC_TIME5, m_csTime5);
//}}AFX_DATA_MAP
// DDX_Text(pDX, IDC_FACE_TYPE1, m_bColorFace);
}
BEGIN_MESSAGE_MAP(CFaceDemoDlg, CDialog)
ON_CONTROL_RANGE(BN_CLICKED,IDC_FACE_TYPE1,IDC_FACE_TYPE3,OnChangeFaceType)
//{{AFX_MSG_MAP(CFaceDemoDlg)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_WM_MOVE()
ON_BN_CLICKED(IDC_START_CAP, OnStartCap)
ON_BN_CLICKED(IDC_STOP_CAP, OnStopCap)
ON_BN_CLICKED(IDC_EXIT, OnExit)
ON_WM_CLOSE()
ON_BN_CLICKED(IDC_CHECK_FILE, OnCheckFile)
ON_BN_CLICKED(IDC_STOPALL, OnStopall)
//}}AFX_MSG_MAP
ON_MESSAGE(WM_CAPFACEMESSAGE,OnClientMessage)
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CFaceDemoDlg message handlers
BOOL CFaceDemoDlg::OnInitDialog()
{
CDialog::OnInitDialog();
// Add "About..." menu item to system menu.
// IDM_ABOUTBOX must be in the system command range.
ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX < 0xF000);
CMenu* pSysMenu = GetSystemMenu(FALSE);
if (pSysMenu != NULL)
{
CString strAboutMenu;
strAboutMenu.LoadString(IDS_ABOUTBOX);
if (!strAboutMenu.IsEmpty())
{
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
}
}
// Set the icon for this dialog. The framework does this automatically
// when the application's main window is not a dialog
SetIcon(m_hIcon, TRUE); // Set big icon
SetIcon(m_hIcon, FALSE); // Set small icon
// TODO: Add extra initialization here
////////////////////以下是为初始化抓face准备
m_pPic = NULL;
g_cfHwnd=this->m_hWnd;
char *p;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -