后面页面完整代码哦~~~
首先说一下,我这里用到了axios element-ui的loading

先看一下我的效果图吧

 

vue3调用jquery_人工智能

 说明:我这里是调用摄像头识别人脸,根据返回的信息,再加以描述,右边的小图片是,根据返回的人脸位置,宽度大小截取出来的

 首先我们得申请一个百度ai人脸识别的接口,并且获取key 和secret 这样才能后续使用。

第一步:先写html
<template>
  <div class="main">
    <div class="cam">
      <div class="video-box">
        <div class="videos">
          <video
            id="video"
            style="width: 100%;height: 100%; object-fit: fill;"
            preload
            autoplay
            loop
            muted
          ></video>
        </div>
        <div class="button-box" @click="submit()">
          <img src="../assets/cam.png" />
        </div>
      </div>
      <div class="title-box">
        识别分析
      </div>
      <div class="right-box">
        <div
          ref="mainscroll"
          class="face-box"
          v-loading="loading"
          element-loading-text="拼命加载中"
          element-loading-spinner="el-icon-loading"
          element-loading-background="transparent"
        >
          <div
            class="details"
            v-for="(item, index) in threeImageArray"
            :key="index"
          >
            <div class="image-box">
              <img :src="item.image" />
            </div>
            <div class="list-box">
              <div class="sex-one">年龄:{{ item.age }}</div>              
            </div>
          </div>
        </div>
      </div>
      <div class="canva-box">
        <canvas ref="canvas" id="canvas" width="1000" height="700"></canvas>
      </div>
    </div>
  </div>
</template>
说明:因为需求时只显示摄像头,所以,我把截图的图片canvas部分放在了摄像头的底层,大家根据需求来写css样式吧
 第二步:写css
<style scoped>

.main {
  width: 100%;
  height: 100vh;
  display: flex;

  align-items: center;
  justify-content: center;
}

.cam {
  width: 50%;
  height: 90%;
  display: flex;
  flex-direction: column;
  align-items: center;
  background-color: #fff;
  border-radius: 20px;
}
.canva-box {
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  position: absolute;
  top: 0;
  z-index: -99;
}

.button-box {
  position: absolute;
  top: 35%;
  border: 2px solid #fff;
  padding: calc(100vw * 20 / 1920);
  border-radius: 50%;
}
.button-box img {
  width: calc(100vw * 40 / 1920);
  height: calc(100vw * 40 / 1920);
}
.title-box {
  height: 5%;
  font-size: calc(100vw * 40 / 1920);
  font-weight: bold;
  width: 40%;
}
.right-box {
  width: 100%;
  height: 30%;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: space-evenly;
}
.video-box {
  width: 100%;
  height: 65%;
  display: flex;
  justify-content: center;
}
.videos {
  width: 100%;
  height: 100%;
}
.face-box {
  width: 100%;
  height: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  overflow: auto;
}
.details {
  display: flex;

  width: 100%;
  height: 90%;
  margin-top: 4px;
}
.image-box {
  width: 30%;
  height: 100%;
  display: flex;
  justify-content: center;
}

.image-box img {
  width: calc(100vw * 150 / 1920);
  height: calc(100vw * 150 / 1920);
}
.list-box {
  width: 60%;
  height: calc(100vw * 300 / 1920);
  display: flex;
  flex-direction: column;
  text-indent: calc(100vw * 16 / 1920);
  font-size: calc(100vw * 18 / 1920);
  padding-bottom: 20px;
}
</style>

 第三步:下载axios   npm i axios
 第四步:下载element-ui 
                npm i element-ui
                //引入 使用
                import ElementUI from "element-ui";
                import "element-ui/lib/theme-chalk/index.css";
                // 引入echarts
                import * as echarts from "echarts";
                Vue.prototype.$echarts = echarts;
第五步:js部分
首先调用摄像头(这里我也是根据网上找的,但是忘记哪个文章了)
//可以是点击方法,可以放在mounted()中,看自己的需求
getCompetence() {
      var _this = this;
      this.thisCancas = document.getElementById("canvas");
      this.thisContext = this.thisCancas.getContext("2d");
      this.thisVideo = document.getElementById("video");
      // 旧版本浏览器可能根本不支持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);
          });
        };
      }
      var constraints = {
        audio: false,
        video: {
          width: this.videoWidth,
          height: this.videoHeight,
          transform: "scaleX(-1)"
        }
      };
      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);
        });
    },
 记得销毁调用摄像头哦!
// 关闭摄像头  在vue生命周期的销毁页面中写
    this.trackerTask.closeCamera();

 接下来先把调用百度ai 部分写出来
