javascript - face-api 和 tensorflow.js 在浏览器中不起作用

标签 javascript html tensorflow.js face-api

我正在尝试在浏览器中运行此示例
https://justadudewhohacks.github.io/face-api.js/docs/index.html#getting-started-browser
特别是这里的代码

<!DOCTYPE html>
<html>
<head>
  <script src="assets/face-api.js"></script>
  <script src="assets/commons.js"></script>
  <script src="assets/faceDetectionControls.js"></script>
  <link rel="stylesheet" href="assets/styles.css">
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.100.2/css/materialize.css">
  <script type="text/javascript" src="https://code.jquery.com/jquery-2.1.1.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.100.2/js/materialize.min.js"></script>
</head>
<body>
  <div id="navbar"></div>
  <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>
      <canvas id="overlay" />
    </div>

    <div class="row side-by-side">

      <!-- face_detector_selection_control -->
      <div id="face_detector_selection_control" class="row input-field" style="margin-right: 20px;">
        <select id="selectFaceDetector">
          <option value="ssd_mobilenetv1">SSD Mobilenet V1</option>
          <option value="tiny_face_detector">Tiny Face Detector</option>
        </select>
        <label>Select Face Detector</label>
      </div>
      <!-- face_detector_selection_control -->

      <!-- check boxes -->
      <div class="row" style="width: 220px;">
        <input type="checkbox" id="hideBoundingBoxesCheckbox" onchange="onChangeHideBoundingBoxes(event)" />
        <label for="hideBoundingBoxesCheckbox">Hide Bounding Boxes</label>
      </div>
      <!-- check boxes -->

      <!-- fps_meter -->
      <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>
      <!-- fps_meter -->

    </div>


    <!-- ssd_mobilenetv1_controls -->
    <span id="ssd_mobilenetv1_controls">
      <div class="row side-by-side">
        <div class="row">
          <label for="minConfidence">Min Confidence:</label>
          <input disabled value="0.5" id="minConfidence" type="text" class="bold">
        </div>
        <button
          class="waves-effect waves-light btn"
          onclick="onDecreaseMinConfidence()"
        >
          <i class="material-icons left">-</i>
        </button>
        <button
          class="waves-effect waves-light btn"
          onclick="onIncreaseMinConfidence()"
        >
          <i class="material-icons left">+</i>
        </button>
      </div>
    </span>
    <!-- ssd_mobilenetv1_controls -->

    <!-- tiny_face_detector_controls -->
    <span id="tiny_face_detector_controls">
      <div class="row side-by-side">
        <div class="row input-field" style="margin-right: 20px;">
          <select id="inputSize">
            <option value="" disabled selected>Input Size:</option>
            <option value="128">128 x 128</option>
            <option value="160">160 x 160</option>
            <option value="224">224 x 224</option>
            <option value="320">320 x 320</option>
            <option value="416">416 x 416</option>
            <option value="512">512 x 512</option>
            <option value="608">608 x 608</option>
          </select>
          <label>Input Size</label>
        </div>
        <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>
    <!-- tiny_face_detector_controls -->

  </body>

  <script>
    let forwardTimes = []
    let withBoxes = true

    function onChangeHideBoundingBoxes(e) {
      withBoxes = !$(e.target).prop('checked')
    }

    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)}`)
    }

    async function onPlay() {
      const videoEl = $('#inputVideo').get(0)

      if(videoEl.paused || videoEl.ended || !isFaceDetectionModelLoaded())
        return setTimeout(() => onPlay())


      const options = getFaceDetectorOptions()

      const ts = Date.now()

      const result = await faceapi.detectSingleFace(videoEl, options).withFaceExpressions()

      updateTimeStats(Date.now() - ts)

      if (result) {
        const canvas = $('#overlay').get(0)
        const dims = faceapi.matchDimensions(canvas, videoEl, true)

        const resizedResult = faceapi.resizeResults(result, dims)
        const minConfidence = 0.05
        if (withBoxes) {
          faceapi.draw.drawDetections(canvas, resizedResult)
        }
        faceapi.draw.drawFaceExpressions(canvas, resizedResult, minConfidence)
      }

      setTimeout(() => onPlay())
    }

    async function run() {
      // load face detection and face expression recognition models
      await changeFaceDetector(TINY_FACE_DETECTOR)
      await faceapi.loadFaceExpressionModel('/')
      changeInputSize(224)

      // try to access users webcam and stream the images
      // to the video element
      const stream = await navigator.mediaDevices.getUserMedia({ video: {} })
      const videoEl = $('#inputVideo').get(0)
      videoEl.srcObject = stream
    }

    function updateResults() {}

    $(document).ready(function() {
      renderNavBar('#navbar', 'webcam_face_expression_recognition')
      initFaceDetectionControls()
      run()
    })
  </script>
</body>
</html>
不幸的是,这不起作用(我已将关联的库加载到 Assets 中,即 https://github.com/justadudewhohacks/face-api.js/tree/master/dist 并将此示例中的其他文件移至此处
https://github.com/justadudewhohacks/face-api.js/tree/master/examples/examples-browser
我究竟做错了什么?我正在将其加载到我网站上的页面上
https://moodmap.app/webcamFaceExpressionRecognition.html如果您想查看浏览器中发生的情况。
基于以下更改,
这是我设置保存内容的节点服务器 - 是否可以只更改它?因为现在在进行下面建议的更改时,模型中需要的分片也出现了一个单独的问题。
谢谢!
const config = require('../../config');

const express = require('express');
const app = express();
const server = require('http').createServer(app);
const io = require('socket.io')(server, { wsEngine: 'ws' });
const mysql = require('mysql');
const expressSession = require('express-session');
const ExpressMysqlSessionStore = require('express-mysql-session')(expressSession);
const sharedsession = require('express-socket.io-session');
const path = require('path');

const utils = require('./utils');

// remove from header "X-Powered-By: Express"
app.disable('x-powered-by');

server.listen(config.serverParams.port, config.serverParams.address, () => {
    console.log(`Server running at http://${server.address().address}:${server.address().port}`);
});

