安装完opencv后在安装目录的build\java目录下有jar包,将其依赖进项目
<dependency>
<groupId>org.opencv</groupId>
<artifactId>opencv</artifactId>
<version>4.8.0</version>
<scope>system</scope>
<systemPath>${project.basedir}/src/main/resources/lib/opencv/linux/opencv-480.jar</systemPath>
</dependency>
import org.opencv.core.*;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;
import org.opencv.objdetect.CascadeClassifier;
import java.net.URL;
import java.util.Arrays;
public class OpenCvUtil {
static {
// 加载OpenCV本地库
String sys = OpenCvUtil.getOperatingSystem();
URL url = null;
if (sys.equals("Windows")) {
url = ClassLoader.getSystemResource("lib/opencv/windows/opencv_java480.dll");
System.load(url.getPath());
} else {
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
}
}
// 该方法不能使用相对路径,只能使用系统上的绝对路径
static CascadeClassifier faceDetector = OpenCvUtil.getOperatingSystem().equals("Windows") ?
new CascadeClassifier("D:\\openCv\\opencv\\sources\\data\\haarcascades\\haarcascade_frontalface_alt.xml")
: new CascadeClassifier("/app/haarcascade_frontalface_alt.xml");
public static void imageFaceDetection(String imgPath) {
// 读取测试图片
Mat image = Imgcodecs.imread(imgPath);
if (image.empty()) {
throw new RuntimeException("图片内存为空");
}
// 检测脸部
MatOfRect face = new MatOfRect();
// 检测图像中的人脸
faceDetector.detectMultiScale(image, face);
// 匹配Rect矩阵
Rect[] rects = face.toArray();
System.out.println("识别人脸个数: " + rects.length);
// 识别图片中的所以人脸并分别保存
int i = 1;
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);
// 进行图片裁剪
imageCut(imgPath, "D:\\user\\" + i + ".jpg", rect.x, rect.y, rect.width, rect.height);
i++;
}
// 图片中人脸画框保存到本地
Imgcodecs.imwrite("D:\\user\\test1.png", image);
}
/**
* 裁剪人脸
*
* @param readPath 读取文件路径
* @param outPath 写出文件路径
* @param x 坐标X
* @param y 坐标Y
* @param width 截图宽度
* @param height 截图长度
*/
public static void imageCut(String readPath, String outPath, int x, int y, int width, int height) {
// 原始图像
Mat image = Imgcodecs.imread(readPath);
// 截取的区域
Rect rect = new Rect(x, y, width, height);
// Mat sub = new Mat(image,rect);
Mat sub = image.submat(rect);
Mat mat = new Mat();
Size size = new Size(width, height);
// 人脸进行截图并保存
Imgproc.resize(sub, mat, size);
Imgcodecs.imwrite(outPath, mat);
}
/**
* 传入图片地址人脸识别比较
*
* @param image1
* @param image2
* @return
*/
public static double faceRecognitionComparison(String image1, String image2) {
try {
Mat mat1 = conv_Mat(image1);
Mat mat2 = conv_Mat(image2);
Mat mat3 = new Mat();
Mat mat4 = new Mat();
// 颜色范围
MatOfFloat ranges = new MatOfFloat(0f, 256f);
// 直方图大小, 越大匹配越精确 (越慢)
MatOfInt histSize = new MatOfInt(2000);
Imgproc.calcHist(Arrays.asList(mat1), new MatOfInt(0), new Mat(), mat3, histSize, ranges);
Imgproc.calcHist(Arrays.asList(mat2), new MatOfInt(0), new Mat(), mat4, histSize, ranges);
// 比较两个密集或两个稀疏直方图
return Imgproc.compareHist(mat3, mat4, Imgproc.CV_COMP_CORREL);
} catch (Exception e) {
return 0;
}
}
/**
* 传入图片字节流人脸识别比较
*
* @param image1
* @param image2
* @return
*/
public static double faceRecognitionComparison(byte[] image1, byte[] image2) {
try {
Mat mat1 = conv_Mat(image1);
Mat mat2 = conv_Mat(image2);
Mat mat3 = new Mat();
Mat mat4 = new Mat();
// 颜色范围
MatOfFloat ranges = new MatOfFloat(0f, 256f);
// 直方图大小, 越大匹配越精确 (越慢)
MatOfInt histSize = new MatOfInt(5000);
Imgproc.calcHist(Arrays.asList(mat1), new MatOfInt(0), new Mat(), mat3, histSize, ranges);
Imgproc.calcHist(Arrays.asList(mat2), new MatOfInt(0), new Mat(), mat4, histSize, ranges);
// 比较两个密集或两个稀疏直方图
return Imgproc.compareHist(mat3, mat4, Imgproc.CV_COMP_CORREL);
} catch (Exception e) {
return 0;
}
}
/**
* 传入图片地址灰度化人脸
*
* @param img
* @return
*/
public static Mat conv_Mat(String img) {
// 读取图像
Mat mat1 = Imgcodecs.imread(img);
Mat mat2 = new Mat();
// 灰度化:将图像从一种颜色空间转换为另一种颜色空间
Imgproc.cvtColor(mat1, mat2, Imgproc.COLOR_BGR2GRAY);
// 探测人脸:检测到的对象作为矩形列表返回
MatOfRect faceDetections = new MatOfRect();
faceDetector.detectMultiScale(mat1, faceDetections);
// rect中人脸图片的范围
for (Rect rect : faceDetections.toArray()) {
Mat face = new Mat(mat1, rect);
return face;
}
return null;
}
/**
* 传入图片字节流灰度化人脸
*
* @param img
* @return
*/
public static Mat conv_Mat(byte[] img) {
// 读取图像
Mat mat1 = byteStreamToMat(img);
Mat mat2 = new Mat();
// 灰度化:将图像从一种颜色空间转换为另一种颜色空间
Imgproc.cvtColor(mat1, mat2, Imgproc.COLOR_BGR2GRAY);
// 探测人脸:检测到的对象作为矩形列表返回
MatOfRect faceDetections = new MatOfRect();
faceDetector.detectMultiScale(mat1, faceDetections);
// rect中人脸图片的范围
for (Rect rect : faceDetections.toArray()) {
Mat face = new Mat(mat1, rect);
return face;
}
return null;
}
public static Mat byteStreamToMat(byte[] byteStream) {
// 将字节流转换为OpenCV的Mat对象
MatOfByte matOfByte = new MatOfByte(byteStream);
Mat image = Imgcodecs.imdecode(matOfByte, Imgcodecs.IMREAD_UNCHANGED);
matOfByte.release();
return image;
}
public static String getOperatingSystem() {
String os = System.getProperty("os.name").toLowerCase();
if (os.contains("win")) {
return "Windows";
} else if (os.contains("nix") || os.contains("nux") || os.contains("mac")) {
return "Linux";
} else {
return "Unknown";
}
}
}
ps:可直接调用faceRecognitionComparison方法进行人脸识别校验
使用docker搭建opencv的linux运行环境可以参考下面链接的Dockerfile
https://bigxiamu.blog.csdn.net/article/details/135251651