当今天知道java只需要调用opencv就可以实现高精度的人脸检测时,激动地我不得不写个文章把它记录下来。
csdn有位大神已经写好了它的python版本,大家可以去看看。我这里只是用java将它实现一下,方便我们java开发者使用。
首先,我们在java项目中引入opencv4.5.4及以上版本是必须的,然后下载yunet.onnx文件,我是放在项目根目录下的,大家可以根据需要放在某个目录下。然后就是具体代码实现:
import org.opencv.core.*; import org.opencv.core.Point; import org.opencv.imgcodecs.Imgcodecs; import org.opencv.imgproc.Imgproc; import org.opencv.objdetect.FaceDetectorYN;
import javax.imageio.ImageIO; import java.awt.*; import java.awt.image.BufferedImage; import java.io.*; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.IntBuffer; import java.util.ArrayList; import java.util.List;
public Mat faceDetect(BufferedImage bufferedImage) throws Exception{ int backendId = 0; //0: default, 1: Halide, 2: Intel's Inference Engine, 3: OpenCV, 4: VKCOM, 5: CUDA int targetId = 0; //0: CPU, 1: OpenCL, 2: OpenCL FP16, 3: Myriad, 4: Vulkan, 5: FPGA, 6: CUDA, 7: CUDA FP16, 8: HDDL float scoreThreshold = 0.9f; float nmsThreshold = 0.3f; int topK = 5000; Mat srcImg = BufferedImageToMat(bufferedImage,"jpg"); Mat faces=new Mat(); FaceDetectorYN faceDetectorYN = FaceDetectorYN.create(System.getProperty("user.dir")+"/yunet.onnx","", new Size(320, 320),scoreThreshold, nmsThreshold, topK, backendId, targetId); faceDetectorYN.setInputSize(srcImg.size()); faceDetectorYN.detect(srcImg,faces); for (int i = 0; i < faces.height(); i++) { // 画人脸框 Imgproc.rectangle(srcImg, new Rect((int) (faces.get(i, 0)[0]), (int)(faces.get(i, 1)[0]), (int)(faces.get(i, 2)[0]), (int)(faces.get(i, 3)[0])), new Scalar(0, 255, 0), 2); // 画关键点 Imgproc.circle(srcImg, new Point(faces.get(i, 4)[0], faces.get(i, 5)[0]), 2,new Scalar(255, 0, 0), 2); Imgproc.circle(srcImg, new Point(faces.get(i, 6)[0], faces.get(i, 7)[0]), 2, new Scalar(0, 0, 255), 2); Imgproc.circle(srcImg, new Point(faces.get(i, 8)[0], faces.get(i, 9)[0]), 2, new Scalar(0, 255, 0), 2); Imgproc.circle(srcImg, new Point(faces.get(i, 10)[0], faces.get(i, 11)[0]), 2, new Scalar(255, 0, 255), 2); Imgproc.circle(srcImg, new Point(faces.get(i, 12)[0], faces.get(i, 13)[0]), 2, new Scalar(0, 255, 255), 2); Imgcodecs.imwrite("result.jpg",srcImg); } return faces; }
private Mat BufferedImageToMat(BufferedImage bufferedImage, String formatName) throws Exception{ ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); ImageIO.write(bufferedImage, formatName, byteArrayOutputStream); byteArrayOutputStream.flush(); Mat mat = Imgcodecs.imdecode(new MatOfByte(byteArrayOutputStream.toByteArray()), Imgcodecs.IMREAD_UNCHANGED); return mat; }