You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

845 lines
21 KiB

// Demo_Live_MFCDlg.cpp : 实现文件
//
#include "stdafx.h"
#include "Demo_Live_MFC.h"
#include "Demo_Live_MFCDlg.h"
#include "afxdialogex.h"
#include "CWFaceDetection.h"
#include "CWFaceVersion.h"
#include "CWFaceNisLiveness.h"
#define NIRLIV_FACE_NUM 1 //红外检测人脸数
#define MAX_DET_NUM_FACES 10 // 检测线程的人脸数
#define MAX_NISLIVE_NUM_FACES 3 // 红外检测时人脸数
#define NUM_LIST_MAT 5 // 图片数据链表长度,5个中有三个为活体,则判断为活体
#define CW_LICENCE "" // 云从授权码
#define WM_THREAD_SHOWVIDEO WM_USER + 101 // 自定义消息
//线条颜色,画框的
static cv::Scalar& color = cv::Scalar(0, 0, 255);
static cv::Scalar& colorGreen = cv::Scalar(0, 255, 0);
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
// CDemo_Live_MFCDlg 对话框
CDemo_Live_MFCDlg::CDemo_Live_MFCDlg(CWnd* pParent /*=NULL*/)
: CDialogEx(CDemo_Live_MFCDlg::IDD, pParent)
{
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
m_pDetThread = nullptr;
m_bInitNirLiv = false;
m_bStartThread = false;
m_pNirLiv = nullptr;
}
void CDemo_Live_MFCDlg::DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
DDX_Control(pDX, IDC_EDIT_VERSION, m_edtVersion);
DDX_Control(pDX, IDC_EDIT_SCORE, m_edtCameraLiveScore);
DDX_Control(pDX, IDC_EDIT_RESULT, m_edtCameraLiveResult);
DDX_Control(pDX, IDC_EDIT_TIME, m_edtCameraLiveTime);
DDX_Control(pDX, IDC_EDIT_SCORE2, m_edtPicLiveScore);
DDX_Control(pDX, IDC_EDIT_RESULT2, m_edtPicLiveResult);
DDX_Control(pDX, IDC_EDIT_TIME2, m_edtPicLiveTime);
DDX_Control(pDX, IDC_STATIC_PIC1, m_staticPic1);
DDX_Control(pDX, IDC_STATIC_PIC2, m_staticPic2);
DDX_Control(pDX, IDC_STATIC_VIDEO, m_staticVideo);
}
BEGIN_MESSAGE_MAP(CDemo_Live_MFCDlg, CDialogEx)
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_BN_CLICKED(IDC_BTN_INIT, &CDemo_Live_MFCDlg::OnBnClickedBtnInit)
ON_BN_CLICKED(IDC_BTN_OPENUSB, &CDemo_Live_MFCDlg::OnBnClickedBtnOpenusb)
ON_BN_CLICKED(IDC_BTN_LIVE_CAMERA, &CDemo_Live_MFCDlg::OnBnClickedBtnLiveCamera)
ON_BN_CLICKED(IDC_BTN_CAMERA, &CDemo_Live_MFCDlg::OnBnClickedBtnCamera)
ON_BN_CLICKED(IDC_BTN_LOAD1, &CDemo_Live_MFCDlg::OnBnClickedBtnLoad1)
ON_BN_CLICKED(IDC_BTN_LOAD2, &CDemo_Live_MFCDlg::OnBnClickedBtnLoad2)
ON_BN_CLICKED(IDC_BTN_PIC_LIVE, &CDemo_Live_MFCDlg::OnBnClickedBtnPicLive)
ON_MESSAGE(WM_THREAD_SHOWVIDEO, &CDemo_Live_MFCDlg::OnThreadShowVideo)
ON_WM_DESTROY()
END_MESSAGE_MAP()
// CDemo_Live_MFCDlg 消息处理程序
BOOL CDemo_Live_MFCDlg::OnInitDialog()
{
CDialogEx::OnInitDialog();
// 设置此对话框的图标。当应用程序主窗口不是对话框时,框架将自动
// 执行此操作
SetIcon(m_hIcon, TRUE); // 设置大图标
SetIcon(m_hIcon, FALSE); // 设置小图标
// TODO: 在此添加额外的初始化代码
m_staticPic1.GetClientRect(&m_rectPic1);
m_hDCPic1 = m_staticPic1.GetDC()->GetSafeHdc();
m_staticPic2.GetClientRect(&m_rectPic2);
m_hDCPic2 = m_staticPic2.GetDC()->GetSafeHdc();
m_staticVideo.GetClientRect(&m_rectVideo);
m_hDCVideo = m_staticVideo.GetDC()->GetSafeHdc();
return TRUE; // 除非将焦点设置到控件,否则返回 TRUE
}
// 如果向对话框添加最小化按钮,则需要下面的代码
// 来绘制该图标。对于使用文档/视图模型的 MFC 应用程序,
// 这将由框架自动完成。
void CDemo_Live_MFCDlg::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this); // 用于绘制的设备上下文
SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);
// 使图标在工作区矩形中居中
int cxIcon = GetSystemMetrics(SM_CXICON);
int cyIcon = GetSystemMetrics(SM_CYICON);
CRect rect;
GetClientRect(&rect);
int x = (rect.Width() - cxIcon + 1) / 2;
int y = (rect.Height() - cyIcon + 1) / 2;
// 绘制图标
dc.DrawIcon(x, y, m_hIcon);
}
else
{
CDialogEx::OnPaint();
}
}
//当用户拖动最小化窗口时系统调用此函数取得光标
//显示。
HCURSOR CDemo_Live_MFCDlg::OnQueryDragIcon()
{
return static_cast<HCURSOR>(m_hIcon);
}
// 初始化
void CDemo_Live_MFCDlg::OnBnClickedBtnInit()
{
// TODO: 在此添加控件通知处理程序代码
char szVersion[100] = {0};
cw_errcode_t errCode = cwGetSDKVersion(szVersion, 100);
m_edtVersion.SetWindowText((CString)szVersion);
// [3/3/2017 Lit]:创建句柄
if (m_bInitNirLiv)
{
MessageBox(_T("已初始化过,不再初始化"));
return;
}
if (CreateFaceHandle())
{
MessageBox(_T("初始化成功"));
}
}
// 开启双目摄像头
void CDemo_Live_MFCDlg::OnBnClickedBtnOpenusb()
{
// TODO: 在此添加控件通知处理程序代码
// TODO: 在此添加控件通知处理程序代码
if (nullptr == m_pDetThread)
{
MessageBox(_T("检测句柄为空,请先初始化创建句柄"));
return;
}
if (m_bStartThread)
{
MessageBox(_T("摄像头已打开"));
return;
}
if (!m_captureVis.open(1))
{
MessageBox(_T("可见光摄像头打开失败"));
return;
}
if (!m_captureNis.open(0))
{
MessageBox(_T("红外摄像头打开失败"));
return;
}
m_bStartThread = true;
m_threadFaceDet = std::thread(&CDemo_Live_MFCDlg::ThreadFaceDet, this);
m_threadFaceDet.detach();
}
// 动态摄像头红外活体检测
void CDemo_Live_MFCDlg::OnBnClickedBtnLiveCamera()
{
// TODO: 在此添加控件通知处理程序代码
if (!m_bStartThread)
{
MessageBox(_T("请先打开双目摄像头"));
return;
}
ListMat visTemp, nisTemp;
{
std::lock_guard<std::mutex> lock(m_mutex);
if (m_listVisFrame.size() != NUM_LIST_MAT)
{
MessageBox(_T("可见光图片数据链表长度不为5"));
return;
}
if (m_listNisFrame.size() != NUM_LIST_MAT)
{
MessageBox(_T("红外图片数据链表长度不为5"));
return;
}
visTemp = m_listVisFrame;
nisTemp = m_listNisFrame;
}
DWORD tmBegin = GetTickCount();
ListMat::iterator itVis = visTemp.begin();
ListMat::iterator itNis = nisTemp.begin();
cw_nirliv_res_t resLive;
int iLiveNum = 0;
for (int i = 0; i < NUM_LIST_MAT; i++, itVis++, itNis++)
{
if (GetNisLiveStateByMat(*itVis, *itNis, &resLive) == CW_NIRLIV_OK && resLive.livRst == CW_NIR_LIV_DET_LIVE)
{
iLiveNum++;
}
}
CString sScore, sResult, sTime;
sTime.Format(_T("%d ms"), GetTickCount() - tmBegin);
sScore.Format(_T("%d"), iLiveNum);
if (iLiveNum >= 3)
{
sResult = _T("活体");
}
else
{
sResult = _T("非活体");
}
m_edtCameraLiveScore.SetWindowText(sScore);
m_edtCameraLiveResult.SetWindowText(sResult);
m_edtCameraLiveTime.SetWindowText(sTime);
}
// 双目摄像头拍照
void CDemo_Live_MFCDlg::OnBnClickedBtnCamera()
{
// TODO: 在此添加控件通知处理程序代码
if (!m_bStartThread)
{
MessageBox(_T("请先打开双目摄像头"));
return;
}
{
std::lock_guard<std::mutex> lock(m_mutex);
if (!m_listVisFrame.empty())
{
cv::imwrite("./1.jpg", m_listVisFrame.back());
}
else
{
MessageBox(_T("可见光图片数据链表为空"));
return;
}
if (!m_listNisFrame.empty())
{
cv::imwrite("./2.jpg", m_listNisFrame.back());
}
else
{
MessageBox(_T("红外图片数据链表为空"));
return;
}
}
m_sPic1Path = "./1.jpg";
m_sPic2Path = "./2.jpg";
ShowImg(m_sPic1Path, m_hDCPic1, m_rectPic1);
ShowImg(m_sPic2Path, m_hDCPic2, m_rectPic2);
}
// 导入可见光照片
void CDemo_Live_MFCDlg::OnBnClickedBtnLoad1()
{
// TODO: 在此添加控件通知处理程序代码
CFileDialog dlg(TRUE, _T("jpg|bmp|png"), NULL, OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,
_T("Image Files(*.jpg;*.bmp;*.png)|*.jpg;*.bmp;*.png|All Files(*.*)|*.*||"), this);
if (IDOK != dlg.DoModal())
{
return;
}
m_sPic1Path = dlg.GetPathName();
ShowImg(m_sPic1Path, m_hDCPic1, m_rectPic1);
}
// 导入红外照片
void CDemo_Live_MFCDlg::OnBnClickedBtnLoad2()
{
// TODO: 在此添加控件通知处理程序代码
CFileDialog dlg(TRUE, _T("jpg|bmp|png"), NULL, OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,
_T("Image Files(*.jpg;*.bmp;*.png)|*.jpg;*.bmp;*.png|All Files(*.*)|*.*||"), this);
if (IDOK != dlg.DoModal())
{
return;
}
m_sPic2Path = dlg.GetPathName();
ShowImg(m_sPic2Path, m_hDCPic2, m_rectPic2);
}
// 静态图片红外活体检测
void CDemo_Live_MFCDlg::OnBnClickedBtnPicLive()
{
// TODO: 在此添加控件通知处理程序代码
if (!m_bInitNirLiv)
{
MessageBox(_T("请先点击初始化按钮,初始化红外活体检测服务"));
return;
}
if (m_sPic1Path.IsEmpty())
{
MessageBox(_T("请先导入可见光人脸图片"));
return;
}
if (m_sPic2Path.IsEmpty())
{
MessageBox(_T("请先导入红外人脸图片"));
return;
}
cv::Mat matImageVis = cv::imread((std::string)(_bstr_t)(LPCWSTR)m_sPic1Path);
if (matImageVis.empty())
{
MessageBox(_T("PicVis Not Found"));
return;
}
cv::Mat matImageNis = cv::imread((std::string)(_bstr_t)(LPCWSTR)m_sPic2Path);
if (matImageNis.empty())
{
MessageBox(_T("PicNis Not Found"));
return;
}
DWORD tmBegin = GetTickCount();
cw_nirliv_res_t resLive;
int iRetLive = GetNisLiveStateByMat(matImageVis, matImageNis, &resLive);
CString sScore, sResult, sTime;
sTime.Format(_T("%d ms"), GetTickCount() - tmBegin);
sScore.Format(_T("%.6f"), resLive.score);
if (iRetLive == CW_NIRLIV_OK) // 红外活体检测成功,显示状态(活体非活体)
{
sResult.Format(_T("%d"), resLive.livRst);
}
else // 红外活体检测失败,显示错误码
{
sResult.Format(_T("%d"), iRetLive);
}
m_edtPicLiveScore.SetWindowText(sScore);
m_edtPicLiveResult.SetWindowText(sResult);
m_edtPicLiveTime.SetWindowText(sTime);
}
int CDemo_Live_MFCDlg::GetNisLiveStateByMat(const cv::Mat &matImageVis, const cv::Mat &matImageNir, cw_nirliv_res_t *res)
{
// 判断图片通道值
cw_img_form_t formatVis;
if (matImageVis.channels()==1)
{
formatVis = CW_IMAGE_GRAY8;
}
else if (matImageVis.channels()==3)
{
formatVis = CW_IMAGE_BGR888;
}
else if (matImageVis.channels()==4)
{
formatVis = CW_IMAGE_BGRA8888;
}
else
{
return CW_NIRLIV_ERR_VISIMAGE;
}
cw_img_form_t formatNir;
if (matImageNir.channels()==1)
{
formatNir = CW_IMAGE_GRAY8;
}
else if (matImageNir.channels()==3)
{
formatNir = CW_IMAGE_BGR888;
}
else if (matImageNir.channels()==4)
{
formatNir = CW_IMAGE_BGRA8888;
}
else
{
return CW_NIRLIV_ERR_NIRIMAGE;
}
cw_nirliv_det_rst_t state = CW_NIR_LIV_DET_IS_INIT;
float fScore = 0.0f;
cw_errcode_t errCode = NirLivDet((char*)matImageVis.data, 0, matImageVis.cols, matImageVis.rows, formatVis,
(char*)matImageNir.data, 0, matImageNir.cols, matImageNir.rows, formatNir, &state, &fScore);
res->livRst = state;
res->score = fScore;
return errCode;
}
int CDemo_Live_MFCDlg::GetFaceInfoByMat(void *pDetHandle, const cv::Mat &matImage, cw_face_res_t* pFaceBuffer)
{
if (matImage.empty())
{
return 0;
}
cw_img_t srcImg;
srcImg.frameId = 0;
srcImg.data = (char*)matImage.data;
srcImg.width = matImage.cols;
srcImg.height = matImage.rows;
srcImg.angle = CW_IMAGE_ANGLE_0;
srcImg.mirror = CW_IMAGE_MIRROR_NONE;
if (matImage.channels()==1)
{
srcImg.format = CW_IMAGE_GRAY8;
}
else if (matImage.channels()==3)
{
srcImg.format = CW_IMAGE_BGR888;
}
else if (matImage.channels()==4)
{
srcImg.format = CW_IMAGE_BGRA8888;
}
else
{
return 0;
}
int iFaceNum = 0;
// 检测,关键点与质量分
cw_errcode_t errCode = cwFaceDetection(pDetHandle, &srcImg, pFaceBuffer, MAX_NISLIVE_NUM_FACES, &iFaceNum, CW_OP_DET | CW_OP_KEYPT | CW_OP_QUALITY);
if (errCode != CW_SDKLIT_OK)
{
/*
CString sErrorTip;
sErrorTip.Format(_T("人脸检测失败,错误码:%d"), errCode);
MessageBox(sErrorTip);*/
return 0;
}
if (iFaceNum < 1)
{
return 0;
}
return iFaceNum;
}
void CDemo_Live_MFCDlg::ThreadFaceDet()
{
cv::Mat matImage, matImageVis, matImageNis;
cw_face_res_t faceBuffers[MAX_DET_NUM_FACES];
while (m_bStartThread)
{
{
std::lock_guard<std::mutex> lock(m_mutex);
// 可见光
m_captureVis >> matImageVis;
if (matImageVis.empty())
{
continue;
}
// 红外
m_captureNis >> matImageNis;
if (matImageNis.empty())
{
continue;
}
if (m_listVisFrame.size() >= NUM_LIST_MAT)
{
m_listVisFrame.pop_front();
}
m_listVisFrame.push_back(matImageVis.clone());
if (m_listNisFrame.size() >= NUM_LIST_MAT)
{
m_listNisFrame.pop_front();
}
m_listNisFrame.push_back(matImageNis.clone());
matImage = matImageVis.clone();
}
// 给图像结构体赋值
cw_img_t srcImg;
srcImg.frameId = 0;
srcImg.data = (char*)matImage.data;
srcImg.width = matImage.cols;
srcImg.height = matImage.rows;
srcImg.angle = CW_IMAGE_ANGLE_0;
srcImg.mirror = CW_IMAGE_MIRROR_NONE;
if (matImage.channels() ==1 )
{
srcImg.format = CW_IMAGE_GRAY8;
}
else if (matImage.channels() == 3)
{
srcImg.format = CW_IMAGE_BGR888;
}
else if (matImage.channels() == 4)
{
srcImg.format = CW_IMAGE_BGRA8888;
}
else
{
continue;
}
// 人脸检测
int iFaceNum = 0;
cw_errcode_t errCode = cwFaceDetection(m_pDetThread, &srcImg, faceBuffers, MAX_DET_NUM_FACES, &iFaceNum, CW_OP_DET);
for (int i = 0; i < iFaceNum; i++)
{
cv::Point dst1(faceBuffers[i].faceRect.x, faceBuffers[i].faceRect.y);
cv::Point dst2(faceBuffers[i].faceRect.x + faceBuffers[i].faceRect.width, faceBuffers[i].faceRect.y + faceBuffers[i].faceRect.height);
//画框
cv::rectangle(matImage, dst1, dst2, color, 3);
}
SendMessage(WM_THREAD_SHOWVIDEO, 0, (LPARAM)&matImage);
}
}
LRESULT CDemo_Live_MFCDlg::OnThreadShowVideo(WPARAM wPapam, LPARAM lPapam)
{
cv::Mat matImage = *((cv::Mat*)lPapam);
if (!matImage.empty())
{
ShowVideo((char*)(matImage.data), matImage.cols, matImage.rows);
}
return 0;
}
bool CDemo_Live_MFCDlg::CreateFaceHandle()
{
// 32位和64位检测模型不能共用,64位用_configs_frontend.xml,非64位用_configs_frontend_x86_arm.xml
#ifdef DEMO_X64
std::string sModelXmlPath = "../../CWModels/_configs_frontend.xml";
#else
std::string sModelXmlPath = "../../CWModels/_configs_frontend_x86_arm.xml";
#endif // DEMO_X64
CString sErrorTip;
cw_errcode_t errCode = CW_SDKLIT_OK;
if (m_pDetThread != nullptr)
{
MessageBox(_T("检测句柄已创建过,不再创建"));
}
else
{
m_pDetThread = cwCreateDetHandle(&errCode, sModelXmlPath.c_str(), CW_LICENCE);
if (CW_SDKLIT_OK != errCode || nullptr == m_pDetThread)
{
sErrorTip.Format(_T("创建检测句柄错误,错误码:%d"), errCode);
MessageBox(sErrorTip);
return false;
}
cw_det_param_t param;
cwGetFaceParam(m_pDetThread, &param);
param.minSize = 48;
param.maxSize = 600;
param.pConfigFile = sModelXmlPath.c_str(); // 设置接口功能参数
cwSetFaceParam(m_pDetThread, &param);
}
//创建活体句柄
if (m_pNirLiv == NULL)
{
cw_nirliveness_err_t errCodeNir = CW_NIRLIV_OK;
m_pNirLiv = cwCreateNirLivenessHandle(&errCodeNir,"../../CWModels/nirLiveness_model_20181102_pc.bin","../../CWModels/hd171019.bin",
"../../CWModels/matrix_para480x640.xml", "./log", 0.35, CW_LICENCE);
if (NULL == m_pNirLiv)
{
sErrorTip.Format(_T("红外活体服务初始化失败,错误码:%d"), errCode);
MessageBox(sErrorTip);
return (cw_errcode_t)errCodeNir;
}
}
m_bInitNirLiv = true;
return true;
}
void CDemo_Live_MFCDlg::ReleaseFaceHandle()
{
m_bStartThread = false;
m_captureVis.release();
m_captureNis.release();
// 程序退出时销毁句柄
if (m_pDetThread != nullptr)
{
cwReleaseDetHandle(m_pDetThread);
m_pDetThread = nullptr;
}
//关闭红外活体服务
if (m_pNirLiv != NULL)
{
cwReleaseNirLivenessHandle(m_pNirLiv);
m_pNirLiv = NULL;
}
DeleteDC(m_hDCVideo);
DeleteDC(m_hDCPic1);
DeleteDC(m_hDCPic2);
}
cw_errcode_t CDemo_Live_MFCDlg::NirLivDet(char* imgDataVis, int iDataLenVis, int iWidthVis, int iHeightVis, cw_img_form_t formatVis,
char* imgDataNir, int iDataLenNir, int iWidthNir, int iHeightNir, cw_img_form_t formatNir,
cw_nirliv_det_rst_t *state, float *fScore)
{
if (imgDataVis == NULL)
{
return (cw_errcode_t)CW_NIRLIV_ERR_VISIMAGE;
}
if (imgDataNir == NULL)
{
return (cw_errcode_t)CW_NIRLIV_ERR_NIRIMAGE;
}
// 可见光人脸检测
cw_face_res_t *faceBuffersVis = new cw_face_res_t();
cw_errcode_t errCode = GetFaceInfoByImg(m_pDetThread, imgDataVis, iDataLenVis, iWidthVis, iHeightVis, formatVis, faceBuffersVis);
if (errCode != CW_SDKLIT_OK)
{
delete faceBuffersVis;
if (errCode == -1)
{
return (cw_errcode_t)CW_NIRLIV_ERR_VIS_NO_FACE;
}
else
{
return errCode;
}
}
// 红外人脸检测
cw_face_res_t *faceBuffersNir = new cw_face_res_t();
errCode = GetFaceInfoByImg(m_pDetThread, imgDataNir, iDataLenNir, iWidthNir, iHeightNir, formatNir, faceBuffersNir);
if (errCode != CW_SDKLIT_OK)
{
delete faceBuffersVis;
delete faceBuffersNir;
if (errCode == -1)
{
return (cw_errcode_t)CW_NIRLIV_ERR_NIR_NO_FACE;
}
else
{
return errCode;
}
}
// 红外活体检测
cw_nirliv_detinfo_t detInfo;
detInfo.nLandmarks = faceBuffersVis->keypt.nkeypt;
// 红外图片数据
detInfo.pNirImg = new cw_nirliv_img_t();
detInfo.pNirImg->data = imgDataNir;
detInfo.pNirImg->dataLen = iDataLenNir;
detInfo.pNirImg->width = iWidthNir;
detInfo.pNirImg->height = iHeightNir;
detInfo.pNirImg->format = formatNir;
// 可见光图片数据
detInfo.pVisImg = new cw_nirliv_img_t();
detInfo.pVisImg->data = imgDataVis;
detInfo.pVisImg->dataLen = iDataLenVis;
detInfo.pVisImg->width = iWidthVis;
detInfo.pVisImg->height = iHeightVis;
detInfo.pVisImg->format = formatVis;
detInfo.pVisInfo = new cw_nirliv_face_param_t(); // 可见光人脸信息
detInfo.pVisInfo->pKeypoints = faceBuffersVis->keypt.points;
detInfo.pVisInfo->fKeyScore = faceBuffersVis->keypt.keyptScore; // 质量分
detInfo.pVisInfo->fSkinScore = faceBuffersVis->quality.scores[6]; // 肤色分
detInfo.pNirInfo = new cw_nirliv_face_param_t(); // 红外人脸信息
detInfo.pNirInfo->pKeypoints = faceBuffersNir->keypt.points;
detInfo.pNirInfo->fKeyScore = faceBuffersNir->keypt.keyptScore; // 质量分
detInfo.pNirInfo->fSkinScore = faceBuffersNir->quality.scores[6]; // 肤色分
cw_nirliv_res_t *pNisLivenessRes = new cw_nirliv_res_t();
cw_nirliveness_err_t errNis = cwFaceNirLivenessDet(m_pNirLiv, &detInfo, pNisLivenessRes);
if (errNis == CW_NIRLIV_OK)
{
*state = pNisLivenessRes->livRst;
*fScore = pNisLivenessRes->score;
}
delete faceBuffersVis;
delete faceBuffersNir;
delete detInfo.pNirImg;
delete detInfo.pVisImg;
delete detInfo.pVisInfo;
delete detInfo.pNirInfo;
delete pNisLivenessRes;
return (cw_errcode_t)errNis;
}
cw_errcode_t CDemo_Live_MFCDlg::GetFaceInfoByImg(void *pDetHandle, char *pImgData, int iImgLen, int iWidth,
int iHeight, cw_img_form_t format, cw_face_res_t* pFaceBuffer)
{
cw_img_t srcImg;
srcImg.frameId = 0;
srcImg.data = pImgData;
srcImg.dataLen = iImgLen;
srcImg.width = iWidth;
srcImg.height = iHeight;
srcImg.angle = CW_IMAGE_ANGLE_0;
srcImg.mirror = CW_IMAGE_MIRROR_NONE;
srcImg.format = format;
int iFaceNum = 0;
// 检测,关键点与质量分
cw_errcode_t errCode = cwFaceDetection(pDetHandle, &srcImg, pFaceBuffer, NIRLIV_FACE_NUM, &iFaceNum, CW_OP_DET | CW_OP_KEYPT | CW_OP_QUALITY);
if (errCode != CW_SDKLIT_OK)
{
return errCode;
}
if (iFaceNum < 1)
{
return (cw_errcode_t)-1;
}
return CW_SDKLIT_OK;
}
/************************************************************************/
/* 显示视频 */
/************************************************************************/
void CDemo_Live_MFCDlg::ShowVideo(char* szFrame, int iImgWidth, int iImgHeight)
{
BITMAPINFO BmpInfo;
BmpInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
BmpInfo.bmiHeader.biWidth = (LONG)iImgWidth;
BmpInfo.bmiHeader.biHeight = (LONG)iImgHeight;
BmpInfo.bmiHeader.biPlanes = 1;
BmpInfo.bmiHeader.biBitCount = 24;
BmpInfo.bmiHeader.biCompression = BI_RGB;
BmpInfo.bmiHeader.biSizeImage = 0;
BmpInfo.bmiHeader.biXPelsPerMeter = 0;
BmpInfo.bmiHeader.biYPelsPerMeter = 0;
BmpInfo.bmiHeader.biClrUsed = 0;
BmpInfo.bmiHeader.biClrImportant = 0;
SetStretchBltMode(m_hDCVideo, COLORONCOLOR);
StretchDIBits(m_hDCVideo, 0, (m_rectVideo.bottom - m_rectVideo.top), (m_rectVideo.right - m_rectVideo.left), (m_rectVideo.top - m_rectVideo.bottom),
0, 0, iImgWidth, iImgHeight, szFrame, &BmpInfo, DIB_RGB_COLORS, SRCCOPY);
}
void CDemo_Live_MFCDlg::ShowImg(CString sPicPath, HDC hDCVideo, RECT rectVideo)
{
cv::Mat matImage = cv::imread((std::string)(_bstr_t)(LPCWSTR)sPicPath);
if (matImage.empty())
{
return;
}
if (matImage.channels() == 4)
{
cv::Mat matTemp;
cv::cvtColor(matImage, matTemp, CV_BGRA2BGR);
matImage = matTemp.clone();
}
// 要显示宽度必须是4的倍数
int iWidth = matImage.cols;
int iHeight = matImage.rows;
if (0 != iWidth % 4)
{
iWidth = iWidth / 4 * 4;
int iWidthCut = matImage.cols - iWidth;
int iLeft = iWidthCut / 2;
int iRight = iWidth + iLeft;
matImage = matImage.colRange(iLeft, iRight).clone();
}
BITMAPINFO BmpInfo;
BmpInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
BmpInfo.bmiHeader.biWidth = (LONG)iWidth;
BmpInfo.bmiHeader.biHeight = (LONG)iHeight;
BmpInfo.bmiHeader.biPlanes = 1;
BmpInfo.bmiHeader.biBitCount = 24;
BmpInfo.bmiHeader.biCompression = BI_RGB;
BmpInfo.bmiHeader.biSizeImage = 0;
BmpInfo.bmiHeader.biXPelsPerMeter = 0;
BmpInfo.bmiHeader.biYPelsPerMeter = 0;
BmpInfo.bmiHeader.biClrUsed = 0;
BmpInfo.bmiHeader.biClrImportant = 0;
SetStretchBltMode(hDCVideo, COLORONCOLOR);
StretchDIBits(hDCVideo, 0, (rectVideo.bottom - rectVideo.top), (rectVideo.right - rectVideo.left), (rectVideo.top - rectVideo.bottom),
0, 0, iWidth, iHeight, matImage.data, &BmpInfo, DIB_RGB_COLORS, SRCCOPY);
}
void CDemo_Live_MFCDlg::OnDestroy()
{
CDialogEx::OnDestroy();
// TODO: 在此处添加消息处理程序代码
ReleaseFaceHandle();
}