调用本地摄像头(多摄像头选择调用),原来如此简单

视频监控,人脸识别等场景,必不可少的要用到外接摄像头,但是如何调用,外接多个如何选择想要的那个却愁眉苦恼。不要急,以下内容希望帮助到遇到问题的所有人

后台获取摄像头,通过opencv

首先引入opencv所需的jar包

 <dependency>
    <groupId>org.bytedeco</groupId>
    <artifactId>javacv</artifactId>
    <version>1.4.3</version>
</dependency>
<dependency>
    <groupId>org.bytedeco</groupId>
    <artifactId>javacpp</artifactId>
    <version>1.4.3</version>
</dependency>
<!-- 选择合适自己系统的,以下适合windows -->
<dependency>
    <groupId>org.bytedeco.javacpp-presets</groupId>
    <artifactId>opencv</artifactId>
    <version>3.4.3-1.4.3</version>
    <classifier>windows-x86_64</classifier>
</dependency>
<dependency>
    <groupId>org.bytedeco.javacpp-presets</groupId>
    <artifactId>openblas</artifactId>
    <version>0.3.3-1.4.3</version>
    <classifier>windows-x86_64</classifier>
</dependency>

使用opencv,获取本机摄像头


import org.bytedeco.javacpp.opencv_core;
import org.bytedeco.javacpp.opencv_imgproc;
import org.bytedeco.javacv.CanvasFrame;
import org.bytedeco.javacv.Frame;
import org.bytedeco.javacv.FrameGrabber;
import org.bytedeco.javacv.OpenCVFrameConverter;
import org.bytedeco.javacv.OpenCVFrameGrabber;
import org.opencv.core.Core;

import javax.swing.*;
import java.awt.*;
import java.io.*;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import static com.arcsoft.face.toolkit.ImageFactory.getRGBData;
import static org.bytedeco.javacpp.opencv_core.*;

/**
 * @ Author     :
 * @ Date       :Created in 11:47 2020/5/21
 * @ Description:调用摄像头实现实时人脸识别
 */
public class VideoMain {

    public static void main(String[] args) throws Exception {

		//参数代表本地摄像头序号,获取方式见下图
        OpenCVFrameGrabber grabber= new OpenCVFrameGrabber(0);
//        grabber.setImageHeight(600);
//        grabber.setImageWidth(600);
        grabber.start();
        CanvasFrame canvasFrame = new CanvasFrame("摄像头");
        canvasFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        canvasFrame.setAlwaysOnTop(true);
//        canvasFrame.setCanvasSize(600,600);
        OpenCVFrameConverter.ToIplImage converter = new OpenCVFrameConverter.ToIplImage();
        
        for(;;){
        	opencv_core.IplImage iplImage = converter.convert(grabber.grab());
            Frame frame = converter.convert(iplImage);
            Mat img = converter.convertToMat(frame);
            Mat dst1 = new Mat(img.rows(), img.cols(), CV_8UC3);
            //由于未知的图像显示问题,需要左右翻转90度
            flip(img, dst1, 1);
            frame = converter.convert(dst1);
            canvasFrame.showImage(frame);

        }
    }
}

设备管理器查看摄像头设备,从0开始获取上面的序号,0是笔记本自带摄像头,1是外接的一个usb摄像头,由于是双目摄像头,所以显示两个
调用本地摄像头(多摄像头选择调用),原来如此简单_第1张图片

使用js获取摄像头,环境使用vue

选择方式在下面getCompetence 方法定义的constraints中,请耐心查看


<template>
  <div class="camera_outer">
    <div style="background-color: black">
      <video id="videoCamera"  :width="videoWidth" :height="videoHeight"  autoplay />
    </div>
    <div>
      <canvas style="display:none;" id="canvasCamera" :width="videoWidth" :height="videoHeight" />
    </div>
    <div v-if="imgSrc" class="img_bg_camera">
      <img :src="imgSrc" alt="" class="tx_img">
    </div>
    <a-button class="a-button" @click="getCompetence()" :disabled="!this.videoState">
      <a-icon type="eye" />
      打开摄像头
    </a-button><br />
    <a-button class="a-button" @click="stopNavigator()" :disabled="this.videoState">
      <a-icon type="eye-invisible" />
      关闭摄像头
    </a-button><br />
    <a-button class="a-button" @click="setImage()" :disabled="this.videoState">
      <a-icon type="camera" />
      拍照识别
    </a-button><br />
  </div>
