uniapp开发移动端人脸抓拍

本文介绍了如何在uniapp移动端使用HTML5摄像头功能,包括初始化摄像头、处理设备访问权限、捕捉视频流以及拍照截图的实现。特别关注了错误处理和兼容性问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

<!-- 父组件 -->
<!-- 调用摄像头必须使用https域名才能调同 -->
<div style="width: 0; height: 0; overflow: hidden">
  <videoCamera width="100px" height="100px" ref="cVideoCameraRef" />
</div>
<button @click="getImage">拍照</button>
methods:{
  getImage() {
    this.$refs.cVideoCameraRef.getImage().then((res) => {
      console.log(res);
    });
  },
 }

 <!-- 子组件 -->

<template>
  <div class="c-video-camera" :style="`width: ${width};height: ${height};`">
    <!-- Video -->
    <video ref="videoCameraRef" class="c-video_video" autoplay></video>
    <!-- Loading -->
    <div v-if="loading" class="c-video_mask">
      <div class="c-video_loading"></div>
    </div>
    <!-- Error -->
    <div v-if="error" class="c-video_mask">
      <div class="c-video_error">
        <!-- <img class="c-video-error--icon" src="./error.png" alt="error" /> -->
        <div class="c-video-error--msg">
          {{ errMsg }} <span @click="openCamera">重新加载</span>
        </div>
      </div>
    </div>
  </div>
</template>

<script>
const msgTypes = {
  devicesnotfounderror: "未检测到摄像头",
  "could not start video source": "无法访问到摄像头",
  "requested device not found": "未检测到摄像头",
  "permission denied": "浏览器禁止本页面使用摄像头,请开启使用摄像头权限",
  "getUserMedia is not implemented in this browser":
    "浏览器不支持访问用户媒体设备,请升级或更换浏览器",
};
// uniapp开发移动端人脸抓拍
export default {
  name: "VideoCamera",
  props: {
    width: {
      type: String,
      default: "100%",
    },
    height: {
      type: String,
      default: "100%",
    },
  },
  data() {
    return {
      videoCameraRef: null,
      loading: false,
      error: false,
      errMsg: "",
      deviceId: "",
      deviceName: "",
      stream: null,
    };
  },
  methods: {
    getErrorMessage(err) {
      const message = err.message || err.name || err || "";
      return msgTypes[message.toLowerCase()] || "未检测到摄像头";
    },
    // 初始化摄像头
    init() {
      if (!navigator.mediaDevices) {
        this.errMsg = this.getErrorMessage("requested device not found");
        return setTimeout(() => {
          this.error = true;
          this.$emit("error", this.errMsg);
        }, 500);
      }
      navigator.mediaDevices.addEventListener("devicechange", () => {
        this.openCamera();
      });
      this.openCamera();
    },
    openCamera() {
      this.error = false;
      this.loading = true;
      if (!navigator.mediaDevices) {
        this.errMsg = this.getErrorMessage("requested device not found");
        return setTimeout(() => {
          this.loading = false;
          this.error = true;
          this.$emit("error", this.errMsg);
        }, 500);
      }
      navigator.mediaDevices.enumerateDevices().then((devices) => {
        const videoDevices = devices.filter(
          (item) => item.kind == "videoinput"
        );
        if (!videoDevices || videoDevices.length == 0) {
          this.errMsg = this.getErrorMessage("requested device not found");
          this.loading = false;
          this.error = true;
          return this.$emit("error", this.errMsg);
        }
        this.deviceId = videoDevices[0].deviceId;
        this.deviceName = videoDevices[0].label;
        this.getStream();
      });
      this.loading = false;
    },
    closeCamera() {
      if (this.stream) {
        this.stream.getVideoTracks().forEach((track) => {
          track.stop();
        });
      }
    },
    getStream() {
      const constraints = {
        audio: false,
        video: {
          facingMode: "user",
        },
      };
      navigator.mediaDevices
        .getUserMedia(constraints)
        .then(function (stream) {
          let video = document.querySelector("video");
          video.srcObject = stream;
          video.play();
        })
        .catch(function (err) {
          console.error("Error getting video:", err);
        });
    },
    // 拍照 截屏
    getImage() {
      return new Promise((resolve, reject) => {
        if (this.loading || this.error) {
          reject();
        } else {
          const canvas = document.createElement("canvas");
          const w =
            this.$refs.videoCameraRef.$el.children[0].childNodes[0].offsetWidth;
          const h =
            this.$refs.videoCameraRef.$el.children[0].childNodes[0]
              .offsetHeight;
          canvas.width = w;
          canvas.height = h;
          const ctx = canvas.getContext("2d");
          ctx.drawImage(
            this.$refs.videoCameraRef.$el.children[0].childNodes[0],
            0,
            0,
            w,
            h
          );
          const image = canvas.toDataURL("image/jpeg", 0.5);
          // const image = canvas.toDataURL('image/jpeg', 0.5).replace('data:image/jpeg;base64,', '')
          resolve(image);
        }
      });
    },
  },
  mounted() {
    this.videoCameraRef = this.$refs.videoCameraRef;
    this.init();
  },
  beforeDestroy() {
    this.closeCamera();
  },
};
</script>
<style lang="scss" scope>
.c-video-camera {
  background-color: #000000;
  position: relative;
  .c-video_video {
    width: 100%;
    height: 100%;
    display: block;
  }
  .c-video_mask {
    position: absolute;
    left: 0;
    top: 0;
    right: 0;
    bottom: 0;
    display: flex;
    align-items: center;
    justify-content: center;
  }
  .c-video_loading {
    width: 30px;
    height: 30px;
    border: 2px solid #ffffff;
    border-top-color: transparent;
    border-radius: 100%;
    animation: circle infinite 0.75s linear;
  }
  .c-video_error {
    .c-video-error--icon {
      width: 32px;
      height: 32px;
      display: block;
      margin: 0 auto;
    }
    .c-video-error--msg {
      // margin-top: 15px;
      color: #ffffff;
      font-size: 14px;
      text-align: center;
      span {
        text-decoration: underline;
        cursor: pointer;
      }
    }
  }

  // 转转转动画
  @keyframes circle {
    0% {
      transform: rotate(0);
    }
    100% {
      transform: rotate(360deg);
    }
  }
}
</style>

