void WebCamData::grab() { if (!d->mCaptureData) { return; } d->data = cvQueryFrame(d->mCaptureData); if (!d->data) { return; } /* int size = d->data->width * d->data->height; unsigned char* end = (unsigned char*) d->data->imageData + (3*size); unsigned char* source = (unsigned char*) d->data->imageData; unsigned char* dest = new unsigned char[4*size]; do { memcpy (dest, source, 3); dest += 4; source += 3; } while ( source < end); */ //// QImage img(source, d->data->width, d->data->height, /// QImage::Format_RGB32); detectFace(OPENCV_ROOT "/share/opencv/haarcascades/haarcascade_frontalface_default.xml"); }
void faceDetector::detectAllFeatures() { detectFace(); detectLeftEye(); detectRightEye(); detectNose(); detectMouth(); }
int perImgProcessing(const Mat img, const string faceDetectModel, const string detectionModelPath, const string trackingModelPath, const float ec_mc_y, const float ec_y, vecM &result) { // face detection #if OPENCV FACE_HANDLE face_detection_handle; int ret_fd_init = getDetectionHandle(&face_detection_handle, faceDetectModel); if(0 != ret_fd_init || NULL == &face_detection_handle) { cout << "Error init for face alignment!" << endl; return -1; } vecR rect; string error; int ret_fd = detectFace(face_detection_handle, img, rect, error); if(0 != ret_fd) { cout << error <<endl; return -1; } #else #endif // face alignment FACE_HANDLE face_alignment_handle; int ret_fa = getAlignmentHandle(&face_alignment_handle, detectionModelPath, trackingModelPath); if(0 != ret_fa || NULL == face_alignment_handle) { cout << "Error init for face alignment!" << endl; return -1; } for(int i = 0; i < rect.size(); ++i) { Mat temp; faceAlignment(face_alignment_handle, img, rect[i], ec_mc_y, ec_y, temp, error); /*if(0 != ret) { cout << error << endl; continue; }*/ result.push_back(temp); } releaseDetectionHandle(&face_detection_handle); releaseAlignmentHandle(&face_alignment_handle); return 0; }
int recognize (IplImage *imagen) { CvRect * pFaceRect = 0; IplImage *clone; int how_many,temp,count; //cvNamedWindow("reco",1); IniciaProbabilidades(); // fprintf( stdout, "(recognize.cpp) recognize function..\n"); count=0; int persona=0; clone = cvCloneImage(imagen); pFaceRect = detectFace(clone,&how_many); //cvShowImage("reco",imageR); if (how_many) { IplImage *tmp = cvCreateImage( cvSize(pFaceRect->width,pFaceRect->height),8,3); IplImage *face = cvCreateImage( cvSize(pFaceRect->width,pFaceRect->height),8,1); cvSetImageROI(clone, *pFaceRect ); cvCopy(clone,tmp,0); cvResetImageROI(clone); cvCvtColor(tmp,face,CV_RGB2GRAY); int temp=ComparaBD(face,count++) ; // printf("(Reconoci a %d)\n",temp); if (temp!=0) { persona=temp; } cvReleaseImage(&tmp); cvReleaseImage(&face); } else fprintf(stdout,"No vi a naiden \n"); cvReleaseImage(&clone); //cvSaveImage("saved.jpg",clone); //cvDestroyWindow("reco"); // fprintf( stdout, "(recognize.cpp) End recognize\n"); return persona; }
bool processReceivedMessage(char buffer [], int size, int sockfd) { printf("[ProcessReceivedMessage] Received message: %s\n", buffer); fflush(stdout); /* Parse the command */ if (strncmp(buffer, "findFace: ", strlen("findFace: ")) == 0) { int faceId; sscanf(buffer + strlen("findFace: "), "%d", &faceId); printf("Processing face #%d\n", faceId); int success = 1; int detected_exit_code = detectFace(faceId); if (detected_exit_code == 0) { success = realignFace(faceId); } char response[1024]; if (success == 0) { sprintf(response, "face %d: success\r\n", faceId); } else { sprintf(response, "face %d: failure\r\n", faceId); } int n = write(sockfd, response, strlen(response)); if (n < 0) error("[Worker] ERROR writing to socket"); printf("[Worker] Finished processing face %d\n", faceId); } else if (strncmp(buffer, "realign: ", strlen("realign: ")) == 0) { int faceId; sscanf(buffer + strlen("realign: "), "%d", &faceId); int exit_code = realignFace(faceId); char response[1024]; if (exit_code == 0) { sprintf(response, "face %d realigned\r\n", faceId); } else { sprintf(response, "problem realigning face %d\r\n", faceId); } int n = write(sockfd, response, strlen(response)); if (n < 0) error("[Worker] ERROR writing to socket"); printf("[Worker] Finished processing face %d\n", faceId); } else if (strncmp(buffer, "shutdown ", strlen("shutdown")) == 0) { printf("Received SHUTDOWN command.\n"); return true; } else { char *response = "unknown command :(\r\n"; int n = write(sockfd, response, strlen(response)); if (n < 0) error("[Worker] ERROR writing to socket"); } fflush(stdout); return false; }
int main() { /*********************************** 主程序用到的参数 ***********************************/ IplImage * srcImg = NULL; // 存放从摄像头读取的每一帧彩色源图像 IplImage * img = NULL; // 存放从摄像头读取的每一帧灰度源图像 CvCapture * capture; // 指向CvCapture结构的指针 CvMemStorage* storage = cvCreateMemStorage(0); // 存放矩形框序列的内存空间 CvSeq* objects = NULL; // 存放检测到人脸的平均矩形框 double scale_factor = 1.2; // 搜索窗口的比例系数 int min_neighbors = 3; // 构成检测目标的相邻矩形的最小个数 int flags = 0; // 操作方式 CvSize min_size = cvSize(40, 40); // 检测窗口的最小尺寸 int i, globalK; int hist[256]; // 存放直方图的数组 int pixelSum; int threshold; // 存储二值化最优阈值 clock_t start, stop; // 计时参数 IplImage* faceImg = NULL; // 存储检测出的人脸图像 int temp = 0; // 临时用到的变量 int temp1 = 0; // 临时用到的变量 int count = 0; // 计数用的变量 int flag = 0; // 标记变量 int * tempPtr = NULL; // 临时指针 CvRect* largestFaceRect; // 存储检测到的最大的人脸矩形框 int * horiProject = NULL; // 水平方向的投影结果(数组指针) int * vertProject = NULL; // 垂直方向的投影结果(数组指针) int * subhoriProject = NULL; // 水平方向的投影结果(数组指针) int * subvertProject = NULL; // 垂直方向的投影结果(数组指针) int WIDTH; // 图像的宽度 int HEIGHT; // 图像的高度 int rEyeCol = 0; // 右眼所在的列数 int lEyeCol = 0; // 左眼所在的列数 int lEyeRow = 0; // 左眼所在的行数 int rEyeRow = 0; // 右眼所在的行数 int eyeBrowThreshold; // 区分眉毛与眼睛之间的阈值 uchar* rowPtr = NULL; // 指向图片每行的指针 uchar* rowPtrTemp = NULL; // 指向图片每行的指针, 中间变量 IplImage* eyeImg = NULL; // 存储眼睛的图像 CvRect eyeRect; // 存储裁剪后的人眼的矩形区域 CvRect eyeRectTemp; // 临时矩形区域 IplImage* lEyeImg = NULL; // 存储左眼的图像 IplImage* rEyeImg = NULL; // 存储右眼的图像 IplImage* lEyeImgNoEyebrow = NULL; // 存储去除眉毛之后的左眼图像 IplImage* rEyeImgNoEyebrow = NULL; // 存储去除眉毛之后的右眼图像 IplImage* lEyeballImg = NULL; // 存储最终分割的左眼框的图像 IplImage* rEyeballImg = NULL; // 存储最终分割的右眼框的图像 IplImage* lMinEyeballImg = NULL; // 存储最终分割的最小的左眼框的图像 IplImage* rMinEyeballImg = NULL; // 存储最终分割的最小的右眼框的图像 int lMinEyeballBlackPixel; // 存储最终分割的最小的左眼框的白色像素个数 int rMinEyeballBlackPixel; // 存储最终分割的最小的右眼框的白色像素个数 double lMinEyeballBlackPixelRate; // 存储最终分割的最小的左眼框的黑色像素占的比例 double rMinEyeballBlackPixelRate; // 存储最终分割的最小的右眼框的黑色像素占的比例 double lMinEyeballRectShape; // 存储最小左眼眶的矩形长宽比值 double rMinEyeballRectShape; // 存储最小右眼眶的矩形长宽比值 double lMinEyeballBeta; // 存储最小左眼眶的中间1/2区域的黑像素比值 double rMinEyeballBeta; // 存储最小右边眼眶的中间1/2区域的黑像素比值 int lEyeState; // 左眼睁(0)、闭(1)状态 int rEyeState; // 右眼睁(0)、闭(1)状态 int eyeState; // 眼睛综合睁(0)、闭(1)状态 int eyeCloseNum = 0; // 统计一次检测过程中闭眼的总数 int eyeCloseDuration = 0; // 统计一次检测过程中连续检测到闭眼状态的次数 int maxEyeCloseDuration = 0; // 一次检测过程中连续检测到闭眼状态的次数的最大值 int failFaceNum = 0; // 统计一次检测过程中未检测到人脸的总数 int failFaceDuration = 0; // 统计一次检测过程中连续未检测到人脸的次数 int maxFailFaceDuration = 0; // 一次检测过程中连续未检测到人脸的次数的最大值 int fatigueState = 1; // 驾驶员的驾驶状态:疲劳驾驶(1),正常驾驶(0) /********************* 创建显示窗口 **************************/ cvNamedWindow("img", CV_WINDOW_AUTOSIZE); // 显示灰度源图像 cvNamedWindow("分割后的人脸", 1); // 显示分割出大致眼眶区域的人脸 cvNamedWindow("大致的左眼区域", 1); // 显示大致的左眼区域 cvNamedWindow("大致的右眼区域", 1); // 显示大致的右眼区域 cvNamedWindow("l_binary"); // 显示大致右眼区域的二值化图像 cvNamedWindow("r_binary"); // 显示大致左眼区域的二值化图像 cvNamedWindow("lEyeImgNoEyebrow", 1); // 显示去除眉毛区域的左眼图像 cvNamedWindow("rEyeImgNoEyebrow", 1); // 显示去除眉毛区域的右眼图像 cvNamedWindow("lEyeCenter", 1); // 显示标出虹膜中心的左眼图像 cvNamedWindow("rEyeCenter", 1); // 显示标出虹膜中心的右眼图像 cvNamedWindow("lEyeballImg", 1); // 根据lEyeImgNoEyebrow大小的1/2区域重新划分的左眼图像 cvNamedWindow("rEyeballImg", 1); // 根据rEyeImgNoEyebrow大小的1/2区域重新划分的右眼图像 cvNamedWindow("lkai", 1); // 左眼进行开运算之后的图像 cvNamedWindow("rkai", 1); // 右眼进行开运算之后的图像 cvNamedWindow("lMinEyeballImg", 1); // 缩小至边界区域的左眼虹膜图像 cvNamedWindow("rMinEyeballImg", 1); // 缩小至边界区域的右眼眼虹膜图像 capture = cvCreateCameraCapture(0); if( capture == NULL ) return -1; for( globalK = 1; globalK <= DETECTTIME; globalK ++ ){ start = clock(); srcImg = cvQueryFrame(capture); img = cvCreateImage(cvGetSize(srcImg), IPL_DEPTH_8U, 1); cvCvtColor(srcImg, img, CV_BGR2GRAY); if( !img ) continue; cvShowImage("img", img); cvWaitKey(20); /************************************* 检测人脸 ****************************************/ cvClearMemStorage(storage); // 将存储块的 top 置到存储块的头部,既清空存储块中的存储内容 detectFace( img, // 灰度图像 objects, // 输出参数:检测到人脸的矩形框 storage, // 存储矩形框的内存区域 scale_factor, // 搜索窗口的比例系数 min_neighbors, // 构成检测目标的相邻矩形的最小个数 flags, // 操作方式 cvSize(20, 20) // 检测窗口的最小尺寸 ); // 提取人脸区域 if ( !objectsTemp->total ){ printf("Failed to detect face!\n"); // 调试代码 failFaceNum ++; // 统计未检测到人脸的次数 failFaceDuration ++; // 统计连续未检测到人脸的次数 // 检测过程中判断全是闭眼和检测不到人脸的情况,没有睁开眼的情况,导致maxEyeCloseDuration = 0; (eyeCloseDuration > maxEyeCloseDuration) ? maxEyeCloseDuration = eyeCloseDuration : maxEyeCloseDuration; eyeCloseDuration = 0; if( globalK == DETECTTIME ){ // 当一次检测过程中,所有的过程都检测不到人脸,则要在此更新 maxFailFaceDuration (failFaceDuration > maxFailFaceDuration) ? maxFailFaceDuration = failFaceDuration : maxFailFaceDuration; printf("\nFATIGUETHRESHOLD: %d\n", FATIGUETHRESHOLD); printf("eyeCloseNum: %d\tmaxEyeCloseDuration: %d\n", eyeCloseNum, maxEyeCloseDuration); printf("failFaceNum: %d\tmaxFailFaceDuration: %d\n", failFaceNum, maxFailFaceDuration); // 进行疲劳状态的判别 fatigueState = recoFatigueState(FATIGUETHRESHOLD, eyeCloseNum, maxEyeCloseDuration, failFaceNum, maxFailFaceDuration); if( fatigueState == 1 ) printf("驾驶员处于疲劳驾驶状态\n\n"); else if( fatigueState == 0 ) printf("驾驶员处于正常驾驶状态\n\n"); // 进入下一次检测过程前,将变量清零 globalK = 0; lEyeState = 1; rEyeState = 1; eyeState = 1; eyeCloseNum = 0; eyeCloseDuration = 0; maxEyeCloseDuration = 0; failFaceNum = 0; failFaceDuration = 0; maxFailFaceDuration = 0; fatigueState = 1; cvWaitKey(0); } continue; } else{ // 统计连续未检测到人脸的次数中的最大数值 (failFaceDuration > maxFailFaceDuration) ? maxFailFaceDuration = failFaceDuration : maxFailFaceDuration; failFaceDuration = 0; // 找到检测到的最大的人脸矩形区域 temp = 0; for(i = 0; i < (objectsTemp ? objectsTemp->total : 0); i ++) { CvRect* rect = (CvRect*) cvGetSeqElem(objectsTemp, i); if ( (rect->height * rect->width) > temp ){ largestFaceRect = rect; temp = rect->height * rect->width; } } // 根据人脸的先验知识分割出大致的人眼区域 temp = largestFaceRect->width / 8; largestFaceRect->x = largestFaceRect->x + temp; largestFaceRect->width = largestFaceRect->width - 3*temp/2; largestFaceRect->height = largestFaceRect->height / 2; largestFaceRect->y = largestFaceRect->y + largestFaceRect->height / 2; largestFaceRect->height = largestFaceRect->height / 2; cvSetImageROI(img, *largestFaceRect); // 设置ROI为检测到的最大的人脸区域 faceImg = cvCreateImage(cvSize(largestFaceRect->width, largestFaceRect->height), IPL_DEPTH_8U, 1); cvCopy(img, faceImg, NULL); cvResetImageROI(img); // 释放ROI cvShowImage("分割后的人脸", faceImg); eyeRectTemp = *largestFaceRect; // 根据人脸的先验知识分割出大致的左眼区域 largestFaceRect->width /= 2; cvSetImageROI(img, *largestFaceRect); // 设置ROI为检测到的最大的人脸区域 lEyeImg = cvCreateImage(cvSize(largestFaceRect->width, largestFaceRect->height), IPL_DEPTH_8U, 1); cvCopy(img, lEyeImg, NULL); cvResetImageROI(img); // 释放ROI cvShowImage("大致的左眼区域", lEyeImg); // 根据人脸的先验知识分割出大致的右眼区域 eyeRectTemp.x += eyeRectTemp.width / 2; eyeRectTemp.width /= 2; cvSetImageROI(img, eyeRectTemp); // 设置ROI为检测到的最大的人脸区域 rEyeImg = cvCreateImage(cvSize(eyeRectTemp.width, eyeRectTemp.height), IPL_DEPTH_8U, 1); cvCopy(img, rEyeImg, NULL); cvResetImageROI(img); // 释放ROI cvShowImage("大致的右眼区域", rEyeImg); /********************************** 二值化处理 ***********************************/ // 图像增强:直方图均衡化在detectFace中实现了一次;可尝试非线性点运算 /*** 二值化左眼大致区域的图像 ***/ //lineTrans(lEyeImg, lEyeImg, 1.5, 0); // 线性点运算 cvSmooth(lEyeImg, lEyeImg, CV_MEDIAN); // 中值滤波 默认窗口大小为3*3 nonlineTrans(lEyeImg, lEyeImg, 0.8); // 非线性点运算 memset(hist, 0, sizeof(hist)); // 初始化直方图的数组为0 histogram(lEyeImg, hist); // 计算图片直方图 // 计算最佳阈值 pixelSum = lEyeImg->width * lEyeImg->height; threshold = ostuThreshold(hist, pixelSum, 45); cvThreshold(lEyeImg, lEyeImg, threshold, 255, CV_THRESH_BINARY);// 对图像二值化 // 显示二值化后的图像 cvShowImage("l_binary",lEyeImg); /*** 二值化右眼大致区域的图像 ***/ //lineTrans(rEyeImg, rEyeImg, 1.5, 0); // 线性点运算 cvSmooth(rEyeImg, rEyeImg, CV_MEDIAN); // 中值滤波 默认窗口大小为3*3 nonlineTrans(rEyeImg, rEyeImg, 0.8); // 非线性点运算 memset(hist, 0, sizeof(hist)); // 初始化直方图的数组为0 histogram(rEyeImg, hist); // 计算图片直方图 // 计算最佳阈值 pixelSum = rEyeImg->width * rEyeImg->height; threshold = ostuThreshold(hist, pixelSum, 45); cvThreshold(rEyeImg, rEyeImg, threshold, 255, CV_THRESH_BINARY);// 对图像二值化 // 显示二值化后的图像 cvShowImage("r_binary",rEyeImg); /***************************************** 检测人眼 ********************************************/ /** 如果有明显的眉毛区域,则分割去除眉毛 **/ // 分割左眼眉毛 HEIGHT = lEyeImg->height; WIDTH = lEyeImg->width; // 分配内存 horiProject = (int*)malloc(HEIGHT * sizeof(int)); vertProject = (int*)malloc(WIDTH * sizeof(int)); if( horiProject == NULL || vertProject == NULL ){ printf("Failed to allocate memory\n"); cvWaitKey(0); return -1; } // 内存置零 for(i = 0; i < HEIGHT; i ++) *(horiProject + i) = 0; for(i = 0; i < WIDTH; i ++) *(vertProject + i) = 0; histProject(lEyeImg, horiProject, vertProject); // 计算直方图投影 lEyeRow = removeEyebrow(horiProject, WIDTH, HEIGHT, 10); // 计算分割眉毛与眼框的位置 // 分割右眼眉毛 HEIGHT = rEyeImg->height; WIDTH = rEyeImg->width; // 分配内存 horiProject = (int*)malloc(HEIGHT * sizeof(int)); vertProject = (int*)malloc(WIDTH * sizeof(int)); if( horiProject == NULL || vertProject == NULL ){ printf("Failed to allocate memory\n"); cvWaitKey(0); return -1; } // 内存置零 for(i = 0; i < HEIGHT; i ++) *(horiProject + i) = 0; for(i = 0; i < WIDTH; i ++) *(vertProject + i) = 0; histProject(rEyeImg, horiProject, vertProject); // 计算直方图投影 rEyeRow = removeEyebrow(horiProject, WIDTH, HEIGHT, 10); // 计算分割眉毛与眼框的位置 // 显示去除眉毛后的人眼大致区域 eyeRect = cvRect(0, lEyeRow, lEyeImg->width, (lEyeImg->height - lEyeRow)); // 去眉毛的眼眶区域在lEyeImg中的矩形框区域 cvSetImageROI(lEyeImg, eyeRect); // 设置ROI为去除眉毛的眼眶,在下面释放ROI lEyeImgNoEyebrow = cvCreateImage(cvSize(eyeRect.width, eyeRect.height), IPL_DEPTH_8U, 1); cvCopy(lEyeImg, lEyeImgNoEyebrow, NULL); cvShowImage("lEyeImgNoEyebrow", lEyeImgNoEyebrow); eyeRectTemp = cvRect(0, rEyeRow, rEyeImg->width, (rEyeImg->height - rEyeRow)); // 去眉毛的眼眶区域在rEyeImg中的矩形框区域 cvSetImageROI(rEyeImg, eyeRectTemp); // 设置ROI为去除眉毛的眼眶,在下面释放ROI rEyeImgNoEyebrow = cvCreateImage(cvSize(eyeRectTemp.width, eyeRectTemp.height), IPL_DEPTH_8U, 1); cvCopy(rEyeImg, rEyeImgNoEyebrow, NULL); cvShowImage("rEyeImgNoEyebrow", rEyeImgNoEyebrow); ///////////////// 定位眼睛中心点在去除眉毛图像中的行列位置 /////////////////// HEIGHT = lEyeImgNoEyebrow->height; WIDTH = lEyeImgNoEyebrow->width; // 分配内存 subhoriProject = (int*)malloc(HEIGHT * sizeof(int)); subvertProject = (int*)malloc(WIDTH * sizeof(int)); if( subhoriProject == NULL || subvertProject == NULL ){ printf("Failed to allocate memory\n"); cvWaitKey(0); return -1; } // 内存置零 for(i = 0; i < HEIGHT; i ++) *(subhoriProject + i) = 0; for(i = 0; i < WIDTH; i ++) *(subvertProject + i) = 0; histProject(lEyeImgNoEyebrow, subhoriProject, subvertProject); // 重新对分割出的左眼图像进行积分投影 lEyeRow = getEyePos(subhoriProject, HEIGHT, HEIGHT/5); // 定位左眼所在的行 lEyeCol = getEyePos(subvertProject, WIDTH, WIDTH/5); // 定位左眼所在的列 HEIGHT = rEyeImgNoEyebrow->height; WIDTH = rEyeImgNoEyebrow->width; // 分配内存 subhoriProject = (int*)malloc(HEIGHT * sizeof(int)); subvertProject = (int*)malloc(WIDTH * sizeof(int)); if( subhoriProject == NULL || subvertProject == NULL ){ printf("Failed to allocate memory\n"); cvWaitKey(0); return -1; } // 内存置零 for(i = 0; i < HEIGHT; i ++) *(subhoriProject + i) = 0; for(i = 0; i < WIDTH; i ++) *(subvertProject + i) = 0; histProject(rEyeImgNoEyebrow, subhoriProject, subvertProject); // 重新对分割出的右眼图像进行积分投影 rEyeRow = getEyePos(subhoriProject, HEIGHT, HEIGHT/5); // 定位右眼所在的行 rEyeCol = getEyePos(subvertProject, WIDTH, WIDTH/5); // 定位右眼所在的列 /* printf("************ image of eyes without eyebrow ***********\n"); printf("Left eye: width: %d\theight: %d\n", lEyeImgNoEyebrow->width, lEyeImgNoEyebrow->height); printf("Right eye: width: %d\theight: %d\n", rEyeImgNoEyebrow->width, rEyeImgNoEyebrow->height); printf("Right eye: WIDTH: %d\tHEIGHT: %d\n", WIDTH, HEIGHT); printf("Centers positon of Eyes. lEyeRow: %d lEyeCol: %d\trEyeRow: %d rEyeCol: %d\n\n", lEyeRow, lEyeCol, rEyeRow, rEyeCol); */ // 标记眼睛的位置 cvCircle(lEyeImgNoEyebrow, cvPoint(lEyeCol, lEyeRow), 3, CV_RGB(0,0,255), 1, 8, 0); cvCircle(rEyeImgNoEyebrow, cvPoint(rEyeCol, rEyeRow), 3, CV_RGB(0,0,255), 1, 8, 0); cvShowImage("lEyeCenter", lEyeImgNoEyebrow); cvShowImage("rEyeCenter", rEyeImgNoEyebrow); /********************************** 判断人眼睁闭状态 ***********************************/ ////////////////// 分割出以找到的中心为中心的大致眼眶 ///////////////// // 左眼眶 HEIGHT = lEyeImgNoEyebrow->height; WIDTH = lEyeImgNoEyebrow->width; // 计算大致眼眶的区域: eyeRect eyeRect = cvRect(0, 0, WIDTH, HEIGHT); calEyeSocketRegion(&eyeRect, WIDTH, HEIGHT, lEyeCol, lEyeRow); /* printf("************lEyeImgNoEyebrow************\n"); printf("width: %d\theight: %d\n", WIDTH, HEIGHT); printf("**********lEyeballRect**********\n"); printf("eyeRect.x = %d\teyeRect.width = %d\n", eyeRect.x, eyeRectTemp.width); printf("eyeRect.y = %d\teyeRect.height = %d\n\n", eyeRectTemp.y, eyeRectTemp.height); */ cvSetImageROI(lEyeImgNoEyebrow, eyeRect); // 设置ROI为检测到眼眶区域 lEyeballImg = cvCreateImage(cvGetSize(lEyeImgNoEyebrow), IPL_DEPTH_8U, 1); cvCopy(lEyeImgNoEyebrow, lEyeballImg, NULL); cvResetImageROI(lEyeImgNoEyebrow); cvShowImage("lEyeballImg", lEyeballImg); // 右眼眶 HEIGHT = rEyeImgNoEyebrow->height; WIDTH = rEyeImgNoEyebrow->width; // 计算大致眼眶的区域: eyeRectTemp eyeRect = cvRect(0, 0, WIDTH, HEIGHT); calEyeSocketRegion(&eyeRect, WIDTH, HEIGHT, rEyeCol, rEyeRow); /* printf("************rEyeImgNoEyebrow************\n"); printf("width: %d\theight: %d\n", WIDTH, HEIGHT); printf("**********rEyeballRect**********\n"); printf("eyeRect.x = %d\teyeRect.width = %d\n", eyeRect.x, eyeRect.width); printf("eyeRect.y = %d\teyeRect.height = %d\n\n", eyeRect.y, eyeRect.height); */ cvSetImageROI(rEyeImgNoEyebrow, eyeRect); // 设置ROI为检测到眼眶区域 rEyeballImg = cvCreateImage(cvGetSize(rEyeImgNoEyebrow), IPL_DEPTH_8U, 1); cvCopy(rEyeImgNoEyebrow, rEyeballImg, NULL); cvResetImageROI(rEyeImgNoEyebrow); cvShowImage("rEyeballImg", rEyeballImg); /////////////////////////// 闭运算 /////////////////////////// cvErode(lEyeballImg, lEyeballImg, NULL, 2); //腐蚀图像 cvDilate(lEyeballImg, lEyeballImg, NULL, 2); //膨胀图像 cvShowImage("lkai", lEyeballImg); cvErode(rEyeballImg, rEyeballImg, NULL, 1); //腐蚀图像 cvDilate(rEyeballImg, rEyeballImg, NULL, 1); //膨胀图像 cvShowImage("rkai", rEyeballImg); /////////////////// 计算最小眼睛的矩形区域 //////////////////// ///////////////////////////左眼 HEIGHT = lEyeballImg->height; WIDTH = lEyeballImg->width; // 分配内存 subhoriProject = (int*)malloc(HEIGHT * sizeof(int)); subvertProject = (int*)malloc(WIDTH * sizeof(int)); if( subhoriProject == NULL || subvertProject == NULL ){ printf("Failed to allocate memory\n"); cvWaitKey(0); return -1; } // 内存置零 for(i = 0; i < HEIGHT; i ++) *(subhoriProject + i) = 0; for(i = 0; i < WIDTH; i ++) *(subvertProject + i) = 0; histProject(lEyeballImg, subhoriProject, subvertProject); // 计算左眼最小的矩形区域 eyeRectTemp = cvRect(0, 0 , 1, 1); // 初始化 getEyeMinRect(&eyeRectTemp, subhoriProject, subvertProject, WIDTH, HEIGHT, 5, 3); /* printf("eyeRectTemp.y: %d\n", eyeRectTemp.y); printf("eyeRectTemp.height: %d\n", eyeRectTemp.height); printf("eyeRectTemp.x: %d\n", eyeRectTemp.x); printf("eyeRectTemp.width: %d\n", eyeRectTemp.width); */ // 计算最小左眼矩形的长宽比, 判断眼睛状态时用的到 lMinEyeballRectShape = (double)eyeRectTemp.width / (double)eyeRectTemp.height; //printf("\nlMinEyeballRectShape: %f\n", lMinEyeballRectShape); cvSetImageROI(lEyeballImg, eyeRectTemp); // 设置ROI为检测到最小面积的眼眶 lMinEyeballImg = cvCreateImage(cvGetSize(lEyeballImg), IPL_DEPTH_8U, 1); cvCopy(lEyeballImg, lMinEyeballImg, NULL); cvResetImageROI(lEyeballImg); cvShowImage("lMinEyeballImg", lMinEyeballImg); //////////////////////// 统计左眼黑像素个数 ///////////////////// HEIGHT = lMinEyeballImg->height; WIDTH = lMinEyeballImg->width; // 分配内存 subhoriProject = (int*)malloc(HEIGHT * sizeof(int)); subvertProject = (int*)malloc(WIDTH * sizeof(int)); if( subhoriProject == NULL || subvertProject == NULL ){ printf("Failed to allocate memory\n"); cvWaitKey(0); return -1; } // 内存置零 for(i = 0; i < HEIGHT; i ++) *(subhoriProject + i) = 0; for(i = 0; i < WIDTH; i ++) *(subvertProject + i) = 0; histProject(lMinEyeballImg, subhoriProject, subvertProject); // 统计lEyeballImg中黑色像素的个数 temp = 0; // 白像素个数 for( i = 0; i < WIDTH; i ++ ) temp += *(subvertProject + i); temp /= 255; lMinEyeballBlackPixel = WIDTH * HEIGHT - temp; lMinEyeballBlackPixelRate = (double)lMinEyeballBlackPixel / (double)(WIDTH * HEIGHT); //printf("WIDTH * HEIGHT: %d\tlMinEyeballBlackSum;%d\n\n", WIDTH * HEIGHT, lMinEyeballBlackPixel); //printf("lMinEyeballBlackPixelRate;%f\n\n", lMinEyeballBlackPixelRate); // 统计lMinEyeballImg中的1/2区域内黑像素的比例 lMinEyeballBeta = 0; lMinEyeballBeta = calMiddleAreaBlackPixRate(subvertProject, &eyeRectTemp, WIDTH, HEIGHT, lEyeCol, lMinEyeballBlackPixel); //printf("lMinEyeballBeta; %f\n\n", lMinEyeballBeta); ////////////////////////////////////右眼 HEIGHT = rEyeballImg->height; WIDTH = rEyeballImg->width; // 分配内存 subhoriProject = (int*)malloc(HEIGHT * sizeof(int)); subvertProject = (int*)malloc(WIDTH * sizeof(int)); if( subhoriProject == NULL || subvertProject == NULL ){ printf("Failed to allocate memory\n"); cvWaitKey(0); return -1; } // 内存置零 for(i = 0; i < HEIGHT; i ++) *(subhoriProject + i) = 0; for(i = 0; i < WIDTH; i ++) *(subvertProject + i) = 0; histProject(rEyeballImg, subhoriProject, subvertProject); // 计算右眼最小的矩形区域 eyeRectTemp = cvRect(0, 0 , 1, 1); getEyeMinRect(&eyeRectTemp, subhoriProject, subvertProject, WIDTH, HEIGHT, 5, 3); // 计算最小右眼矩形的长宽比,判断眼睛状态时用的到 rMinEyeballRectShape = (double)eyeRectTemp.width / (double)eyeRectTemp.height; //printf("\nrMinEyeballRectShape: %f\n", rMinEyeballRectShape); cvSetImageROI(rEyeballImg, eyeRectTemp); // 设置ROI为检测到最小面积的眼眶 rMinEyeballImg = cvCreateImage(cvGetSize(rEyeballImg), IPL_DEPTH_8U, 1); cvCopy(rEyeballImg, rMinEyeballImg, NULL); cvResetImageROI(rEyeballImg); cvShowImage("rMinEyeballImg", rMinEyeballImg); //////////////////////// 统计右眼黑像素个数 ///////////////////// HEIGHT = rMinEyeballImg->height; WIDTH = rMinEyeballImg->width; // 分配内存 subhoriProject = (int*)malloc(HEIGHT * sizeof(int)); subvertProject = (int*)malloc(WIDTH * sizeof(int)); if( subhoriProject == NULL || subvertProject == NULL ){ printf("Failed to allocate memory\n"); cvWaitKey(0); return -1; } // 内存置零 for(i = 0; i < HEIGHT; i ++) *(subhoriProject + i) = 0; for(i = 0; i < WIDTH; i ++) *(subvertProject + i) = 0; histProject(rMinEyeballImg, subhoriProject, subvertProject);// 计算直方图积分投影 // 统计lEyeballImg中黑色像素的个数 temp = 0; for( i = 0; i < WIDTH; i ++ ) temp += *(subvertProject + i); temp /= 255; rMinEyeballBlackPixel = WIDTH * HEIGHT - temp; rMinEyeballBlackPixelRate = (double)rMinEyeballBlackPixel / (double)(WIDTH * HEIGHT); //printf("WIDTH * HEIGHT: %d\trMinEyeballBlackSum;%d\n\n", WIDTH * HEIGHT, rMinEyeballBlackPixel); //printf("rMinEyeballBlackPixelRate; %f\n\n", rMinEyeballBlackPixelRate); // 统计lMinEyeballImg中的1/2区域内黑像素的比例 rMinEyeballBeta = 0; rMinEyeballBeta = calMiddleAreaBlackPixRate(subvertProject, &eyeRectTemp, WIDTH, HEIGHT, rEyeCol, rMinEyeballBlackPixel); //printf("temp:%d\trMinEyeballBeta; %f\n\n", temp, rMinEyeballBeta); // 判断眼睛睁闭情况 lEyeState = 1; // 左眼状态,默认闭眼 rEyeState = 1; // 右眼状态,默认闭眼 eyeState = 1; // 眼睛综合状态,默认闭眼 if( lMinEyeballBlackPixel > 50) lEyeState = getEyeState(lMinEyeballRectShape, lMinEyeballBlackPixelRate, lMinEyeballBeta); else lEyeState = 1; if( rMinEyeballBlackPixel > 50) rEyeState = getEyeState(rMinEyeballRectShape, rMinEyeballBlackPixelRate, rMinEyeballBeta); else rEyeState = 1; (lEyeState + rEyeState) == 2 ? eyeState = 1 : eyeState=0; // 统计眼睛闭合的次数 if( eyeState == 1 ){ eyeCloseNum ++; // 统计 eyeCloseNum 眼睛闭合次数 eyeCloseDuration ++; if( globalK == DETECTTIME){ // 检测过程中判断全是闭眼情况,没有睁眼和检测不到人脸的情况 (eyeCloseDuration > maxEyeCloseDuration) ? maxEyeCloseDuration = eyeCloseDuration : maxEyeCloseDuration; eyeCloseDuration = 0; } } else{ (eyeCloseDuration > maxEyeCloseDuration) ? maxEyeCloseDuration = eyeCloseDuration : maxEyeCloseDuration; eyeCloseDuration = 0; } } // 承接判断是否检测到人脸的if语句 /* printf("\n************** 眼睛状态 ***************\n"); printf("lEyeState: %d\trEyeState: %d\n", lEyeState, rEyeState); printf("eyeState: %d\n\n\n\n", eyeState); */ // 计时:执行一次循环的时间 stop = clock(); //printf("run time: %f\n", (double)(stop - start) / CLOCKS_PER_SEC); printf("eyeState: %d\n", eyeState); // 调整循环变量,进入下一次检测过程 if( globalK == DETECTTIME ){ printf("\nFATIGUETHRESHOLD*****: %d\n", FATIGUETHRESHOLD); printf("eyeCloseNum: %d\tmaxEyeCloseDuration: %d\n", eyeCloseNum, maxEyeCloseDuration); printf("failFaceNum: %d\tmaxFailFaceDuration: %d\n", failFaceNum, maxFailFaceDuration); // 进行疲劳状态的判别 fatigueState = recoFatigueState(FATIGUETHRESHOLD, eyeCloseNum, maxEyeCloseDuration, failFaceNum, maxFailFaceDuration); if( fatigueState == 1 ) printf("驾驶员处于疲劳驾驶状态\n\n"); else if( fatigueState == 0 ) printf("驾驶员处于正常驾驶状态\n\n"); // 进入下一次检测过程前,将变量清零 globalK = 0; lEyeState = 1; rEyeState = 1; eyeState = 1; eyeCloseNum = 0; eyeCloseDuration = 0; maxEyeCloseDuration = 0; failFaceNum = 0; failFaceDuration = 0; maxFailFaceDuration = 0; fatigueState = 1; char c = cvWaitKey(0); if( c == 27 ) break; else continue; } } // 承接检测过程的 for 循环 // 释放内存 cvDestroyWindow("分割后的人脸"); cvDestroyWindow("大致的左眼区域"); cvDestroyWindow("大致的右眼区域"); cvDestroyWindow("l_binary"); cvDestroyWindow("r_binary"); cvDestroyWindow("lEyeImgNoEyebrow"); cvDestroyWindow("rEyeImgNoEyebrow"); cvDestroyWindow("lEyeCenter"); cvDestroyWindow("rEyeCenter"); cvDestroyWindow("lEyeballImg"); cvDestroyWindow("rEyeballImg"); cvDestroyWindow("lkai"); cvDestroyWindow("rkai"); cvDestroyWindow("lMinEyeballImg"); cvDestroyWindow("rMinEyeballImg"); cvReleaseMemStorage(&storage); cvReleaseImage(&eyeImg); free(horiProject); free(vertProject); free(subhoriProject); free(subvertProject); return 0; }
int batchProcessing(const string rootPath, const string listPath, const string faceDetectModel, const string detectionModelPath, const string trackingModelPath, const float ec_mc_y, const float ec_y, const string saveRootPath, const int size) { ofstream logfile("log.txt"); ifstream infile(listPath); string filename; vecS lines; while(infile >> filename) lines.push_back(filename); infile.close(); cout << "A total of " << lines.size() << " images." << endl; string str; Mat img; FACE_HANDLE face_detection_handle; int ret_fd_init = getDetectionHandle(&face_detection_handle, faceDetectModel); if(0 != ret_fd_init || NULL == &face_detection_handle) { cout << "Error init for face alignment!" << endl; return -1; } vecR rect; string error; FACE_HANDLE face_alignment_handle; int ret_fa = getAlignmentHandle(&face_alignment_handle, detectionModelPath, trackingModelPath); if(0 != ret_fa || NULL == face_alignment_handle) { cout << "Error init for face alignment!" << endl; return -1; } for(int i = 0; i < lines.size(); ++i) { rect.clear(); str = rootPath + lines[i]; img = imread(str, CV_LOAD_IMAGE_GRAYSCALE); int ret_fd = detectFace(face_detection_handle, img, rect, error); if(0 != ret_fd) { cout << "The " << i << " image has "<< error <<endl; logfile << lines[i] << " [Face Detection Error]." << endl; continue; } for(int j = 0; j < rect.size(); ++j) { Mat result; int ret_fa = faceAlignment(face_alignment_handle, img, rect[j], ec_mc_y, ec_y, result, error); if(0 != ret_fa) { cout << "The " << i << " image has "<< error <<endl; logfile << lines[i] << " [Facial Points Detection Error]." << endl; continue; } resize(result, result, Size(size, size)); string savePath; stringstream count; char dir[1024]; //sprintf(savePath, "%s%s_%d.jpg", saveRootPath.c_str(), lines[i].c_str(), j); count << j; savePath = saveRootPath + lines[i] + "_" + count.str() + ".jpg"; get_dir_from_filename(savePath.c_str(), dir); int ret = create_directory(dir); if(0 != ret) { cout << savePath << " create file error!" << endl; logfile << lines[i] << " [IO Error]." << endl; } else cout << savePath << " is finished." << endl; imwrite(savePath, result); } } logfile.close(); releaseDetectionHandle(&face_detection_handle); releaseAlignmentHandle(&face_alignment_handle); }