十分钟教你学会 Java+opencv视频人脸检测

引言

忽然心血来潮,想写写东西,这是我的首个博客,不知道写些什么内容好。
那好吧,拿个以前做的一个项目讲讲。

项目介绍:

项目的目的是视频人脸的检测和人脸对比,使用的当然是opencv(不收费,开源啊),本章要介绍的是视频的读取,并将视频转换为图片流进行人脸识别。废话不多说,直接进入正题(为了更好理解,我拆开来讲,哈哈哈)。



一、环境搭建

本次演示demo使用eclipse开发工具,opencv计算机视觉库,当然也要有jdk(都懂的,不懂百度以下jdk的安装和使用,环境变量的配置等)。opencv则需要下载的开源库,下载官网地址为: opencv官网
直接上图:
十分钟教你学会 Java+opencv视频人脸检测_第1张图片
大家看到了,我下载的是Windows版本的(有兴趣也可以试试其他平台),最好不要下载最新版本(为什么呢,偷偷告诉你,别告诉别人,最新有可能有较多的bug,毕竟开源你懂的,如果不适用新版本的功能就不建议下最新版本,学习使用低版本就够了,踩坑出来的经验哈哈哈)。官网是比较慢的,请耐心等待,等待不了的就去其他国内的网站下,找其他人要资源,网上百度找下载地址都可以。



二、OpenCV项目构建

项目以一个个功能模块开始讲,不细说具体项目实现(看完我的文章,你可以试试设计一个自己的系统,这样更有成就感)。

  • 新建项目
    File->New ->Project 如图:

    		此处有一张图(发挥想象力)
    

开个玩笑啊,按提示走就对了,项目新建完成后,接着下面操作。

  • 配置项目
    找到下载好的文件,你下载可能是 :opencv-3.4.11-vc14_vc15.exe(按我说的做就是下载这样的),那么你可以双击打开进入安装流程,安装好后,找到安装目录:
    十分钟教你学会 Java+opencv视频人脸检测_第2张图片
    看到没,有个*.jar文件,没错我们就是要用这个文件,复制还是粘贴的把他搞到我们的Java项目的lib目录中来,如图:

十分钟教你学会 Java+opencv视频人脸检测_第3张图片
点击opencv-341.jar -> 右键 -> build path->add to build path 。将jar添加为项目依赖,拷贝opencv_java341.dll到更目录下,如上图所示。接着测试是否成功,测试代码:

public class Show {
     
	
	static {
     
		//这里一定要加,不然报错的
		System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
	}

	public static void main(String[] args) {
     

		String srcPath = "E:\\TestImage\\test\\84.jpg";	
		Mat src = Imgcodecs.imread(srcPath);	
		HighGui.imshow("图片显示", src);
		HighGui.waitKey(10);		
		System.out.println("end");
	}
}

srcPath就是你要处理的图片路径,运行代码后显示出一张图片,那么恭喜你,环境搭建成功。不行的同学仔细检查检查,哪里出问题了,代码就不解释了,下面遇到再细说。



二、视频读取模块

上一章节主要是讲给第一次用opencv的同学听的,第二章节才是我们的核心内容。
喂喂,认真听,别睡觉了,拿个小本本记起来。


视频的读取需要一个视频的地址,可以是网络摄像头地址(如:192.168.1.53)、网络视频地址(如:测试的短视频)、本地视频(如:E:\FaceRecognition\video\test\zhao.mp4)、本机摄像头(大概就这几种了)。代码如下:

VideoCapture capture = new VideoCapture(videoPath);	
double totalFrameNumber = capture.get(7);

直接拿到摄像头对象,get(7)获取视频的总帧数(这里不讲远程摄像头实时获取视频流的情况,目的为了方便简单更好理解,我们的核心不是视频的获取!)

三、从视频数据中获取图片

我们要清楚一个概念,视频是由一帧一帧的图片构成的,帧率表示每秒的图片帧数(如:20fps表示每秒显示20帧(张)图像,帧率越高,视频看起来越流畅,如果一段视频从20fps改变为60fps,具体表现为视频速度加快3倍,为什么呢?

视频如何变成一帧一帧的图像呢?不多说,直接上代码:


	public static void VideoToImage(String videoPath, String imagePath, int num) {
     
		// get video
		VideoCapture capture = new VideoCapture(videoPath);
		double totalFrameNumber = capture.get(7);// 获取帧数
		System.out.println("总帧数:" + totalFrameNumber);
		Mat frame = new Mat(); // 定义一个Mat变量,用来存放存储每一帧图像
		boolean flags = true; // 循环标志位
		long currentFrame = 0; // 定义当前帧
		long sum = 0; // 定义保存图片数

		while (flags) {
     
			capture.read(frame); // 读取视频每一帧
			if (currentFrame % num == 0) {
     
				String fname = sum + ".jpg";
				Imgcodecs.imwrite(imagePath + "/" + fname, frame); // 将帧转成图片输出
				sum++;
			}
			if (currentFrame >= totalFrameNumber) {
     
				flags = false;
			}
			currentFrame++;
		}
		capture.release();
		System.out.println("视频解析结束!");
	}

介于有些同学没有熟悉openCV我有必要讲解一下,while里面的

capture.read(frame); // 读取视频每一帧

循环读取每一帧直到等于总帧数时,读取完毕,循环结束。while循环的主要操作有:


1、读取每一帧:	capture.read(frame)

2、每隔num帧取一帧图像:	currentFrame%num

3、将图像帧保存到本地目录中:	Imgcodecs.imwrite()


再来说说函数的参数
VideoToImage(String videoPath, String imagePath, int num)

videoPath: 视频的地址(路径)
imagePath: 解析出来的图片保存路径
num: 取帧间隔)

演示一波调用,不会的同学可以看看

public static void main(String[] args) {
     
		String videoPath = "E:\\FaceRecognition\\video\\test\\zhao.mp4";
		String imagePath = "E:\\FaceRecognition\\video\\test\\toImage";	
		
		ImageUtils.VideoToImage(videoPath, imagePath, 10);
		System.out.println("end");
}

我们的测试视频如下,有需要的同学可以下载(直接网页爬虫哈哈哈,不会的再说)

赵丽颖代言水密码广告

视频现在才找的不知道和以前的是不是一样的(我用的是下载好的,不记得下载位置了嘻嘻嘻。


我们到图片保存的位置看看,嗯还不错。
十分钟教你学会 Java+opencv视频人脸检测_第4张图片

四、人脸检测与人脸裁剪

人脸检测的意思是在一张图片中检测出多少个人脸,每个人脸的位置等信息。
人脸裁剪的意思是提取出检测到的人脸,并保存人脸。

也许有同学会直接跳下来直接看人脸检测,确实该章节比较有意思。先来讲讲人脸检测:

  • 人脸检测
    人脸识别的迅猛发展,从传统机器学习到深度学习的突破,使人脸识别等人工智能领域得到了突破性进展。不管是人脸比对,活体检测、人脸检测都需要训练一个识别或检测的模型,本文为了简化过程,暂时不讨论如何训练模型。而是直接使用openCV提供的人脸检测模型。
D:\\OpenCV\\opencv341\\sources\\data\\haarcascades\\haarcascade_frontalface_alt_tree.xml

具体需要看自己opencv的安装路径,找到 haarcascade_frontalface_alt_tree.xml 文件
使用方式为:

public static MatOfRect FaceDetect(Mat srcImage, Mat dstImage) {
     
		Mat grayImage = new Mat();
		srcImage.copyTo(dstImage);
		Imgproc.cvtColor(srcImage, grayImage, Imgproc.COLOR_BGR2GRAY);
		CascadeClassifier cascade = new CascadeClassifier(haarcascades);
		MatOfRect faceDetections = new MatOfRect();
		cascade.detectMultiScale(grayImage, faceDetections);
		
		return faceDetections;
}
haarcascades:		上面人脸检测模型的路径

cascade.detectMultiScale(grayImage, faceDetections) 	检测多张人脸坐标

faceDetections 人脸坐标集合

  • 人脸裁剪

人脸检测出来了,一堆坐标,啥也看不懂啊,怎么办呢?

一般来说通过画脸框来显示检测到的人脸:

for (Rect rect : faceDetections.toArray()) {
     
	Imgproc.rectangle(dstImage, new Point(rect.x, rect.y), new Point(rect.x + rect.width, rect.y + rect.height),new Scalar(0, 0, 255), 2);
}

代码看得懂对吧,那好,我们接着下面内容。

。。
。。。
裁剪保存人脸更加直观的看到效果,关键是拿到裁剪后的人脸图像有用(人脸识别训练的样本,训练自己的模型需要大量的人脸样本哦


老样子,上代码:

public void getCutFace(String srcPath,String savePath,int name) {
     
		int noface=0,face=0;
		List<String> files = FileUtils.getFiles(srcPath);
		for (String filepath : files) {
     //循环读取目录下的每一张图片
			Mat image = Imgcodecs.imread(filepath);
			Rect[] rect = FaceDetection.FaceDetect(image);
			if(rect.length==0) {
     
				noface++;
				continue;
			}
			face++;
			Mat cut_dest = ImageUtils.cutImage(image, rect[0]);
			Imgcodecs.imwrite(savePath+"/"+n+".jpg", cut_dest);
			name++;
		}
		System.out.println("无法检测到人脸:"+noface+"\t检测到人脸:"+face);
	}

getFiles() 获取图片存放的路径
rect[0] 表示取一张图像中众多人脸中的其中一张人脸,一般为最大人脸。
getCutFace()函数参数。第一个参数为图片存放的文件夹,第二个参数为裁剪后图片保存路径,第三个参数为图片命名

有图有真相:
十分钟教你学会 Java+opencv视频人脸检测_第5张图片

五、总结

本人觉得还是讲的比较清晰的,如果你是第一次接触opencv可能比较吃力了,不过没关系,有些东西是很容易百度出来的,文章讲述opencv的视频人脸检测实现框架和基本流程,提供一个基本的实现思路,帮助理解这个实现过程的重要技术,我相信,一定对你有所帮助和启发。

最后,感谢您的阅读和欣赏,本人第一次些博客,请各位海涵,如有好的想法和建议,请留言给我!有其他不懂的也可以问问,我有空尽量给予解答,互相交流,共同进步,thank you!

你可能感兴趣的:(opencv,java,机器学习,人脸识别)