1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656 |
- // libfacecapture.cpp : 定义 DLL 应用程序的导出函数。
- //
- #include "stdafx.h"
- #include "libfacecapture.h"
- #include <string.h>
- #include <atlstr.h>
- #include <math.h>
- #include <windows.h>
- #include "cv.h"
- #include "highgui.h"
- #include "libvideoqueue.h"
- #include "libsharememory.h"
- //#define SHAREMEM
- #ifndef SPBASE_API
- #define CUUID __int64
- #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
- {
- CUUID 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;
- m_hVieoMonitorThread = NULL;
- m_bStopVieoMonitor = false;
- m_pEnvironMinVideoQueue = NULL;
- m_pEnvironMaxVideoQueue =NULL;
- m_pOperatorVideoQueue =NULL;
- m_nVieoMonitorExitCode = 0;
- m_nVieoMonitorThreadId = 0;
- 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));
- }
- InitializeCriticalSection(&CS);
- m_hStopEventWait= ::CreateEventA(NULL, TRUE, 0, 0);
- if (!m_hStopEventWait) {
- *pResult = false;
- pHostAPI->Debug(FACECAP_INFO, "create hEventWait failed!");
- return;
- }
- 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()
- {
- if (true == StopVideoMonitor()){
- m_pHostApi->Debug(FACECAP_DEBUG, "Stop Video Monitor Thread Success!");
- }
- if (NULL != m_pEnvironMinVideoQueue){
- delete m_pEnvironMinVideoQueue;
- m_pEnvironMinVideoQueue = NULL;
- }
- if (NULL != m_pEnvironMaxVideoQueue){
- delete m_pEnvironMaxVideoQueue;
- m_pEnvironMaxVideoQueue = NULL;
- }
- if (NULL != m_pOperatorVideoQueue){
- delete m_pOperatorVideoQueue;
- m_pOperatorVideoQueue = NULL;
- }
- return true;
- }
- ~Clibfacecapture_impl()
- {
- DeleteCriticalSection(&CS);
- 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:
- HANDLE m_hStopEventWait; // CreateEvent
- CRITICAL_SECTION CS;
- 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];
- HANDLE m_hVieoMonitorThread;
- DWORD m_nVieoMonitorExitCode;
- DWORD m_nVieoMonitorThreadId;
- 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,"\\");
- strcat(dir,CascadeType);
- }
- //写人脸检测数据
- bool WriteAllFaceInfo(CAllFaceInfo faceInfo)
- {
- EnterCriticalSection(&CS);
- m_stFaceRstStorage = faceInfo;
- LeaveCriticalSection(&CS);
- 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_INFO, "获取环境相机图像队列长度错误!");
- }
- else if (videoqueue == m_pOperatorVideoQueue)
- {
- m_pHostApi->Debug(FACECAP_INFO, "获取操作相机图像队列长度错误!");
- }
- return false;
- }
- int size = videoqueue->GetFrameSize(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); //创建图像
- }
- }
- 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)
- {
- if (eCamera == EnvironCamera){
- if (m_pEnvironMinVideoQueue == NULL){
- return false;
- }
- bool bRslt = GetCurImg(m_pEnvironMinVideoQueue);
- if (!bRslt){
- return false;
- }
- }
- else if(eCamera == OperatorCamera){
- if (m_pOperatorVideoQueue == NULL){
- return false;
- }
- bool bRslt = GetCurImg(m_pOperatorVideoQueue);
- if (!bRslt){
- return false;
- }
- }
- 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;i<MAX_FACE_NUM;i++)
- {
- memset(&m_stAllFaceInfo.astFaceInfo[i], 0, sizeof(CCustomerInfo));
- }
- }
- //特征检测,检测眼睛,鼻子,嘴巴
- bool FeatureDetect(CvHaarClassifierCascade *pCascade, CvRect *pFaceRect,CvMemStorage* pFaceStorage)
- {
- //搜索区域图像
- CvRect RegionRect;
- if (pCascade == m_pEyeCascade)
- {
- //眼睛
- RegionRect.x = pFaceRect->x;
- 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;i<FaceRect->height;i++)
- {
- for(int j=0;j<FaceRect->width;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;i<FaceRect->height;i++)
- {
- for(int j=0;j<FaceRect->width;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)
- {
- if (!GetImage(eCamera))
- {
- RecordError("获取图像失败");
- 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; num<m_stAllFaceInfo.nTatolFaceNum; num++)
- {
- nPreFaceNum = m_stAllFaceInfo.nTatolFaceNum;
- m_PreFaceRect[num] = m_stAllFaceInfo.astFaceInfo[num].stRegion.stFaceRect;
- }
- //清除上一次的记录
- ClearInspectResult();
- }
- for(int i=0;i<(pfaceSeq?pfaceSeq->total:0)&&(i<MAX_FACE_NUM);i++)
- {
- m_stAllFaceInfo.nTatolFaceNum++;
- //获取脸部矩形
- pFaceRect = (CvRect*)cvGetSeqElem(pfaceSeq,i);
- //如果是前端检测则需要特征检测,如果是坐席则不需检测
- if (m_stFaceConfig.nServersType == 0)
- {
- //找眼睛
- m_stAllFaceInfo.astFaceInfo[nFaceSerial].stCustomerCover.bShowEyes = FeatureDetect(m_pEyeCascade,pFaceRect,m_pFaceStorage);
- //找鼻子
- m_stAllFaceInfo.astFaceInfo[nFaceSerial].stCustomerCover.bShowNose = FeatureDetect(m_pNoseCascade,pFaceRect,m_pFaceStorage);
- //找嘴巴
- m_stAllFaceInfo.astFaceInfo[nFaceSerial].stCustomerCover.bShowMouth = FeatureDetect(m_pMouthCascade,pFaceRect,m_pFaceStorage);
- }
- else
- {
- //找眼睛
- m_stAllFaceInfo.astFaceInfo[nFaceSerial].stCustomerCover.bShowEyes = false;
- //找鼻子
- m_stAllFaceInfo.astFaceInfo[nFaceSerial].stCustomerCover.bShowNose = false;
- //找嘴巴
- m_stAllFaceInfo.astFaceInfo[nFaceSerial].stCustomerCover.bShowMouth = false;
- }
- if(!(m_stAllFaceInfo.astFaceInfo[nFaceSerial].stCustomerCover.bShowEyes||
- m_stAllFaceInfo.astFaceInfo[nFaceSerial].stCustomerCover.bShowNose||
- m_stAllFaceInfo.astFaceInfo[nFaceSerial].stCustomerCover.bShowMouth))
- {
- m_stAllFaceInfo.astFaceInfo[nFaceSerial].stCustomerCover.bClearFace = false;
- }
- else
- {
- m_stAllFaceInfo.astFaceInfo[nFaceSerial].stCustomerCover.bClearFace = true;
- }
- //计算当前人脸位置,如果当前人脸位置与上次人脸位置小于偏移量则取上次人脸位置,防止人脸图像跳变
- for (int num=0; num<nPreFaceNum; num++)
- {
- if ((abs(pFaceRect->x - m_PreFaceRect[num].x)<m_stFaceConfig.nFaceSizeOffset) && (abs(pFaceRect->y-m_PreFaceRect[num].y)<m_stFaceConfig.nFaceSizeOffset)
- && (abs(pFaceRect->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)&&(CurDistance<TempDistance))||
- //如果当前数据不在中心区域,temp数据在中心区域,且当前数据距离更近,则更新temp
- ((CurRegion != FaceRegionCenter)&&(TempRegion == FaceRegionCenter)&&(CurDistance<TempDistance))||
- //如果当前数据不在中心区域,temp数据也不在中心区域,且距离一样,若当前数据更靠近历史数据,则当前数据作为temp
- ((TempRegion!=FaceRegionCenter)&&(CurRegion!=FaceRegionCenter)&&(CurDistance==TempDistance)&&(CurPointDist<TempPointDist)))
- {
- if((TempRegion != 0)&&(TempDistance != 0.0))
- {
- CCustomerInfo Temp = UserFaceTemp;
- UserFaceTemp = m_stAllFaceInfo.astFaceInfo[nFaceSerial];
- m_stAllFaceInfo.astFaceInfo[nFaceSerial] = Temp;
- nFaceSerial++;
- }
- else
- {
- UserFaceTemp = m_stAllFaceInfo.astFaceInfo[nFaceSerial];
- memset(&m_stAllFaceInfo.astFaceInfo[nFaceSerial],0,sizeof(CCustomerInfo));
- }
- }
- else
- {
- nFaceSerial++;
- }
- }
- 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_stAllFaceInfo.astFaceInfo[0].eBrightness = CalcFaceBrightness(m_pProcessImg,&m_stAllFaceInfo.astFaceInfo[0].stRegion.stFaceRect);
- }
- }
- //清空存储区
- cvResetImageROI(m_pProcessImg);
- if (pfaceSeq != NULL)
- {
- cvReleaseMemStorage(&pfaceSeq->storage);
- pfaceSeq = NULL;
- }
- for(int i=0; i<MAX_FACE_NUM; i++)
- {
- m_PreFaceRect[i] = cvRect(0,0,0,0);
- }
- if(m_stAllFaceInfo.nTatolFaceNum == 0)
- {
- ClearInspectResult();
- return false;
- }
- else
- {
- return true;
- }
- }
- //人脸检测,对上次检测到的人脸区域进行搜索
- bool FaceDetect(CameraEnum eCamera,CvRect rect)
- {
- if (!GetImage(eCamera))
- {
- return false;
- }
- CvMemStorage*pFaceStorage = NULL;
- if (eCamera == EnvironCamera)
- {
- pFaceStorage = m_pFaceStorage;
- }
- else
- {
- pFaceStorage = m_pFaceStorage;
- }
- CCustomerInfo UserFaceTemp;
- CCustomerInfo astFaceTemp;
- memset(&astFaceTemp,0,sizeof(CCustomerInfo));
- memset(&UserFaceTemp,0,sizeof(CCustomerInfo));
- CvRect* pFaceRect = NULL; //人脸矩形
- cvResetImageROI(m_pProcessImg);
- cvSetImageROI(m_pProcessImg,rect);
- //内存初始化
- if (pFaceStorage)
- {
- pFaceStorage = cvCreateMemStorage(0);
- cvClearMemStorage(pFaceStorage);
- }
- else
- {
- pFaceStorage = cvCreateMemStorage(0);
- }
- //人脸搜索
- if (m_pFaceCascade == NULL)
- {
- 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)
- {
- cvReleaseMemStorage(&pfaceSeq->storage);
- pfaceSeq = NULL;
- return false;
- }
- for(int i=0;i<(pfaceSeq?pfaceSeq->total:0)&&(i<MAX_FACE_NUM);i++)
- {
- //获取脸部矩形
- pFaceRect = (CvRect*)cvGetSeqElem(pfaceSeq,i);
- //如果是前端检测则需要特征检测,如果是坐席则不需检测
- if (m_stFaceConfig.nServersType == 0)
- {
- //找眼睛
- astFaceTemp.stCustomerCover.bShowEyes = FeatureDetect(m_pEyeCascade,pFaceRect,pFaceStorage);
- //找鼻子
- astFaceTemp.stCustomerCover.bShowNose = FeatureDetect(m_pNoseCascade,pFaceRect,pFaceStorage);
- //找嘴巴
- astFaceTemp.stCustomerCover.bShowMouth = FeatureDetect(m_pMouthCascade,pFaceRect,pFaceStorage);
- }
- else
- {
- //找眼睛
- astFaceTemp.stCustomerCover.bShowEyes = false;
- //找鼻子
- astFaceTemp.stCustomerCover.bShowNose = false;
- //找嘴巴
- astFaceTemp.stCustomerCover.bShowMouth = false;
- }
- if(!(astFaceTemp.stCustomerCover.bShowEyes||astFaceTemp.stCustomerCover.bShowNose||astFaceTemp.stCustomerCover.bShowMouth))
- {
- astFaceTemp.stCustomerCover.bClearFace = false;
- }
- else
- {
- astFaceTemp.stCustomerCover.bClearFace = true;
- }
- //计算当前人脸位置如果当前人脸位置与上次人脸位置小于偏移量则取上次人脸位置,防止人脸图像跳变
- //坐标变换
- pFaceRect->x = pFaceRect->x+rect.x;
- pFaceRect->y = pFaceRect->y+rect.y;
- if ((abs(pFaceRect->x - m_stAllFaceInfo.astFaceInfo[0].stRegion.stFaceRect.x)<m_stFaceConfig.nFaceSizeOffset)
- && (abs(pFaceRect->y-m_stAllFaceInfo.astFaceInfo[0].stRegion.stFaceRect.y)<m_stFaceConfig.nFaceSizeOffset)
- && (abs(pFaceRect->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;
- //截取人脸图像,放大截取区域,截取半身头像
- CalcUpbodyRegion(pFaceRect);
- 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);
- int CurPointDist = CalcTwoFaceDist(&astFaceTemp.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)&&(CurDistance<TempDistance))||
- //如果当前数据不在中心区域,temp数据在中心区域,且当前数据距离更近,则更新temp
- ((CurRegion != FaceRegionCenter)&&(TempRegion == FaceRegionCenter)&&(CurDistance<TempDistance))||
- //如果当前数据不在中心区域,temp数据也不在中心区域,且距离一样,若当前数据更靠近历史数据,则当前数据作为temp
- ((TempRegion!=FaceRegionCenter)&&(CurRegion!=FaceRegionCenter)&&(CurDistance==TempDistance)&&(CurPointDist<TempPointDist)))
- {
- UserFaceTemp = astFaceTemp;
- memset(&astFaceTemp,0,sizeof(CCustomerInfo));
- }
- }
- 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_stAllFaceInfo.astFaceInfo[0].eBrightness = CalcFaceBrightness(m_pProcessImg,&m_stAllFaceInfo.astFaceInfo[0].stRegion.stFaceRect);
- }
- }
- //清空存储区
- if (pfaceSeq!=NULL)
- {
- cvReleaseMemStorage(&pfaceSeq->storage);
- pfaceSeq = NULL;
- }
- cvResetImageROI(m_pProcessImg);
- return true;
- }
- //人脸卡图
- void CaptureOperatorFace(IplImage*img)
- {
- //判断客户号,客户ID是否更换
- if(m_pHostApi->IsCustomerChange())
- {
- if (!m_bCapFaceCompleted && (strcmp(m_SaveImgName,"")!=0))
- {
- SaveOperatorFace(m_SaveImgName);
- }
- else if (m_bCapFaceCompleted)
- {
- m_bCapFaceCompleted = false;
- m_nCapFaceNum = 0;
- }
- m_pHostApi->GetFaceImgName(m_SaveImgName, MAX_PATH);
- }
- if (m_bCapFaceCompleted)
- {
- return;
- }
- if (m_stAllFaceInfo.nTatolFaceNum >0)
- {
- bool bRst = GetImage(m_stAllFaceInfo.astFaceInfo[0].eCamera);
- if (!bRst)
- {
- return;
- }
- //往3个人脸图像中填数据
- if (m_nCapFaceNum<3)
- {
- 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;
- cvResetImageROI(img);
- cvSetImageROI(img,m_stCapFace[m_nCapFaceNum].stCustomerRegion.stUpperBodyRect);
- 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);
- cvCopy(img,m_stCapFace[m_nCapFaceNum].img,NULL);
- if(m_stBrightAdjParam.fHigh != 0.0)
- {
- AdjustImgBrightness(m_stCapFace[m_nCapFaceNum].img->imageData,m_stCapFace[m_nCapFaceNum].stCustomerRegion.stUpperBodyRect.width,
- m_stCapFace[m_nCapFaceNum].stCustomerRegion.stUpperBodyRect.height,m_stBrightAdjParam);
- }
- cvResetImageROI(img);
- m_nCapFaceNum++;
- }
- else //如果有三张人脸,立即保存
- {
- //if (m_stAllFaceInfo.astFaceInfo[0].stCustomerCover.bShowEyes&&m_stAllFaceInfo.astFaceInfo[0].stCustomerCover.bShowMouth&&
- // m_stAllFaceInfo.astFaceInfo[0].stCustomerCover.bShowNose)
- //{
- //int num = 0;
- //while (m_stCapFace[num].stFaceCover.bShowEyes&&m_stCapFace[num].stFaceCover.bShowMouth&&
- // m_stCapFace[num].stFaceCover.bShowNose&&(num<3))
- //{
- // num++;
- //}
- ////如果3个人脸特征不完整,则往3个人脸图像中填替换数据
- //if (num<3)
- //{
- // m_stCapFace[num].stFaceCover.bShowEyes = m_stAllFaceInfo.astFaceInfo[0].stCustomerCover.bShowEyes;
- // m_stCapFace[num].stFaceCover.bShowMouth = m_stAllFaceInfo.astFaceInfo[0].stCustomerCover.bShowMouth;
- // m_stCapFace[num].stFaceCover.bShowNose = m_stAllFaceInfo.astFaceInfo[0].stCustomerCover.bShowNose;
- // m_stCapFace[num].stCustomerRegion.stFaceRect = m_stAllFaceInfo.astFaceInfo[0].stRegion.stFaceRect;
- // m_stCapFace[num].stCustomerRegion.stUpperBodyRect = m_stAllFaceInfo.astFaceInfo[0].stRegion.stUpperBodyRect;
- // cvResetImageROI(img);
- // cvSetImageROI(img,m_stCapFace[num].stCustomerRegion.stUpperBodyRect);
- // if (m_stCapFace[num].img)
- // {
- // cvReleaseImage(&m_stCapFace[num].img);
- // m_stCapFace[num].img = NULL;
- // }
- // m_stCapFace[num].img = cvCreateImage(cvSize(m_stCapFace[num].stCustomerRegion.stUpperBodyRect.width,
- // m_stCapFace[num].stCustomerRegion.stUpperBodyRect.height),IPL_DEPTH_8U,3);
- // cvCopy(img,m_stCapFace[num].img,NULL);
- // if(m_stBrightAdjParam.fHigh != 0.0)
- // {
- // AdjustImgBrightness(m_stCapFace[num].img->imageData,m_stCapFace[num].stCustomerRegion.stUpperBodyRect.width,
- // m_stCapFace[num].stCustomerRegion.stUpperBodyRect.height,m_stBrightAdjParam,NULL);
- // }
- // cvResetImageROI(img);
- //}
- //else//如果3个人脸特征完整,则保存照片
- //{
- //写文件
- if (strcmp(m_SaveImgName,"")==0)
- {
- m_pHostApi->GetFaceImgName(m_SaveImgName, MAX_PATH);
- }
- else
- {
- SaveOperatorFace(m_SaveImgName);
- m_bCapFaceCompleted = true;
- m_nCapFaceNum = 0;
- }
- //}
- //}
- }
- }
- else
- {
- return;
- }
- }
- //保存人脸图像
- bool SaveOperatorFace(char*filename)
- {
- //for(int i=0;i<3;i++)
- //{
- // if(m_stCapFace[i].img != NULL)
- // {
- // //设置文件名
- // char strFileName[MAX_PATH];
- // memset(strFileName,0,MAX_PATH);
- // sprintf_s(strFileName,"%s_%d.jpg",filename,i);
- // cvSaveImage(strFileName,m_stCapFace[i].img);
- // }
- //}
- for(int j = 0; j < 3; j++)
- {
- if(m_stCapFace[j].img != NULL)
- {
- cvReleaseImage(&m_stCapFace[j].img);
- }
- }
- m_nCapFaceNum = 0;
- 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;i<m_stObjTrackRslt.nObjNum;i++)
- {
- cvResetImageROI(m_pProcessImg);
- cvSetImageROI(m_pProcessImg,m_stObjTrackRslt.ObjRect[i]);
- 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);
- //如果发现有人脸到达靠近区域,置有人靠近状态
- 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->GenerateCloseEvent(); //产生有人靠近事件
- }
- 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->GenerateEnterOperateEvent(); //产生有人进入操作距离事件
- }
- 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->GenerateAppearEvent(); //产生有人出现事件
- }
- }
- }
- 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 (m_pFaceCascade == NULL)
- {
- 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);
- //如果发现有人脸到达靠近区域,置有人靠近状态
- 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->GenerateCloseEvent(); //产生有人靠近事件
- }
- 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->GenerateEnterOperateEvent(); //产生有人进入操作距离事件
- }
- 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->GenerateAppearEvent(); //产生有人出现事件
- }
- }
- CvRect*pFaceRect = (CvRect*)cvGetSeqElem(pfaceSeq, nCurafaceSerial);
- //截取人脸图像,放大截取区域,截取半身头像
- CalcUpbodyRegion(pFaceRect);
- m_stAllFaceInfo.astFaceInfo[0].stRegion.stUpperBodyRect = *pFaceRect;
- }
- else {
- m_pHostApi->Debug(FACECAP_DEBUG, "未检测到人脸");
- }
-
- 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))
- {
- //RecordError("运动跟踪获取图像失败");
- 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 RecordError(char*error, ...)
- {
- #ifdef debugerror
- m_pHostApi->Debug(FACECAP_INFO, error);
- #endif
- }
- //计算监控线程下一步
- void VideoMonitorThreadNextStep()
- {
- if(m_stAllFaceInfo.astFaceInfo[0].eDistance == OperateDistance)
- {
- if (m_eMonitorState != SomebodyOperate)
- {
- m_eMonitorState = SomebodyOperate;
- m_stAllFaceInfo.astFaceInfo[0].eScene = ForwardScened;
- m_pHostEvent->GenerateEnterOperateEvent(); //产生有人进入操作距离事件
- 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->GenerateCaptureFaceEvent(); //发送捕获人脸事件
- //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->GenerateLeaveEvent(); //产生客户离开事件
- 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->GenerateBackToCloseEvent(); //产生客户退回到接近距离事件
- 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->GenerateCloseEvent(); //产生有人靠近事件
- }
- }
- // 计算当前人脸是否进入另外一个相机的最佳视野中
- 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_INFO, "获取环境相机图像队列长度错误!");
- 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("获取操作相机图像队列长度错误!");
- 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_INFO, "获取环境相机图像队列长度错误!");
- 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("获取操作相机图像队列长度错误!");
- 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 FSleep(int ms)
- {
- DWORD dwRet = WaitForSingleObject(m_hStopEventWait, ms);
- if (dwRet == WAIT_OBJECT_0)
- {
- throw std::exception();
- }
- }
- void ReleaseMotionTrackRst()
- {
- 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);
- m_pMhBuf = NULL;
- }
- m_nLastBuf=0;
- }
- int VideoMonitor()
- {
- bool bRst = false;
- uint32_t nSearchFailNum = 0; //搜索人脸失败次数
- uint32_t nDetectFailNum = 0; //检测人脸失败的次数
- uint32_t nBreakDownNum = 0;
- uint32_t nMotionTrackNum = 0;
- //select camera
- if (m_pOperatorVideoQueue != NULL)
- {
- m_eCamera = (CameraEnum)m_stFaceConfig.nPrimCamera;
- }
- else
- {
- if((m_nCameraState == 0)||(m_nCameraState ==2))
- {
- m_eCamera = EnvironCamera;
- }
- else if (m_nCameraState == 1)
- {
- m_eCamera = OperatorCamera;
- }
- else if (m_nCameraState == 3)
- {
- m_eCamera = ErrorCamera;
- }
- }
- while (!m_bStopVieoMonitor)
- {
- try
- {
- //如果摄像头没启动或故障,停止扫描,休眠5s
- if (m_nCameraState == 3)
- {
- FSleep(2000);
- m_pHostApi->Debug(FACECAP_INFO, "camera stop or all camera error!");
- continue;
- }
- //灯光变化时,清空历史记录,防止误判
- if (m_bLightChange)
- {
- ReleaseMotionTrackRst();
- nMotionTrackNum=0;
- m_bLightChange = false;
- }
- //if no people,start motion tracker
- if(NoBody == m_eMonitorState)
- {
- m_pHostApi->Debug(FACECAP_DEBUG, "NoBody");
- ////if no people,start motion tracker
- //bRst = MotionTrack(m_eCamera,m_stFaceConfig.nThresholdNum);
- //if (!bRst)
- //{
- // //RecordError("Search motion obj Fail");
- // nMotionTrackNum++;
- // FSleep(m_stFaceConfig.nSleepShort);
- // if (nMotionTrackNum >= 4)
- // {
- // (m_eCamera==EnvironCamera)?(m_eCamera=OperatorCamera):(m_eCamera=EnvironCamera);
- // ReleaseMotionTrackRst();
- // nMotionTrackNum=0;
- // }
- // //SetUpperbodyToCenter(m_eCamera);
- // continue;
- //}
- //else
- //{
- // if (!m_bLightChange&&(m_nCameraState != 3))
- // {
- // m_pHostEvent->GenerateAppearEvent(); //产生有人出现事件
- // m_pHostApi->Debug("运动跟踪,有人出现!");
- // SetUpperbodyToCenter(m_eCamera);
- // nMotionTrackNum = 0;
- // }
- //}
- ////search face from motion tracker result
- //int size = (int)((m_nImgHeight>m_nImgWidth)?m_nImgHeight:m_nImgWidth)/m_stFaceConfig.fSearchFaceSize;
- //bRst = FaceSearch(m_stObjTrackRslt,size);
- //if(!bRst)
- //{
- // //RecordError("Search face from motion obj Fail");
- // (m_eCamera==EnvironCamera)?(m_eCamera=OperatorCamera):(m_eCamera=EnvironCamera);
- // bRst = GetImage(m_eCamera);
- // if (bRst)
- // {
- // int size = (int)m_nImgHeight/m_stFaceConfig.fSearchFaceSize;
- // bRst = FaceSearch(size);
- // if (!bRst)
- // {
- // //RecordError("Far distance, search Face Fail");
- // SetUpperbodyToCenter();
- // FSleep(m_stFaceConfig.nSleepMiddle);
- // continue;
- // }
- // else
- // {
- // WriteAllFaceInfo(m_stAllFaceInfo);
- // FSleep(m_stFaceConfig.nSleepShort);
- // continue;
- // }
- // }
- //}
- //else
- //{
- // //RecordError("Search face from motion obj Success");
- // WriteAllFaceInfo(m_stAllFaceInfo);
- // continue;
- //}
- bRst = GetImage(m_eCamera);
- if (bRst)
- {
- int size = (int)m_nImgHeight/m_stFaceConfig.fSearchFaceSize;
- bRst = FaceSearch(size);
- if (!bRst)
- {
- SetUpperbodyToCenter();
- FSleep(m_stFaceConfig.nSleepLong);
- continue;
- }
- else
- {
- WriteAllFaceInfo(m_stAllFaceInfo);
- FSleep(m_stFaceConfig.nSleepMiddle);
- continue;
- }
- }
- else
- {
- FSleep(m_stFaceConfig.nSleepMiddle);
- }
- }
- else if (SomebodyFar == m_eMonitorState) //if somebody space 2.5m
- {
- m_pHostApi->Debug(FACECAP_DEBUG, "SomebodyFar");
- //RecordError("Enter far distance search Face ");
- bRst = GetImage(m_eCamera);
- if (bRst)
- {
- int size = (int)m_nImgHeight/m_stFaceConfig.fSearchFaceSize;
- bRst = FaceSearch(size);
- if (!bRst)
- {
- //RecordError("Far distance, search Face Fail");
- SetUpperbodyToCenter();
- FSleep(m_stFaceConfig.nSleepMiddle);
- continue;
- }
- else
- {
- if (m_eMonitorState <= SomebodyFar)
- {
- //RecordError("Far distance, search Face Success");
- WriteAllFaceInfo(m_stAllFaceInfo);
- FSleep(m_stFaceConfig.nSleepShort);
- }
- continue;
- }
- }
- else
- {
- FSleep(m_stFaceConfig.nSleepMiddle);
- }
- }
- else if (SomebodyClose == m_eMonitorState) //close distance,1.5m
- {
- m_pHostApi->Debug(FACECAP_DEBUG, "SomebodyClose");
- //RecordError("close distance,search Face by operatorCamera");
- bRst = FaceDetect(m_eCamera);
- if(!bRst)
- {
- //RecordError("Close distance,EnvironCamera Search face Fail");
- //dual camera mod
- if(m_pOperatorVideoQueue != NULL)
- {
- //RecordError("Close distance,search Face by operatorCamera");
- (m_eCamera==EnvironCamera)?(m_eCamera=OperatorCamera):(m_eCamera=EnvironCamera);
- bRst = FaceDetect(m_eCamera);
- if (!bRst)
- {
- //RecordError("Close distance,operatorCamera Search face Fail");
- nSearchFailNum++;
- if(nSearchFailNum >2) //if search face fail,return motiontracker
- {
- SetUpperbodyToCenter();
- m_eMonitorState = NoBody;
- m_pHostEvent->GenerateLeaveEvent();
- m_pHostApi->Debug(FACECAP_DEBUG, "客户离开!");
- nSearchFailNum = 0;
- FSleep(m_stFaceConfig.nSleepLong);
- }
- else
- {
- FSleep(m_stFaceConfig.nSleepMiddle);
- }
- continue;
- }
- else
- {
- //RecordError("Close distance,operatorCamera Search face Success");
- nSearchFailNum = 0;
- VideoMonitorThreadNextStep();
- WriteAllFaceInfo(m_stAllFaceInfo);
- FSleep(m_stFaceConfig.nSleepShort);
- continue;
- }
- }
- else //single camera mod
- {
- nSearchFailNum++;
- if(nSearchFailNum >2) //if search face fail,return motiontracker
- {
- SetUpperbodyToCenter();
- m_eMonitorState = NoBody;
- m_pHostEvent->GenerateLeaveEvent();
- m_pHostApi->Debug(FACECAP_DEBUG, "客户离开!");
- nSearchFailNum = 0;
- FSleep(m_stFaceConfig.nSleepLong);
- }
- else
- {
- FSleep(m_stFaceConfig.nSleepMiddle);
- }
- continue;
- }
- }
- else
- {
- //if curcamera search face success,judge which camera result is the best
- //RecordError("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);
- FSleep(m_stFaceConfig.nSleepShort);
- continue;
- }
- }
- 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)
- {
- //RecordError("Operator distance,CurCamera search last face Region");
- bRst = FaceDetect(m_eCamera,m_stAllFaceInfo.astFaceInfo[0].stRegion.stUpperBodyRect);
- }
- else
- {
- bRst = false;
- }
- if(!bRst)
- {
- //RecordError("Operator distance,search Face by CurCamera ");
- bRst = FaceDetect(m_eCamera);
- }
- }
- else //如果单相机模式
- {
- //m_eCamera = (CameraEnum)m_stFaceConfig.nPrimCamera;
- //先搜索上次搜索到人脸的区域
- if(m_stAllFaceInfo.nTatolFaceNum > 0)
- {
- //RecordError("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);
- //在另一个相机中重新搜索
- //RecordError("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)
- {
- CaptureOperatorFace(m_pProcessImg);
- }
- WriteAllFaceInfo(m_stAllFaceInfo);
- FSleep(m_stFaceConfig.nSleepLong);
- continue;
- }
- else //如果在当前相机中未找到用户
- {
- //如果双相机模式
- if(m_pOperatorVideoQueue!=NULL)
- {
- (m_eCamera == OperatorCamera)?(m_eCamera = EnvironCamera):(m_eCamera = OperatorCamera);
- //RecordError("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)
- {
- CaptureOperatorFace(m_pProcessImg);
- }
- WriteAllFaceInfo(m_stAllFaceInfo);
- //RecordError("Record Face info Success");
- FSleep(m_stFaceConfig.nSleepLong);
- continue;
- }
- else
- {
- nDetectFailNum++;
- if(nDetectFailNum >2) //如果连续2次未找到人脸,回到有人靠近状态
- {
- m_eMonitorState = SomebodyClose;
- m_stAllFaceInfo.astFaceInfo[0].eScene = UnLockScene;
- m_pHostEvent->GenerateLoseFaceEvent(); //发送失去人脸事件
- m_pHostApi->Debug(FACECAP_DEBUG, "人脸失去锁定!");
- nDetectFailNum = 0;
- }
- FSleep(m_stFaceConfig.nSleepShort);
- continue;
- }
- }
- else //如果单相机模式
- {
- nDetectFailNum++;
- if(nDetectFailNum >3) //如果连续3次未找到人脸,回到有人靠近状态
- {
- m_eMonitorState = SomebodyClose;
- m_stAllFaceInfo.astFaceInfo[0].eScene = UnLockScene;
- m_pHostEvent->GenerateLoseFaceEvent(); //发送失去人脸事件
- m_pHostApi->Debug(FACECAP_DEBUG, "人脸失去锁定!");
- nDetectFailNum = 0;
- }
- FSleep(m_stFaceConfig.nSleepShort);
- continue;
- }
- }
- }
- }
- catch (...)
- {
- //清空存储区
- if (pfaceSeq!=NULL)
- {
- cvReleaseMemStorage(&pfaceSeq->storage);
- pfaceSeq = NULL;
- }
- if (NULL != m_pProcessImg){
- cvResetImageROI(m_pProcessImg);
- }
-
- nBreakDownNum++;
- if (nBreakDownNum == 5)
- {
- m_pHostEvent->GenerateFaceCaptureFC(); //发送人脸崩溃事件
- m_pHostApi->Debug(FACECAP_INFO, "opencv library breakdown!");
- }
- Sleep(3*m_stFaceConfig.nSleepShort);
- m_pHostApi->Debug(FACECAP_DEBUG, "stop Video Monitor");
- }
- }
- return 0;
- }
- static unsigned int __stdcall VideoMonitorThread(void* pParam)
- {
- Clibfacecapture_impl* VideoFaceMonitor = (Clibfacecapture_impl*)pParam;
- return VideoFaceMonitor->VideoMonitor();
- }
- public:
- //开始视频监控,pHost:事件,nMonitorFreq:监控频率,单位ms,MonitorType:监控类型,有三种模式可供选择
- bool StartVideoMonitor(CHostApi *pHostAPI, CVideoMonitorEvent*pHost, MonitorEnum eMonitorType)
- {
- if (m_hVieoMonitorThread == NULL){
- m_pHostApi->Debug(FACECAP_DEBUG, "create video monitor thread.");
- m_hVieoMonitorThread = (HANDLE)_beginthreadex(NULL, 0, VideoMonitorThread, this, 0, (unsigned int*)&m_nVieoMonitorThreadId);
- }
- return true;
- }
- //停止视频监控
- bool StopVideoMonitor()
- {
- m_bStopVieoMonitor = true;
- SetEvent(m_hStopEventWait);
- WaitForSingleObject(m_hVieoMonitorThread, INFINITE);
- CloseHandle(m_hVieoMonitorThread);
- m_hVieoMonitorThread = NULL;
- return true;
- }
- //快照
- bool SnapShot(CImageFrame&img)
- {
- //if((m_stAllFaceInfo.astFaceInfo[0].eCamera == EnvironCamera)||(m_stAllFaceInfo.astFaceInfo[0].eCamera == 0) )
- //{
- // if (m_pEnvironMaxVideoQueue)
- // {
- // if (m_pEnvironMaxVideoQueue->GetVideoLens()<=0)
- // {
- // return FALSE;
- // }
- // }
- // else
- // {
- // if (m_pEnvironMinVideoQueue->GetVideoLens()<=0)
- // {
- // return FALSE;
- // }
- // }
- // int size = 0;
- // if (m_pEnvironMaxVideoQueue)
- // {
- // size = m_pEnvironMaxVideoQueue->GetFrameSize(m_nImgWidth,m_nImgHeight);
- // }
- // else
- // {
- // size = m_pEnvironMinVideoQueue->GetFrameSize(m_nImgWidth,m_nImgHeight);
- // }
- //
- // if((img.width > m_nImgWidth)||(img.height > m_nImgHeight))
- // {
- // return FALSE;
- // }
- // IplImage*cvimgtmp = cvCreateImage(cvSize(img.width,img.height),8,3);
- // char m_FileName[MAX_PATH];
- // SYSTEMTIME nowTime; // 系统时间结构体
- // GetLocalTime(&nowTime);
- // sprintf_s(m_FileName,"%4d%02d%02d%02d%02d%02d",nowTime.wYear,nowTime.wMonth,nowTime.wDay,nowTime.wHour,nowTime.wMinute,nowTime.wSecond);
- // CvFont fontEvent = cvFont(1.6,2);
- // IplImage*cvimg = cvCreateImage(cvSize(m_nImgWidth,m_nImgHeight),8,3);
- // videoq_frame*videoframe = new videoq_frame;
- // videoframe->data = (unsigned char*)cvimg->imageData;
- // BOOL bGetvideo = FALSE;
- // if (m_pEnvironMaxVideoQueue)
- // {
- // bGetvideo = m_pEnvironMaxVideoQueue->GetVideo(videoframe,VIDEOQUEUE_FLAG_VERTICAL_FLIP);
- // }
- // else
- // {
- // bGetvideo = m_pEnvironMinVideoQueue->GetVideo(videoframe,VIDEOQUEUE_FLAG_VERTICAL_FLIP);
- // }
- // if (!bGetvideo)
- // {
- // delete videoframe;
- // return FALSE;
- // }
- // int nstartx = 0;
- // int nstarty = 0;
- // if((img.width < m_nImgWidth)||(img.height < m_nImgHeight))
- // {
- // nstartx = (int)((cvimg->width-img.width)/2);
- // nstarty = (int)((cvimg->height-img.height)/2);
- // cvSetImageROI(cvimg,cvRect(nstartx,nstarty,img.width,img.height));
- // }
- // cvCopy(cvimg,cvimgtmp);
- // cvPutText(cvimgtmp, m_FileName,cvPoint(img.width-230,img.height-10), &fontEvent, CV_RGB( 255, 0, 0));
- // memcpy(img.data,cvimgtmp->imageData,img.framesize);
- // cvReleaseImage(&cvimg);
- // cvReleaseImage(&cvimgtmp);
- // delete videoframe;
- // AdjustImgBrightness((char*)img.data,img.width,img.height,m_stBrightAdjParam,NULL);
- //}
- //else if (m_stAllFaceInfo.astFaceInfo[0].eCamera == OperatorCamera)
- //{
- // if (m_pOperatorVideoQueue->GetVideoLens()<=0)
- // {
- // return FALSE;
- // }
- // int size = m_pOperatorVideoQueue->GetFrameSize(m_nImgWidth,m_nImgHeight);
- // if((img.width > m_nImgWidth)||(img.height > m_nImgHeight))
- // {
- // return FALSE;
- // }
- // IplImage*cvimgtmp = cvCreateImage(cvSize(img.width,img.height),8,3);
- // char m_FileName[MAX_PATH];
- // SYSTEMTIME nowTime; // 系统时间结构体
- // GetLocalTime(&nowTime);
- // sprintf_s(m_FileName,"%4d%02d%02d%02d%02d%02d",nowTime.wYear,nowTime.wMonth,nowTime.wDay,nowTime.wHour,nowTime.wMinute,nowTime.wSecond);
- // CvFont fontEvent = cvFont(2,2);
- // IplImage*cvimg = cvCreateImage(cvSize(m_nImgWidth,m_nImgHeight),8,3);
- // videoq_frame*videoframe = new videoq_frame;
- // videoframe->data = (unsigned char*)cvimg->imageData;
- // BOOL bGetvideo = m_pOperatorVideoQueue->GetVideo(videoframe,VIDEOQUEUE_FLAG_VERTICAL_FLIP);
- // if (!bGetvideo)
- // {
- // delete videoframe;
- // return FALSE;
- // }
- // int nstartx = 0;
- // int nstarty = 0;
- // if((img.width < m_nImgWidth)||(img.height < m_nImgHeight))
- // {
- // nstartx = (int)((cvimg->width-img.width)/2);
- // nstarty = (int)((cvimg->height-img.height)/2);
- // cvSetImageROI(cvimg,cvRect(nstartx,nstarty,img.width,img.height));
- // }
- // cvCopy(cvimg,cvimgtmp);
- // cvPutText(cvimgtmp, m_FileName,cvPoint(img.width-230,img.height-10), &fontEvent, CV_RGB( 255, 0, 0));
- // memcpy(img.data,cvimg->imageData,img.framesize);
- // cvReleaseImage(&cvimg);
- // cvReleaseImage(&cvimgtmp);
- // delete videoframe;
- // AdjustImgBrightness((char*)img.data,img.width,img.height,m_stBrightAdjParam,NULL);
- //}
- return true;
- }
- //有多少其他用户
- bool GetCustomerNum(uint32_t& num)
- {
- EnterCriticalSection(&CS);
- num = m_stFaceRstStorage.nTatolFaceNum;
- LeaveCriticalSection(&CS);
- return true;
- }
- //获取主用户的常规属性
- bool GetMainCustomerStatus(CUUID&FaceID, CCustomerStatus &Property)
- {
- EnterCriticalSection(&CS);
- //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;
- LeaveCriticalSection(&CS);
- return true;
- }
- //获取用户的常规属性
- bool GetCustomerStatus(CUUID FaceID, CCustomerStatus &Property)
- {
- EnterCriticalSection(&CS);
- bool bSearch = false;
- for (int i =0; i<m_stFaceRstStorage.nTatolFaceNum&&!bSearch; i++)
- {
- if(m_stFaceRstStorage.astFaceInfo[i].FaceID == FaceID)
- {
- Property.eBrightness = m_stFaceRstStorage.astFaceInfo[i].eBrightness;
- Property.stCustomerCover = m_stFaceRstStorage.astFaceInfo[i].stCustomerCover;
- Property.stCustomerPos.eCamera = m_stFaceRstStorage.astFaceInfo[i].eCamera;
- Property.stCustomerPos.eDistance = m_stFaceRstStorage.astFaceInfo[i].eDistance;
- Property.stCustomerPos.ePose = m_stFaceRstStorage.astFaceInfo[i].ePose;
- Property.stCustomerPos.eScene = m_stFaceRstStorage.astFaceInfo[i].eScene;
- Property.stCustomerPos.stRange.sX = m_stFaceRstStorage.astFaceInfo[i].stRegion.stUpperBodyRect.x
- +(short)m_stFaceRstStorage.astFaceInfo[i].stRegion.stUpperBodyRect.width/2-(short)m_nImgWidth/2;
- Property.stCustomerPos.stRange.sY = m_stFaceRstStorage.astFaceInfo[i].stRegion.stUpperBodyRect.y
- +(short)m_stFaceRstStorage.astFaceInfo[i].stRegion.stUpperBodyRect.height/2-(short)m_nImgHeight/2;
- Property.stCustomerPos.stRange.sH = (short)m_stFaceRstStorage.astFaceInfo[i].stRegion.stUpperBodyRect.height/2;
- bSearch = true;
- }
- }
- LeaveCriticalSection(&CS);
- return true;
- }
- //获取所有用户FACEID
- bool GetTrackFace(CUUID *arrFaceIDs, int *size)
- {
- EnterCriticalSection(&CS);
- for (int i = 0;i<m_stFaceRstStorage.nTatolFaceNum && i < *size;i++)
- {
- arrFaceIDs[i] = m_stFaceRstStorage.astFaceInfo[i].FaceID;
- }
- LeaveCriticalSection(&CS);
- return true;
- }
- //获取用户的交互属性
- bool GetCustomerAppearance(CUUID FaceID,CCustomerAppearance &Property)
- {
- EnterCriticalSection(&CS);
- bool bSearch = false;
- for (int i =0;i<m_stFaceRstStorage.nTatolFaceNum&&!bSearch;i++)
- {
- if(m_stFaceRstStorage.astFaceInfo[i].FaceID == FaceID)
- {
- Property.eHeight =m_stFaceRstStorage.astFaceInfo[i].eHeight;
- Property.eSex = m_stFaceRstStorage.astFaceInfo[i].eSex;
- Property.eYoungOld = m_stFaceRstStorage.astFaceInfo[i].eYoungOld;
- bSearch = true;
- }
- }
- LeaveCriticalSection(&CS);
- return true;
- }
- };
- // 这是已导出类的构造函数。
- // 有关类定义的信息,请参阅 libfacecapture.h
- Clibfacecapture::Clibfacecapture(bool *pResult, CHostApi *pHostAPI, CVideoMonitorEvent*pHost, const char* EnvironMinVideoName, const char* EnvironMaxVideoName, const char* OperateVideoName, MonitorEnum eMonitorType)
- {
- m_pImpl = new Clibfacecapture_impl(pResult, pHostAPI, pHost, EnvironMinVideoName, EnvironMaxVideoName, OperateVideoName, eMonitorType);
- }
- Clibfacecapture::~Clibfacecapture(void)
- {
- delete m_pImpl;
- }
- //快照
- bool Clibfacecapture::SnapShot(CImageFrame&img)
- {
- return m_pImpl->SnapShot(img);
- }
- //有多少其他用户
- bool Clibfacecapture::GetCustomerNum(uint32_t& num)
- {
- return m_pImpl->GetCustomerNum(num);
- }
- //获取主用户的常规属性
- bool Clibfacecapture::GetMainCustomerStatus(CUUID&FaceID,CCustomerStatus &Property)
- {
- return m_pImpl->GetMainCustomerStatus(FaceID,Property);
- }
- //获取其他用户的常规属性
- bool Clibfacecapture::GetCustomerStatus (CUUID FaceID,CCustomerStatus &Property)
- {
- return m_pImpl->GetCustomerStatus(FaceID,Property);
- }
- //获取主用户的交互属性
- bool Clibfacecapture::GetCustomerAppearance(CUUID FaceID,CCustomerAppearance &Property)
- {
- return m_pImpl->GetCustomerAppearance(FaceID,Property);
- }
- //获取所有用户FACEID
- bool Clibfacecapture::GetTrackFace(CUUID *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];
- SYSTEMTIME nowTime; // 系统时间结构体
- GetLocalTime(&nowTime);
- sprintf_s(m_FileName,"%4d%02d%02d%02d%02d%02d",nowTime.wYear,nowTime.wMonth,nowTime.wDay,nowTime.wHour,nowTime.wMinute,nowTime.wSecond);
- 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;
- }
|