// 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(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(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 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 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 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, ¶m); param.minSize = 48; param.maxSize = 600; param.pConfigFile = sModelXmlPath.c_str(); // 设置接口功能参数 cwSetFaceParam(m_pDetThread, ¶m); } //创建活体句柄 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(); }