async detectFace(imageData) {
        //access_token需要通过申请的key 和secret来获取,登录百度ai文档中就有教程
      this.loading = true;
      try {
        const response = await axios.post(
          "https://aip.baidubce.com/rest/2.0/face/v3/detect?access_token=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
          {
            image: imageData,
            image_type: "BASE64",
            face_field: "age,gender,emotion,glasses,mask,expression",
            max_face_num: 10
          }
        );

        // 处理接口返回的结果

        if (response.data.error_code == 0) {
            //这里是接口返回的打印
          console.log("调用成功显示结果", response);
          this.faceInfomation = response.data.result;
          this.faceArray = response.data.result.face_list;
            //这里我用一个数组接收返回的人脸信息
          this.faceArray.forEach((item, i) => {
            console.log("item", item);
                //这里是人脸的位置宽高信息
            const left = parseInt(item.location.left);
            const top = parseInt(item.location.top);
            const width = parseInt(item.location.width);
            const height = parseInt(item.location.height);
            const faceCanvas = document.createElement("canvas");
            
            faceCanvas.width = width;
            faceCanvas.height = height;
            //将截取的人脸再重新铺到canvas画布上,好展示出来
            const faceCtx = faceCanvas.getContext("2d");
            faceCtx.drawImage(
              this.canvas,
              left,
              top,
              width,
              height,
              0,
              0,
              width,
              height
            );

            this.faceImg = faceCanvas.toDataURL("image/png");
            //将截取的头像放在新的数组中
            this.newImageArray.push(this.faceImg);
          });
            //因为截取的人脸头像和人脸文字描述不是一个数组,所以将两个数组合并一个数组了,这样在遍历循环列表的时候,更好的画css样式 
          this.threeImageArray = this.faceArray.map((item, index) => {
            return { ...item, image: this.newImageArray[index] };
          });
        }
      } catch (error) {
        console.error(error);
      } finally {
        this.loading = false;
      }
    },
如果有不清晰的地方可以留言评论,我会会的,虽然不知道对不对哈哈
 摄像头获取的图片放在canvas是上后,转成接口可用的类型
submit() {
      console.log("点击了这个");
       //每次点击的时候都清空一下上一次的内容
      this.newImageArray = [];
      this.faceArray = [];
        //loading加载
      this.fullscreenLoading = true;
      setTimeout(() => {
        this.fullscreenLoading = false;
      }, 2000);
      
      let that = this;
      let canvas = document.getElementById("canvas");
      let context = canvas.getContext("2d");
      let video = document.getElementById("video");
        //将摄像头拍下的照片放在canvas画布上
      context.drawImage(video, 0, 0, 1000, 700);
        //将图片转换成 接口需要的类型
      canvas.toBlob(blob => {
        var reader = new FileReader();
        reader.onloadend = () => {
          this.imageData = reader.result;

          this.newimage = this.imageData.replace(
            /^data:image\/\w+;base64,/,
            ""
          );
            //截取一下图片
          this.headerimg = this.imageData.slice(5, 15);
          this.imageArray.push(this.headerimg);
            //调用识别方法
          this.detectFace(this.newimage);
        };
        reader.readAsDataURL(blob);
      });
    },
完整代码 
<template>
  <div class="main">
    <div class="cam">
      <div class="video-box">
        <div class="videos">
          <video
            id="video"
            style="width: 100%;height: 100%; object-fit: fill;"
            preload
            autoplay
            loop
            muted
          ></video>
        </div>
        <div class="button-box" @click="submit()">
          <img src="../assets/cam.png" />
        </div>
      </div>
      <div class="title-box">
        识别分析
      </div>
      <div class="right-box">
        <div
          ref="mainscroll"
          class="face-box"
          v-loading="loading"
          element-loading-text="拼命加载中"
          element-loading-spinner="el-icon-loading"
          element-loading-background="transparent"
        >
          <div
            class="details"
            v-for="(item, index) in threeImageArray"
            :key="index"
          >
            <div class="image-box">
              <img :src="item.image" />
            </div>
            <div class="list-box">
              <div class="sex-one">年龄:{{ item.age }}</div>              
            </div>
          </div>
        </div>
      </div>
      <div class="canva-box">
        <canvas ref="canvas" id="canvas" width="1000" height="700"></canvas>
      </div>
    </div>
  </div>
</template>

<script>
import axios from "axios";