/* DATABASE */
global.db = mysql.createConnection(config.db);
db.connect();
/* DATABASE */

/* SESSION */
const sessionStore = new ExpressMysqlSessionStore(config.sessionStore, db);
const session = expressSession({
    ...config.session,
    store: sessionStore,
});
app.use(session);
/* SESSION */

app.use(express.static(config.frontendDir));
app.use(express.static(path.join(__dirname, './src/assets')))
app.use(express.static(path.join(__dirname, './src/assets/weights')))

app.use((req,res,next)=>{
    //can reaplce * with website we want to allow access
    res.header('Access-Control-Allow-Origin', '*');
  next();
  });

app.get([
    '/signup',
    '/stats',
    '/pay',
], (req, res) => res.sendFile(path.join(`${config.frontendDir}${req.path}.html`)));

io.use(sharedsession(session, {
    autoSave: true
}));

io.on('connection', socket => {

    socket.use((packet, next) => {
        if (packet[0]) {
            console.log('METHOD:', packet[0]);
            const sessionData = socket.handshake.session.user;
            const noSessionNeed = [ 'login', 'signup', 'checkAuth' ].includes(packet[0]);
            let error;
            if ( ! sessionData && ! noSessionNeed) error = { code: -1, message: 'You need to login in extension!' };
            if (error) return next(new Error(JSON.stringify(error)));
            else next();
        }
    });

    const auth = require('./auth')(socket);
    socket.on('checkAuth', auth.checkAuth);
    socket.on('login', auth.login);
    socket.on('signup', auth.signup);
    socket.on('logout', auth.logout);

    const users = require('./users')(socket);
    socket.on('users.get', users.get);

    const sentiment = require('./sentiment')(socket);
    socket.on('sentiment.get', sentiment.get);
    socket.on('sentiment.set', sentiment.set);

    socket.on('disconnect', () => {

    });

});
由于某种原因仍然出现错误的原因如下,?
fetchOrThrow.ts:11 Uncaught (in promise) Error: failed to fetch: (404) , from url: https://moodmap.app/assets/tiny_face_detector_model-weights_manifest.json
    at fetchOrThrow.ts:11
    at step (drawContour.ts:28)
    at Object.next (drawContour.ts:28)
    at fulfilled (drawContour.ts:28)
