canvas像素点操作之视频绿幕抠图


Posted in HTML / CSS onSeptember 11, 2018

 本文介绍了canvas像素点操作之视频绿幕抠图,分享给大家,具体如下:

用法:

context.putImageData(imgData, x, y, dX, dY, dWidth, dHeight);
   

参数 描述
imgData 规定要放回画布的 ImageData 对象。
x ImageData 对象左上角的 x 坐标,以像素计。
y ImageData 对象左上角的 y 坐标,以像素计。
dX 可选。水平值(x),以像素计,在画布上放置图像的位置。
dY 可选。水平值(y),以像素计,在画布上放置图像的位置。
dWidth 可选。在画布上绘制图像所使用的宽度。
dHeight 可选。在画布上绘制图像所使用的高度。

下面的栗子简单实现了几个简单的滤镜效果,具体算法参考的这里,学过《数字图像处理》的同学应该对此理解更深刻。

demo

canvas像素点操作之视频绿幕抠图

该栗子纯属为了演示功能而做,如果只强调效果而不在乎数据的话,用CSS3的filter属性便能高效又轻松地搞定。

部分代码

import imgUrl from './component/sample.jpg';

export default {
	data () {
		return {
			imgUrl: imgUrl
		}
	},

	methods: {
		onOperate1 () {
			this.ctx.putImageData(this.onCompute1(), 0, 0);
		},

		onOperate2 () {
			this.ctx.putImageData(this.onCompute2(), 0, 0);
		},

		...

		onCancel () {
			this.reload();
		},

		onCompute1 () {
			let data = this.frameData.data;

	        for (let i = 0; i < this.imgDataLength; i += 4) {
	          	let r = data[i + 0],
	          		g = data[i + 1],
	          		b = data[i + 2];
	          	
          		data[i + 0] = 255 - r;
          		data[i + 1] = 255 - g;
          		data[i + 2] = 255 - b;
	        }

	        return this.frameData;
		},

		onCompute2 () {
			let data = this.frameData.data;

	        for (let i = 0; i < this.imgDataLength; i += 4) {
	          	data[i] = Math.abs(data[i + 1] - data[i + 2] + data[i + 1] + data[i]) * data[i] / 256;  
            	data[i + 1] = Math.abs(data[i + 2] - data[i + 1] + data[i + 2] + data[i]) * data[i] / 256;  
            	data[i + 2] = Math.abs(data[i + 2] - data[i + 1] + data[i + 2] + data[i]) * data[i + 1] / 256;
	        }

	        return this.frameData;
		},

		...
	},

	mounted () {
        this.canvas = this.$refs['canvas'];
        this.ctx = this.canvas.getContext('2d');

        this.reload();
	}
}

上周跟同学去了一趟溧阳天目湖的南山竹海,在景区被忽悠拍了一张照片,就是这张 ——

canvas像素点操作之视频绿幕抠图

然后被朋友圈吐槽抠图。其实当时就是站在一块绿幕前拍的:joy: 。

PS中魔法棒工具可以把图片中一定容差下的相近像素都选中、清空,轻松做到一键“抠图”,前提是主体一定要与背景有大的差异,即像素值差值越大,抠图效果越好。

Canvas同样可以做到,并且可以处理视频帧,其中的原理是一样的 —— 将每个视频帧中绿幕的像素块透明度置0即可。像这样 ——

demo

canvas像素点操作之视频绿幕抠图

部分代码

import videoUrl from './component/video.ogv';
import imgUrl from './component/sample.jpg';

const TOLERANCE = 5;
export default {
	data () {
		return {
			videoUrl: videoUrl,
			imgUrl: imgUrl
		}
	},

	methods: {
		draw () {
			if (this.video.paused || this.video.ended) {
	          	return;
	        }
			this.ctx.drawImage(this.video, 0, 0, this.width, this.height);
			this.ctx.putImageData(this.cutOut(), 0, 0);
		},

		cutOut () {
			let frameData = this.ctx.getImageData(0, 0, this.width, this.height),
				len = frameData.data.length / 4;

	        for (let i = 0; i < len; i++) {
	          	let r = frameData.data[i * 4 + 0],
	          		g = frameData.data[i * 4 + 1],
	          		b = frameData.data[i * 4 + 2];
	          	if (r - 100 >= TOLERANCE 
	          	 && g - 100 >= TOLERANCE 
	          	 && b - 43 <= TOLERANCE) {
		            frameData.data[i * 4 + 3] = 0;
	          	}
	        }
	        return frameData;
		}
	},

	mounted () {
		this.video = this.$refs['video'];
        this.canvas = this.$refs['canvas'];
        this.ctx = this.canvas.getContext('2d');
        this.timer = null;

        this.video.addEventListener('play', () => {
            this.width = this.video.videoWidth;
            this.height = this.video.videoHeight;

            this.timer && clearInterval(this.timer);
            this.timer = setInterval(() => {
            	this.draw();
            }, 50);
        }, false);
	}
}