export default {
  name: "testTracking",
  data() {
    return {
      loading: false,
      contentAnwer: false,
      contentShow: true,
      API_KEY: "这里是你申请的key",
      SECRET_KEY: "这里是你申请的secret",
      imageData: null,
      newimage: null,
      faceInfomation: {},
      faceArray: [],
      age: null,
      imageArray: [],
      headerimg: "",
      location: {},
      left: 0,
      top: 0,
      width: 0,
      height: 0,
      faceImg: null,
      canvas: null,
      newImageArray: [],
      threeImageArray: []
    };
  },
  methods: {
   
   submit() {
      console.log("点击了这个");
       //每次点击的时候都清空一下上一次的内容
      this.newImageArray = [];
      this.faceArray = [];
        //loading加载
      this.fullscreenLoading = true;
      setTimeout(() => {
        this.fullscreenLoading = false;
      }, 2000);
      
      let that = this;
      let canvas = document.getElementById("canvas");
      let context = canvas.getContext("2d");
      let video = document.getElementById("video");
        //将摄像头拍下的照片放在canvas画布上
      context.drawImage(video, 0, 0, 1000, 700);
        //将图片转换成 接口需要的类型
      canvas.toBlob(blob => {
        var reader = new FileReader();
        reader.onloadend = () => {
          this.imageData = reader.result;

          this.newimage = this.imageData.replace(
            /^data:image\/\w+;base64,/,
            ""
          );
            //截取一下图片
          this.headerimg = this.imageData.slice(5, 15);
          this.imageArray.push(this.headerimg);
            //调用识别方法
          this.detectFace(this.newimage);
        };
        reader.readAsDataURL(blob);
      });
    },
   //可以是点击方法,可以放在mounted()中,看自己的需求
getCompetence() {
      var _this = this;
      this.thisCancas = document.getElementById("canvas");
      this.thisContext = this.thisCancas.getContext("2d");
      this.thisVideo = document.getElementById("video");
      // 旧版本浏览器可能根本不支持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);
          });
        };
      }
      var constraints = {
        audio: false,
        video: {
          width: this.videoWidth,
          height: this.videoHeight,
          transform: "scaleX(-1)"
        }
      };
      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);
        });
    },

    async detectFace(imageData) {
        //access_token需要通过申请的key 和secret来获取,登录百度ai文档中就有教程
      this.loading = true;
      try {
        const response = await axios.post(
          "https://aip.baidubce.com/rest/2.0/face/v3/detect?access_token=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
          {
            image: imageData,
            image_type: "BASE64",
            face_field: "age,gender,emotion,glasses,mask,expression",
            max_face_num: 10
          }
        );

        // 处理接口返回的结果

        if (response.data.error_code == 0) {
            //这里是接口返回的打印
          console.log("调用成功显示结果", response);
          this.faceInfomation = response.data.result;
          this.faceArray = response.data.result.face_list;
            //这里我用一个数组接收返回的人脸信息
          this.faceArray.forEach((item, i) => {
            console.log("item", item);
                //这里是人脸的位置宽高信息
            const left = parseInt(item.location.left);
            const top = parseInt(item.location.top);
            const width = parseInt(item.location.width);
            const height = parseInt(item.location.height);
            const faceCanvas = document.createElement("canvas");
            
            faceCanvas.width = width;
            faceCanvas.height = height;
            //将截取的人脸再重新铺到canvas画布上,好展示出来
            const faceCtx = faceCanvas.getContext("2d");
            faceCtx.drawImage(
              this.canvas,
              left,
              top,
              width,
              height,
              0,
              0,
              width,
              height
            );

            this.faceImg = faceCanvas.toDataURL("image/png");
            //将截取的头像放在新的数组中
            this.newImageArray.push(this.faceImg);
          });
            //因为截取的人脸头像和人脸文字描述不是一个数组,所以将两个数组合并一个数组了,这样在遍历循环列表的时候,更好的画css样式 
          this.threeImageArray = this.faceArray.map((item, index) => {
            return { ...item, image: this.newImageArray[index] };
          });
        }
      } catch (error) {
        console.error(error);
      } finally {
        this.loading = false;
      }
    },
    
  },
  mounted() {
    this.getCompetence();
    this.canvas = this.$refs.canvas;

  },
  computed: {},
  destroyed() {
    // 关闭摄像头
    this.trackerTask.closeCamera();
  }
};
</script>
<style scoped>

.main {
  width: 100%;
  height: 100vh;
  display: flex;

  align-items: center;
  justify-content: center;
}

.cam {
  width: 50%;
  height: 90%;
  display: flex;
  flex-direction: column;
  align-items: center;
  background-color: #fff;
  border-radius: 20px;
}
.canva-box {
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  position: absolute;
  top: 0;
  z-index: -99;
}

.button-box {
  position: absolute;
  top: 35%;
  border: 2px solid #fff;
  padding: calc(100vw * 20 / 1920);
  border-radius: 50%;
}
.button-box img {
  width: calc(100vw * 40 / 1920);
  height: calc(100vw * 40 / 1920);
}
.title-box {
  height: 5%;
  font-size: calc(100vw * 40 / 1920);
  font-weight: bold;
  width: 40%;
}
.right-box {
  width: 100%;
  height: 30%;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: space-evenly;
}
.video-box {
  width: 100%;
  height: 65%;
  display: flex;
  justify-content: center;
}
.videos {
  width: 100%;
  height: 100%;
}
.face-box {
  width: 100%;
  height: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  overflow: auto;
}
.details {
  display: flex;

  width: 100%;
  height: 90%;
  margin-top: 4px;
}
.image-box {
  width: 30%;
  height: 100%;
  display: flex;
  justify-content: center;
}

.image-box img {
  width: calc(100vw * 150 / 1920);
  height: calc(100vw * 150 / 1920);
}
.list-box {
  width: 60%;
  height: calc(100vw * 300 / 1920);
  display: flex;
  flex-direction: column;
  text-indent: calc(100vw * 16 / 1920);
  font-size: calc(100vw * 18 / 1920);
  padding-bottom: 20px;
}
</style>