当前位置: 首页 > Web前端 > vue.js

前端使用tensorflow.js模型实现浏览器摄像头视频流人像识别,背景虚化&背景替换

时间:2023-04-01 01:59:41 vue.js

背景实习期间有需要。前端需要调用算法模型,打包成npm包,供视频会议组使用。实现视频会议中的背景虚化和背景替换功能。后续可能会进一步增加一些有趣的功能,比如面部特效(胡子、一字眉)、头发颜色更换等。实现效果应该类似腾讯会议界面如下:为了演示给大家需求端,首先利用Google的TensorFlow.js的BodyPix模型做了一个小demo,先实现了背景虚化和背景替换功能。显示画面流畅。TensorFlow.js是一个JavaScript库。我们可以使用它来创建新的机器学习模型并直接在JavaScript中部署现有模型。对于前端人员入门机器学习非常友好。TensorFlow.js提供了很多开箱即用的预训练模型(见下图):这里选择图像处理类的BodyPix模型。这是BodyPix的官方demohttps://storage.googleapis.co...,demo中的功能对我们的需求来说有点太复杂了,而且没有后台更换功能。因此,我写了一个背景模糊和背景替换场景的demo。介绍思路:在浏览器中打开相机,获取视频流图片,调用tensorflow.js的body-pix模型的方法绘制结果。其中背景虚化相对容易实现,直接使用模型提供的drawBokehEffect方法即可;模型没有现成的背景替换接口,模型的toMask方法返回的mask对象被canvas绘制方法使用(由前景色&背景色的像素组成的点数组,其中前景色代表人像区域,背景颜色代表其他区域)经过一些处理实现背景替换(后面会详细介绍)。用到的技术:vue+elementui,tensorflow.js(不用专门学习,直接用例子)和canvas的一些简单操作。本项目的代码已经放在了githubhttps://github.com/SprinaLF/f...实现效果,先来看看最终效果:1.初始界面:视频播放完毕后会显示在下方相机开启,拍摄的照片会显示在视频下方。背景虚化:中、高、低可选一级模糊背景替换:模式切换为背景替换后,显示背景图片列表,可以切换背景。核心流程1.导入模型有两种方式。https://cdn.jsdelivr.net/npm/@tensorflow/tfjs@1.2">安装,使用如下命令(我的项目中已经安装了tensorflow.js和bodyPix,运行时只需yarninstall安装依赖即可)$npminstall@tensorflow/tfjsoryarnadd@tensorflow/tfjs$npminstall@tensorflow-models/body-pix2.加载模型body-pix有两种算法模型架构,MobileNetV1和ResNet50。经过本地实验,ResNet50启动非常慢,加载时间长,对GPU要求高,不适合一般电脑和移动设备。这里我们只考虑MobileNetV1的初始loadAndPredict方法来预加载模型。参数预设为:model:{architecture:'MobileNetV1',outputStride:16,//8,16的值越小,输出分辨率越大,模型越准确,速度越慢multiplier:0.75,//0.5,0.75,1的值越大,层越快越大,模型越准确,速度越慢quantBytes:2/*1,2,4这个参数控制用于权重量化的字节'4.每个浮点数4个字节(无量化)。最大精度和原始模型尺寸','2。每个浮点数2个字节。精度略低,模型尺寸小2倍','1.每个浮点数1个字节。准确率降低,模型体积缩小4倍'*/},asyncloadAndPredict(model){//加载模型this.net=awaitbodyPix.load(model);}3.背景虚化官网示例:其中net.segmentPerson(img)返回图像像素分析的结果,如下图,使用已有的bodyPix.drawBokehEffect方法,传入要模糊的图像和要绘制的canvas对象,分割和度数的一些参数blurring,可以将结果绘制到传入的画布上。模糊背景代码:asyncblurBackground(){constimg=this.$refs['video']//获取视频帧constsegmentation=awaitthis.net.segmentPerson(img);bodyPix.drawBokehEffect(this.videoCanvas,img,segmentation,this.backgroundBlurAmount,this.edgeBlurAmount,this.flipHorizo??ntal);if(this.radio===2){//选择背景模糊时,使用requestAnimationFrame不断调用blurBackgroundrequestAnimationFrame(this.blurBackground)}elsethis.clearCanvas(this.videoCanvas)//this.timer=setInterval(async()=>{//this.segmentation=awaitthis.net.segmentPerson(img);//bodyPix.drawBokehEffect(//this.videoCanvas,img,this.segmentation,3,//this.edgeBlurAmount,this.flipHorizo??ntal);//},60)},补充:这里需要不断处理视频帧,绘制到画布上,保证流畅的体验。最初设置了一个定时器,每60ms执行一次相应的方法,但是效果并不好,可以明显感觉到卡住了,性能也不好。于是看了一下bodyPix的demo代码,是用window.requestAnimationFrame来代替timer的。用这种方法替换定时器后,性能和流畅度都有了很大的提升。4.背景替换bodyPix没有提供现成的背景替换方法,但是有返回一个遮罩对象的方法,人像部分是传入的前景色,背景部分是传入的背景色(见下图)).您可以使用canvas的globalCompositeOperation属性设置绘制新形状时要应用的合成操作的类型,并处理遮罩以替换背景。globalCompositeOperation有很多类型供我们设置在之前的画布上绘制新图形的操作(如并行操作、绘制层次、色调和亮度保留),默认值是source-over,在现有的绘制新图形在画布上下文之上。这里使用source-in和destination-over绘制背景图source-in用于绘制要替换的新背景图。预先将人像部分(前景色)设置为透明,当globalCompositeOperation为source-in类型时,背景图只会绘制在背景色区域,如下图:只需要切换到destination-over,将画像绘制到画布上,按照已有的内容即可。这样背景会挡住之前的背景,人像就会显示出来。背景替换代码:asyncreplaceBackground(){if(!this.isOpen)returnconstimg=this.$refs['video']constsegmentation=awaitthis.net.segmentPerson(img);constforegroundColor={r:0,g:0,b:0,a:0}//前景色设置为完全透明constbackgroundColor={r:0,g:0,b:0,a:255}//背景颜色letbackgroundDarkeningMask=bodyPix.toMask(segmentation,foregroundColor,backgroundColor)if(backgroundDarkeningMask){letcontext=this.videoCanvas.getContext('2d')//compositecontext.putImageData(backgroundDarkeningMask,0,0)context.globalCompositeOperation='source-in'//newGraphics只在重叠区域绘制context.drawImage(this.backgroundImg,0,0,this.videoCanvas.width,this.videoCanvas.height)context.globalCompositeOperation='destination-over'//新图形只绘制在非重叠区域context.drawImage(img,0,0,this.videoCanvas.width,this.videoCanvas.height)context.globalCompositeOperation='source-over'//restore}if(this.radio===3){requestAnimationFrame(this.replaceBackground)}else{this.clearCanvas(this.videoCanvas)}},others:镜像没有使用bodyPix方法,虽然它给我们提供了这样的操作它直接通过css3实现,借助Vue的v-bind动态切换类.flipHorizo??ntal{变换:rotateY(180deg);}参考打开相机:https://www.cnblogs.com/ljx20...TensorFlow.js模型:https://github.com/tensorflow...canvas:https://github.com/tensorflow。..canvas:https://github.com/tensorflow://developer.mozilla.org...JS统计函数执行时间:https://blog.csdn.net/K346K34...开启相机:https://www.cnblogs.com/ljx20...bodyPix实现实时相机背景虚化/背景替换https://www.tytion.net/archiv...