我需要做一个功能,就是网站页面调用摄像头截图。现在由于要用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中直接获取MatMat 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) {//加载dllURL 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)));}//预测第二张图片的人脸IDIntBuffer 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加上调摄像头截图支持