1. OpenCV的获取和安装
1.1 OpenCV简介
OpenCV是一个跨平台的计算机视觉的开源库,实现了图像处理和计算机视觉方面的很多通用算法,如果你是打算玩玩图像处理这一领域,那么OpenCV是你避免不了要接触到的东西,下面就Eclipse说一下怎么安装和配置OpenCV,少走不必要的弯路,节约时间。
1.2 OpenCV安装和配置
点击OpenCV到官网下载
下载解压后如图所示,它包括build和sources两个文件夹,当然下载完是不能直接用的,我们需要为Eclipse配置OpenCV的开发环境。
第一步:找到你下载解压后的OpenCV进入build—>Java--->可以看到一个jar包,我是4.20版本的。
第二步:配置User Libraries,点击windows--->preferences--->Java--->Build Path--->User Librarie如图进行操作
可以看到Native library location:(None)
点击它 找到OpenCV安装的java下的x64路径(不是外面的x64路径)
第三步:在项目中进行添加Build Path,右键项目名进行Build Path
到此完成OpenCV配置。
1.3 OpenCV测试
public class text {
static {
// 1 加载openCV类库
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
}
public static void main(String[] args) {
Mat m = Mat.eye(3,3, CvType.CV_8UC1);
System.out.println(m.dump());
}
}
至此Eclipse的OpenCV开发环境配置成功。接下来利用OpenCV实现图像处理功能。
2. 图像灰度化处理
public class text {
/**
* 灰度化人脸工具类,对图片进行预处理
*
* @param img
*/
public static void convMat(String img) {
System.out.println("灰度化方法启动。。。。。。");
Mat image0 = Imgcodecs.imread(img);
Mat image1 = new Mat();
// 灰度化
Imgproc.cvtColor(image0, image1, Imgproc.COLOR_BGR2GRAY);
HighGui.imshow("图像灰度化", image1);
HighGui.waitKey(0);
}
public static void main(String[] args) {
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
convMat("G:\\images\\2.jpg");
}
}
3 人脸裁剪
public class face_CutFace {
static {
//加载openCV类库
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
}
/**
* 裁剪人脸
* @param imagePath
* @param outImage
* @param posX
* @param posY
* @param width
* @param height
* @return
*/
public static void faceCut(Mat image,String outImage,int posX,int posY,int width,int height) {
//获取图像
System.out.println("图片截取开始。。。。。。。。。");
//截取的区域:坐标X,坐标Y,截取宽度、高度
Rect rect = new Rect(posX,posY,width,height);
Mat sub = new Mat(image,rect);
Mat mat = new Mat();
Size size = new Size(width,height);
//人脸截图并进行保存
Imgproc.resize(sub, mat, size);
Imgcodecs.imwrite(outImage, mat);
System.out.println(String.format("图片裁剪成功,裁剪后图片为: %s", outImage));
}
}
4 静态人脸检测
调用人脸裁剪工具类,对检测出的人脸进行裁剪,并保存到本地。
public class face_DetectStatic {
static CascadeClassifier faceDetector;
static {
// 1 加载openCV类库
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
faceDetector = new CascadeClassifier(
"F:\\intsall\\OpenCV\\opencv\\sources\\data\\haarcascades\\haarcascade_frontalface_alt.xml");
}
/**
* 静态人脸检测模型
* @param sysImage 原图片
* @param outImage 检测人脸画矩形框并输出
*/
public static void faceDetect(String sysImage,String outImage) throws Exception{
// 2 读取测试图片
Mat image=Imgcodecs.imread(sysImage);
if(image.empty()){
System.out.println("image 内容不存在!");
return;
}
// 3 特征匹配
MatOfRect face = new MatOfRect();
faceDetector.detectMultiScale(image, face);
// 4 匹配 Rect 矩阵 数组
Rect[] rects=face.toArray();
System.out.println("匹配到 "+rects.length+" 个人脸");
// 5 为每张识别到的人脸画矩形框
int i =1 ;
if(rects.length==0) {
System.out.println("未检测到人脸");
}
for (Rect rect : face.toArray()) {
Imgproc.rectangle(image, new Point(rect.x, rect.y), new Point(rect.x + rect.width, rect.y + rect.height),
new Scalar(0, 255, 0), 3);
//调用人脸裁剪faceCut()方法进行切割 切割后图片名为uuid前五位。如不需要裁剪可以注释掉
face_CutFace.faceCut(image, outImage+UUID.randomUUID().toString().replace("-", " ").substring(0,5)+".png", rect.x, rect.y, rect.width, rect.height);
i++;
}
// 6 展示图片
HighGui.imshow("人脸检测", image);
HighGui.waitKey(0);
}
public static void main(String[] args) throws Exception {
faceDetect("E:\\temp\\face_database\\training\\anger\\1111.tiff", "G:\\images\\");
}
}
5 调用摄像头实时人脸检测
5.1 实时人脸检测工具类
主要对实时人脸检测的通用代码部分进行封装,下面几个实时的检测都会用到这个工具类,直接调用就可。
public class face_GetVideoUtil {
static CascadeClassifier faceDetector;
static int i=0;
static {
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
faceDetector = new CascadeClassifier(
"F:\\intsall\\OpenCV\\opencv\\sources\\data\\haarcascades\\haarcascade_frontalface_alt.xml");
}
/**
*
* @param image 待处理Mat图片(视频中的某一帧)
* @return 处理后的图片
*/
public static Mat getFace(Mat image) {
// 特征匹配类
MatOfRect face = new MatOfRect();
// 特征匹配
faceDetector.detectMultiScale(image, face);
Rect[] rects=face.toArray();
System.out.println("匹配到 "+rects.length+" 个人脸");
if(rects != null && rects.length >= 1) {
// 4 在视频中识别到的人脸画一个矩形框
for (int i = 0; i < rects.length; i++) {
Imgproc.rectangle(image, new Point(rects[i].x, rects[i].y), new Point(rects[i].x + rects[i].width, rects[i].y + rects[i].height), new Scalar(0, 255, 0));
Imgproc.putText(image, "Human", new Point(rects[i].x, rects[i].y), Imgproc.FONT_HERSHEY_SCRIPT_SIMPLEX, 1.0, new Scalar(0, 255, 0), 1, Imgproc.LINE_AA, false);
}
i++;
if(i==3) {// 获取匹配成功第10次的照片
Imgcodecs.imwrite("G:\\images\\" + UUID.randomUUID().toString().replace("-", " ").substring(0,5)+".png", image);
}
}
return image;
}
}
5.2 实时人脸检测实现类
public class face_CaptureFace {
// 初始化人脸探测器
static CascadeClassifier faceDetector;
static int i=0;
static {
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
faceDetector = new CascadeClassifier(
"F:\\intsall\\OpenCV\\opencv\\sources\\data\\haarcascades\\haarcascade_frontalface_alt.xml");
}
/**
* 实时摄像头捕捉人脸
*/
public static void getVideoFromCamera() {
//1 如果要从摄像头获取视频 则要在 VideoCapture 的构造方法写 0
VideoCapture capture=new VideoCapture(0);
Mat video=new Mat();
int index=0;
if (capture.isOpened()) {
while(i<3) {// 匹配成功3次退出
capture.read(video);
HighGui.imshow("实时人脸检测", face_GetVideoUtil.getFace(video));
index=HighGui.waitKey(100);
if (index==27) {
capture.release();
break;
}
}
}else{
System.out.println("摄像头未开启");
}
try {
capture.release();
Thread.sleep(1000);
System.exit(0);
} catch (InterruptedException e) {
e.printStackTrace();
}
return;
}
public static void main(String[] args) {
getVideoFromCamera();
}
}
6 从视频流中检测人脸
public class face_GetVideoFace {
static CascadeClassifier faceDetector;
static {
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
faceDetector = new CascadeClassifier(
"F:\\intsall\\OpenCV\\opencv\\sources\\data\\haarcascades\\haarcascade_frontalface_alt.xml");
}
/***
* @return 从视频文件中解析出人脸帧
*/
public static void getVideoFromFile(String videoPath) {
VideoCapture capture = new VideoCapture();
capture.open(videoPath);// 1 读取视频文件的路径
if (!capture.isOpened()) {
System.out.println("读取视频文件失败!");
return;
}
Mat video = new Mat();
int index = 0;
while (capture.isOpened()) {
capture.read(video);// 2 视频文件的视频写入 Mat video 中,调用实时人脸检测工具类
HighGui.imshow("本地视频识别人脸", face_GetVideoUtil.getFace(video));// 3 显示图像
index = HighGui.waitKey(100);// 4 获取键盘输入
if (index == 27) {// 5 如果是 Esc 则退出
capture.release();
return;
}
}
}
public static void main(String[] args) {
getVideoFromFile("G:\\");
}
}
7 利用OpenCV进行视频采集
public class face_GetVideo {
static CascadeClassifier faceDetector;
static int i = 0;
static {
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
faceDetector = new CascadeClassifier(
"F:\\intsall\\OpenCV\\opencv\\sources\\data\\haarcascades\\haarcascade_frontalface_alt.xml");
}
/**
* 调用本地摄像头录制视频 ,并保存到本地 ,供face_GetVideoFace类调用
*/
public static void getVideo() {
// 1 如果要从摄像头获取视频 则要在 VideoCapture 的构造方法写 0
VideoCapture capture = new VideoCapture(0);
Mat video = new Mat();
int index = 0;
Size size = new Size(capture.get(Videoio.CAP_PROP_FRAME_WIDTH), capture.get(Videoio.CAP_PROP_FRAME_HEIGHT));
VideoWriter writer = new VideoWriter("G:/a.mp4", VideoWriter.fourcc('D', 'I', 'V', 'X'), 15.0, size, true);
while (capture.isOpened()) {
capture.read(video);// 2 将摄像头的视频写入 Mat video 中
writer.write(video);
HighGui.imshow("像头获取视频", video);// 3 显示图像
index = HighGui.waitKey(100);// 4 获取键盘输入
if (index == 27) {// 5 如果是 Esc 则退出
capture.release();
writer.release();
return;
}
}
}
}
8 人脸比较
这个主要是静态的人脸比较,对两个人脸图片进行匹配,比较相似度,利用OpenCV内部算法,进行识别,一般相似度大于0.72,就可以认为是同一个人。这里面调用了灰度化方法。
public class face_CompareFace {
// 初始化人脸探测器
static CascadeClassifier faceDetector;
static int i = 0;
static {
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
faceDetector = new CascadeClassifier(
"F:\\intsall\\OpenCV\\opencv\\sources\\data\\haarcascades\\haarcascade_frontalface_alt.xml");
}
/**
* 人脸比对
*
* @param img_1
* @param img_2
* @return
*/
public static double compare_image(String img_1, String img_2) {
// 先对图片进行灰度化 调用face_GrayImage.convMat()方法对图片进行灰度化
Mat mat_1 = face_GrayImageUtil.convMat(img_1);
Mat mat_2 = face_GrayImageUtil.convMat(img_2);
Mat hist_1 = new Mat();
Mat hist_2 = new Mat();
// 颜色范围
MatOfFloat ranges = new MatOfFloat(0f, 256f);
// 直方图大小, 越大匹配越精确 (越慢)
MatOfInt histSize = new MatOfInt(1000);
Imgproc.calcHist(Arrays.asList(mat_1), new MatOfInt(0), new Mat(), hist_1, histSize, ranges);
Imgproc.calcHist(Arrays.asList(mat_2), new MatOfInt(0), new Mat(), hist_2, histSize, ranges);
// CORREL 相关系数
double res = Imgproc.compareHist(hist_1, hist_2, Imgproc.CV_COMP_CORREL);
return res;
}
public static void main(String[] args) {
String basePicPath = "G:\\images\\";
double compareHist = compare_image(basePicPath + "83064.png", basePicPath + "e1e5a.png");
System.out.println(compareHist);
if (compareHist > 0.75) {
System.out.println("人脸匹配");
} else {
System.out.println("人脸不匹配");
}
}
}
关于OpenCV实现对人脸检测的功能已经基本上大致的实现。