【前端笔记】100行多一点代码,实现前端检测情绪

自从大二初次接触前端以来,一直都有记markdown笔记的习惯.又因为掘金最近有一个活动.所以开了这个专栏。我会写一些业务相关的小技巧和前端知识中的重点内容之类的整理一下发上来。难免有点地方不够细致。欢迎大家指教

这个文章讲一下 怎么用face.js 和 javascript 实现视频的人脸替换.最后你会实现下图效果

打个码嘿嘿

第一步:引入依赖和样式

xml 复制代码
<head>
  <script src="face-api.js"></script> <!-- 引入face-api.js库 -->
  <script src="js/commons.js"></script> <!-- 引入commons.js脚本 -->
  <script src="js/faceDetectionControls.js"></script> <!-- 引入faceDetectionControls.js脚本 -->
  <link rel="stylesheet" href="styles.css"> <!-- 引入本地样式表styles.css -->
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.100.2/css/materialize.css"> <!-- 引入Materialize样式表 -->
  <script type="text/javascript" src="./jq.js"></script> <!-- 引入jq.js脚本 -->
  <script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.100.2/js/materialize.min.js"></script> <!-- 引入Materialize JavaScript库 -->
</head>

第二步:创建页面结构

xml 复制代码
<body>
  <div class="center-content page-container">
    <div class="progress" id="loader"> <!-- 显示加载进度 -->
      <div class="indeterminate"></div>
    </div>
    <div style="position: relative" class="margin">
      <video onloadedmetadata="onPlay(this)" id="inputVideo" autoplay muted playsinline></video> <!-- 创建视频元素并调用onPlay函数 -->
      <canvas id="overlay" /> <!-- 创建画布元素 -->
    </div>

    <div class="row side-by-side">
      <div id="fps_meter" class="row side-by-side"> <!-- 显示帧率信息 -->
        <div>
          <label for="time">Time:</label>
          <input disabled value="-" id="time" type="text" class="bold">
          <label for "fps">Estimated Fps:</label>
          <input disabled value="-" id="fps" type="text" class="bold">
        </div>
      </div>
    </div>

    <span id="tiny_face_detector_controls">
      <div class="row side-by-side">
        
        <div class="row">
          <label for "scoreThreshold">Score Threshold:</label>
          <input disabled value="0.5" id="scoreThreshold" type="text" class="bold">
        </div>
        <button
          class="waves-effect waves-light btn"
          onclick="onDecreaseScoreThreshold()"
        >
          <i class="material-icons left">-</i>
        </button>
        <button
          class="waves-effect waves-light btn"
          onclick="onIncreaseScoreThreshold()"
        >
          <i class="material-icons left">+</i>
        </button>
      </div>
    </span>
  </div>
</body>

第三步:添加JavaScript代码

scss 复制代码
// 步骤 1: 初始化变量
let forwardTimes = [] // 创建一个空数组用于存储时间信息
let withBoxes = true // 布尔值,用于控制是否显示人脸框

// 步骤 2: 更新时间统计信息
function updateTimeStats(timeInMs) {
  forwardTimes = [timeInMs].concat(forwardTimes).slice(0, 30) // 记录运行时间
  const avgTimeInMs = forwardTimes.reduce((total, t) => total + t) / forwardTimes.length
  $('#time').val(`${Math.round(avgTimeInMs)} ms`) // 更新时间统计信息到页面
  $('#fps').val(`${faceapi.utils.round(1000 / avgTimeInMs)}`) // 更新帧率信息到页面
}

// 步骤 3: 视频播放时触发的函数
async function onPlay() {
  const videoEl = $('#inputVideo').get(0)

  // 步骤 3.1: 获取视频元素
  const options = getFaceDetectorOptions() // 步骤 3.2: 获取人脸检测选项

  const ts = Date.now()

  // 步骤 3.3: 进行人脸检测和表情识别
  const result = await faceapi.detectSingleFace(videoEl, options).withFaceExpressions()

  // 步骤 3.4: 更新时间统计信息、
  updateTimeStats(Date.now() - ts)

  console.log(result?.expressions) // 步骤 3.5: 打印表情识别结果

  if (result) {
    // 步骤 3.6: 获取画布元素并匹配尺寸
    const canvas = $('#overlay').get(0)
    const dims = faceapi.matchDimensions(canvas, videoEl, true)

    // 步骤 3.7: 调整结果尺寸
    const resizedResult = faceapi.resizeResults(result, dims)

    const minConfidence = 0.05 // 步骤 3.8: 设置最小置信度
    if (withBoxes) {
      // 步骤 3.9: 绘制人脸框
      faceapi.draw.drawDetections(canvas, resizedResult)
    }

    // 步骤 3.10: 绘制表情识别结果
    faceapi.draw.drawFaceExpressions(canvas, resizedResult, minConfidence)
  }

  // 步骤 3.11: 控制视频播放频率
  setTimeout(()=>{onPlay()},10)
}

// 步骤 4: 加载人脸检测和表情识别模型
async function run() {
  await changeFaceDetector(TINY_FACE_DETECTOR)
  await faceapi.loadFaceExpressionModel('./')
  changeInputSize(224)

  // 步骤 4.1: 尝试访问用户的摄像头并将图像流传输到视频元素
  const stream = await navigator.mediaDevices.getUserMedia({ video: {} })
  const videoEl = $('#inputVideo').get(0)
  videoEl.srcObject = stream
}

// 步骤 5: 初始化人脸检测控件
initFaceDetectionControls()

// 步骤 6: 运行主程序
run()

注意 这个 console.log(result?.expressions) 。会持续输出 表情数据,如果不想让它 输出的 太快 。可以在 setTimeout(()=>{onPlay()},10) 中 把 时间拉长一点

完整源码

视频地址:www.bilibili.com/video/BV1sz...

源码地址:gitee.com/Electrolux/...

相关推荐
过往记忆3 小时前
告别 Shuffle!深入探索 Spark 的 SPJ 技术
大数据·前端·分布式·ajax·spark
高兴蛋炒饭4 小时前
RouYi-Vue框架,环境搭建以及使用
前端·javascript·vue.js
m0_748240444 小时前
《通义千问AI落地—中》:前端实现
前端·人工智能·状态模式
ᥬ 小月亮4 小时前
Vue中接入萤石等直播视频(更新中ing)
前端·javascript·vue.js
夜斗(dou)5 小时前
node.js文件压缩包解析,反馈解析进度,解析后的文件字节正常
开发语言·javascript·node.js
恩爸编程5 小时前
纯 HTML+CSS+JS 实现一个炫酷的圣诞树动画特效
javascript·css·html·圣诞树·圣诞树特效·圣诞树js实现·纯js实现圣诞树
神雕杨5 小时前
node js 过滤空白行
开发语言·前端·javascript
网络安全-杰克6 小时前
《网络对抗》—— Web基础
前端·网络
m0_748250746 小时前
2020数字中国创新大赛-虎符网络安全赛道丨Web Writeup
前端·安全·web安全
周伯通*6 小时前
策略模式以及优化
java·前端·策略模式