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;
/**
* <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) {
image = this.ConvertImage(newimage);
return;
}
/*
* 将对象转换为BufferedImage,以在帧内显示它
*/
public BufferedImage ConvertImage(Mat matrix) {
// 列和缓冲区图像对象的对象大小
int cols = matrix.cols();
int rows = matrix.rows();
int elemSize = (int) matrix.elemSize();
byte[] data = new byte[cols * rows * elemSize];
int type;
matrix.get(0, 0, data);
// 在颜色空间中显示对象的通道数。
switch (matrix.channels()) {
// 单通道使用灰色矩阵
case 1:
type = BufferedImage.TYPE_BYTE_GRAY;
break;
// 如果有3个通道
case 3:
type = BufferedImage.TYPE_3BYTE_BGR;
/*
* 由于 opencv 将 rgb 颜色空间保留为 bgr, 因此我们将它转换为 rgb 空间, 在成像中实现整洁的图像
*/
byte b;
for (int i = 0; i < data.length; i = i + 3) {
b = data[i];
data[i] = data[i + 2];
data[i + 2] = b;
}
break;
default:
return null;
}
BufferedImage bufferedImage = new BufferedImage(cols, rows, type);
bufferedImage.getRaster().setDataElements(0, 0, cols, rows, data);
return bufferedImage;
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
BufferedImage temp = getimage();
if (temp != null) {
// 裁剪
updateImage = temp.getSubimage(450, 0, 400, 600);
// 绘制
g.drawImage(updateImage, 0, 0, 400, 600, this);
}
}
}
摄像头像素较差(百度的度目摄像头)
效果图(本人就不上镜了)
OK,搞定