(anonymous) @   fetchOrThrow.ts:11
step    @   drawContour.ts:28
(anonymous) @   drawContour.ts:28
fulfilled   @   drawContour.ts:28
async function (async)      
run @   webcamFaceExpressionRecognition.html:142
(anonymous) @   webcamFaceExpressionRecognition.html:158
j   @   jquery-2.1.1.min.js:2
fireWith    @   jquery-2.1.1.min.js:2
ready   @   jquery-2.1.1.min.js:2
I   @   jquery-2.1.1.min.js:2
提前致谢!

最佳答案

因此,您在问题中谈论的错误是:

Uncaught (in promise) Error: failed to fetch: (404) , from URL: 
https://moodmap.app/tiny_face_detector_model-weights_manifest.json
所以,这个错误意味着文件 tiny_face_detector_model-weights_manifest.json找不到。正如我在您的网站上看到的那样,所有其他 manifest.json 文件也会发生这种情况。
您在问题中提到所有关联的库都在 中。 Assets 文件夹。所以,你的 tiny_face_detector_model-weights_manifest.json文件和其他 manifest.json 文件也在 assets 中文件夹,我会根据它为您提供解决方案,但如果您将文件位置更改为另一个文件夹,只需替换 assets与您的文件所在的任何文件夹一起使用。
face-api.js 行:1976
face-api.js Linke: 188-190
在这里,在 1976 行 你看 defaultModelName .这告诉了要加载的文件。

1. 因此,如果您的应用只有加载 tiny_face_detector_model-weights_manifest.json 的问题[ 对于这种情况,所有 manifest.json 都显示 404 错误,因此请跳到 以下] 然后
face-api.js 行:5627
face-api.js Line: 470
转到 face-api.js 中的第 5627 行并更改"tiny_face_detector_model""./assets/tiny_face_detector_model"
2. 如果您的所有 list 文件在加载时都显示 404 错误,这对于这种情况是正确的,因为您的所有文件都在 assets 文件夹中。
因此,在这种情况下,请转到 face-api.js 的第 1976 行 ,
只需更换:
var defaultManifestFilename=defaultModelName+"-weights_manifest.json";
和:
var defaultManifestFilename="./assets/"+defaultModelName+"-weights_manifest.json";
这意味着只是 连接文件夹名称路径 list 文件存在于提到的变量的位置。这将解决所有 的路径问题manifest.json 应用程序中的文件。
注意:如果在查找我提到的行号的代码时遇到问题,请使用搜索。

关于javascript - face-api 和 tensorflow.js 在浏览器中不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63578210/

相关文章:

Javascript动态脚本通过函数加载...如何重新执行onload或readyState?

javascript - 数组内的对象

html - 更改 HTML 背景图像的不透明度

tensorflow - 在tensorflow.js中,如何计算模型输入的梯度?

tensorflow - 如何将 tensorflow.js 模型和权重转换为标准 tensorflow?

javascript - 将日期选择器添加到动态创建的字段的问题

javascript - 如何将series-label默认设置为false并更改highchart中系列标签文本的颜色

html - 如何限制输入框只能输入数字?

javascript - 单击 anchor 时,如何定位没有任何 UL 的 LI

javascript - Tensorflow.js 使用 Node 保存模型