记一次Java调用本地/百度度目 摄像头(基于OpenCV)
OpenCV官网下载地址(下载安装后,在安装目录可以找到动态链接库和OpenCv.jar)
安装完成后,这是我的安装目录
maven 依赖(这个是安装完成后我把jar放到maven本地仓库中,然后在maven中就可以直接引用了)
<!-- opencv依赖 --> <dependency> <groupId>org.opencv</groupId> <artifactId>opencv</artifactId> <version>440</version> </dependency>
1.配置OpenCV环境
新建本地依赖
自己定义依赖库的名称
选择动态链接库dll文件的目录
选择OpenCV的安装目录
这个是根据你的JDK来选择,如果你的JDK是64位的就选择x64
2.摄像头获取类
package com.crow.safeBoxHardware; import java.awt.FlowLayout; import java.awt.event.WindowEvent; import java.awt.event.WindowListener; import java.io.File; import java.io.IOException; import java.io.InputStream; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.WindowConstants; import org.opencv.core.Core; import org.opencv.core.Mat; import org.opencv.core.MatOfRect; import org.opencv.core.Rect; import org.opencv.core.Size; import org.opencv.imgcodecs.Imgcodecs; import org.opencv.imgproc.Imgproc; import org.opencv.objdetect.CascadeClassifier; import org.opencv.videoio.VideoCapture; import org.opencv.videoio.Videoio; import lombok.extern.log4j.Log4j2; @Log4j2 public class Test2 { // 从配置文件lbpcascade_frontalface.xml中创建一个人脸识别器,该文件位于opencv安装目录中 private CascadeClassifier faceDetector; private JFrame cameraFrame; public CamarePanel panelCamera; // 是否打开摄像头 private boolean open = false; // 相机 public VideoCapture capture; // 人脸图像 public Mat faceMat; // 摄像头读取的帧 public Mat capImg; public Test2() { // 初始化人脸检测器 // faceDetector = new CascadeClassifier( // "C:\\worksplace\\safeBoxHardware\\src\\main\\resources\\native\\face\\xml\\haarcascade_frontalface_alt.xml"); capture = new VideoCapture(); } /** * 打开摄像头 * * @param x * @param y */ public void open(int x, int y) { capImg = new Mat(); faceMat = new Mat(); cameraFrame = new JFrame("camare"); panelCamera = new CamarePanel(); // 打开相机 capture.open(0); boolean grab = capture.grab(); if (!grab) { throw new BizException(BizErrorCode.CAMARE_OPEN_ERROE); } // 打开摄像头 open = true; capture.set(Videoio.CAP_PROP_FRAME_WIDTH, 1280); capture.set(Videoio.CAP_PROP_FRAME_HEIGHT, 720); capture.set(Videoio.CAP_PROP_FPS, 30); // 添加到Frame cameraFrame.setContentPane(panelCamera); // 设置去掉边框 cameraFrame.setUndecorated(true); // 是否显示窗口 cameraFrame.setVisible(true); // 设置在最顶层 cameraFrame.setAlwaysOnTop(true); // 设置关闭 cameraFrame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); // 窗口关闭事件 cameraFrame.addWindowListener(new WindowListener() { @Override public void windowOpened(WindowEvent e) { } @Override public void windowIconified(WindowEvent e) { } @Override public void windowDeiconified(WindowEvent e) { } @Override public void windowDeactivated(WindowEvent e) { } @Override public void windowClosing(WindowEvent e) { close(); } @Override public void windowClosed(WindowEvent e) { } @Override public void windowActivated(WindowEvent e) { } }); // 设置位置 if (x > 0 && y > 0) { cameraFrame.setBounds(x, y, 400, 600); } else { // 设置大小 cameraFrame.setSize(400, 600); // 居中显示 cameraFrame.setLocationRelativeTo(null); } while (open) { capture.read(capImg); if (!capImg.empty()) { // 转换成BufferImage并绘制到Panel panelCamera.setImageWithMat(capImg); // 重新绘制 cameraFrame.repaint(); //检测人脸并保存 //detectFace(capImg, "C:\\Users\\Crow\\Desktop\\"+System.currentTimeMillis()+".png"); } } log.info("相机已关闭......"); } /** * 关闭窗口和摄像头释放资源 */ public void close() { // 关闭循环 open = false; if (cameraFrame != null) { // 关闭窗口 cameraFrame.dispose(); cameraFrame = null; } if (panelCamera != null) { // 清空 panelCamera = null; } if (capture != null && capture.isOpened()) { // 关闭视频文件或捕获设备,并释放资源 capture.release(); } log.warn("关闭相机..........................."); } /** * 检测人脸,并保存 * * @param videoMat * @param savePath * @return */ public Mat detectFace(Mat videoMat, String savePath) { File file = new File(savePath); // 验证父目录是否存在,不存在则新建 if (!file.getParentFile().exists()) { file.getParentFile().mkdirs(); } // 创建用来装检测出来的人脸的容器 MatOfRect faces = new MatOfRect(); // 检测人脸,videoMat为要检测的图片,faces用来存放检测结果 faceDetector.detectMultiScale(videoMat, faces); Rect[] facesArray = faces.toArray(); if (facesArray.length > 0) { for (int i = 0; i < facesArray.length; i++) { Rect rect = facesArray[i]; // 只获取人脸行和人脸列 Mat faceImage = videoMat.rowRange(rect.y, rect.y + rect.height).colRange(rect.x, rect.x + rect.width); // 设置大小 Size size = new Size(400, 600); // 调整图像 Imgproc.resize(faceImage, faceMat, size); // 保存 Imgcodecs.imwrite(savePath, faceMat); } } return faceMat; } public boolean isOpen() { return open; } public void setOpen(boolean open) { this.open = open; } public CamarePanel getPanelCamera() { return panelCamera; } public Mat getFaceMat() { return faceMat; } public static void main(String[] args) { //加载opencv动态链接库 System.loadLibrary(Core.NATIVE_LIBRARY_NAME); //打开摄像头,并设置位置 new Test2().open(298, 81); } }
3.图像显示Panel容器
package com.crow.safeBoxHardware.components.hardware.camare; import java.awt.Graphics; import java.awt.GraphicsConfiguration; import java.awt.GraphicsDevice; import java.awt.GraphicsEnvironment; import java.awt.HeadlessException; import java.awt.Image; import java.awt.Transparency; import java.awt.image.BufferedImage; import javax.swing.ImageIcon; import javax.swing.JPanel; import org.opencv.core.Mat;
import org.opencv.highgui.HighGui; /** * <p> * 用于在面板上显示和拍摄 * </p> * * @author Crow * @version 0.0.1 * @since 2020-9-158:54:36 */ public class CamarePanel extends JPanel { private static final long serialVersionUID = 1L; //摄像头获取的原始图像 private BufferedImage image; //裁剪修正后的图像 private BufferedImage updateImage; public CamarePanel() { super(); } private BufferedImage getimage() { return image; } /** * 裁剪修正后的图像 * @return */ public BufferedImage getUpdateImage() { return updateImage; } public void setUpdateImage(BufferedImage updateImage) { this.updateImage = updateImage; } public void setImage(BufferedImage newimage) { image = newimage; return; } public void setImageWithMat(Mat newimage) {
// 将Mat转换成BufferedImage
image = (BufferedImage) HighGui.toBufferedImage(newimage);
} @Override protected void paintComponent(Graphics g) { super.paintComponent(g);
if (image!= null) {
// 裁剪
updateImage = image.getSubimage(450, 0, 400, 600);
// 绘制
g.drawImage(updateImage, 0, 0, 400, 600, this);
} } }
摄像头像素较差(百度的度目摄像头)
效果图(本人就不上镜了)
OK,搞定