### UniApp 开发 APP人脸打卡功能实现方案 #### 使用 Effet.js 和百度人脸识别插件集成人脸检测与验证 为了实现在 UniApp开发 APP 端的人脸打卡功能,可以采用 Effet.js 结合百度人脸识别插件的方式。Effet.js 提供了一套用于处理面部特征的基础工具集[^1],而百度人脸识别插件则提供了具体的应用场景支持,如属性识别等功能[^4]。 #### 创建人脸模型服务 对于服务器端部分,可以通过定义 `CheckinService` 接口来管理用户的人脸数据。此接口中的 `createFaceModel` 方法负责接收用户的 ID 和图像路径参数,并据此建立相应的人脸模板[^2]: ```java public interface CheckinService { ... public void createFaceModel(int userId, String path); } ``` #### 集成百度人脸识别插件 针对 Android 平台,可以直接引入官方提供的百度人脸识别插件 YL-FaceDetect 来完成实际的面部捕捉工作。该插件能够实时获取并分析摄像头前的人物信息,包括但不限于性别、年龄以及活体检测分数等重要指标。 需要注意的是,当前版本仅限于 Android 设备上运行;如果计划覆盖 iOS 用户,则可能需要额外寻找适配 XCode 的解决方案或等待厂商更新跨平台的支持能力[^3]。 #### 客户端逻辑设计 客户端应用程序应当具备如下几个核心模块: - **初始化环境配置**:加载必要的 SDK 资源文件; - **启动相机权限请求流程**:确保应用有权访问设备摄像装置; - **调用人脸采集界面**:引导用户按照提示操作直至成功捕获清晰正面照; - **上传照片至云端存储空间**:将拍摄所得影像发送给后台服务器进行下一步处理; - **反馈结果通知机制**:告知使用者最终匹配状态(例如签到是否有效)。 以下是简化版代码片段展示如何在页面内嵌入上述步骤之一——开启前置镜头预览画面: ```javascript // pages/face-check-in/index.vue <template> <view class="container"> <!-- 显示视频流 --> <video id="preview" autoplay></video> <!-- 控制按钮组 --> <button @click="startCapture">开始录制</button> <button @click="stopCapture">停止录制</button> <!-- 错误消息区域 --> <text v-if="errorMessage">{{ errorMessage }}</text> </view> </template> <script> export default { data() { return { stream: null, videoElement: null, errorMessage: '' }; }, mounted() { this.videoElement = document.getElementById('preview'); }, methods: { async startCapture() { try { const constraints = { audio: false, video: true }; this.stream = await navigator.mediaDevices.getUserMedia(constraints); this.videoElement.srcObject = this.stream; } catch (err) { console.error(err); this.errorMessage = '无法打开摄像头'; } }, stopCapture() { if (!this.stream) return; this.stream.getTracks().forEach(track => track.stop()); this.videoElement.srcObject = null; } } }; </script> ``` 这段 Vue 组件展示了基本的 HTML5 `<video>` 元素配合 JavaScript 获取媒体流的能力,作为后续更复杂交互逻辑的良好起点。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值