tensorflow.js使用models,生产环境存和开发环境的差异

1,293 阅读3分钟

TensorFlow.js模型使用\color{Goldenrod}TensorFlow.js模型使用


人脸识别

发现问题

因为项目需要前端创建一个人脸识别活人检测的功能,因此查询相关功能,最终在大佬 (wangpeng1478 - 前端实现活体人脸检测 - 掘金 )学习了相关人脸特征点检测模型,并且进行修改后应用到了项目中。

本地环境中项目运行正常,我也没有发现其他什么BUG,于是胸有成竹的上传到测试环境,哪知道这才是我这两天噩梦的开始...

企业微信截图_16708375356364

是的,这个报错就是我接下来的一切的开始。

排查思考

为什么? 这是我的第一想法,紧接着就是这个报错是 哪个地方的?

点进报错所在的位置,发现因为打包代码已然揉成一团,但还是能够识别出报错代码处在立即执行函数中,这一般是依赖包内的js文件,而依赖包的问题,那就去node_modules中找出相关js文件,终于发现node_modules@tensorflow-models\face-landmarks-detection\dist\face-landmarks-detection.esm.js文件中有引入另外几个依赖

raycast-untitled

很明显,报错是因为依赖包 @mediapipe/face_mesh 找不到所导致,可是我确定已经安装了相应的依赖包,不然本地运行项目早报错了,所以我判断不是依赖包的问题,很可能是因为nodejs版本导致的打包问题,这个也是比较常见的问题。

切换多个nodejs版本进行打包再用nginx代理打包后的dist包达到线上的效果,从而测试问题是否得到解决,很遗憾的是问题并没有解决...

好吧,问题依旧存在,那该死的xxx.faceMesh is not a constructor一直跳动在我项目的报错里,就在我百思不得其解的时候,xxx这个突然引起了我的注意,这个是什么?

raycast-untitled (2)

生产环境中xxx是一个空对象,而开发环境却是引入的依赖包,这一对比更加让我确定了问题就出在依赖包上!

解决方法

既然不是nodejs版本问题,那就直接去查找 @mediapipe/face_mesh依赖包,各种方法尝试了个遍,目前就一种方法解决了我的问题

那就是直接在项目中采用cdn的方式引入使用,其实我还看到github上面的issue提到使用:

faceDetection = new FaceDetection({
      locateFile: (path, base) => {
        return `base/node_modules/@mediapipe/face_detection/${path}`;
      }
    });

这个方法我也尝试过,并没有解决我的问题(当然也可能是我比较菜吧


通过cdn引入也很简单,这里就直接贴代码
// index.html
<html lang="en">
   <head>
    <meta charset="UTF-8" />
    <link rel="icon" href="/logo.ico" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <script type="module" src="https://unpkg.com/@mediapipe/face_mesh"></script>
  </head>
  
  <body>
    <div id="app"></div>
    <script type="module" src="/src/main.ts"></script>
  </body>
</html>

接着是在vite.config.ts文件中进行打包设置,主要使用到了rollup-plugin-commonjs和rollup-plugin-external-globals,配置网上很多我就不详细展开了

// vite.config.ts
import commonjs from 'rollup-plugin-commonjs'
import externalGlobals from 'rollup-plugin-external-globals'

export default {
    build: {
        rollupOptions: {
        external: [
          '@mediapipe/face_mesh',
        ],
        plugins: [
          commonjs(),
          externalGlobals({
            '@mediapipe/face_mesh': 'face_mesh',
          }),
        ],
      },
    }
    
}

配置之后,本地环境还是正常通过import 引入包进行依赖包的使用,只有打包会排除掉@mediapipe/face_mesh依赖,通过cdn方式引入使用。

希望这篇文章能够帮到你解决问题!

本文正在参加「金石计划 . 瓜分6万现金大奖」