</template>
<script>
export default {
  name: 'camera',
  data () {
    return {
      videoWidth: 500,
      videoHeight: 300,
      imgSrc: '',
      thisCancas: null,
      thisContext: null,
      thisVideo: null,
      videoState: true
    }
  },
  methods: {
    // 调用权限(打开摄像头功能)
    getCompetence () {
      this.videoState = false
      var _this = this
      this.thisCancas = document.getElementById('canvasCamera')
      this.thisContext = this.thisCancas.getContext('2d')
      this.thisVideo = document.getElementById('videoCamera')
      // 旧版本浏览器可能根本不支持mediaDevices,我们首先设置一个空对象
      if (navigator.mediaDevices === undefined) {
        navigator.mediaDevices = {}
      }
      // 一些浏览器实现了部分mediaDevices,我们不能只分配一个对象
      // 使用getUserMedia,因为它会覆盖现有的属性。
      // 这里,如果缺少getUserMedia属性,就添加它。
      if (navigator.mediaDevices.getUserMedia === undefined) {
        navigator.mediaDevices.getUserMedia = function (constraints) {
          // 首先获取现存的getUserMedia(如果存在)
          var getUserMedia = navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.getUserMedia
          // 有些浏览器不支持,会返回错误信息
          // 保持接口一致
          if (!getUserMedia) {
            return Promise.reject(new Error('getUserMedia is not implemented in this browser'))
          }
          // 否则,使用Promise将调用包装到旧的navigator.getUserMedia
          return new Promise(function (resolve, reject) {
            getUserMedia.call(navigator, constraints, resolve, reject)
          })
        }
      }
      //使用此方式获取本地音频视频输入输出设备,找到要使用的设备id,方式见下图
      var enumeratorPromise = navigator.mediaDevices.enumerateDevices()
      console.log(enumeratorPromise)
      //把上面获取到的设备deviceId填入下面video的deviceId中,就可以选择要调用的摄像头了
      var constraints = { audio: false, video: { deviceId: 'becf7e45fe56e42bcb4ec3f78b1b6b0fcffd6c6ccd890d30fffc2430a92c99bb', width: this.videoWidth, height: this.videoHeight } }
      navigator.mediaDevices.getUserMedia(constraints).then(function (stream) {
        // 旧的浏览器可能没有srcObject
        if ('srcObject' in _this.thisVideo) {
          _this.thisVideo.srcObject = stream
        } else {
          // 避免在新的浏览器中使用它,因为它正在被弃用。
          _this.thisVideo.src = window.URL.createObjectURL(stream)
        }
        _this.thisVideo.onloadedmetadata = function (e) {
          _this.thisVideo.play()
        }
      }).catch(err => {
        console.log(err)
      })
    },
    //  绘制图片(拍照功能)
    setImage () {
      var _this = this
      // 点击,canvas画图
      _this.thisContext.drawImage(_this.thisVideo, 0, 0, _this.videoWidth, _this.videoHeight)
      // 获取图片base64链接
      var image = this.thisCancas.toDataURL('image/png')
      _this.imgSrc = image
      this.$emit('setImgSrc', this.imgSrc)
    },
    clearImgSrc () {
      this.imgSrc = ''
    },
    // base64转文件
    dataURLtoFile (dataurl, filename) {
      var arr = dataurl.split(',')
      var mime = arr[0].match(/:(.*?);/)[1]
      var bstr = atob(arr[1])
      var n = bstr.length
      var u8arr = new Uint8Array(n)
      while (n--) {
        u8arr[n] = bstr.charCodeAt(n)
      }
      return new File([u8arr], filename, { type: mime })
    },
    // 关闭摄像头
    stopNavigator () {
      this.videoState = true
      this.thisVideo.srcObject.getTracks()[0].stop()
    }
  }
}

</script>
<style scoped>
  .camera_outer {
    position: relative;
    overflow: hidden;
    /*background: url("../../assets/img/user_0608_04.png") no-repeat center;*/
    background-size: 100%
  }
  /*#videoCamera,#canvasCamera,.tx_img{*/
    /*-moz-transform:scaleX(-1);*/
    /*-webkit-transform:scaleX(-1);*/
    /*-o-transform:scaleX(-1);*/
    /*transform:scaleX(-1);*/
  /*}*/
  .img_bg_camera{
    position: absolute;
    bottom: 0;
    left: 0;
    right: 0;
    top: 0;
  }
  .a-button{
    margin-top: 10px;
    margin-left: 50px;
  }
</style>

label就是设备管理器中显示的设备名称
调用本地摄像头(多摄像头选择调用),原来如此简单_第2张图片

你可能感兴趣的:(java)