社区微信群开通啦,扫一扫抢先加入社区官方微信群
社区微信群
昨天使用javacv写了个实时人脸检测的简单程序,网上找了很多代码,但是觉得都太冗余了,大多是人脸检测和对比之类的代码一起写的,加上javacv版本不同,有些函数和数据结构不同,看的我一脸混乱,我只是想要一个单独的人脸检测有人脸检测功能的代码而已,所以这里简单剥离了一下,只留下了最核心的人脸检测部分的代码(不是识别或者匹配)。
我这里使用的是javacv1.2+myeclipse blue 2014,(javacv0.8之前的版本貌似要使用opencv+javacv才行,0.8以后貌似不用引入opencv了)。
ps:之前我在同一个项目中同时导入了javacv1.2的包和opencv3.2/build/java/opencv_320.jar包。发现javacv的包和opencv的包里面的类发生了冲突,两个包中都有Mat,但是像个包中的类(Mat)互不相通,一时间搞得代码相当混乱,这里建议opencv和javacv还是分开用,不要再同一个项目中同时导入。
首先是javacv包的下载,这个直接在百度下载就行了,下载之后解压,将javacv-1.2-bin目录下的opencv.jar,javacv.jar,javacpp.jar,opencv_windows_x86_64.jar(如果是32位程序,这个包换成opencv_windows_x86.jar导入),这四个包直接导入eclispse就行,简单快捷。之后我们就可以开始使用javacv了。
首先我们获取电脑摄像头,这里javacv封装好了,我们几句就可以调用:
OpenCVFrameGrabber grabber = new OpenCVFrameGrabber(0); //初始化摄像头
grabber.start(); //开始获取摄像头数据
Frame frame=grabber.grab();//获取摄像头图像的一帧
获取到的图片,我们用FrameCanvas来展示,这是一个窗口,其中可以传入Frame类型的数据,这个窗口将展示Frame代表的图像,当然你可以使用swing或者awt来展示,只是用FrameCanvas简单太多了,只要下面几行代码就可以实现一张图片的展示:
CanvasFrame canvas = new CanvasFrame("人脸检测");//新建一个窗口
canvas.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//设置关闭窗口时销毁窗口
canvas.showImage(frame);//在canvas窗口上显示frame代表的图像
将这两部分结合起来,我们可以实现实时展示摄像头内容的功能:
OpenCVFrameGrabber grabber = new OpenCVFrameGrabber(0);
grabber.start(); //开始获取摄像头数据
CanvasFrame canvas = new CanvasFrame("人脸检测");//新建一个窗口
canvas.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
while(true)
{
if(!canvas.isEnabled())
{//窗口是否关闭
grabber.stop();//停止抓取
System.exit(0);//退出
}
Frame frame=grabber.grab();
canvas.showImage(frame);//获取摄像头图像并放到窗口上显示, 这里的Frame frame=grabber.grab(); frame是一帧视频图像
Thread.sleep(50);//50毫秒刷新一次图像
}
整个架子搭好了,我们只需要对获取到的每一帧图像拿去做一下人脸检测,然后吧检测到人脸的区域画出来就行了。这一部分javacv已经做了很多很好的封装,写起来也相当简单,下面我们来实现人脸检测的代码:
整个检测的过程主要依赖CascadeClassifier来实现,opencv/source/data目录下lbpcascades,haarcascades_cuda和haarcascades目录下都有已经训练好的人脸检测器,各个xml文件的后缀名frontalface的文件为人脸检测器,如lbpcascades/lbpcascade_frontalface.xml,各个检测器的比较这里就不多说,有需要的同学可以网上查。
CascadeClassifier cascade = new CascadeClassifier("G:\opencv3.2\opencv\sources\data\lbpcascades\lbpcascade_frontalface.xml");//初始化人脸检测器
RectVector faces=new RectVector();//创建用来装检测出来的人脸的容器
cascade.detectMultiScale(grayscr, faces);//检测人脸,grayscr为要检测的图片,faces用来存放检测结果
for(int i=0;i<faces.size();i++)//遍历检测出来的人脸
{
Rect face_i=faces.get(i);
rectangle(src, face_i, new Scalar(0, 0, 255, 1));//在原图上画出人脸的区域
}
完整的detectFace函数代码如下:
public static Mat detectFace(Mat src)
{
Mat grayscr=new Mat();
cvtColor(src,grayscr,COLOR_BGRA2GRAY);//摄像头是彩色图像,所以先灰度化下
equalizeHist(grayscr,grayscr);//均衡化直方图
RectVector faces=new RectVector();
cascade.detectMultiScale(grayscr, faces);
for(int i=0;i<faces.size();i++)
{
Rect face_i=faces.get(i);
rectangle(src, face_i, new Scalar(0, 0, 255, 1));
}
return src;
}
到这里,人脸检测的函数就写完了,接下来只要将这个函数应用到,摄像头获取的每一帧图像中去就可以实时检测人脸了。
public static void JavavcCameraTest() throws Exception, InterruptedException
{
OpenCVFrameGrabber grabber = new OpenCVFrameGrabber(0);
grabber.start(); //开始获取摄像头数据
CanvasFrame canvas = new CanvasFrame("人脸检测");//新建一个窗口
canvas.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
while(true)
{
if(!canvas.isEnabled())
{//窗口是否关闭
grabber.stop();//停止抓取
System.exit(0);//退出
}
Frame frame=grabber.grab();
Mat scr=convertor.convertToMat(frame);//将获取的frame转化成mat数据类型
detectFace(scr);//人脸检测
frame=convertor.convert(scr);//将检测结果重新的mat重新转化为frame
canvas.showImage(frame);//获取摄像头图像并放到窗口上显示,frame是一帧视频图像
Thread.sleep(50);//50毫秒刷新一次图像
}
}
到这里,简单的实时人脸检测就完成了,效果如下:
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!