使用opencv检测bmp图片中人脸,主要使用cvHaarDetectObjects函数实现。
函数定义
CvSeq* cvHaarDetectObjects( const CvArr* image, CvHaarClassifierCascade* cascade,
CvMemStorage* storage, double scale_factor=1.1,
int min_neighbors=3, int flags=0, CvSize(min_size=cvSize(0,0) ,CvSize max_size=cvSize(0,0));
参数说明
image 被检图像
cascade haar 分类器级联的内部标识形式
storage 用来存储检测到的一序列候选目标矩形框的内存区域。
scale_factor 在前后两次相继的扫描中,搜索窗口的比例系数。例如1.1指将搜索窗口依次扩大10%
min_neighbors 构成检测目标的相邻矩形的最小个数(缺省-1)。如果组成检测目标的小矩形的个数和小于min_neighbors-1 都会被排除。如果min_neighbors 为 0, 则函数不做任何操作就返回所有的被检候选矩形框,这种设定值一般用在用户自定义对检测结果的组合程序上。
flags 操作方式。当前唯一可以定义的操作方式是 CV_HAAR_DO_CANNY_PRUNING。如果被设定,函数利用Canny边缘检测器来排除一些边缘很少或者很多的图像区域,因为这样的区域一般不含被检目标。人脸检测中通过设定阈值使用了这种方法,并因此提高了检测速度。
min_size 检测窗口的最小尺寸。缺省的情况下被设为分类器训练时采用的样本尺寸(人脸检测中缺省大小是~20×20)。
具体函数调用
faces = cvHaarDetectObjects(imgTmp, cascade, storage, 1.5, 4, 0, cvSize(50,50) );
cascade是加载了haarcascade_frontalface_alt2.xml人脸标识的文件。
返回值faces是检测到的人脸信息,包括坐标和宽高信息。
根据faaces中的信息,再利用cvRectangle函数,将人脸的矩形框绘制出来。
/*******************************************************
* file:testFace.c
* date:2021-07-17
* version:1.0.0.1
* author:jack8126
* description: bmp file, dectect face
*******************************************************/
#include "cv.h"
#include "highgui.h"
#include "stdio.h"
#include
int main(int argc, char* argv[])
{
struct timeval timeStart,timeEnd;
unsigned long timeCount;
char u8PicNameRead[64] = {0};
char u8PicNameOut[64] = {0};
int i = 0;
if(argc < 3)
{
printf("please input like this:\r\n");
printf("./testFace.bin test.bmp test-out.bmp\r\n");
printf("test.bmp ---------------- input file \r\n");
printf("test-out.bmp ------------ output file \r\n");
return -1;
}
sprintf(u8PicNameRead,"%s",argv[1]);
sprintf(u8PicNameOut,"%s",argv[2]);
printf("u8PicNameRead=%s\r\n",u8PicNameRead);
IplImage* img = NULL;
IplImage* cutImg = NULL;
CvMemStorage* storage = cvCreateMemStorage(0);
CvHaarClassifierCascade* cascade = (CvHaarClassifierCascade*)cvLoad("./haarcascade_frontalface_alt2.xml", 0, 0, 0);
CvSeq* faces;
//加载图像
img = cvLoadImage(u8PicNameRead, 1); // 0 - gray; 1 - color
//缩放到1/2大小
IplImage *imgTmp = cvCreateImage(cvSize(img->width, img->height), 8, img->nChannels);
printf("imgTmp w=%d h=%d\n", imgTmp->width, imgTmp->height);
cvResize(img, imgTmp);
//检测并计时
gettimeofday(&timeStart,0);
faces = cvHaarDetectObjects(imgTmp, cascade, storage, 1.5, 4, 0, cvSize(50,50) );
gettimeofday(&timeEnd,0);
timeCount = (timeEnd.tv_sec-timeStart.tv_sec)*1000000 + timeEnd.tv_usec-timeStart.tv_usec;
printf("use time: %uus\n",timeCount);
if (faces->total == 0){
printf("no face!\n");
goto ERROR;
}
for( i = 0; i < (faces ? faces->total : 0); i++ )
{
CvRect* r = (CvRect*)cvGetSeqElem( faces, i );
printf("face detected! i=%d, x=%d, y=%d\n",i, r->x,r->y);
printf("face detected! i=%d, width=%d, height=%d\n",i, r->width,r->height);
cvRectangle(img,
cvPoint(r->x, r->y),
cvPoint(r->x + r->width, r->y + r->height),
cvScalar(255, 0, 0),
1
);
}
cvSaveImage(u8PicNameOut, img);
cvResetImageROI(img);
printf("face detected! in face.bmp! total:%d\n",faces->total);
ERROR:
//释放内存
cvReleaseImage(&img);
cvReleaseImage(&imgTmp);
return 0;
}
makefile文件
PWD_DIR := $(shell pwd)
OPENCV_BASE_DIR := /usr/local/
OPENCV_DIR := -I$(OPENCV_BASE_DIR)/include
OPENCV1_DIR := -I$(OPENCV_BASE_DIR)/include/opencv
OPENCV2_DIR := -I$(OPENCV_BASE_DIR)/include/opencv2
OPENCV_LIB_DIR := -L$(OPENCV_BASE_DIR)lib/
OPENCV_LIB_DIR2 := -L$(OPENCV_BASE_DIR)lib/
OPENCV_LIBS := $(OPENCV_LIB_DIR)libopencv_highgui.a\
$(OPENCV_LIB_DIR)libopencv_core.a\
$(OPENCV_LIB_DIR)libopencv_imgproc.a\
$(OPENCV_LIB_DIR)libopencv_objdetect.a
INC_FLAGS := $(OPENCV_DIR) $(OPENCV1_DIR) $(OPENCV2_DIR)
SRC := $(wildcard *.c)
OBJ := $(SRC:%.c=%.o)
TARGET := $(OBJ:%.o=%)
.PHONY : clean all
all: testFace.bin
testFace.bin:
g++ -g testFace.cpp $(INC_FLAGS) -lpthread -lrt -lopencv_highgui -lopencv_core -lopencv_imgproc -lopencv_objdetect -o testFace.bin
clean:
rm testFace.bin
编译命令如下
make
执行完上述命令之后,会生成testOpenCvBinarization.bin文件,后面执行程序时需要该文件。
使用如下命令执行程序,可检测出bmp图片中的人脸。
执行完上述命令后,生成image-out.bmp文件。
原图
检测后的图片