📄 mainfrm.cpp
字号:
// MainFrm.cpp : implementation of the CMainFrame class
//
#include "stdafx.h"
#include "VideoCapture.h"
#include "MainFrm.h"
#include "Math.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CMainFrame
IMPLEMENT_DYNCREATE(CMainFrame, CFrameWnd)
BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
//{{AFX_MSG_MAP(CMainFrame)
ON_WM_CREATE()
ON_COMMAND(ID_FORMAT, OnFormat)
ON_COMMAND(ID_PREVIEW, OnPreview)
ON_COMMAND(ID_SOURCE, OnSource)
ON_COMMAND(ID_CAPTURE, OnCapture)
ON_COMMAND(ID_FACE, OnFace)
ON_COMMAND(ID_FACELOCATION, OnFacelocation)
ON_COMMAND(ID_Videofacelac, OnVideofacelac)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
static UINT indicators[] =
{
ID_SEPARATOR, // status line indicator
ID_INDICATOR_CAPS,
ID_INDICATOR_NUM,
ID_INDICATOR_SCRL,
};
//-------------------------------------------------------------
unsigned char bgr_max(unsigned char b,unsigned char g,unsigned char r)
{
unsigned char max;
max=(b>g?b:g);
max=(max>r?max:r);
return(max);
}
unsigned char bgr_min(unsigned char b,unsigned char g,unsigned char r)
{
unsigned char min;
min=(b<g?b:g);
min=(min<r?min:r);
return(min);
}
//-------------------------------------------------------------
//三个回调函数的定义
//-------------------------------------------------------------
LRESULT CALLBACK EXPORT ErrorCallbackProc(HWND hWnd,int nErrID,LPSTR lpErrorText)
//错误回调函数
//hWnd: Applocation main window handle
//nErrID: Error code for the encountered error
//lpErrorText: Error text string for the encountered error
{
if(nErrID==0)
return TRUE; //Clear out old errors...
AfxMessageBox(lpErrorText,MB_OK,NULL);
return TRUE;
}
//--------------------------------------------------------------
LRESULT FAR PASCAL StatusCallbackProc(HWND hWnd,int nID,LPSTR lpStatusText)
//状态回调函数
//hWnd: Application main window handle
//Nid: Status code for the current status
//lpStatusText: Status text string for the crurrent status
{
static int CurrentID;
//the CAP_END message sometimes overwrites a useful
//statistics message;
if(nID==IDS_CAP_END)
{
if((CurrentID==IDS_CAP_STAT_VIDEOAUDIO)||
(CurrentID==IDS_CAP_STAT_VIDEOONLY))
return(TRUE);
}
CurrentID=nID;
return(LRESULT)TRUE;
}
//--------------------------------------------------------------
BOOL videoflag;
LRESULT FAR PASCAL VideoCallbackProc(HWND hWnd,LPVIDEOHDR lpVHdr)
//视频流回调函数
{
// AfxMessageBox("开始执行视频流回调函数",MB_OK,NULL);
CWnd * p=AfxGetMainWnd();
if (!p) return (LRESULT)TRUE;
((CMainFrame*)p)->m_dibinfo.bitmapinfoheader.biSizeImage=lpVHdr->dwBytesUsed;
// AfxMessageBox("得到视频流图像大小",MB_OK,NULL);
memcpy(((CMainFrame*)AfxGetMainWnd())->m_dibinfo.buffer
+((CMainFrame*)AfxGetMainWnd())->m_dibinfo.VideoFormatSize,
lpVHdr->lpData,lpVHdr->dwBytesUsed);
// AfxMessageBox("视频流拷贝到内存",MB_OK,NULL);
CWnd * p_CWnd=AfxGetMainWnd();
CMainFrame * p_CMainFrame=(CMainFrame*)p_CWnd;
p_CMainFrame->m_iscapture=TRUE;
//--------------------------------------------------------------
if(videoflag)
{
int FaceNum=0;
// if(p_CMainFrame->m_enable_skindect)
// {
// p_CMainFrame->m_iscapture=FALSE;
// p_CMainFrame->m_after_skindect=TRUE;
p_CMainFrame->RGBToYCrCb();
p_CMainFrame->Skin_detection();
FaceNum=p_CMainFrame->ErasionFalseArea();
// }
if(FaceNum!=0)
{
int i,j;
// int BlackPixelNum=0;
// int flagy=0;
//标记是否出现下边界,0表示没有出现下边界,1表示出现了下边界;
// int flagx=0;
//标记是否出现左边界,0表示没有出现左边界,1表示出现了左边界;
long Offset;
unsigned char * lpb;
lpb=p_CMainFrame->m_ycc_buffer;
// lpb=m_rgb_buffer;
LPBITMAPINFOHEADER lpbi;
lpbi=&(p_CMainFrame->m_bitmapheader);
//lpbi_ycc是指向"存放'以YCrCb色彩空间表达的数据信息'的信息头信息"的指针;
// lpbi=&m_rgb_bitmapheader;
DWORD wBytesPerLine=p_CMainFrame->BytePerLine(lpbi);
//得到每行像素所占用的字节数;
// int m_y1=p_CMainFrame->m_y1;
// int m_y2=p_CMainFrame->m_y2;
// int m_x1=p_CMainFrame->m_x1;
// int m_x2=p_CMainFrame->m_x2;
const int AREAPIXEL=1200;//表示人脸的像素个数必须大于AREAPIXEL;
int square=0;
while(square<AREAPIXEL)
{
p_CMainFrame->m_x1=-1;
p_CMainFrame->m_x2=-1;
p_CMainFrame->m_y1=-1;
p_CMainFrame->m_y2=-1;
p_CMainFrame->scan();
square=(p_CMainFrame->m_x2-p_CMainFrame->m_x1)*(p_CMainFrame->m_y2-p_CMainFrame->m_y1);
if(square<AREAPIXEL)
{
for(i=p_CMainFrame->m_y1;i<=(p_CMainFrame->m_y2);i++)
for(j=p_CMainFrame->m_x1;j<=(p_CMainFrame->m_x2);j++)
{
Offset=p_CMainFrame->PixelOffset(i,j,wBytesPerLine);
*(lpb+Offset)=0;
*(lpb+Offset+1)=0;
*(lpb+Offset+2)=0;
}
}
}
lpb=((CMainFrame*)AfxGetMainWnd())->m_dibinfo.buffer
+((CMainFrame*)AfxGetMainWnd())->m_dibinfo.VideoFormatSize;
//用矩形定位人脸,矩形边线呈绿色
//画人脸的下边界
i=p_CMainFrame->m_y1;
for(j=p_CMainFrame->m_x1;j<=p_CMainFrame->m_x2;j++)
{
Offset=p_CMainFrame->PixelOffset(i,j,wBytesPerLine);
//得到像素点数据在整个数据区中的偏移;
*(lpb+Offset)=0;
*(lpb+Offset+1)=255;
*(lpb+Offset+2)=0;
}
//画人脸的上边界;
i=p_CMainFrame->m_y2;
for(j=p_CMainFrame->m_x1;j<=p_CMainFrame->m_x2;j++)
{
Offset=p_CMainFrame->PixelOffset(i,j,wBytesPerLine);
//得到像素点数据在整个数据区中的偏移;
*(lpb+Offset)=0;
*(lpb+Offset+1)=255;
*(lpb+Offset+2)=0;
}
//画人脸的左边界;
j=p_CMainFrame->m_x1;
for(i=p_CMainFrame->m_y1;i<=p_CMainFrame->m_y2;i++)
{
Offset=p_CMainFrame->PixelOffset(i,j,wBytesPerLine);
//得到像素点数据在整个数据区中的偏移;
*(lpb+Offset)=0;
*(lpb+Offset+1)=255;
*(lpb+Offset+2)=0;
}
//画人脸的右边界;
j=p_CMainFrame->m_x2;
for(i=p_CMainFrame->m_y1;i<=p_CMainFrame->m_y2;i++)
{
Offset=p_CMainFrame->PixelOffset(i,j,wBytesPerLine);
//得到像素点数据在整个数据区中的偏移;
*(lpb+Offset)=0;
*(lpb+Offset+1)=255;
*(lpb+Offset+2)=0;
}
// m_iscapture=TRUE;
// m_after_skindect=FALSE;
// (((CMainFrame*)AfxGetMainWnd())->GetActiveView())->
// InvalidateRect(NULL,FALSE);
}
}
//--------------------------------------------------------------
(((CMainFrame*)AfxGetMainWnd())->GetActiveView())->
InvalidateRect(NULL,FALSE);
// AfxMessageBox("回调结束,返回",MB_OK,NULL);
return(LRESULT)TRUE;
}
//----------------------------------------------------------------
/*
LRESULT PASCAL FrameCallbackProc(HWND hWnd,LPVIDEOHDR lpVHdr)
//单帧回调函数
{
CWnd * p=AfxGetMainWnd();
if (!p) return (LRESULT)TRUE;
((CMainFrame*)p)->m_dibinfo.bitmapinfoheader.biSizeImage=lpVHdr->dwBytesUsed;
memcpy(((CMainFrame*)AfxGetMainWnd())->m_dibinfo.buffer
+((CMainFrame*)AfxGetMainWnd())->m_dibinfo.VideoFormatSize,
lpVHdr->lpData,lpVHdr->dwBytesUsed);
CWnd * p_CWnd=AfxGetMainWnd();
CMainFrame * p_CMainFrame=(CMainFrame*)p_CWnd;
p_CMainFrame->m_iscapture=TRUE;
(((CMainFrame*)AfxGetMainWnd())->GetActiveView())->
InvalidateRect(NULL,FALSE);
return(LRESULT)TRUE;
}
//-----------------------------------------------------------
*/
//ChangeSize的定义
//-----------------------------------------------------------------
void CMainFrame::ChangeSize()
{
static UINT uiVideoX=0;
static UINT uiVideoY=0;
CAPSTATUS cs;
RECT rc;
m_wndSource.GetWindowRect(&rc);
capGetStatus(m_hWndCap,&cs,sizeof(cs));
if(uiVideoX!=cs.uiImageWidth||uiVideoY!=cs.uiImageHeight)
{
m_wndSource.MoveWindow(rc.left,rc.top,
cs.uiImageWidth+4,cs.uiImageHeight+28);
uiVideoX=cs.uiImageWidth;
uiVideoY=cs.uiImageWidth;
}
//Get Video format
m_dibinfo.VideoFormatSize=capGetVideoFormatSize(m_hWndCap);
capGetVideoFormat(m_hWndCap,&m_dibinfo.bitmapinfoheader,
m_dibinfo.VideoFormatSize);//得到视频流的图像信息头
}
//----------------------------------------------------------------
/////////////////////////////////////////////////////////////////////////////
// CMainFrame construction/destruction
CMainFrame::CMainFrame()
{
// TODO: add member initialization code here
}
CMainFrame::~CMainFrame()
{
this->m_wndSource.CloseWindow();
}
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CFrameWnd::OnCreate(lpCreateStruct) == -1)
return -1;
if (!m_wndToolBar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE | CBRS_TOP
| CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC) ||
!m_wndToolBar.LoadToolBar(IDR_MAINFRAME))
{
TRACE0("Failed to create toolbar\n");
return -1; // fail to create
}
if (!m_wndStatusBar.Create(this) ||
!m_wndStatusBar.SetIndicators(indicators,
sizeof(indicators)/sizeof(UINT)))
{
TRACE0("Failed to create status bar\n");
return -1; // fail to create
}
// TODO: Delete these three lines if you don't want the toolbar to
// be dockable
m_wndToolBar.EnableDocking(CBRS_ALIGN_ANY);
EnableDocking(CBRS_ALIGN_ANY);
DockControlBar(&m_wndToolBar);
//---------------------------------------------------------------
m_iscapture=FALSE;
m_after_skindect=FALSE;
m_enable_skindect=FALSE;
m_enable_facelac=FALSE;
videoflag=FALSE;
m_x1=-1;
m_x2=-1;
m_y1=-1;
m_y2=-1;
if(!m_wndSource.CreateEx(WS_EX_TOPMOST,NULL,"Source",
WS_CAPTION,CRect(100,100,150,180),NULL,0))
return -1;
m_wndSource.ShowWindow(SW_HIDE);
// AfxMessageBox("创建采集窗口",MB_OK,NULL);
m_hWndCap=capCreateCaptureWindow((LPSTR)"Video Capture Windows",
WS_CHILD|WS_VISIBLE,0,0,320,240,m_wndSource.m_hWnd,0);
capSetCallbackOnError(m_hWndCap,(FARPROC)ErrorCallbackProc);
capSetCallbackOnStatus(m_hWndCap,(FARPROC)StatusCallbackProc);
capSetCallbackOnVideoStream(m_hWndCap,(FARPROC)VideoCallbackProc);
// capSetCallbackOnFrame(m_hWndCap,(FARPROC)FrameCallbackProc);
capDriverConnect(m_hWndCap,0);//connect to the first VIDEOdriver;
capDriverGetCaps(m_hWndCap,&m_caps,sizeof(CAPDRIVERCAPS));
ChangeSize();
//---------------------------------------------------------------
return 0;
}
BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)
{
if( !CFrameWnd::PreCreateWindow(cs) )
return FALSE;
// TODO: Modify the Window class or styles here by modifying
// the CREATESTRUCT cs
return TRUE;
}
/////////////////////////////////////////////////////////////////////////////
// CMainFrame diagnostics
#ifdef _DEBUG
void CMainFrame::AssertValid() const
{
CFrameWnd::AssertValid();
}
void CMainFrame::Dump(CDumpContext& dc) const
{
CFrameWnd::Dump(dc);
}
#endif //_DEBUG
/////////////////////////////////////////////////////////////////////////////
// CMainFrame message handlers
//------------------------------------------------------------------
//TODO:Add your message handler code here and/or call default
void CMainFrame::OnAppExit()
{
capSetCallbackOnVideoStream(m_hWndCap,NULL);
capCaptureAbort(m_hWndCap);//stop to capture
capDriverDisconnect(m_hWndCap);
}
//----------------------------------------------------------------
//利用ClassWizard处理WM_CLOSE消息,结束相应的视频处理.
//----------------------------------------------------------------
void CMainFrame::OnClose()
{
OnAppExit();
CFrameWnd::OnClose();
}
//----------------------------------------------------------
//-----------------------------------------------------------------
void CMainFrame::OnFormat()
{
// TODO: Add your command handler code here
if(m_caps.fHasDlgVideoFormat )
{
capDlgVideoFormat(m_hWndCap);
ChangeSize();
}
}
void CMainFrame::OnPreview()
{
// TODO: Add your command handler code here
static BOOL bPreview = FALSE;
bPreview = !bPreview;
capPreviewRate(m_hWndCap,10);
capPreview(m_hWndCap,bPreview);
}
void CMainFrame::OnSource()
{
// TODO: Add your command handler code here
static BOOL bShow=FALSE;
bShow=!bShow;
m_wndSource.ShowWindow (bShow?SW_SHOW:SW_HIDE);
}
void CMainFrame::OnCapture()
{
// TODO: Add your command handler code here
static BOOL bCapture=FALSE;
CAPTUREPARMS CapParms;
bCapture=!bCapture;
m_x1=-1;
m_x2=-1;
m_y1=-1;
m_y2=-1;
m_iscapture=FALSE;
m_after_skindect=FALSE;
m_enable_skindect=FALSE;
m_enable_facelac=FALSE;
if(bCapture)
{
// AfxMessageBox("设置采集参数",MB_OK,NULL);
//Get the default setup for video capture from the AVICap Window
capCaptureGetSetup(m_hWndCap,&CapParms,sizeof(CAPTUREPARMS));
//set the defaults we won't bother the user with
CapParms.dwIndexSize=324000;//3(hour)*30(fps)*60*60
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -