忽然心血来潮,想写写东西,这是我的首个博客,不知道写些什么内容好。
那好吧,拿个以前做的一个项目讲讲。
项目的目的是视频人脸的检测和人脸对比,使用的当然是opencv(不收费,开源啊),本章要介绍的是视频的读取,并将视频转换为图片流进行人脸识别。废话不多说,直接进入正题(为了更好理解,我拆开来讲,哈哈哈)。
本次演示demo使用eclipse开发工具,opencv计算机视觉库,当然也要有jdk(都懂的,不懂百度以下jdk的安装和使用,环境变量的配置等)。opencv则需要下载的开源库,下载官网地址为: opencv官网
直接上图:
大家看到了,我下载的是Windows版本的(有兴趣也可以试试其他平台),最好不要下载最新版本(为什么呢,偷偷告诉你,别告诉别人,最新有可能有较多的bug,毕竟开源你懂的,如果不适用新版本的功能就不建议下最新版本,学习使用低版本就够了,踩坑出来的经验哈哈哈)。官网是比较慢的,请耐心等待,等待不了的就去其他国内的网站下,找其他人要资源,网上百度找下载地址都可以。
项目以一个个功能模块开始讲,不细说具体项目实现(看完我的文章,你可以试试设计一个自己的系统,这样更有成就感)。
新建项目
File->New ->Project 如图:
此处有一张图(发挥想象力)
开个玩笑啊,按提示走就对了,项目新建完成后,接着下面操作。
点击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");
}
我们的测试视频如下,有需要的同学可以下载(直接网页爬虫哈哈哈,不会的再说)
赵丽颖代言水密码广告
视频现在才找的不知道和以前的是不是一样的(我用的是下载好的,不记得下载位置了嘻嘻嘻。
我们到图片保存的位置看看,嗯还不错。
人脸检测的意思是在一张图片中检测出多少个人脸,每个人脸的位置等信息。
人脸裁剪的意思是提取出检测到的人脸,并保存人脸。
也许有同学会直接跳下来直接看人脸检测,确实该章节比较有意思。先来讲讲人脸检测:
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()函数参数。第一个参数为图片存放的文件夹,第二个参数为裁剪后图片保存路径,第三个参数为图片命名
本人觉得还是讲的比较清晰的,如果你是第一次接触opencv可能比较吃力了,不过没关系,有些东西是很容易百度出来的,文章讲述opencv的视频人脸检测实现框架和基本流程,提供一个基本的实现思路,帮助理解这个实现过程的重要技术,我相信,一定对你有所帮助和启发。
最后,感谢您的阅读和欣赏,本人第一次些博客,请各位海涵,如有好的想法和建议,请留言给我!有其他不懂的也可以问问,我有空尽量给予解答,互相交流,共同进步,thank you!