// libfacecapture.cpp : 定义 DLL 应用程序的导出函数。 // #include "libfacecapture.h" #include #ifdef _WIN32 #include #include #else #include #include #include #endif #include #include #include "cv.h" #include "highgui.h" #include "libvideoqueue.h" #define SLASH '/' #define BACK_SLASH '\\' #define MB_SLASH_STR "/" #define MB_BACK_SLASH_STR "\\" #define W_SLASH_STR L"/" #define W_BACK_SLASH_STR L"\\" #if defined(UNICODE) || defined(_UNICODE) #define SLASH_STR W_SLASH_STR #define BACK_SLASH_STR W_BACK_SLASH_STR #else #define SLASH_STR MB_SLASH_STR #define BACK_SLASH_STR MB_BACK_SLASH_STR #endif #ifdef _WIN32 #define SPLIT_SLASH BACK_SLASH #define SPLIT_SLASH_STR BACK_SLASH_STR #define MB_SPLIT_SLASH_STR MB_BACK_SLASH_STR #define W_SPLIT_SLASH_STR W_BACK_SLASH_STR #define LINE_BREAK_STR "\r\n" #else #define SPLIT_SLASH SLASH #define SPLIT_SLASH_STR SLASH_STR #define MB_SPLIT_SLASH_STR MB_SLASH_STR #define W_SPLIT_SLASH_STR W_SLASH_STR #define LINE_BREAK_STR "\n" #endif #define CASCADE_FACE "haarcascade_frontalface_alt.xml" #define CASCADE_EYE "haarcascade_mcs_eyepair_small.xml" #define CASCADE_NOSE "haarcascade_mcs_nose.xml" #define CASCADE_MOUTH "haarcascade_mcs_mouth.xml" #define MAX_FACE_NUM 6 //最多保留6张人脸 #define RGB_IMG 1 //RGB格式的图像 //将图像区域分成9宫格,此枚举用来表示人脸所处9宫格的区域 enum FaceRegionEnum { FaceError = 0, FaceRegionLeftup, //左上角 FaceRegionUp, //正上方 FaceRegionRightUP, //右上角 FaceRegionLeft, //左边 FaceRegionCenter, //中央 FaceRegionRight, //右边 FaceRegionLeftDn, //左下角 FaceRegionDn, //正下方 FaceRegionRightDn, //右下角 }; //运动跟踪结果 struct CMotionTrackRslt { int nObjNum; //当前图像中运动物体的数量 CvRect ObjRect[MAX_FACE_NUM]; //存放运动物体 }; //客户位置 struct CCustomerRegion { FaceRegionEnum eRegion; //人脸中心点在图像9宮格中属于哪个宮格 CvRect stFaceRect; //脸部矩形,使用crect表示人脸在图像中精确位置 CvRect stUpperBodyRect; //脸部剪辑矩形,使用crect表示人脸剪辑区域 }; //客户信息,程序内部逻辑使用 struct CCustomerInfo { uint64_t FaceID; //人脸ID号 CameraEnum eCamera; //1、2号摄像头 CCustomerRegion stRegion; //客户位置,客户脸部的矩形区域 SceneEnum eScene; //0不确定,1开始锁定、2失去锁定、3晃动、4向前、5向后 DistanceEnum eDistance; //0不确定,1操作距离,2近端,3远端 PoseEnum ePose; //0不确定,1-站立,2-坐立 CCover stCustomerCover; //覆盖属性 BrightnessEnum eBrightness; //人脸亮度 SexEnum eSex; //0不知道,1女,2男 YoungOldEnum eYoungOld; //0不知道,1小孩,2年轻人,3中年人,4老人 HeightEnunm eHeight; //0不知道,1矮,2中等,3高 }; //计算过程中用于存储人脸的缓存 struct CAllFaceInfo { int nTatolFaceNum; //当前图像帧中人脸数量 CCustomerInfo astFaceInfo[MAX_FACE_NUM]; //所有用户的人脸,astFaceInfo[0]为主用户的人脸 }; //图像亮度调整参数 struct CBrightAdjParam { double fLow; //映射前低值 double fHigh; //映射前高值 double fBottom; //映射后低值 double fTop; //映射后高值 double fGamma; //gamma变换值 }; //用于本地保存人脸的结构体 struct CLocalFaceInfo { CCover stFaceCover; //人脸覆盖 CCustomerRegion stCustomerRegion; //人脸位置 IplImage*img; //人脸图像 }; enum MonitorStateEnum { NoBody = 0, //当前没有人 SomebodyFar, //远距离有人 SomebodyClose, //有人在靠近 SomebodyOperate //客户进入操作区域 }; class Clibfacecapture_impl { public: Clibfacecapture_impl(bool *pResult, CHostApi *pHostAPI, CVideoMonitorEvent*pHost, const char* EnvironMinVideoName, const char* EnvironMaxVideoName, const char* OperateVideoName = NULL, MonitorEnum eMonitorType = MotionTarckAndFaceDetect) { m_pResult = pResult; m_pHostApi = pHostAPI; m_pHostEvent = pHost; m_eType = eMonitorType; m_pFaceCascade = NULL; //脸部分类器 m_pEyeCascade = NULL; //眼睛分类器 m_pMouthCascade = NULL; //嘴巴分类器 m_pNoseCascade = NULL; //鼻子分类器 m_pFaceStorage = NULL; pfaceSeq = NULL; m_pProcessImg = NULL; #ifdef _WIN32 m_hVieoMonitorThread = NULL; m_nVieoMonitorThreadId = 0; #else m_videomonitorthreadid = 0; #endif m_bStopVieoMonitor = false; m_pEnvironMinVideoQueue = NULL; m_pEnvironMaxVideoQueue = NULL; m_pOperatorVideoQueue = NULL; m_nImgWidth = 0; m_nImgHeight = 0; m_pMhImg = NULL; m_pMhBuf = NULL; m_bLightChange = false; m_nCameraState = 0; m_nLastBuf = 0; //m_nCapFaceNum = 0; //m_bCapFaceCompleted = false; m_eMonitorState = NoBody; memset(m_envminqueuename, 0, MAX_PATH); memset(m_envmaxqueuename, 0, MAX_PATH); memset(m_optqueuename, 0, MAX_PATH); if (NULL != EnvironMinVideoName){ strncpy(m_envminqueuename, EnvironMinVideoName, (strlen(EnvironMinVideoName) > MAX_PATH) ? (MAX_PATH - 1) : strlen(EnvironMinVideoName)); } if (NULL != EnvironMaxVideoName) { strncpy(m_envmaxqueuename, EnvironMaxVideoName, (strlen(EnvironMaxVideoName) > MAX_PATH) ? (MAX_PATH - 1) : strlen(EnvironMaxVideoName)); } if (NULL != OperateVideoName) { strncpy(m_optqueuename, OperateVideoName, (strlen(OperateVideoName) > MAX_PATH) ? (MAX_PATH - 1) : strlen(OperateVideoName)); } #ifdef _WIN32 InitializeCriticalSection(&CS); m_hStopEventWait= ::CreateEventA(NULL, TRUE, 0, 0); if (!m_hStopEventWait) { *pResult = false; pHostAPI->Debug(FACECAP_INFO, "create hEventWait failed!"); return; } #else pthread_mutex_init(&cs_mutex, NULL); sem_init(&m_semt, 0, 0); #endif memset(&m_stFaceConfig,0,sizeof(CFaceCaptureConfig)); memset(&m_stFaceRstStorage,0,sizeof(CFaceCaptureConfig)); //读取配置文件 *pResult = pHostAPI->LoadConfig(m_stFaceConfig); if (!*pResult){ pHostAPI->Debug(FACECAP_INFO, "Load Configuration failed!"); return; } *pResult = InitFaceCapture(m_stFaceConfig.strFaceDataDirPath); if (!*pResult){ return; } for (int i = 0; i < MAX_FACE_NUM; i++) { m_PreFaceRect[i] = cvRect(0, 0, 0, 0); } memset(&m_stAllFaceInfo, 0, sizeof(CAllFaceInfo)); //初始化剪辑区域为屏幕中央区域 m_stAllFaceInfo.astFaceInfo[0].stRegion.stUpperBodyRect = cvRect(160, 60, 320, 240); //for (int j = 0; j < 3; j++) { // memset(&m_stCapFace[j], 0, sizeof(CLocalFaceInfo)); //} //memset(m_SaveImgName, 0, MAX_PATH); memset(&m_stObjTrackRslt, 0, sizeof(CMotionTrackRslt)); memset(&m_stBrightAdjParam, 0, sizeof(CBrightAdjParam)); *pResult = WriteAllFaceInfo(m_stAllFaceInfo); if (!*pResult) { return; } } bool StartFaceCapture() { m_pEnvironMinVideoQueue = new Clibvideoqueue(m_envminqueuename); if (strlen(m_envmaxqueuename)) { m_pEnvironMaxVideoQueue = new Clibvideoqueue(m_envmaxqueuename); } if (strlen(m_optqueuename)) { m_pOperatorVideoQueue = new Clibvideoqueue(m_optqueuename); } else { m_pOperatorVideoQueue = NULL; } //开始视频监控线程 return StartVideoMonitor(m_pHostApi, m_pHostEvent, m_eType); } bool StopFaceCapture() { m_pHostApi->Debug(FACECAP_DEBUG, "%s:%d.", __FUNCTION__, __LINE__); if (true == StopVideoMonitor()){ m_pHostApi->Debug(FACECAP_DEBUG, "Stop Video Monitor Thread Success!"); } m_pHostApi->Debug(FACECAP_DEBUG, "%s:%d.", __FUNCTION__, __LINE__); if (NULL != m_pEnvironMinVideoQueue){ delete m_pEnvironMinVideoQueue; m_pEnvironMinVideoQueue = NULL; } m_pHostApi->Debug(FACECAP_DEBUG, "%s:%d.", __FUNCTION__, __LINE__); if (NULL != m_pEnvironMaxVideoQueue){ delete m_pEnvironMaxVideoQueue; m_pEnvironMaxVideoQueue = NULL; } m_pHostApi->Debug(FACECAP_DEBUG, "%s:%d.", __FUNCTION__, __LINE__); if (NULL != m_pOperatorVideoQueue){ delete m_pOperatorVideoQueue; m_pOperatorVideoQueue = NULL; } m_pHostApi->Debug(FACECAP_DEBUG, "%s:%d.", __FUNCTION__, __LINE__); return true; } ~Clibfacecapture_impl() { #ifdef _WIN32 DeleteCriticalSection(&CS); if (!m_hStopEventWait) { CloseHandle(m_hStopEventWait); m_hStopEventWait = NULL; } #else pthread_mutex_destroy(&cs_mutex); #endif if (m_pMhImg) { cvReleaseImage(&m_pMhImg); m_pMhImg = NULL; } if(m_pMhBuf) { for (int i=0;i<3;i++) { if (m_pMhBuf[i] != NULL) { cvReleaseImage(&m_pMhBuf[i]); m_pMhBuf[i] = NULL; } } free(m_pMhBuf); } if (m_pProcessImg) { cvReleaseImage(&m_pProcessImg); m_pProcessImg = NULL; } if (m_pFaceCascade) { cvReleaseHaarClassifierCascade(&m_pFaceCascade); m_pFaceCascade = NULL; } if (m_pEyeCascade) { cvReleaseHaarClassifierCascade(&m_pEyeCascade); m_pEyeCascade = NULL; } if (m_pMouthCascade) { cvReleaseHaarClassifierCascade(&m_pMouthCascade); m_pMouthCascade = NULL; } if (m_pNoseCascade) { cvReleaseHaarClassifierCascade(&m_pNoseCascade); m_pNoseCascade = NULL; } } public: bool m_bLightChange; int m_nCameraState; //0:无故障1:env故障,2:opt故障,3:全部故障 private: #ifdef _WIN32 HANDLE m_hStopEventWait; // CreateEvent CRITICAL_SECTION CS; #else pthread_mutex_t cs_mutex; sem_t m_semt; #endif bool* m_pResult; MonitorEnum m_eType; CvHaarClassifierCascade* m_pFaceCascade; //脸部分类器 CvHaarClassifierCascade* m_pEyeCascade; //眼睛分类器 CvHaarClassifierCascade* m_pMouthCascade; //嘴巴分类器 CvHaarClassifierCascade* m_pNoseCascade; //鼻子分类器 CMotionTrackRslt m_stObjTrackRslt; //运动跟踪的结果 IplImage *m_pMhImg; //MHI: motion history image IplImage **m_pMhBuf; int m_nLastBuf; CFaceCaptureConfig m_stFaceConfig; int m_nImgWidth; //当前摄像头图像宽 int m_nImgHeight; //当前摄像头图像高 CvSeq* pfaceSeq; //人脸序列 CvMemStorage* m_pFaceStorage; //人脸内部存储空间 IplImage* m_pProcessImg; //用于处理的图像 //存储前一帧的人脸矩形(不包括人脸) CvRect m_PreFaceRect[MAX_FACE_NUM]; #ifdef _WIN32 HANDLE m_hVieoMonitorThread; unsigned int m_nVieoMonitorThreadId; #else pthread_t m_videomonitorthreadid; #endif bool m_bStopVieoMonitor; Clibvideoqueue* m_pEnvironMinVideoQueue; //环境摄像头小分辨率视频队列 Clibvideoqueue* m_pEnvironMaxVideoQueue; //环境摄像头大分辨率视频队列 Clibvideoqueue* m_pOperatorVideoQueue; //操作摄像头视频队列 //CLocalFaceInfo m_stCapFace[3]; //int m_nCapFaceNum; //bool m_bCapFaceCompleted; //char m_SaveImgName[MAX_PATH]; CAllFaceInfo m_stAllFaceInfo; CAllFaceInfo m_stFaceRstStorage; CBrightAdjParam m_stBrightAdjParam; //亮度调节参数 MonitorStateEnum m_eMonitorState; CVideoMonitorEvent* m_pHostEvent; CHostApi* m_pHostApi; CameraEnum m_eCamera; char m_envminqueuename[MAX_PATH]; char m_envmaxqueuename[MAX_PATH]; char m_optqueuename[MAX_PATH]; //初始化 bool InitFaceCapture(const char *base_dir) { char dir[MAX_PATH] = {0}; FIGetDir(CASCADE_FACE, base_dir, dir); m_pFaceCascade=(CvHaarClassifierCascade*)cvLoad(dir,NULL,NULL,NULL); if (!m_pFaceCascade){ m_pHostApi->Debug(FACECAP_INFO, "加载脸部分类器失败!"); return false; } FIGetDir(CASCADE_EYE, base_dir, dir); m_pEyeCascade=(CvHaarClassifierCascade*)cvLoad(dir,NULL,NULL,NULL); if (!m_pEyeCascade){ m_pHostApi->Debug(FACECAP_INFO, "加载眼睛分类器失败!"); return false; } FIGetDir(CASCADE_MOUTH, base_dir, dir); m_pMouthCascade=(CvHaarClassifierCascade*)cvLoad(dir,NULL,NULL,NULL); if (!m_pMouthCascade){ m_pHostApi->Debug(FACECAP_INFO, "加载嘴巴分类器失败!"); return false; } FIGetDir(CASCADE_NOSE, base_dir, dir); m_pNoseCascade=(CvHaarClassifierCascade*)cvLoad(dir,NULL,NULL,NULL); if (!m_pMouthCascade){ m_pHostApi->Debug(FACECAP_INFO, "加载鼻子分类器失败!"); return false; } return true; } //获取分类器路径 void FIGetDir(const char*CascadeType,const char *base_dir,char*dir) { strcpy(dir, m_stFaceConfig.strFaceDataDirPath); strcat(dir, SPLIT_SLASH_STR); strcat(dir,CascadeType); } //写人脸检测数据 bool WriteAllFaceInfo(CAllFaceInfo faceInfo) { m_pHostApi->Debug(FACECAP_DEBUG, "Enter WriteAllFaceInfo."); #ifdef _WIN32 EnterCriticalSection(&CS); #else pthread_mutex_lock(&cs_mutex); #endif m_stFaceRstStorage = faceInfo; #ifdef _WIN32 LeaveCriticalSection(&CS); #else pthread_mutex_unlock(&cs_mutex); #endif m_pHostApi->Debug(FACECAP_DEBUG, "Exit WriteAllFaceInfo."); return true; } //计算人脸所处的区域 FaceRegionEnum CalcFaceRegion(CvRect FaceRect, int nImgWidth, int nImgHeight) { //计算人脸的中心坐标 CvPoint FaceCenter; FaceCenter.x = FaceRect.x + (int)FaceRect.width/2; FaceCenter.y = FaceRect.y + (int)FaceRect.height/2; if(FaceCenter.y < (int)nImgHeight/3) { if(FaceCenter.x < (int)nImgWidth/3) { return FaceRegionLeftup; } else if((FaceCenter.x > (int)nImgWidth/3)&&(FaceCenter.x < (int)nImgWidth*2/3)) { return FaceRegionUp; } else if (FaceCenter.x > (int)nImgWidth*2/3) { return FaceRegionRightUP; } } else if((FaceCenter.y > (int)nImgHeight/3)&&(FaceCenter.y < (int)nImgHeight*2/3)) { if(FaceCenter.x < (int)nImgWidth/3) { return FaceRegionLeft; } else if((FaceCenter.x > (int)nImgWidth/3)&&(FaceCenter.x < (int)nImgWidth*2/3)) { return FaceRegionCenter; } else if (FaceCenter.x > (int)nImgWidth*2/3) { return FaceRegionRight; } } else if(FaceCenter.y > (int)nImgHeight*2/3) { if(FaceCenter.x < (int)nImgWidth/3) { return FaceRegionLeftDn; } else if((FaceCenter.x > (int)nImgWidth/3)&&(FaceCenter.x < (int)nImgWidth*2/3)) { return FaceRegionDn; } else if (FaceCenter.x > (int)nImgWidth*2/3) { return FaceRegionRightDn; } } return FaceError; } //计算人脸到机具的距离 DistanceEnum CalcFaceDistance(CvRect FaceRect) { if(FaceRect.height>(int)(m_nImgHeight/m_stFaceConfig.fOperateFaceSize)) { return OperateDistance; //可操作距离0.5m } else if((FaceRect.height<(int)(m_nImgHeight/m_stFaceConfig.fOperateFaceSize))&&(FaceRect.height>(int)(m_nImgHeight/m_stFaceConfig.fCloseFaceSize))) { return CloseDistance; //近端1.5m } else { return FarDistance; //远端2.5m } } //从共享队列获取图像 bool GetCurImg(Clibvideoqueue* videoqueue) { if (videoqueue->GetVideoLens()<=0) { if (videoqueue == m_pEnvironMinVideoQueue) { m_pHostApi->Debug(FACECAP_DEBUG, "获取环境相机图像队列长度错误!"); } else if (videoqueue == m_pOperatorVideoQueue) { m_pHostApi->Debug(FACECAP_DEBUG, "获取操作相机图像队列长度错误!"); } return false; } int iSize = videoqueue->GetFrameSize(m_nImgWidth,m_nImgHeight); m_pHostApi->Debug(FACECAP_DEBUG, "iSize = %d, m_nImgWidth = %d, m_nImgHeight = %d.", iSize, m_nImgWidth, m_nImgHeight); videoq_frame* videoframe = new videoq_frame; if (m_pProcessImg == NULL) { m_pProcessImg = cvCreateImage(cvSize(m_nImgWidth, m_nImgHeight), 8, 3); //创建图像 } else { if((m_pProcessImg->height != m_nImgHeight)||(m_pProcessImg->width != m_nImgWidth)) { cvReleaseImage(&m_pProcessImg); m_pProcessImg = NULL; m_pProcessImg = cvCreateImage(cvSize(m_nImgWidth,m_nImgHeight), 8, 3); //创建图像 } } m_pHostApi->Debug(FACECAP_DEBUG, "m_pProcessImg->align = %d, m_pProcessImg->nChannels = %d, m_pProcessImg->depth = %d, m_pProcessImg->width = %d, m_pProcessImg->height = %d, m_pProcessImg->imageSize = %d, m_pProcessImg->widthStep = %d.", m_pProcessImg->align, m_pProcessImg->nChannels, m_pProcessImg->depth, m_pProcessImg->width, m_pProcessImg->height, m_pProcessImg->imageSize, m_pProcessImg->widthStep); videoframe->data = (unsigned char*)m_pProcessImg->imageData; bool bGetvideo = videoqueue->GetVideo(videoframe, 0); if (!bGetvideo) { delete videoframe; m_pHostApi->Debug(FACECAP_INFO, "从队列获取图像错误!"); return false; } m_nImgWidth = videoframe->width; m_nImgHeight = videoframe->height; delete videoframe; return true; } bool GetImage(CameraEnum eCamera) { m_pHostApi->Debug(FACECAP_DEBUG, "%s:%d Enter GetImage eCamera = %d.", __FUNCTION__, __LINE__, eCamera); if (eCamera == EnvironCamera){ if (m_pEnvironMinVideoQueue == NULL){ m_pHostApi->Debug(FACECAP_DEBUG, "%s:%d Exit GetImage", __FUNCTION__, __LINE__); return false; } bool bRslt = GetCurImg(m_pEnvironMinVideoQueue); if (!bRslt){ m_pHostApi->Debug(FACECAP_DEBUG, "%s:%d Exit GetImage", __FUNCTION__, __LINE__); return false; } } else if(eCamera == OperatorCamera){ if (m_pOperatorVideoQueue == NULL){ m_pHostApi->Debug(FACECAP_DEBUG, "%s:%d Exit GetImage", __FUNCTION__, __LINE__); return false; } bool bRslt = GetCurImg(m_pOperatorVideoQueue); if (!bRslt){ m_pHostApi->Debug(FACECAP_DEBUG, "%s:%d Exit GetImage", __FUNCTION__, __LINE__); return false; } } m_pHostApi->Debug(FACECAP_DEBUG, "%s:%d Exit GetImage", __FUNCTION__, __LINE__); return true; } //清空上次检测结果 void ClearInspectResult() { //清除上一次的记录 m_stAllFaceInfo.nTatolFaceNum = 0; m_stAllFaceInfo.astFaceInfo[0].stCustomerCover.bClearFace = false; m_stAllFaceInfo.astFaceInfo[0].stCustomerCover.bShowEyes = false; m_stAllFaceInfo.astFaceInfo[0].stCustomerCover.bShowMouth = false; m_stAllFaceInfo.astFaceInfo[0].stCustomerCover.bShowNose = false; m_stAllFaceInfo.astFaceInfo[0].eDistance = UncertainDistance; m_stAllFaceInfo.astFaceInfo[0].eHeight = UncertainHeight; m_stAllFaceInfo.astFaceInfo[0].ePose = UncertainPose; //m_stAllFaceInfo.astFaceInfo[0].eScene = UnLockScene; m_stAllFaceInfo.astFaceInfo[0].eSex = UncertainSex; m_stAllFaceInfo.astFaceInfo[0].eYoungOld = UncertainAge; //memset(&m_stBrightAdjParam,0,sizeof(CBrightAdjParam)); for (int i=1;ix; RegionRect.y = pFaceRect->y; RegionRect.width = pFaceRect->width; RegionRect.height = (int)pFaceRect->height*1/2; } else if (pCascade == m_pNoseCascade) { //鼻子 RegionRect.x = (int)pFaceRect->x+(pFaceRect->width)*1/6; RegionRect.y = (int)pFaceRect->y+pFaceRect->height*1/6; RegionRect.width = (int)pFaceRect->width*2/3; RegionRect.height = (int)pFaceRect->height*2/3; } else if (pCascade == m_pMouthCascade) { //嘴巴 RegionRect.x = (int)pFaceRect->x; RegionRect.y = (int)pFaceRect->y+pFaceRect->height*1/2; RegionRect.width = (int)pFaceRect->width; RegionRect.height = (int)pFaceRect->height*1/2; } CvRect RectTemp = cvRect(0,0,0,0); //设置roi if(m_pProcessImg->roi) { RectTemp.x = m_pProcessImg->roi->xOffset; RectTemp.y = m_pProcessImg->roi->yOffset; RectTemp.width = m_pProcessImg->roi->width; RectTemp.height = m_pProcessImg->roi->height; RegionRect.x = RectTemp.x+RegionRect.x; RegionRect.y = RectTemp.y+RegionRect.y; } cvResetImageROI(m_pProcessImg); cvSetImageROI(m_pProcessImg,RegionRect); //特征搜索 CvSeq* pEyesSeq = cvHaarDetectObjects(m_pProcessImg,pCascade,pFaceStorage,1.2,2,CV_HAAR_DO_CANNY_PRUNING,cvSize(10,10)); cvResetImageROI(m_pProcessImg); if((RectTemp.height!=0)&&RectTemp.width!=0) { cvSetImageROI(m_pProcessImg,RectTemp); } if (pEyesSeq?pEyesSeq->total:0) { return true; } else { return false; } } //计算两个人脸数据的距离 int CalcTwoFaceDist(CvRect *pSrcRect,CvRect *pDstRect) { CvPoint p1; CvPoint p2; p1.x = (int)pSrcRect->x+pSrcRect->width/2; p1.y = (int)pSrcRect->y+pSrcRect->height/2; p2.x = (int)pDstRect->x+pDstRect->width/2; p2.y = (int)pDstRect->y+pDstRect->height/2; return (int)sqrt((double)(p1.x-p2.x)*(p1.x-p2.x) + (double)(p1.y-p2.y)*(p1.y-p2.y)); } //计算人脸亮度,同时计算人脸亮度调节参数 BrightnessEnum CalcFaceBrightness(IplImage*img,CvRect* FaceRect) { cvResetImageROI(img); cvSetImageROI(img,*FaceRect); IplImage* FaceImgTmp = cvCreateImage(cvSize(FaceRect->width,FaceRect->height),IPL_DEPTH_8U,3); cvCopy(img,FaceImgTmp,NULL); cvResetImageROI(img); IplImage* FaceImg = cvCreateImage(cvSize(FaceRect->width,FaceRect->height),IPL_DEPTH_8U,1); cvCvtColor(FaceImgTmp, FaceImg, CV_BGR2GRAY); cvReleaseImage(&FaceImgTmp); int aver=0; unsigned char *data=(uchar*)FaceImg->imageData; for(int i=0;iheight;i++) { for(int j=0;jwidth;j++) { aver+=data[i*FaceImg->widthStep+j]; } } aver=aver/FaceRect->width/FaceRect->height; cvReleaseImage(&FaceImg); if (aver>230) { m_stBrightAdjParam.fLow = 0.8; m_stBrightAdjParam.fHigh = 1.0; m_stBrightAdjParam.fBottom = 0.45; m_stBrightAdjParam.fTop = 0.75; m_stBrightAdjParam.fGamma = 1; return VeryHigh; } else if((aver<230)&&(aver>205)) { m_stBrightAdjParam.fLow = 0.75; m_stBrightAdjParam.fHigh = 1.0; m_stBrightAdjParam.fBottom = 0.5; m_stBrightAdjParam.fTop = 0.8; m_stBrightAdjParam.fGamma = 1; return Higher; } else if((aver<205)&&(aver>180)) { m_stBrightAdjParam.fLow = 0.7; m_stBrightAdjParam.fHigh = 1.0; m_stBrightAdjParam.fBottom = 0.5; m_stBrightAdjParam.fTop = 0.8; m_stBrightAdjParam.fGamma = 1; return NorMal; } else if((aver<180)&&(aver>70)) { m_stBrightAdjParam.fLow = 0.0; m_stBrightAdjParam.fHigh = 0.0; m_stBrightAdjParam.fBottom = 0.0; m_stBrightAdjParam.fTop = 0.0; m_stBrightAdjParam.fGamma = 0.0; return NorMal; } else if((aver<70)&&(aver>50)) { m_stBrightAdjParam.fLow = 0; m_stBrightAdjParam.fHigh = 0.3; m_stBrightAdjParam.fBottom = 0.15; m_stBrightAdjParam.fTop = 0.55; m_stBrightAdjParam.fGamma = 1; return NorMal; } else if((aver<50)&&(aver>30)) { m_stBrightAdjParam.fLow = 0; m_stBrightAdjParam.fHigh = 0.25; m_stBrightAdjParam.fBottom = 0.25; m_stBrightAdjParam.fTop = 0.65; m_stBrightAdjParam.fGamma = 1; return Lower; } else { m_stBrightAdjParam.fLow = 0; m_stBrightAdjParam.fHigh = 0.2; m_stBrightAdjParam.fBottom = 0.25; m_stBrightAdjParam.fTop = 0.65; m_stBrightAdjParam.fGamma = 1; return VeryLow; } } //计算人脸亮度调节参数 bool CalcBrightAdjParam(IplImage*img, CvRect* FaceRect) { cvResetImageROI(img); cvSetImageROI(img,*FaceRect); IplImage* FaceImgTmp = cvCreateImage(cvSize(FaceRect->width,FaceRect->height),IPL_DEPTH_8U,3); cvCopy(img,FaceImgTmp,NULL); cvResetImageROI(img); IplImage* FaceImg = cvCreateImage(cvSize(FaceRect->width,FaceRect->height),IPL_DEPTH_8U,1); cvCvtColor(FaceImgTmp, FaceImg, CV_BGR2GRAY); cvReleaseImage(&FaceImgTmp); int aver=0; unsigned char *data=(uchar*)FaceImg->imageData; for(int i=0;iheight;i++) { for(int j=0;jwidth;j++) { aver+=data[i*FaceImg->widthStep+j]; } } aver=aver/FaceRect->width/FaceRect->height; if (aver>230) { m_stBrightAdjParam.fLow = 0.8; m_stBrightAdjParam.fHigh = 1.0; m_stBrightAdjParam.fBottom = 0.45; m_stBrightAdjParam.fTop = 0.75; m_stBrightAdjParam.fGamma = 1; } else if((aver<230)&&(aver>205)) { m_stBrightAdjParam.fLow = 0.75; m_stBrightAdjParam.fHigh = 1.0; m_stBrightAdjParam.fBottom = 0.5; m_stBrightAdjParam.fTop = 0.8; m_stBrightAdjParam.fGamma = 1; } else if((aver<205)&&(aver>180)) { m_stBrightAdjParam.fLow = 0.7; m_stBrightAdjParam.fHigh = 1.0; m_stBrightAdjParam.fBottom = 0.5; m_stBrightAdjParam.fTop = 0.8; m_stBrightAdjParam.fGamma = 1; } else if((aver<70)&&(aver>60)) { m_stBrightAdjParam.fLow = 0; m_stBrightAdjParam.fHigh = 0.3; m_stBrightAdjParam.fBottom = 0.15; m_stBrightAdjParam.fTop = 0.55; m_stBrightAdjParam.fGamma = 1; } else if((aver<60)&&(aver>30)) { m_stBrightAdjParam.fLow = 0; m_stBrightAdjParam.fHigh = 0.25; m_stBrightAdjParam.fBottom = 0.25; m_stBrightAdjParam.fTop = 0.65; m_stBrightAdjParam.fGamma = 1; } else { m_stBrightAdjParam.fLow = 0; m_stBrightAdjParam.fHigh = 0.2; m_stBrightAdjParam.fBottom = 0.25; m_stBrightAdjParam.fTop = 0.65; m_stBrightAdjParam.fGamma = 1; } cvReleaseImage(&FaceImg); return true; } //人脸检测,直接对load进来的图像进行全局检测 bool FaceDetect(CameraEnum eCamera) { m_pHostApi->Debug(FACECAP_DEBUG, "%s:%d Enter FaceDetect", __FUNCTION__, __LINE__); if (!GetImage(eCamera)){ m_pHostApi->Debug(FACECAP_DEBUG, "获取图像失败"); return false; } CCustomerInfo UserFaceTemp; int nFaceSerial = 1; memset(&UserFaceTemp,0,sizeof(CCustomerInfo)); CvRect* pFaceRect = NULL; //人脸矩形 int nPreFaceNum = 0; cvResetImageROI(m_pProcessImg); //内存初始化 if (m_pFaceStorage){ m_pFaceStorage = cvCreateMemStorage(0); //cvClearMemStorage(pFaceStorage); } else{ m_pFaceStorage = cvCreateMemStorage(0); } //人脸搜索 if (m_pFaceCascade == NULL){ ClearInspectResult(); return false; } int size = (int)(m_nImgHeight/m_stFaceConfig.fDetectFaceSize); pfaceSeq = cvHaarDetectObjects(m_pProcessImg,m_pFaceCascade,m_pFaceStorage,1.1,3,CV_HAAR_DO_CANNY_PRUNING,cvSize(size,size)); if (!pfaceSeq || !pfaceSeq->total) { cvReleaseMemStorage(&pfaceSeq->storage); pfaceSeq = NULL; ClearInspectResult(); return false; } else { //保存上次人脸矩形,对当前人脸位置进行微调防止跳动 for(int num=0; numtotal:0)&&(ix - m_PreFaceRect[num].x)y-m_PreFaceRect[num].y)width-m_PreFaceRect[num].width)<(m_stFaceConfig.nFaceSizeOffset*2)) && (abs(pFaceRect->height-m_PreFaceRect[num].height)<(m_stFaceConfig.nFaceSizeOffset*2))) { pFaceRect->x = m_PreFaceRect[num].x; pFaceRect->y = m_PreFaceRect[num].y; pFaceRect->width = m_PreFaceRect[num].width; pFaceRect->height = m_PreFaceRect[num].height; } } //搜索到人脸,计算人脸数据 m_stAllFaceInfo.astFaceInfo[nFaceSerial].stRegion.stFaceRect = *pFaceRect; m_stAllFaceInfo.astFaceInfo[nFaceSerial].stRegion.eRegion = CalcFaceRegion(*pFaceRect,m_nImgWidth,m_nImgHeight); m_stAllFaceInfo.astFaceInfo[nFaceSerial].eDistance = CalcFaceDistance(*pFaceRect); m_stAllFaceInfo.astFaceInfo[nFaceSerial].eCamera = eCamera; //获取UUID if (m_stAllFaceInfo.astFaceInfo[nFaceSerial].FaceID == 0) { m_stAllFaceInfo.astFaceInfo[nFaceSerial].FaceID = m_pHostApi->GenerateUUID(); } //截取人脸图像,放大截取区域,截取半身头像 CalcUpbodyRegion(pFaceRect); m_stAllFaceInfo.astFaceInfo[nFaceSerial].stRegion.stUpperBodyRect = *pFaceRect; //当前数据的区域和距离,temp数据的区域和距离 int CurRegion = m_stAllFaceInfo.astFaceInfo[nFaceSerial].stRegion.eRegion; DistanceEnum CurDistance = m_stAllFaceInfo.astFaceInfo[nFaceSerial].eDistance; int TempRegion = UserFaceTemp.stRegion.eRegion; DistanceEnum TempDistance = UserFaceTemp.eDistance; int TempPointDist = CalcTwoFaceDist(&UserFaceTemp.stRegion.stFaceRect,&m_stAllFaceInfo.astFaceInfo[0].stRegion.stFaceRect); int CurPointDist = CalcTwoFaceDist(&m_stAllFaceInfo.astFaceInfo[nFaceSerial].stRegion.stFaceRect, &m_stAllFaceInfo.astFaceInfo[0].stRegion.stFaceRect); //计算当前操作者的人脸区域 if(//如果temp数据为0,则更新temp ((TempRegion== 0)&&(TempDistance == 0.0)) || //如果当前数据在中心区域,temp数据也在中心区域,且当前距离比temp数据更近,则更新temp ((CurRegion == FaceRegionCenter)&&(TempRegion == FaceRegionCenter)&&(CurDistance < TempDistance))|| //如果当前数据不在中心区域,temp数据也不在中心区域,且当前数据比temp数据更近。则更新temp ((TempRegion != FaceRegionCenter)&&(CurRegion != FaceRegionCenter)&&(CurDistance < TempDistance))|| //如果当前数据在中心区域,temp数据不在中心区域,且当前距离更近,则更新temp ((CurRegion == FaceRegionCenter)&&(TempRegion != FaceRegionCenter)&&(CurDistancestorage); pfaceSeq = NULL; } for(int i=0; iDebug(FACECAP_DEBUG, "%s:%d", __FUNCTION__, __LINE__); if(m_stAllFaceInfo.nTatolFaceNum == 0) { ClearInspectResult(); m_pHostApi->Debug(FACECAP_DEBUG, "%s:%d Exit FaceDetect.", __FUNCTION__, __LINE__); return false; } else { m_pHostApi->Debug(FACECAP_DEBUG, "%s:%d Exit FaceDetect.", __FUNCTION__, __LINE__); return true; } } //人脸检测,对上次检测到的人脸区域进行搜索 bool FaceDetect(CameraEnum eCamera, CvRect rect) { m_pHostApi->Debug(FACECAP_DEBUG, "%s:%d Enter FaceDetect", __FUNCTION__, __LINE__); if (!GetImage(eCamera)){ return false; } m_pHostApi->Debug(FACECAP_DEBUG, "%s:%d FaceDetect", __FUNCTION__, __LINE__); CvMemStorage*pFaceStorage = NULL; if (eCamera == EnvironCamera){ pFaceStorage = m_pFaceStorage; } else{ pFaceStorage = m_pFaceStorage; } m_pHostApi->Debug(FACECAP_DEBUG, "%s:%d FaceDetect", __FUNCTION__, __LINE__); CCustomerInfo UserFaceTemp; m_pHostApi->Debug(FACECAP_DEBUG, "%s:%d FaceDetect", __FUNCTION__, __LINE__); CCustomerInfo astFaceTemp; m_pHostApi->Debug(FACECAP_DEBUG, "%s:%d FaceDetect", __FUNCTION__, __LINE__); memset(&astFaceTemp,0,sizeof(CCustomerInfo)); m_pHostApi->Debug(FACECAP_DEBUG, "%s:%d FaceDetect", __FUNCTION__, __LINE__); memset(&UserFaceTemp,0,sizeof(CCustomerInfo)); m_pHostApi->Debug(FACECAP_DEBUG, "%s:%d FaceDetect", __FUNCTION__, __LINE__); CvRect* pFaceRect = NULL; //人脸矩形 m_pHostApi->Debug(FACECAP_DEBUG, "%s:%d FaceDetect", __FUNCTION__, __LINE__); cvResetImageROI(m_pProcessImg); m_pHostApi->Debug(FACECAP_DEBUG, "%s:%d FaceDetect", __FUNCTION__, __LINE__); cvSetImageROI(m_pProcessImg,rect); m_pHostApi->Debug(FACECAP_DEBUG, "%s:%d FaceDetect", __FUNCTION__, __LINE__); //内存初始化 if (pFaceStorage){ m_pHostApi->Debug(FACECAP_DEBUG, "%s:%d FaceDetect", __FUNCTION__, __LINE__); pFaceStorage = cvCreateMemStorage(0); m_pHostApi->Debug(FACECAP_DEBUG, "%s:%d FaceDetect", __FUNCTION__, __LINE__); cvClearMemStorage(pFaceStorage); m_pHostApi->Debug(FACECAP_DEBUG, "%s:%d FaceDetect", __FUNCTION__, __LINE__); } else{ m_pHostApi->Debug(FACECAP_DEBUG, "%s:%d FaceDetect", __FUNCTION__, __LINE__); pFaceStorage = cvCreateMemStorage(0); m_pHostApi->Debug(FACECAP_DEBUG, "%s:%d FaceDetect", __FUNCTION__, __LINE__); } m_pHostApi->Debug(FACECAP_DEBUG, "%s:%d FaceDetect", __FUNCTION__, __LINE__); //人脸搜索 if (m_pFaceCascade == NULL){ m_pHostApi->Debug(FACECAP_DEBUG, "%s:%d FaceDetect", __FUNCTION__, __LINE__); return false; } int size = (int)m_nImgHeight/m_stFaceConfig.fDetectFaceSize; pfaceSeq = cvHaarDetectObjects(m_pProcessImg,m_pFaceCascade,pFaceStorage,1.2,3,CV_HAAR_DO_CANNY_PRUNING,cvSize(size,size)); if (!pfaceSeq || !pfaceSeq->total) { m_pHostApi->Debug(FACECAP_DEBUG, "%s:%d FaceDetect", __FUNCTION__, __LINE__); cvReleaseMemStorage(&pfaceSeq->storage); m_pHostApi->Debug(FACECAP_DEBUG, "%s:%d FaceDetect", __FUNCTION__, __LINE__); pfaceSeq = NULL; return false; } for(int i=0;i<(pfaceSeq?pfaceSeq->total:0)&&(ix = pFaceRect->x+rect.x; pFaceRect->y = pFaceRect->y+rect.y; if ((abs(pFaceRect->x - m_stAllFaceInfo.astFaceInfo[0].stRegion.stFaceRect.x)y-m_stAllFaceInfo.astFaceInfo[0].stRegion.stFaceRect.y)width-m_stAllFaceInfo.astFaceInfo[0].stRegion.stFaceRect.width)<(m_stFaceConfig.nFaceSizeOffset*2)) && (abs(pFaceRect->height-m_stAllFaceInfo.astFaceInfo[0].stRegion.stFaceRect.height)<(m_stFaceConfig.nFaceSizeOffset*2))) { pFaceRect->x = m_stAllFaceInfo.astFaceInfo[0].stRegion.stFaceRect.x; pFaceRect->y = m_stAllFaceInfo.astFaceInfo[0].stRegion.stFaceRect.y; pFaceRect->width = m_stAllFaceInfo.astFaceInfo[0].stRegion.stFaceRect.width; pFaceRect->height = m_stAllFaceInfo.astFaceInfo[0].stRegion.stFaceRect.height; } //搜索到人脸,计算人脸数据 astFaceTemp.stRegion.stFaceRect = *pFaceRect; astFaceTemp.stRegion.eRegion = CalcFaceRegion(*pFaceRect,m_nImgWidth,m_nImgHeight); astFaceTemp.eDistance = CalcFaceDistance(*pFaceRect); astFaceTemp.eCamera = eCamera; m_pHostApi->Debug(FACECAP_DEBUG, "%s:%d FaceDetect", __FUNCTION__, __LINE__); //截取人脸图像,放大截取区域,截取半身头像 CalcUpbodyRegion(pFaceRect); m_pHostApi->Debug(FACECAP_DEBUG, "%s:%d FaceDetect", __FUNCTION__, __LINE__); astFaceTemp.stRegion.stUpperBodyRect = *pFaceRect; //当前数据的区域和距离,temp数据的区域和距离 int CurRegion = astFaceTemp.stRegion.eRegion; DistanceEnum CurDistance = astFaceTemp.eDistance; int TempRegion = UserFaceTemp.stRegion.eRegion; DistanceEnum TempDistance = UserFaceTemp.eDistance; int TempPointDist = CalcTwoFaceDist(&UserFaceTemp.stRegion.stFaceRect, &m_stAllFaceInfo.astFaceInfo[0].stRegion.stFaceRect); m_pHostApi->Debug(FACECAP_DEBUG, "%s:%d FaceDetect", __FUNCTION__, __LINE__); int CurPointDist = CalcTwoFaceDist(&astFaceTemp.stRegion.stFaceRect, &m_stAllFaceInfo.astFaceInfo[0].stRegion.stFaceRect); m_pHostApi->Debug(FACECAP_DEBUG, "%s:%d FaceDetect", __FUNCTION__, __LINE__); //计算当前操作者的人脸区域 if(//如果temp数据为0,则更新temp ((TempRegion== 0)&&(TempDistance == 0.0)) || //如果当前数据在中心区域,temp数据也在中心区域,且当前距离比temp数据更近,则更新temp ((CurRegion == FaceRegionCenter)&&(TempRegion == FaceRegionCenter)&&(CurDistance < TempDistance))|| //如果当前数据不在中心区域,temp数据也不在中心区域,且当前数据比temp数据更近。则更新temp ((TempRegion != FaceRegionCenter)&&(CurRegion != FaceRegionCenter)&&(CurDistance < TempDistance))|| //如果当前数据在中心区域,temp数据不在中心区域,且当前距离更近,则更新temp ((CurRegion == FaceRegionCenter)&&(TempRegion != FaceRegionCenter)&&(CurDistanceDebug(FACECAP_DEBUG, "%s:%d FaceDetect", __FUNCTION__, __LINE__); if((UserFaceTemp.stRegion.eRegion!=0)&&(UserFaceTemp.eDistance!=0)) { m_stAllFaceInfo.astFaceInfo[0].stRegion.stFaceRect = UserFaceTemp.stRegion.stFaceRect; m_stAllFaceInfo.astFaceInfo[0].eDistance = UserFaceTemp.eDistance; m_stAllFaceInfo.astFaceInfo[0].stRegion.eRegion = UserFaceTemp.stRegion.eRegion; m_stAllFaceInfo.astFaceInfo[0].stRegion.stUpperBodyRect = UserFaceTemp.stRegion.stUpperBodyRect; m_stAllFaceInfo.astFaceInfo[0].eCamera = UserFaceTemp.eCamera; m_stAllFaceInfo.astFaceInfo[0].stCustomerCover = UserFaceTemp.stCustomerCover; //计算人脸亮度 if (m_stFaceConfig.nServersType == 0) { m_pHostApi->Debug(FACECAP_DEBUG, "%s:%d FaceDetect", __FUNCTION__, __LINE__); m_stAllFaceInfo.astFaceInfo[0].eBrightness = CalcFaceBrightness(m_pProcessImg,&m_stAllFaceInfo.astFaceInfo[0].stRegion.stFaceRect); m_pHostApi->Debug(FACECAP_DEBUG, "%s:%d FaceDetect", __FUNCTION__, __LINE__); } } //清空存储区 if (pfaceSeq!=NULL){ m_pHostApi->Debug(FACECAP_DEBUG, "%s:%d FaceDetect", __FUNCTION__, __LINE__); cvReleaseMemStorage(&pfaceSeq->storage); pfaceSeq = NULL; m_pHostApi->Debug(FACECAP_DEBUG, "%s:%d FaceDetect", __FUNCTION__, __LINE__); } m_pHostApi->Debug(FACECAP_DEBUG, "%s:%d FaceDetect", __FUNCTION__, __LINE__); cvResetImageROI(m_pProcessImg); m_pHostApi->Debug(FACECAP_DEBUG, "%s:%d Exit FaceDetect", __FUNCTION__, __LINE__); return true; } // //人脸卡图 // void CaptureOperatorFace(IplImage* img) // { // m_pHostApi->Debug(FACECAP_DEBUG, "Enter CaptureOperatorFace"); // //判断客户号,客户ID是否更换 // if(m_pHostApi->IsCustomerChange()) // { // if (!m_bCapFaceCompleted && (strcmp(m_SaveImgName,"") != 0)) // { // m_pHostApi->Debug(FACECAP_DEBUG, "%s:%d", __FUNCTION__, __LINE__); // SaveOperatorFace(m_SaveImgName); // m_pHostApi->Debug(FACECAP_DEBUG, "%s:%d", __FUNCTION__, __LINE__); // } // else if (m_bCapFaceCompleted) // { // m_bCapFaceCompleted = false; // m_nCapFaceNum = 0; // } // m_pHostApi->Debug(FACECAP_DEBUG, "%s:%d", __FUNCTION__, __LINE__); // m_pHostApi->GetFaceImgName(m_SaveImgName, MAX_PATH); // m_pHostApi->Debug(FACECAP_DEBUG, "%s:%d", __FUNCTION__, __LINE__); // } // // if (m_bCapFaceCompleted) // { // m_pHostApi->Debug(FACECAP_DEBUG, "%s:%d Exit CaptureOperatorFace", __FUNCTION__, __LINE__); // return; // } // // if (m_stAllFaceInfo.nTatolFaceNum > 0) // { // m_pHostApi->Debug(FACECAP_DEBUG, "%s:%d", __FUNCTION__, __LINE__); // bool bRst = GetImage(m_stAllFaceInfo.astFaceInfo[0].eCamera); // m_pHostApi->Debug(FACECAP_DEBUG, "%s:%d", __FUNCTION__, __LINE__); // if (!bRst){ // m_pHostApi->Debug(FACECAP_DEBUG, "%s:%d Exit CaptureOperatorFace", __FUNCTION__, __LINE__); // return; // } // m_pHostApi->Debug(FACECAP_DEBUG, "%s:%d", __FUNCTION__, __LINE__); // //往3个人脸图像中填数据 // if (m_nCapFaceNum < 3) // { // m_pHostApi->Debug(FACECAP_DEBUG, "%s:%d", __FUNCTION__, __LINE__); // m_stCapFace[m_nCapFaceNum].stFaceCover.bShowEyes = m_stAllFaceInfo.astFaceInfo[0].stCustomerCover.bShowEyes; // m_stCapFace[m_nCapFaceNum].stFaceCover.bShowMouth = m_stAllFaceInfo.astFaceInfo[0].stCustomerCover.bShowMouth; // m_stCapFace[m_nCapFaceNum].stFaceCover.bShowNose = m_stAllFaceInfo.astFaceInfo[0].stCustomerCover.bShowNose; // m_stCapFace[m_nCapFaceNum].stCustomerRegion.stFaceRect = m_stAllFaceInfo.astFaceInfo[0].stRegion.stFaceRect; // m_stCapFace[m_nCapFaceNum].stCustomerRegion.stUpperBodyRect = m_stAllFaceInfo.astFaceInfo[0].stRegion.stUpperBodyRect; // // m_pHostApi->Debug(FACECAP_DEBUG, "%s:%d", __FUNCTION__, __LINE__); // cvResetImageROI(img); // // m_pHostApi->Debug(FACECAP_DEBUG, "%s:%d img->width = %d, img->height = %d.", __FUNCTION__, __LINE__, img->width, img->height); // CvRect roirect = m_stCapFace[m_nCapFaceNum].stCustomerRegion.stUpperBodyRect; // m_pHostApi->Debug(FACECAP_DEBUG, "%s:%d roirect.x = %d, roirect.y = %d, roirect.width = %d, roirect.height = %d.", __FUNCTION__, __LINE__, roirect.x, roirect.y, roirect.width, roirect.height); // cvSetImageROI(img, m_stCapFace[m_nCapFaceNum].stCustomerRegion.stUpperBodyRect); // // m_pHostApi->Debug(FACECAP_DEBUG, "%s:%d", __FUNCTION__, __LINE__); // CvRect roirect1 = m_stCapFace[m_nCapFaceNum].stCustomerRegion.stUpperBodyRect; // m_pHostApi->Debug(FACECAP_DEBUG, "%s:%d roirect1.x = %d, roirect1.y = %d, roirect1.width = %d, roirect1.height = %d.", __FUNCTION__, __LINE__, roirect1.x, roirect1.y, roirect1.width, roirect1.height); // // m_stCapFace[m_nCapFaceNum].img = cvCreateImage(cvSize(m_stCapFace[m_nCapFaceNum].stCustomerRegion.stUpperBodyRect.width, // m_stCapFace[m_nCapFaceNum].stCustomerRegion.stUpperBodyRect.height),IPL_DEPTH_8U,3); // // m_pHostApi->Debug(FACECAP_DEBUG, "%s:%d img = 0x%08x, m_nCapFaceNum = %d, m_stCapFace[m_nCapFaceNum].img = 0x%08x.", __FUNCTION__, __LINE__, img, m_nCapFaceNum, m_stCapFace[m_nCapFaceNum].img); // m_pHostApi->Debug(FACECAP_DEBUG, "%s:%d m_stCapFace[m_nCapFaceNum].img->width = %d, m_stCapFace[m_nCapFaceNum].img->height = %d, m_stCapFace[m_nCapFaceNum].img->depth = %d, m_stCapFace[m_nCapFaceNum].img->widthStep = %d.", __FUNCTION__, __LINE__, m_stCapFace[m_nCapFaceNum].img->width, m_stCapFace[m_nCapFaceNum].img->height, m_stCapFace[m_nCapFaceNum].img->depth, m_stCapFace[m_nCapFaceNum].img->widthStep); // m_pHostApi->Debug(FACECAP_DEBUG, "%s:%d img->depth = %d, img->imageSize = %d, m_stCapFace[m_nCapFaceNum].img->depth = %d, m_stCapFace[m_nCapFaceNum].img->imageSize = %d.", __FUNCTION__, __LINE__, img->depth, img->imageSize, m_stCapFace[m_nCapFaceNum].img->depth, m_stCapFace[m_nCapFaceNum].img->imageSize); // cvCopy(img, m_stCapFace[m_nCapFaceNum].img, NULL); // m_pHostApi->Debug(FACECAP_DEBUG, "%s:%d", __FUNCTION__, __LINE__); // // if(m_stBrightAdjParam.fHigh != 0.0) // { // m_pHostApi->Debug(FACECAP_DEBUG, "%s:%d", __FUNCTION__, __LINE__); // AdjustImgBrightness(m_stCapFace[m_nCapFaceNum].img->imageData,m_stCapFace[m_nCapFaceNum].stCustomerRegion.stUpperBodyRect.width, // m_stCapFace[m_nCapFaceNum].stCustomerRegion.stUpperBodyRect.height,m_stBrightAdjParam); // } // m_pHostApi->Debug(FACECAP_DEBUG, "%s:%d", __FUNCTION__, __LINE__); // cvResetImageROI(img); // m_nCapFaceNum++; // m_pHostApi->Debug(FACECAP_DEBUG, "%s:%d", __FUNCTION__, __LINE__); // } // else //如果有三张人脸,立即保存 // { // //写文件 // if (strcmp(m_SaveImgName,"")==0){ // m_pHostApi->GetFaceImgName(m_SaveImgName, MAX_PATH); // } // else{ // SaveOperatorFace(m_SaveImgName); // m_bCapFaceCompleted = true; // m_nCapFaceNum = 0; // } // } // } // else // { // m_pHostApi->Debug(FACECAP_DEBUG, "%s:%d Exit CaptureOperatorFace", __FUNCTION__, __LINE__); // return; // } // m_pHostApi->Debug(FACECAP_DEBUG, "%s:%d Exit CaptureOperatorFace", __FUNCTION__, __LINE__); // } // // //保存人脸图像 // bool SaveOperatorFace(char*filename) // { // m_pHostApi->Debug(FACECAP_DEBUG, "%s:%d", __FUNCTION__, __LINE__); // for(int i=0;i<3;i++) // { // if(m_stCapFace[i].img != NULL) // { // //设置文件名 // char strFileName[MAX_PATH] = {0}; //#ifdef _WIN32 // _snprintf(strFileName, MAX_PATH, "%s_%d.jpg", filename, i); //#else // snprintf(strFileName, MAX_PATH, "%s_%d.jpg", filename, i); //#endif // _WIN32 // cvSaveImage(strFileName,m_stCapFace[i].img); // } // } // m_pHostApi->Debug(FACECAP_DEBUG, "%s:%d", __FUNCTION__, __LINE__); // // for(int j = 0; j < 3; j++) // { // if(m_stCapFace[j].img != NULL) // { // cvReleaseImage(&m_stCapFace[j].img); // } // } // m_nCapFaceNum = 0; // m_pHostApi->Debug(FACECAP_DEBUG, "%s:%d", __FUNCTION__, __LINE__); // // return true; // } //调整图像亮度 bool AdjustImgBrightness(char* src,int width,int height,CBrightAdjParam stAdjParam,int ImgColorType = RGB_IMG) { if(stAdjParam.fLow<0&&stAdjParam.fLow>1&&stAdjParam.fHigh<0&&stAdjParam.fHigh>1 &&stAdjParam.fBottom<0&&stAdjParam.fBottom>1&&stAdjParam.fTop<0&&stAdjParam.fTop>1&& stAdjParam.fLow>stAdjParam.fHigh) return false; if (((stAdjParam.fHigh-0.0)<0.001)&&((stAdjParam.fTop-0.0)<0.001)) return false; double low2 = stAdjParam.fLow*255; double high2 = stAdjParam.fHigh*255; double bottom2 = stAdjParam.fBottom*255; double top2 = stAdjParam.fTop*255; double err_in = high2 - low2; double err_out = top2 - bottom2; int x,y; double val; int nChannels = 0; if (ImgColorType = RGB_IMG) { nChannels = 3; } else { nChannels = 1; } // intensity transform for( y = 0; y < height; y++) { for (x = 0; x < width*3; x++) { val = ((uchar*)(src + width*nChannels*y))[x]; val = pow((val - low2)/err_in, stAdjParam.fGamma) * err_out + bottom2; if(val>255) val=255; if(val<0) val=0; // Make sure src is in the range [low,high] ((uchar*)(src + width*nChannels*y))[x] = (uchar) val; } } return true; } //形态学结构元素的映射 IplConvKernel* IpStructuringElementMap(IplConvKernel* se) { CvMat *mat = cvCreateMat( se->nRows, se->nCols, CV_32SC1); memcpy(mat->data.i, se->values, sizeof(int) * se->nRows * se->nCols ); cvFlip(mat, NULL, -1); IplConvKernel* semap = cvCreateStructuringElementEx( se->nCols, se->nRows, se->nCols-se->anchorX-1, se->nRows-se->anchorY-1, 0, NULL ); semap->nShiftR = se->nShiftR; memcpy( semap->values, mat->data.i, sizeof(int) * se->nRows * se->nCols ); cvReleaseMat(&mat); return semap; } //形态学闭运算 void IpMorpClose(const IplImage*src,IplImage* dst,IplConvKernel* se=NULL, int iterations=1) { cvDilate(src,dst,se,iterations ); IplConvKernel* semap = IpStructuringElementMap(se); cvErode(src,dst,semap,iterations ); cvReleaseStructuringElement(&semap); } //计算半身头像区域,按4:3比例剪辑,防止超出图像界限 void CalcUpbodyRegion(CvRect*pFaceRect) { if (m_nImgWidth > m_nImgHeight) { pFaceRect->y = ((pFaceRect->y-pFaceRect->height*1/3)<0)?0:(int)(pFaceRect->y-pFaceRect->height*1/3); pFaceRect->height = ((pFaceRect->height*19/12+pFaceRect->y)>m_nImgHeight)?(int)(m_nImgHeight-pFaceRect->y):(int)(pFaceRect->height*19/12); if ((int)(pFaceRect->x+pFaceRect->width/2-pFaceRect->height*4/6)<0) { pFaceRect->x = 0; } else if ((pFaceRect->x+pFaceRect->width/2+pFaceRect->height*4/6)>m_nImgWidth) { pFaceRect->x = (int)(m_nImgWidth-pFaceRect->height*4/3); } else { pFaceRect->x=(int)(pFaceRect->x+pFaceRect->width/2-pFaceRect->height*4/6); } pFaceRect->width = pFaceRect->height*4/3; } else { pFaceRect->x = ((pFaceRect->x-pFaceRect->width*7/24)<0)?0:(int)(pFaceRect->x-pFaceRect->width*7/24); pFaceRect->width = ((pFaceRect->width*19/12+pFaceRect->x)>m_nImgWidth)?(int)(m_nImgWidth-pFaceRect->x):(int)(pFaceRect->width*19/12); if ((int)(pFaceRect->y+pFaceRect->height/2-pFaceRect->width*3/8)<0) { pFaceRect->y = 0; } else if ((pFaceRect->y+pFaceRect->height/2+pFaceRect->width*3/8)>m_nImgHeight) { pFaceRect->y = (int)(m_nImgHeight-pFaceRect->width*3/8); } else { pFaceRect->y = (int)(pFaceRect->y+pFaceRect->height/2-pFaceRect->width*3/8); } pFaceRect->height = pFaceRect->width*3/4; } } ////在运动跟踪后根据运动跟踪结果检测是否有人靠近 //bool FaceSearch(CMotionTrackRslt stObjTrackRslt, uint32_t nFaceLimit) //{ // int nFaceNum = 0; // //人脸搜索 // if (m_pFaceCascade == NULL) // { // return false; // } // for(int i=0;itotal) // { // for(int i=0;i<(pfaceSeq?pfaceSeq->total:0);i++) // { // nFaceNum++; // //获取脸部矩形 // CvRect*pFaceRect = (CvRect*)cvGetSeqElem(pfaceSeq,i); // //如果发现有人脸到达靠近区域,置有人靠近状态 // if((pFaceRect->height >= (int)(m_nImgHeight/m_stFaceConfig.fCloseFaceSize))&&(pFaceRect->height <= (int)(m_nImgHeight/m_stFaceConfig.fOperateFaceSize))) // { // if((m_eMonitorState == NoBody) || (m_eMonitorState == SomebodyFar)) // { // m_pHostApi->Debug(FACECAP_INFO, "有人靠近!"); // m_eMonitorState = SomebodyClose; //进入有人靠近状态 // //截取人脸图像,放大截取区域,截取半身头像 // int nWidth = pFaceRect->width; // int nHeight = pFaceRect->height; // pFaceRect->y = m_stObjTrackRslt.ObjRect[i].y+pFaceRect->y; // pFaceRect->x = m_stObjTrackRslt.ObjRect[i].x+pFaceRect->x; // CalcUpbodyRegion(pFaceRect); // m_stAllFaceInfo.astFaceInfo[0].stRegion.stUpperBodyRect = *pFaceRect; // } // m_pHostEvent->GenerateMonitorEvent(Close); //产生有人靠近事件 // } // else if (pFaceRect->height >= (int)(m_nImgHeight/m_stFaceConfig.fOperateFaceSize)) // { // if(m_eMonitorState != SomebodyOperate) // { // m_pHostApi->Debug(FACECAP_INFO, "有人进入操作距离!"); // m_eMonitorState = SomebodyOperate; //进入有人靠近状态 // //截取人脸图像,放大截取区域,截取半身头像 // pFaceRect->y = m_stObjTrackRslt.ObjRect[i].y+pFaceRect->y; // pFaceRect->x = m_stObjTrackRslt.ObjRect[i].x+pFaceRect->x; // CalcUpbodyRegion(pFaceRect); // m_stAllFaceInfo.astFaceInfo[0].stRegion.stUpperBodyRect = *pFaceRect; // } // m_pHostEvent->GenerateMonitorEvent(EnterOperate); //产生有人进入操作距离事件 // } // else // { // if(m_eMonitorState == NoBody) // { // m_stAllFaceInfo.astFaceInfo[0].stRegion.stUpperBodyRect.height = m_nImgHeight/2; // m_stAllFaceInfo.astFaceInfo[0].stRegion.stUpperBodyRect.width = m_nImgWidth/2; // m_stAllFaceInfo.astFaceInfo[0].stRegion.stUpperBodyRect.x = m_nImgWidth/4; // m_stAllFaceInfo.astFaceInfo[0].stRegion.stUpperBodyRect.y = m_nImgHeight/4; // m_pHostApi->Debug(FACECAP_INFO, "有人出现!"); // m_eMonitorState = SomebodyFar; //进入远距离有人状态 // } // m_pHostEvent->GenerateMonitorEvent(Appear); //产生有人出现事件 // } // } // } // if (pfaceSeq != NULL) // { // cvReleaseMemStorage(&pfaceSeq->storage); // pfaceSeq = NULL; // } // } // cvResetImageROI(m_pProcessImg); // if(nFaceNum > 0) // { // //发现有人 // m_stAllFaceInfo.nTatolFaceNum = nFaceNum; // return true; // } // else // { // m_eMonitorState = NoBody; // m_stAllFaceInfo.nTatolFaceNum = 0; // return false; // } //} //对图像进行全局搜索 bool FaceSearch(uint32_t nFaceLimit) { int nFaceNum = 0; int nCurafaceSerial = 0; //人脸搜索 if (NULL == m_pFaceCascade){ return false; } cvResetImageROI(m_pProcessImg); CvRect* pFaceRect = NULL; //人脸矩形 //内存初始化 if (m_pFaceStorage){ m_pFaceStorage = cvCreateMemStorage(0); cvClearMemStorage(m_pFaceStorage); } else{ m_pFaceStorage = cvCreateMemStorage(0); } pfaceSeq = cvHaarDetectObjects(m_pProcessImg, m_pFaceCascade, m_pFaceStorage, 1.2, 3, CV_HAAR_DO_CANNY_PRUNING, cvSize(nFaceLimit,nFaceLimit)); if (pfaceSeq && pfaceSeq->total) { for(int i = 0; i < (pfaceSeq?pfaceSeq->total:0); i++) { nFaceNum++; //获取脸部矩形 CvRect* pFaceRect = (CvRect*)cvGetSeqElem(pfaceSeq, i); m_pHostApi->Debug(FACECAP_DEBUG, "第%d个人脸位置为(%d,%d,%d,%d).", i, pFaceRect->x, pFaceRect->y, pFaceRect->width, pFaceRect->height); m_pHostApi->Debug(FACECAP_DEBUG, "m_nImgHeight/m_stFaceConfig.fCloseFaceSize = %d.", (int)(m_nImgHeight / m_stFaceConfig.fCloseFaceSize)); m_pHostApi->Debug(FACECAP_DEBUG, "m_nImgHeight/m_stFaceConfig.fFarFaceSize = %d.", (int)(m_nImgHeight / m_stFaceConfig.fFarFaceSize)); m_pHostApi->Debug(FACECAP_DEBUG, "m_nImgHeight/m_stFaceConfig.fOperateFaceSize = %d.", (int)(m_nImgHeight / m_stFaceConfig.fOperateFaceSize)); //如果发现有人脸到达靠近区域,置有人靠近状态 if((pFaceRect->height >= (int)(m_nImgHeight/m_stFaceConfig.fCloseFaceSize))&&(pFaceRect->height <= (int)(m_nImgHeight/m_stFaceConfig.fOperateFaceSize))) { if((m_eMonitorState == NoBody) || (m_eMonitorState == SomebodyFar)) { nCurafaceSerial = nFaceNum; m_pHostApi->Debug(FACECAP_INFO, "有人靠近!"); m_eMonitorState = SomebodyClose; //进入有人靠近状态 } m_pHostEvent->GenerateMonitorEvent(Close); //产生有人靠近事件 } else if (pFaceRect->height >= (int)(m_nImgHeight/m_stFaceConfig.fOperateFaceSize)) { if(m_eMonitorState != SomebodyOperate) { nCurafaceSerial = nFaceNum; m_pHostApi->Debug(FACECAP_INFO, "有人进入操作距离!"); m_eMonitorState = SomebodyOperate; //进入有人靠近状态 } m_pHostEvent->GenerateMonitorEvent(EnterOperate); //产生有人进入操作距离事件 } else { if(m_eMonitorState == NoBody) { nCurafaceSerial = nFaceNum; m_pHostApi->Debug(FACECAP_INFO, "有人出现!"); m_eMonitorState = SomebodyFar; //进入远距离有人状态 } else { m_pHostApi->Debug(FACECAP_INFO, "远距离,有人出现!"); m_eMonitorState = SomebodyFar; //进入远距离有人状态 } m_pHostEvent->GenerateMonitorEvent(Appear); //产生有人出现事件 } } CvRect* pFaceRect = (CvRect*)cvGetSeqElem(pfaceSeq, nCurafaceSerial); m_pHostApi->Debug(FACECAP_DEBUG, "当前人脸框位置为:(%d, %d, %d, %d).", pFaceRect->x, pFaceRect->y, pFaceRect->width, pFaceRect->height); //截取人脸图像,放大截取区域,截取半身头像 CalcUpbodyRegion(pFaceRect); m_pHostApi->Debug(FACECAP_DEBUG, "截取和放大后的人脸框位置为:(%d, %d, %d, %d).", pFaceRect->x, pFaceRect->y, pFaceRect->width, pFaceRect->height); m_stAllFaceInfo.astFaceInfo[0].stRegion.stUpperBodyRect = *pFaceRect; } else { m_pHostApi->Debug(FACECAP_DEBUG, "未检测到人脸"); m_pHostEvent->GenerateMonitorEvent(video_monitor_event_type::NoDetectBody); //未检测到人脸 } if (pfaceSeq != NULL) { cvReleaseMemStorage(&pfaceSeq->storage); pfaceSeq = NULL; } cvResetImageROI(m_pProcessImg); if(nFaceNum > 0) { //发现有人 m_stAllFaceInfo.nTatolFaceNum = nFaceNum; return true; } else { m_eMonitorState = NoBody; return false; } } //运动检测 bool MotionTrack(CameraEnum eCamera, int diff_threshold = 10) { if (!GetImage(eCamera)) { m_pHostApi->Debug(FACECAP_DEBUG, "运动跟踪获取图像失败"); return false; } cvResetImageROI(m_pProcessImg); memset(&m_stObjTrackRslt,0,sizeof(CMotionTrackRslt)); const double MHI_DURATION = 0.5; const double MAX_TIME_DELTA = 0.5; const double MIN_TIME_DELTA = 0.05; const int N = 3; //ring image buffer // temporary images IplImage*dst = cvCreateImage( cvSize(m_pProcessImg->width,m_pProcessImg->height), 8, 1 ); cvZero( dst); dst->origin = m_pProcessImg->origin; //get current time in seconds double timestamp = clock()/100.; CvSize size = cvSize(m_pProcessImg->width,m_pProcessImg->height); int i, idx1, idx2; IplImage* silh; IplImage* pyr = cvCreateImage( cvSize((size.width & -2)/2, (size.height & -2)/2), 8, 1 ); CvMemStorage *stor; CvSeq *cont; if( !m_pMhImg || m_pMhImg->width != size.width || m_pMhImg->height != size.height ) { if( m_pMhBuf == 0 ) { m_pMhBuf = (IplImage**)malloc(N*sizeof(m_pMhBuf[0])); memset( m_pMhBuf, 0, N*sizeof(m_pMhBuf[0])); } for( i = 0; i < N; i++ ) { cvReleaseImage( &m_pMhBuf[i] ); m_pMhBuf[i] = cvCreateImage( size, IPL_DEPTH_8U, 1 ); cvZero(m_pMhBuf[i]); } cvReleaseImage( &m_pMhImg ); m_pMhImg = cvCreateImage( size, IPL_DEPTH_32F, 1 ); //clear MHI at the beginning cvZero( m_pMhImg ); } //convert frame to grayscale cvCvtColor( m_pProcessImg, m_pMhBuf[m_nLastBuf], CV_BGR2GRAY ); //cvSaveImage("0.bmp",m_pProcessImg); idx1 = m_nLastBuf; //index of (last - (N-1))th frame idx2 = (m_nLastBuf + 1) % N; m_nLastBuf = idx2; // 做帧差 silh = m_pMhBuf[idx2]; //get difference between frames cvAbsDiff( m_pMhBuf[idx1], m_pMhBuf[idx2], silh ); //cvSaveImage("Diff.bmp",silh); //对差图像做二值化 cvThreshold( silh, silh, 10, 255, CV_THRESH_BINARY ); //cvSaveImage("Threshold.bmp",silh); //更新运动历史图像 cvUpdateMotionHistory( silh, m_pMhImg, timestamp, MHI_DURATION ); cvCvtScale( m_pMhImg, dst, 255./MHI_DURATION, (MHI_DURATION - timestamp)*255./MHI_DURATION ); //cvCvtScale( m_pMhImg, dst, 255./MHI_DURATION, 0 ); // 中值滤波,消除小的噪声 cvSmooth( dst, dst, CV_MEDIAN, 3, 0, 0, 0 ); // 向下采样,去掉噪声 cvPyrDown( dst, pyr, 7 ); //闭运算,消除目标的不连续空洞 //进行闭运算 //IplConvKernel* element = cvCreateStructuringElementEx(20,20,1,1,CV_SHAPE_ELLIPSE); //cvMorphologyEx(pyr,pyr,NULL,element,CV_MOP_CLOSE,1); //膨胀 cvDilate( pyr, pyr, 0, 2 ); // 做膨胀操作,消除目标的不连续空洞 cvPyrUp( pyr, dst, 7 ); // 下面的程序段用来找到轮廓 stor = cvCreateMemStorage(0); cont = cvCreateSeq(CV_SEQ_ELTYPE_POINT, sizeof(CvSeq), sizeof(CvPoint) , stor); // 找到所有轮廓 cvFindContours( dst, stor, &cont, sizeof(CvContour), CV_RETR_LIST , CV_LINK_RUNS, cvPoint(0,0)); cvReleaseImage(&dst); //double fArea = 0.0; // 直接使用CONTOUR中的矩形来画轮廓 for(;cont;cont = cont->h_next) { CvRect r = ((CvContour*)cont)->rect; if((r.height * r.width > m_stFaceConfig.nContourMinAera)&&((r.height * r.width) != (m_nImgWidth*m_nImgHeight))) // 面积小的方形抛弃掉 //{ //fArea = fabs(cvContourArea( cont, CV_WHOLE_SEQ )); //获取当前轮廓面积 //if ((fArea > CONTOUR_MAX_AERA)&&(r.height * r.width != m_nImgWidth*m_nImgHeight)) { m_stObjTrackRslt.ObjRect[m_stObjTrackRslt.nObjNum] = r; m_stObjTrackRslt.nObjNum++; } //} } // free memory cvReleaseMemStorage(&stor); cvReleaseImage( &pyr ); cvResetImageROI(m_pProcessImg); if (m_stObjTrackRslt.nObjNum >0) { return true; } else { return false; } } //计算监控线程下一步 void VideoMonitorThreadNextStep() { m_pHostApi->Debug(FACECAP_DEBUG, "Enter VideoMonitorThreadNextStep"); if(m_stAllFaceInfo.astFaceInfo[0].eDistance == OperateDistance) { if (m_eMonitorState != SomebodyOperate) { m_eMonitorState = SomebodyOperate; m_stAllFaceInfo.astFaceInfo[0].eScene = ForwardScened; m_pHostEvent->GenerateMonitorEvent(EnterOperate); //产生有人进入操作距离事件 m_pHostApi->Debug(FACECAP_INFO, "有人进入操作距离!"); //获取UUID if (m_stAllFaceInfo.astFaceInfo[0].FaceID == 0) { m_stAllFaceInfo.astFaceInfo[0].FaceID = m_pHostApi->GenerateUUID(); } } else { if(m_stAllFaceInfo.astFaceInfo[0].eScene != LockScene) { m_eMonitorState = SomebodyOperate; m_stAllFaceInfo.astFaceInfo[0].eScene = LockScene; } m_pHostEvent->GenerateMonitorEvent(CaptureFace); //发送捕获人脸事件 //m_pHostApi->Debug("锁定人脸!"); } } else if(m_stAllFaceInfo.astFaceInfo[0].eDistance == FarDistance) { if((m_eMonitorState == SomebodyOperate)||(m_eMonitorState == SomebodyClose)) { m_stAllFaceInfo.astFaceInfo[0].eScene = UnLockScene; m_eMonitorState = SomebodyFar; memset(&m_stAllFaceInfo,0,sizeof(CAllFaceInfo)); m_stAllFaceInfo.astFaceInfo[0].stRegion.stUpperBodyRect.height = m_nImgHeight/2; m_stAllFaceInfo.astFaceInfo[0].stRegion.stUpperBodyRect.width = m_nImgWidth/2; m_stAllFaceInfo.astFaceInfo[0].stRegion.stUpperBodyRect.x = m_nImgHeight/4; m_stAllFaceInfo.astFaceInfo[0].stRegion.stUpperBodyRect.y = m_nImgWidth/4; m_pHostEvent->GenerateMonitorEvent(Leave); //产生客户离开事件 m_pHostApi->Debug(FACECAP_INFO, "客户离开!"); //清除UUID m_stAllFaceInfo.astFaceInfo[0].FaceID = 0; } } else if (m_stAllFaceInfo.astFaceInfo[0].eDistance == CloseDistance) { if (SomebodyOperate == m_eMonitorState) { m_stAllFaceInfo.astFaceInfo[0].eScene = BackwardScened; m_eMonitorState = SomebodyClose; m_pHostEvent->GenerateMonitorEvent(BackToClose); //产生客户退回到接近距离事件 m_pHostApi->Debug(FACECAP_INFO, "客户退回到接近距离!"); } else if(SomebodyFar == m_eMonitorState) { m_stAllFaceInfo.astFaceInfo[0].eScene = ForwardScened; m_eMonitorState = SomebodyClose; m_pHostApi->Debug(FACECAP_INFO, "有人靠近!"); //获取UUID if (m_stAllFaceInfo.astFaceInfo[0].FaceID == 0) { m_stAllFaceInfo.astFaceInfo[0].FaceID = m_pHostApi->GenerateUUID(); } } m_pHostEvent->GenerateMonitorEvent(Close); //产生有人靠近事件 } m_pHostApi->Debug(FACECAP_DEBUG, "Exit VideoMonitorThreadNextStep"); } // 计算当前人脸是否进入另外一个相机的最佳视野中 bool IsFacePosOverStep(CameraEnum eCamera,CvRect FaceRect) { if(m_pOperatorVideoQueue == NULL) { return false; } if(EnvironCamera == eCamera) { if(((FaceRect.x > (m_nImgWidth/2-m_nImgHeight/2+m_nImgHeight/m_stFaceConfig.fDetectFaceSize/2))|| (FaceRect.x < (m_nImgWidth/2+m_nImgHeight/2-m_nImgHeight/m_stFaceConfig.fDetectFaceSize/2)))&& (FaceRect.y > (m_nImgHeight-m_nImgHeight/m_stFaceConfig.fDetectFaceSize*4/m_stFaceConfig.nUpCameraEdgeLimit))) { return true; } else { return false; } } else if(OperatorCamera == eCamera) { if(FaceRect.y < ((m_nImgHeight/m_stFaceConfig.fDetectFaceSize)*1/m_stFaceConfig.nDownCameraEdgeLimit)) { return true; } else { return false; } } else { return false; } } void SetUpperbodyToCenter(CameraEnum eCamera) { int nImgWidth,nImgHeight; m_stAllFaceInfo.astFaceInfo[0].eCamera = eCamera; if (m_stAllFaceInfo.astFaceInfo[0].eCamera == EnvironCamera) { if (m_pEnvironMinVideoQueue == NULL) { return; } if (m_pEnvironMinVideoQueue->GetVideoLens()<=0) { m_pHostApi->Debug(FACECAP_DEBUG, "获取环境相机图像队列长度错误!"); return; } int size = m_pEnvironMinVideoQueue->GetFrameSize(nImgWidth,nImgHeight); } else if(m_stAllFaceInfo.astFaceInfo[0].eCamera == OperatorCamera) { if (m_pOperatorVideoQueue == NULL) { return; } if (m_pOperatorVideoQueue->GetVideoLens()<=0) { m_pHostApi->Debug(FACECAP_DEBUG, "获取操作相机图像队列长度错误!"); return ; } int size = m_pOperatorVideoQueue->GetFrameSize(nImgWidth,nImgHeight); } m_stAllFaceInfo.astFaceInfo[0].stRegion.stUpperBodyRect.height = nImgHeight/2; m_stAllFaceInfo.astFaceInfo[0].stRegion.stUpperBodyRect.width = nImgWidth/2; m_stAllFaceInfo.astFaceInfo[0].stRegion.stUpperBodyRect.x = nImgWidth/4; m_stAllFaceInfo.astFaceInfo[0].stRegion.stUpperBodyRect.y = nImgHeight/4; WriteAllFaceInfo(m_stAllFaceInfo); } void SetUpperbodyToCenter() { if(m_stFaceConfig.nPrimCamera == OperatorCamera) { if (m_pOperatorVideoQueue == NULL) { m_stAllFaceInfo.astFaceInfo[0].eCamera = EnvironCamera; } else { m_stAllFaceInfo.astFaceInfo[0].eCamera = OperatorCamera; } } else { m_stAllFaceInfo.astFaceInfo[0].eCamera = EnvironCamera; } int nImgWidth,nImgHeight; if (m_stAllFaceInfo.astFaceInfo[0].eCamera == EnvironCamera) { if (m_pEnvironMinVideoQueue == NULL) { return; } if (m_pEnvironMinVideoQueue->GetVideoLens()<=0) { m_pHostApi->Debug(FACECAP_DEBUG, "获取环境相机图像队列长度错误!"); return ; } int size = m_pEnvironMinVideoQueue->GetFrameSize(nImgWidth,nImgHeight); } else if(m_stAllFaceInfo.astFaceInfo[0].eCamera == OperatorCamera) { if (m_pOperatorVideoQueue == NULL) { return; } if (m_pOperatorVideoQueue->GetVideoLens()<=0) { m_pHostApi->Debug(FACECAP_DEBUG, "获取操作相机图像队列长度错误!"); return ; } int size = m_pOperatorVideoQueue->GetFrameSize(nImgWidth,nImgHeight); } m_stAllFaceInfo.astFaceInfo[0].stRegion.stUpperBodyRect.height = nImgHeight/2; m_stAllFaceInfo.astFaceInfo[0].stRegion.stUpperBodyRect.width = nImgWidth/2; m_stAllFaceInfo.astFaceInfo[0].stRegion.stUpperBodyRect.x = nImgWidth/4; m_stAllFaceInfo.astFaceInfo[0].stRegion.stUpperBodyRect.y = nImgHeight/4; WriteAllFaceInfo(m_stAllFaceInfo); } bool RvcTimeout(int ims) { bool btimeout = true; #ifdef _WIN32 DWORD dwRet = WaitForSingleObject(m_hStopEventWait, ims); if (WAIT_TIMEOUT == dwRet) { } else if (WAIT_OBJECT_0 == dwRet) { btimeout = false; } #else struct timespec ts; clock_gettime(CLOCK_REALTIME, &ts); long unsec = ts.tv_nsec + (1000 * 1000 * ims); ts.tv_sec += (unsec / 1000000000); ts.tv_nsec = (unsec % 1000000000); int itimeout = sem_timedwait(&m_semt, &ts); if (0 != itimeout && (ETIMEDOUT == errno)) { } else if (0 == itimeout) { btimeout = false; } #endif return btimeout; } void ReleaseMotionTrackRst() { if (m_pMhImg) { m_pHostApi->Debug(FACECAP_DEBUG, "%s:%d", __FUNCTION__, __LINE__); cvReleaseImage(&m_pMhImg); m_pHostApi->Debug(FACECAP_DEBUG, "%s:%d", __FUNCTION__, __LINE__); m_pMhImg = NULL; } if(m_pMhBuf) { for (int i=0;i<3;i++) { if (m_pMhBuf[i] != NULL) { m_pHostApi->Debug(FACECAP_DEBUG, "%s:%d", __FUNCTION__, __LINE__); cvReleaseImage(&m_pMhBuf[i]); m_pHostApi->Debug(FACECAP_DEBUG, "%s:%d", __FUNCTION__, __LINE__); m_pMhBuf[i] = NULL; } } free(m_pMhBuf); m_pMhBuf = NULL; } m_nLastBuf=0; } CameraEnum GetInitPrimCamera() { CameraEnum eCamera = (CameraEnum)m_stFaceConfig.nPrimCamera; if (NULL == m_pOperatorVideoQueue) { if ((m_nCameraState == 0) || (m_nCameraState == 2)) { eCamera = EnvironCamera; } else if (m_nCameraState == 1) { eCamera = OperatorCamera; } else if (m_nCameraState == 3) { eCamera = ErrorCamera; } } return eCamera; } int VideoMonitor() { bool bRst = false; uint32_t nSearchFailNum = 0; //搜索人脸失败次数 uint32_t nDetectFailNum = 0; //检测人脸失败的次数 uint32_t nBreakDownNum = 0; uint32_t nMotionTrackNum = 0; //select camera m_eCamera = GetInitPrimCamera(); m_pHostApi->Debug(FACECAP_DEBUG, "m_bStopVieoMonitor flag is %s.", m_bStopVieoMonitor ? "true":"false"); m_pHostApi->Debug(FACECAP_DEBUG, "init prim camera is %d(0 = env, 1 = opt, 2 = cameraerror).", m_eCamera); uint32_t iwaittime = m_stFaceConfig.nSleepShort; while (!m_bStopVieoMonitor) { m_pHostApi->Debug(FACECAP_DEBUG, "%s:%d iwaittime = %dms.", __FUNCTION__, __LINE__, iwaittime); if(RvcTimeout(iwaittime)) { //如果摄像头没启动或故障,停止扫描,休眠2s if (3 == m_nCameraState){ iwaittime = 2000; m_pHostApi->Debug(FACECAP_INFO, "camera stop or all camera error!"); continue; } //灯光变化时,清空历史记录,防止误判 if (m_bLightChange){ m_pHostApi->Debug(FACECAP_DEBUG, "%s:%d", __FUNCTION__, __LINE__); ReleaseMotionTrackRst(); m_pHostApi->Debug(FACECAP_DEBUG, "%s:%d", __FUNCTION__, __LINE__); nMotionTrackNum = 0; m_bLightChange = false; } m_pHostApi->Debug(FACECAP_DEBUG, "%s:%d m_eMonitorState = %d.", __FUNCTION__, __LINE__, m_eMonitorState); //if no people,start motion tracker if(NoBody == m_eMonitorState){ m_pHostApi->Debug(FACECAP_DEBUG, "NoBody"); bRst = GetImage(m_eCamera); if (bRst){ int size = (int)m_nImgHeight/m_stFaceConfig.fSearchFaceSize; m_pHostApi->Debug(FACECAP_DEBUG, "%s:%d size = %d.", __FUNCTION__, __LINE__, size); bRst = FaceSearch(size); if (!bRst){ SetUpperbodyToCenter(); iwaittime = m_stFaceConfig.nSleepLong; } else{ WriteAllFaceInfo(m_stAllFaceInfo); iwaittime = m_stFaceConfig.nSleepMiddle; } } else{ iwaittime = m_stFaceConfig.nSleepMiddle; } } else if (SomebodyFar == m_eMonitorState) //if somebody space 2.5m { m_pHostApi->Debug(FACECAP_DEBUG, "SomebodyFar"); bRst = GetImage(m_eCamera); if (bRst){ int size = (int)m_nImgHeight/m_stFaceConfig.fSearchFaceSize; m_pHostApi->Debug(FACECAP_DEBUG, "%s:%d", __FUNCTION__, __LINE__); bRst = FaceSearch(size); m_pHostApi->Debug(FACECAP_DEBUG, "%s:%d", __FUNCTION__, __LINE__); if (!bRst){ SetUpperbodyToCenter(); iwaittime = m_stFaceConfig.nSleepMiddle; } else{ if (m_eMonitorState <= SomebodyFar){ WriteAllFaceInfo(m_stAllFaceInfo); } iwaittime = m_stFaceConfig.nSleepShort; } } else{ iwaittime = m_stFaceConfig.nSleepMiddle; } } else if (SomebodyClose == m_eMonitorState) //close distance,1.5m { m_pHostApi->Debug(FACECAP_DEBUG, "SomebodyClose"); bRst = FaceDetect(m_eCamera); if(!bRst){ if(NULL != m_pOperatorVideoQueue){ (m_eCamera == EnvironCamera)?(m_eCamera = OperatorCamera):(m_eCamera = EnvironCamera); bRst = FaceDetect(m_eCamera); if (!bRst){ nSearchFailNum++; //if search face fail, return motiontracker if(nSearchFailNum >2){ SetUpperbodyToCenter(); m_eMonitorState = NoBody; m_pHostEvent->GenerateMonitorEvent(Leave); m_pHostApi->Debug(FACECAP_DEBUG, "客户离开!"); nSearchFailNum = 0; iwaittime = m_stFaceConfig.nSleepLong; } else{ iwaittime = m_stFaceConfig.nSleepMiddle; } } else{ nSearchFailNum = 0; VideoMonitorThreadNextStep(); WriteAllFaceInfo(m_stAllFaceInfo); iwaittime = m_stFaceConfig.nSleepShort; } } else //single camera mod { nSearchFailNum++; //if search face fail,return motiontracker if(nSearchFailNum > 2){ SetUpperbodyToCenter(); m_eMonitorState = NoBody; m_pHostEvent->GenerateMonitorEvent(Leave); m_pHostApi->Debug(FACECAP_DEBUG, "客户离开!"); nSearchFailNum = 0; iwaittime = m_stFaceConfig.nSleepLong; } else{ iwaittime = m_stFaceConfig.nSleepMiddle; } } } else { //if curcamera search face success,judge which camera result is the best m_pHostApi->Debug(FACECAP_DEBUG, "Close distance, EnvironCamera Search face Success"); if((m_pOperatorVideoQueue != NULL)&&(m_pEnvironMinVideoQueue != NULL)) { (m_eCamera == EnvironCamera)?(m_eCamera = OperatorCamera):(m_eCamera = EnvironCamera); CAllFaceInfo stFaceInfoTmp = m_stAllFaceInfo; if (FaceDetect(m_eCamera)) { int CurFaceArea = m_stAllFaceInfo.astFaceInfo[0].stRegion.stFaceRect.width* m_stAllFaceInfo.astFaceInfo[0].stRegion.stFaceRect.height; int FrontFaceArea = stFaceInfoTmp.astFaceInfo[0].stRegion.stFaceRect.width* stFaceInfoTmp.astFaceInfo[0].stRegion.stFaceRect.height; //if cur face area less than front face,select front Face if (FrontFaceArea > CurFaceArea){ (m_eCamera == EnvironCamera)?(m_eCamera = OperatorCamera):(m_eCamera = EnvironCamera); m_stAllFaceInfo = stFaceInfoTmp; } } else{ (m_eCamera == EnvironCamera)?(m_eCamera = OperatorCamera):(m_eCamera = EnvironCamera); m_stAllFaceInfo = stFaceInfoTmp; } } nSearchFailNum = 0; VideoMonitorThreadNextStep(); WriteAllFaceInfo(m_stAllFaceInfo); iwaittime = m_stFaceConfig.nSleepShort; } } else if (SomebodyOperate == m_eMonitorState) //当有人进入操作距离时 { m_pHostApi->Debug(FACECAP_DEBUG, "SomebodyOperate"); //如果是双相机模式 if (m_pOperatorVideoQueue != NULL) { m_eCamera = m_stAllFaceInfo.astFaceInfo[0].eCamera; //先搜索上次搜索到人脸的区域 if(m_stAllFaceInfo.nTatolFaceNum > 0) { m_pHostApi->Debug(FACECAP_DEBUG, "Operator distance,CurCamera search last face Region"); bRst = FaceDetect(m_eCamera, m_stAllFaceInfo.astFaceInfo[0].stRegion.stUpperBodyRect); } else { bRst = false; } if(!bRst) { m_pHostApi->Debug(FACECAP_DEBUG, "Operator distance,search Face by CurCamera"); bRst = FaceDetect(m_eCamera); } } else //如果单相机模式 { //m_eCamera = (CameraEnum)m_stFaceConfig.nPrimCamera; //先搜索上次搜索到人脸的区域 if(m_stAllFaceInfo.nTatolFaceNum > 0) { m_pHostApi->Debug(FACECAP_DEBUG, "Operator distance, EnvironCamera Search Last face Region"); bRst = FaceDetect(m_eCamera,m_stAllFaceInfo.astFaceInfo[0].stRegion.stUpperBodyRect); } else { bRst = false; } if(!bRst) { bRst = FaceDetect(m_eCamera); } } if(bRst) //如果在当前相机中找到人脸 { nDetectFailNum = 0; //如果是双相机模式, if(m_pOperatorVideoQueue!=NULL) { //找到人脸后,检测另一个相机中是否有更大的人脸 (m_eCamera == EnvironCamera)?(m_eCamera=OperatorCamera):(m_eCamera=EnvironCamera); CAllFaceInfo stFaceInfoTmp = m_stAllFaceInfo; if (FaceDetect(m_eCamera)) { int CurFaceArea = m_stAllFaceInfo.astFaceInfo[0].stRegion.stFaceRect.width* m_stAllFaceInfo.astFaceInfo[0].stRegion.stFaceRect.height; int FrontFaceArea = stFaceInfoTmp.astFaceInfo[0].stRegion.stFaceRect.width* stFaceInfoTmp.astFaceInfo[0].stRegion.stFaceRect.height; //if cur face area less than front face,select front Face if (FrontFaceArea > CurFaceArea) { (m_eCamera == EnvironCamera)?(m_eCamera=OperatorCamera):(m_eCamera=EnvironCamera); m_stAllFaceInfo = stFaceInfoTmp; } } else { (m_eCamera == EnvironCamera)?(m_eCamera=OperatorCamera):(m_eCamera=EnvironCamera); m_stAllFaceInfo = stFaceInfoTmp; } //判断用户是否进入另外一个相机的视野,如果进入另一个相机的最佳视野 if((m_pEnvironMinVideoQueue!=NULL)&&IsFacePosOverStep(m_eCamera,m_stAllFaceInfo.astFaceInfo[0].stRegion.stFaceRect)) { stFaceInfoTmp = m_stAllFaceInfo; //暂存当前结果 memset(&m_stAllFaceInfo,0,sizeof(CAllFaceInfo)); (m_eCamera == OperatorCamera)?(m_eCamera = EnvironCamera):(m_eCamera = OperatorCamera); //在另一个相机中重新搜索 m_pHostApi->Debug(FACECAP_DEBUG, "Operator distance, Change camera to:%d search Face",(int)m_eCamera); bRst = FaceDetect(m_eCamera); if(!bRst) { (m_eCamera == EnvironCamera)?(m_eCamera=OperatorCamera):(m_eCamera=EnvironCamera); m_stAllFaceInfo = stFaceInfoTmp; } } } VideoMonitorThreadNextStep(); ////人脸卡图 //if (m_stFaceConfig.nServersType == 0) //{ // m_pHostApi->Debug(FACECAP_DEBUG, "%s:%d begin CaptureOperatorFace, m_pProcessImg->depth = %d, m_pProcessImg->width = %d, m_pProcessImg->height = %d, m_pProcessImg->widthStep = %d.", __FUNCTION__, __LINE__, m_pProcessImg->depth, m_pProcessImg->width, m_pProcessImg->height, m_pProcessImg->widthStep); // CaptureOperatorFace(m_pProcessImg); // m_pHostApi->Debug(FACECAP_DEBUG, "%s:%d exit CaptureOperatorFace", __FUNCTION__, __LINE__); //} WriteAllFaceInfo(m_stAllFaceInfo); iwaittime = m_stFaceConfig.nSleepLong; } else //如果在当前相机中未找到用户 { //如果双相机模式 if(m_pOperatorVideoQueue!=NULL) { (m_eCamera == OperatorCamera)?(m_eCamera = EnvironCamera):(m_eCamera = OperatorCamera); m_pHostApi->Debug(FACECAP_DEBUG, "Operator distance, Change camera to:%d search Face",(int)m_eCamera); bRst = FaceDetect(m_eCamera); if(bRst) { nDetectFailNum = 0; VideoMonitorThreadNextStep(); ////人脸卡图 //if (m_stFaceConfig.nServersType == 0) //{ // m_pHostApi->Debug(FACECAP_DEBUG, "%s:%d begin CaptureOperatorFace", __FUNCTION__, __LINE__); // CaptureOperatorFace(m_pProcessImg); // m_pHostApi->Debug(FACECAP_DEBUG, "%s:%d exit CaptureOperatorFace", __FUNCTION__, __LINE__); //} WriteAllFaceInfo(m_stAllFaceInfo); m_pHostApi->Debug(FACECAP_DEBUG, "Write Face info Success"); iwaittime = m_stFaceConfig.nSleepLong; } else { nDetectFailNum++; if(nDetectFailNum >2) //如果连续2次未找到人脸,回到有人靠近状态 { m_eMonitorState = SomebodyClose; m_stAllFaceInfo.astFaceInfo[0].eScene = UnLockScene; m_pHostEvent->GenerateMonitorEvent(LoseFace); //发送失去人脸事件 m_pHostApi->Debug(FACECAP_DEBUG, "人脸失去锁定!"); nDetectFailNum = 0; } iwaittime = m_stFaceConfig.nSleepShort; } } else //如果单相机模式 { nDetectFailNum++; if(nDetectFailNum > 3) //如果连续3次未找到人脸,回到有人靠近状态 { m_eMonitorState = SomebodyClose; m_stAllFaceInfo.astFaceInfo[0].eScene = UnLockScene; m_pHostEvent->GenerateMonitorEvent(LoseFace); //发送失去人脸事件 m_pHostApi->Debug(FACECAP_DEBUG, "人脸失去锁定!"); nDetectFailNum = 0; } iwaittime = m_stFaceConfig.nSleepShort; } } } } else { m_pHostApi->Debug(FACECAP_DEBUG, "%s:%d.", __FUNCTION__, __LINE__); //清空存储区 if (pfaceSeq != NULL){ cvReleaseMemStorage(&pfaceSeq->storage); pfaceSeq = NULL; } m_pHostApi->Debug(FACECAP_DEBUG, "%s:%d.", __FUNCTION__, __LINE__); if (NULL != m_pProcessImg){ cvResetImageROI(m_pProcessImg); } m_pHostApi->Debug(FACECAP_DEBUG, "%s:%d.", __FUNCTION__, __LINE__); nBreakDownNum++; if (nBreakDownNum == 5){ m_pHostEvent->GenerateMonitorEvent(FaceCaptureFC); //发送人脸崩溃事件 m_pHostApi->Debug(FACECAP_INFO, "opencv library breakdown!"); } m_pHostApi->Debug(FACECAP_DEBUG, "%s:%d.", __FUNCTION__, __LINE__); //Sleep(3*m_stFaceConfig.nSleepShort); m_pHostApi->Debug(FACECAP_DEBUG, "stop Video Monitor."); } } m_pHostApi->Debug(FACECAP_DEBUG, "%s:%d exit video monitor thread.", __FUNCTION__, __LINE__); return 0; } #ifdef _WIN32 static unsigned int __stdcall VideoMonitorThread(void* pParam) { Clibfacecapture_impl* VideoFaceMonitor = (Clibfacecapture_impl*)pParam; return VideoFaceMonitor->VideoMonitor(); } #else static void* videomonitorfunc(void* pParam) { Clibfacecapture_impl* VideoFaceMonitor = (Clibfacecapture_impl*)pParam; VideoFaceMonitor->VideoMonitor(); return ((void*)0); } #endif public: //开始视频监控,pHost:事件,nMonitorFreq:监控频率,单位ms,MonitorType:监控类型,有三种模式可供选择 bool StartVideoMonitor(CHostApi *pHostAPI, CVideoMonitorEvent*pHost, MonitorEnum eMonitorType) { #ifdef _WIN32 ResetEvent(m_hStopEventWait); if (NULL == m_hVieoMonitorThread){ m_pHostApi->Debug(FACECAP_DEBUG, "create video monitor thread."); m_hVieoMonitorThread = (HANDLE)_beginthreadex(NULL, 0, VideoMonitorThread, this, 0, (unsigned int*)&m_nVieoMonitorThreadId); m_bStopVieoMonitor = false; m_pHostApi->Debug(FACECAP_DEBUG, "%s:%d m_hVieoMonitorThread = 0x%08x.", __FUNCTION__, __LINE__, m_hVieoMonitorThread); } #else if (0 == pthread_create(&m_videomonitorthreadid, NULL, videomonitorfunc, (void*)this)){ m_pHostApi->Debug(FACECAP_DEBUG, "create video monitor thread and thread id is %u.", m_videomonitorthreadid); m_bStopVieoMonitor = false; } else { m_pHostApi->Debug(FACECAP_INFO, "create video monitor thread failed."); } #endif return true; } //停止视频监控 bool StopVideoMonitor() { m_bStopVieoMonitor = true; #ifdef _WIN32 m_pHostApi->Debug(FACECAP_DEBUG, "%s:%d.", __FUNCTION__, __LINE__); SetEvent(m_hStopEventWait); m_pHostApi->Debug(FACECAP_DEBUG, "%s:%d m_hVieoMonitorThread = 0x%08x.", __FUNCTION__, __LINE__, m_hVieoMonitorThread); DWORD ret = WaitForSingleObject(m_hVieoMonitorThread, INFINITE); if (WAIT_OBJECT_0 == ret) { m_pHostApi->Debug(FACECAP_DEBUG, "normal ...."); } else if (WAIT_ABANDONED == ret) { m_pHostApi->Debug(FACECAP_DEBUG, "abandoned ...."); } m_pHostApi->Debug(FACECAP_DEBUG, "%s:%d.", __FUNCTION__, __LINE__); CloseHandle(m_hVieoMonitorThread); m_pHostApi->Debug(FACECAP_DEBUG, "%s:%d.", __FUNCTION__, __LINE__); m_hVieoMonitorThread = NULL; m_pHostApi->Debug(FACECAP_DEBUG, "%s:%d.", __FUNCTION__, __LINE__); #else sem_post(&m_semt); if (0 == pthread_join(m_videomonitorthreadid, NULL)) { m_pHostApi->Debug(FACECAP_DEBUG, "thread join video monitor thread %u success!", m_videomonitorthreadid); m_videomonitorthreadid = 0; } else{ m_pHostApi->Debug(FACECAP_INFO, "thread join video monitor thread failed!"); } #endif return true; } //有多少其他用户 bool GetCustomerNum(uint32_t& num) { #ifdef _WIN32 EnterCriticalSection(&CS); #else pthread_mutex_lock(&cs_mutex); #endif num = m_stFaceRstStorage.nTatolFaceNum; #ifdef _WIN32 LeaveCriticalSection(&CS); #else pthread_mutex_unlock(&cs_mutex); #endif return true; } //获取主用户的常规属性 bool GetMainCustomerStatus(uint64_t &FaceID, CCustomerStatus &Property) { #ifdef _WIN32 EnterCriticalSection(&CS); #else pthread_mutex_lock(&cs_mutex); #endif //Property.eBrightness = m_stFaceRstStorage.astFaceInfo[0].eBrightness; Property.stCustomerCover = m_stFaceRstStorage.astFaceInfo[0].stCustomerCover; Property.stCustomerPos.eCamera = m_stFaceRstStorage.astFaceInfo[0].eCamera;//1 Property.stCustomerPos.eDistance = m_stFaceRstStorage.astFaceInfo[0].eDistance; Property.stCustomerPos.ePose = m_stFaceRstStorage.astFaceInfo[0].ePose; Property.stCustomerPos.eScene = m_stFaceRstStorage.astFaceInfo[0].eScene; Property.stCustomerPos.stRange.sX = m_stFaceRstStorage.astFaceInfo[0].stRegion.stUpperBodyRect.x +(short)m_stFaceRstStorage.astFaceInfo[0].stRegion.stUpperBodyRect.width/2-(short)m_nImgWidth/2; Property.stCustomerPos.stRange.sY = m_stFaceRstStorage.astFaceInfo[0].stRegion.stUpperBodyRect.y +(short)m_stFaceRstStorage.astFaceInfo[0].stRegion.stUpperBodyRect.height/2-(short)m_nImgHeight/2; Property.stCustomerPos.stRange.sH = (short)m_stFaceRstStorage.astFaceInfo[0].stRegion.stUpperBodyRect.height/2; FaceID = m_stFaceRstStorage.astFaceInfo[0].FaceID; #ifdef _WIN32 LeaveCriticalSection(&CS); #else pthread_mutex_unlock(&cs_mutex); #endif return true; } //获取用户的常规属性 bool GetCustomerStatus(uint64_t FaceID, CCustomerStatus &Property) { #ifdef _WIN32 EnterCriticalSection(&CS); #else pthread_mutex_lock(&cs_mutex); #endif bool bSearch = false; for (int i =0;iGetCustomerNum(num); } //获取主用户的常规属性 bool Clibfacecapture::GetMainCustomerStatus(uint64_t &FaceID,CCustomerStatus &Property) { return m_pImpl->GetMainCustomerStatus(FaceID,Property); } //获取其他用户的常规属性 bool Clibfacecapture::GetCustomerStatus (uint64_t FaceID,CCustomerStatus &Property) { return m_pImpl->GetCustomerStatus(FaceID,Property); } //获取主用户的交互属性 bool Clibfacecapture::GetCustomerAppearance(uint64_t FaceID,CCustomerAppearance &Property) { return m_pImpl->GetCustomerAppearance(FaceID,Property); } //获取所有用户FACEID bool Clibfacecapture::GetTrackFace(uint64_t*arrFaceIDs, int *size) { return m_pImpl->GetTrackFace(arrFaceIDs, size); } //灯光变化 void Clibfacecapture::SetLightChange() { m_pImpl->m_bLightChange = true; } //相机状态 void Clibfacecapture::SetCameraState(int nState) { m_pImpl->m_nCameraState = nState; } bool Clibfacecapture::StartFaceCapture() { return m_pImpl->StartFaceCapture(); } bool Clibfacecapture::StopFaceCapture() { return m_pImpl->StopFaceCapture(); } bool SnapShot(CImageFrame*img) { if(img == NULL){ return false; } IplImage*cvimgtmp = cvCreateImage(cvSize(img->width,img->height),8,3); IplImage*cvimg = cvCreateImage(cvSize(img->width,img->height),8,3); char m_FileName[MAX_PATH] = {0}; #ifdef _WIN32 SYSTEMTIME nowTime; // 系统时间结构体 GetLocalTime(&nowTime); _snprintf(m_FileName, MAX_PATH, "%4d%02d%02d%02d%02d%02d", nowTime.wYear, nowTime.wMonth, nowTime.wDay, nowTime.wHour, nowTime.wMinute, nowTime.wSecond); #else struct tm* pst = NULL; time_t t = time(NULL); pst = localtime(&t); snprintf(m_FileName, MAX_PATH, "%4d%02d%02d%02d%02d%02d", pst->tm_year + 1900, pst->tm_mon + 1, pst->tm_mday, pst->tm_hour, pst->tm_min, pst->tm_wday, pst->tm_sec); #endif // _WIN32 CvFont fontEvent = cvFont(2,2); memcpy(cvimg->imageData,img->data,img->framesize); int nstartx = 0; int nstarty = 0; cvCopy(cvimg,cvimgtmp); cvPutText(cvimgtmp, m_FileName,cvPoint(img->width-280,img->height-10), &fontEvent, CV_RGB( 255, 0, 0)); memcpy(img->data,cvimgtmp->imageData,img->framesize); cvReleaseImage(&cvimg); cvReleaseImage(&cvimgtmp); return true; }