如何在前端给视频进行去除绿幕并替换背景?-----Vue3!!
最近在做这个这项目奇店桶装水小程序V1.3.9安装包+骑手端V2.0.1+小程序前端
最近,我在进行前端开发时,遇到了一个难题“如何给前端的视频进行去除绿幕并替换背景”。这是一个“数字人项目”所需,我一直在冥思苦想。终于有了一个解决方法——使用Canvas来处理。
这是真材实料的文章——让你的Canvas的技术更上一层楼!!!
效果图
实现思路
1. 准备工作 视频和画布元素:在HTML模板中定义了一个标签用于播放视频,以及一个标签用来绘制处理后的视频帧。 初始化:在组件挂载(mounted)时,获取视频和画布元素,并初始化绘图上下文。
Your browser does not support the video tag. export default { data() { return { featherStrength: 0.4, // 羽化强度控制 }; }, mounted() { // 初始化视频和画布引用 this.video = this.$refs.video; this.canvas = this.$refs.canvas; this.ctx = this.canvas.getContext('2d'); this.canvas_tmp = document.createElement('canvas'); this.canvas_tmp.width = this.canvas.width; this.canvas_tmp.height = this.canvas.height; this.ctx_tmp = this.canvas_tmp.getContext('2d'); // 初始化其他变量 this.init(); }, methods: { init() { // 当视频开始播放时,调用computeFrame进行逐帧处理 this.video.addEventListener('play', this.computeFrame); } } };
2. 视频帧处理逻辑 逐帧处理:当视频开始播放时,computeFrame函数会不断被调用,每次调用都会处理一帧视频数据。 临时画布:为了不影响原始视频的播放,所有图像处理都在一个临时创建的画布(canvas_tmp)上进行。 图像数据获取:从临时画布上获取当前帧的图像数据(像素信息)以进行处理。
methods: { computeFrame() { if (!this.video || this.video.paused || this.video.ended) return; // 绘制当前帧到临时画布上 this.ctx_tmp.drawImage(this.video, 0, 0, this.canvas.width, this.canvas.height); // 获取当前帧的图像数据 let frame = this.ctx_tmp.getImageData(0, 0, this.canvas.width, this.canvas.height); // 后续处理... } }
3. 背景移除 颜色检测:假设背景为特定的颜色(例如绿色),对于每个像素点,如果其RGB值符合预设的背景颜色范围,则将其alpha通道设置为0,即变为透明。
methods: { computeFrame() { // ... (前面的代码) const pointLens = frame.data.length / 4; // 遍历每一个像素点 for (let i = 0; i 120 && b4. 羽化效果 边缘检测与平均:对于非透明的像素,计算它周围的像素,取周围像素颜色的平均值作为新颜色,并根据周围的透明度调整当前像素的透明度,以此来实现羽化效果。 强度控制:通过featherStrength参数可以控制羽化的程度,从而让边缘过渡更加自然。
methods: { computeFrame() { // ... (前面的代码) // 创建一个临时的数据副本,避免修改原始数据 const tempData = [...frame.data]; // 对非透明像素应用羽化效果 for (let i = 0; i { let index = this.pointToNum([pRow, pCol], frame.width); rSum += tempData[(index - 1) * 4]; gSum += tempData[(index - 1) * 4 + 1]; bSum += tempData[(index - 1) * 4 + 2]; if (tempData[(index - 1) * 4 + 3] !== 255) opNum++; }); // 计算新的alpha值 let alpha = (255 / aroundPoints.length) * (aroundPoints.length - opNum); // 根据羽化强度调整alpha if (alpha !== 255) { frame.data[i * 4] = parseInt(rSum / aroundPoints.length); frame.data[i * 4 + 1] = parseInt(gSum / aroundPoints.length); frame.data[i * 4 + 2] = parseInt(bSum / aroundPoints.length); frame.data[i * 4 + 3] = parseInt(alpha * this.featherStrength); } } // 将处理后的图像数据绘制到实际显示的画布上 this.ctx.putImageData(frame, 0, 0); // 持续循环 requestAnimationFrame(this.computeFrame); }, numToPoint(num, width) { let col = num % width; let row = Math.floor(num / width); return [row + 1, col === 0 ? width : col]; }, pointToNum(point, width) { let [row, col] = point; return (row - 1) * width + col; }, getAroundPoint(point, width, height, area) { let [row, col] = point; let allAround = []; for (let i = -Math.floor(area / 2); i 0 && pRow width || row { return iRow > 0 && iCol > 0 && iRow { const index = this.pointToNum(position, width); rSum += tempData[(index - 1) * 4]; gSum += tempData[(index - 1) * 4 + 1]; bSum += tempData[(index - 1) * 4 + 2]; if (tempData[(index - 1) * 4 + 3] !== 255) opNum++; }); let alpha = (255 / arroundPoint.length) * (arroundPoint.length - opNum); // 调整羽化效果 if (alpha !== 255) { frame.data[i * 4] = parseInt(rSum / arroundPoint.length); frame.data[i * 4 + 1] = parseInt(gSum / arroundPoint.length); frame.data[i * 4 + 2] = parseInt(bSum / arroundPoint.length); // 根据羽化强度调整 alpha frame.data[i * 4 + 3] = parseInt(alpha * this.featherStrength); } } this.ctx.putImageData(frame, 0, 0); setTimeout(this.computeFrame, 0); } }, mounted () { this.video = this.$refs.video; this.canvas = this.$refs.canvas; this.init(); } };完整项目demo在前端给视频去除绿幕并替换背景: 最近,我在进行前端开发时,遇到了一个难题“如何给前端的视频进行去除绿幕并替换背景”。这是一个“数字人项目”所需,我一直在冥思苦想。终于有了一个解决方法——使用Canvas来处理。 这是真材实料的文章——让你的Canvas的技术更上一层楼!!!
免责声明:我们致力于保护作者版权,注重分享,被刊用文章因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理! 部分文章是来自自研大数据AI进行生成,内容摘自(百度百科,百度知道,头条百科,中国民法典,刑法,牛津词典,新华词典,汉语词典,国家院校,科普平台)等数据,内容仅供学习参考,不准确地方联系删除处理! 图片声明:本站部分配图来自人工智能系统AI生成,觅知网授权图片,PxHere摄影无版权图库和百度,360,搜狗等多加搜索引擎自动关键词搜索配图,如有侵权的图片,请第一时间联系我们。