我需要做一个功能,就是网站页面调用摄像头截图。现在由于要用java,就得研究用java怎么调用摄像头。顺带玩了一下人脸比对,资料有点少。
效果
采用javacv实现,先加Maven引用,后面把下载的包再独立引用不用Maven了
实现代码
package javacv;
import java.awt.image.BufferedImage;
import java.io.File;
import java.net.URL;
import java.nio.IntBuffer;
import java.util.ArrayList;
import java.util.List;
import org.bytedeco.javacv.*;
import org.bytedeco.javacpp.*;
import org.bytedeco.javacpp.indexer.*;
import org.bytedeco.opencv.opencv_core.*;
import org.bytedeco.opencv.opencv_face.LBPHFaceRecognizer;
import org.bytedeco.opencv.opencv_imgproc.*;
import org.bytedeco.opencv.opencv_calib3d.*;
import org.bytedeco.opencv.opencv_objdetect.*;
import org.opencv.core.Core;
import org.opencv.core.MatOfInt;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;
import javax.imageio.ImageIO;
import javax.swing.*;
import static org.bytedeco.opencv.global.opencv_core.*;
import static org.bytedeco.opencv.global.opencv_imgproc.*;
import static org.bytedeco.opencv.global.opencv_calib3d.*;
import static org.bytedeco.opencv.global.opencv_objdetect.*;
/**
* 用来试验调用摄像头
*/
public class Demo {
//使用LBPHFaceRecognizer进行人脸识别
static LBPHFaceRecognizer recognizer =null;
/**
* 测试摄像头操作
*
* @param args
* @throws Exception
*/
public static void main(String[] args) throws Exception {
//用摄像头抓图
//ShowCamera();
//人脸识别
URL url = Demo.class.getResource("/default.xml");
faceDetection(url.getFile().substring(1), 1920, 1080);
}
/**
* 调用摄像头抓图
*
* @throws Exception
*/
public static void ShowCamera() throws Exception {
//新建opencv抓取器,一般的电脑和移动端设备中摄像头默认序号是0,不排除其他情况
FrameGrabber grabber1 = FrameGrabber.createDefault(0);
//设置分辨率
grabber1.setImageWidth(1920);
grabber1.setImageHeight(1080);
//设置帧率
grabber1.setFrameRate(80);
//开始获取摄像头数据
grabber1.start();
//新建一个预览窗口
CanvasFrame canvas = new CanvasFrame("摄像头预览");
canvas.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//用死循环监控摄像头,窗口是否关闭
while (canvas.isDisplayable()) {
Frame frame = grabber1.grab();
/*获取摄像头图像并在窗口中显示,这里Frame frame=grabber.grab()得到是解码后的视频图像*/
canvas.showImage(grabber1.grab());
//可以保存图片
/*
Java2DFrameConverter converter = new Java2DFrameConverter();
BufferedImage image = converter.convert(frame);
//设置文件名
String fileName = "capture.jpg";
// 保存图片到文件
ImageIO.write(image, "jpg", new File(fileName));
*/
}
//停止抓取
grabber1.close();
}
/**
* JavaCV人脸检测
*
* @param cascadeClassifierXml 基于Haar特征的cascade正面人脸分类器
* @param width 图像宽度
* @param height 图像高度
* @author eguid
*/
public static void faceDetection(String cascadeClassifierXml, Integer width, Integer height) throws Exception, InterruptedException {
//开启摄像头,获取图像(得到的图像为frame类型,需要转换为mat类型进行检测和识别)
OpenCVFrameGrabber grabber = new OpenCVFrameGrabber(0);
if (width != null && width > 1 && height != null && height > 1) {
grabber.setImageWidth(width);
grabber.setImageHeight(height);
}
grabber.start();
if (width == null || height == null) {
height = grabber.getImageHeight();
width = grabber.getImageWidth();
}
//新建一个预览窗口
CanvasFrame canvas = new CanvasFrame("人脸检测");
canvas.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
canvas.setVisible(true);
canvas.setFocusable(true);
//窗口置顶
canvas.setAlwaysOnTop(true);
Frame frame = null;
//读取opencv人脸检测器
CascadeClassifier cascade = new CascadeClassifier(cascadeClassifierXml);
for (; canvas.isVisible() && (frame = grabber.grab()) != null; ) {
//从frame中直接获取Mat
Mat img = (Mat) frame.opaque;
//存放灰度图
Mat grayImg = new Mat();
//摄像头色彩模式设置成ImageMode.Gray下不需要再做灰度
//摄像头获取的是彩色图像,所以先灰度化下
cvtColor(img, grayImg, COLOR_BGRA2GRAY);
//如果要获取摄像头灰度图,可以直接对FrameGrabber进行设置grabber.setImageMode(ImageMode.GRAY);,grabber.grab()获取的都是灰度图
//均衡化直方图
equalizeHist(grayImg, grayImg);
// 检测到的人脸
RectVector faces = new RectVector();
cascade.detectMultiScale(grayImg, faces);
//遍历人脸
for (int i = 0; i < faces.size(); i++) {
Rect face_i = faces.get(i);
//绘制人脸矩形区域,scalar色彩顺序:BGR(蓝绿红)
rectangle(img, face_i, new Scalar(0, 255, 0, 1));
int pos_x = Math.max(face_i.tl().x() - 10, 0);
int pos_y = Math.max(face_i.tl().y() - 10, 0);
//在人脸矩形上方绘制提示文字
putText(img, "*", new Point(pos_x, pos_y), FONT_HERSHEY_COMPLEX, 1.0, new Scalar(0, 0, 255, 2.0));
}
//比较人脸相似度
FaceCompare(grayImg);
//获取摄像头图像并放到窗口上显示,frame是一帧视频图像
canvas.showImage(frame);
//40毫秒刷新一次图像
Thread.sleep(40);
}
cascade.close();
canvas.dispose();
//停止抓取
grabber.close();
}
/**
* 比较人脸相似度
*
* @param faceImage2
*/
private static void FaceCompare(Mat faceImage2) {
if(recognizer==null) {
//加载dll
URL urldll = Demo.class.getResource("/opencv_java440.dll");
System.load(urldll.getFile().substring(1));
OpenCVFrameConverter.ToMat converter1 = new OpenCVFrameConverter.ToMat();
//OpenCVFrameConverter.ToOrgOpenCvCoreMat converter2 = new OpenCVFrameConverter.ToOrgOpenCvCoreMat();
//加载作者头像
URL urlzlz = Demo.class.getResource("/zhanglianzhu.png");
org.opencv.core.Mat faceImage1Old = Imgcodecs.imread(urlzlz.getFile().substring(1));
//读取两张人脸图片
Mat faceImage1 = converter1.convert(converter1.convert(faceImage1Old));
//转换图片为灰度图,因为大部分人脸识别算法都在灰度图上运行
org.opencv.core.Mat grayFace1 = new org.opencv.core.Mat();
Imgproc.cvtColor(faceImage1Old, grayFace1, Imgproc.COLOR_BGR2GRAY);
//使用LBPHFaceRecognizer进行人脸识别
recognizer = LBPHFaceRecognizer.create();
//设置阈值
recognizer.setThreshold(100);
//图片向量
MatVector vec = new MatVector();
vec.put(converter1.convert(converter1.convert(grayFace1)));
int[] labels = {0};
MatOfInt labelVector = new MatOfInt(labels);
//训练识别器,这里我们使用同一张脸的图片进行训练和预测,实际中应使用不同的人脸图片进行训练
recognizer.train(vec, converter1.convert(converter1.convert(labelVector)));
}
//预测第二张图片的人脸ID
IntBuffer label = IntBuffer.allocate(1);
int[] label1 = new int[1];
double[] confidence = new double[1];
recognizer.predict(faceImage2, label1, confidence);
System.out.println("置信度:" + confidence[0]);
//输出结果
if (confidence[0] < 25) {
System.out.println("检测到张联珠");
} else {
System.out.println("摄像头前面不是张联珠");
}
}
}
这就是java调摄像头的试验,后面给JRTClient加上调摄像头截图支持