参考资料

Manipulating video using canvas

 Pixel manipulation with canvas

Canvas and images and pixels

HTML / CSS 相关文章推荐
CSS3实现简易版的刮刮乐效果
Sep 27 HTML / CSS
详解CSS3+JS完美实现放大镜模式
Dec 03 HTML / CSS
html5 input元素新特性_动力节点Java学院整理
Jul 06 HTML / CSS
H5 canvas中width、height和style的宽高区别详解
Nov 02 HTML / CSS
详解Html5 Canvas画线有毛边解决方法
Mar 01 HTML / CSS
html5配合css3实现带提示文字的输入框(摆脱js)
Mar 08 HTML / CSS
检测浏览器对HTML5和CSS3支持度的方法
Jun 25 HTML / CSS
基于html5绘制圆形多角图案
Apr 21 HTML / CSS
HTML5视频播放插件 video.js介绍
Sep 29 HTML / CSS
AmazeUI折叠式卡片布局,整合内容列表、表格组件实现
Aug 20 HTML / CSS
css3 实现文字闪烁效果的三种方式示例代码
Apr 25 HTML / CSS
HTML基础详解(下)
Oct 16 HTML / CSS
HTML5中使用json对象的实例代码
Sep 10 #HTML / CSS
html5 figure和figcaption的使用方法
Sep 10 #HTML / CSS
用canvas画心电图的示例代码
Sep 10 #HTML / CSS
Html5 canvas实现粒子时钟的示例代码
Sep 06 #HTML / CSS
canvas离屏技术与放大镜实现代码示例
Aug 31 #HTML / CSS
使用PDF.JS插件在HTML中预览PDF文件的方法
Aug 29 #HTML / CSS
使用canvas对多图片拼合并导出图片的方法
Aug 28 #HTML / CSS
You might like
全国FM电台频率大全 - 7 吉林省
2020/03/11 无线电
PHP程序员面试 切忌急功近利(更需要注重以后的发展)
2010/09/01 PHP
windows平台中配置nginx+php环境
2015/12/06 PHP
基于php实现的验证码小程序
2016/12/13 PHP
使用laravel根据用户类型来显示或隐藏字段
2019/10/17 PHP
JCalendar 日历控件 v1.0 beta[兼容IE&amp;Firefox] 有文档和例子
2007/05/30 Javascript
table insertRow、deleteRow定义和用法总结
2014/05/14 Javascript
javascript为按钮注册回车事件(设置默认按钮)的方法
2015/05/09 Javascript
简介JavaScript中的italics()方法的使用
2015/06/08 Javascript
Bootstrap打造一个左侧折叠菜单的系统模板(一)
2016/05/17 Javascript
实用又漂亮的BootstrapValidator表单验证插件
2016/05/30 Javascript
通过Ajax使用FormData对象无刷新上传文件方法
2016/12/08 Javascript
VUE中v-model和v-for指令详解
2017/06/23 Javascript
js 两数组去除重复数值的实例
2017/12/06 Javascript
Vue自定义指令封装节流函数的方法示例
2018/07/09 Javascript
判断iOS、Android以及PC端的示例代码
2018/11/15 Javascript
Node.js + express实现上传大文件的方法分析【图片、文本文件】
2019/03/14 Javascript
layui table 表格上添加日期控件的两种方法
2019/09/28 Javascript
Python版实现微信公众号扫码登陆
2020/05/28 Javascript
探索Python3.4中新引入的asyncio模块
2015/04/08 Python
Java Web开发过程中登陆模块的验证码的实现方式总结
2016/05/25 Python
详解Python list 与 NumPy.ndarry 切片之间的对比
2017/07/24 Python
python difflib模块示例讲解
2017/09/13 Python
Python实现全排列的打印
2018/08/18 Python
使用python获取电脑的磁盘信息方法
2018/11/01 Python
Python自动发送邮件的方法实例总结
2018/12/08 Python
原来我一直安装 Python 库的姿势都不对呀
2019/11/11 Python
Python3标准库glob文件名模式匹配的问题
2020/03/13 Python
Python坐标轴操作及设置代码实例
2020/06/04 Python
tensorflow 动态获取 BatchSzie 的大小实例
2020/06/30 Python
python list的index()和find()的实现
2020/11/16 Python
Unineed旗下时尚轻奢网站:FABHunt
2019/05/13 全球购物
商务考察邀请函范文
2014/01/21 职场文书
竞选演讲稿范文大全
2014/05/12 职场文书
《桂花雨》教学反思
2016/02/19 职场文书
使用logback实现按自己的需求打印日志到自定义的文件里
2021/08/30 Java/Android