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弹性布局内容对齐(justify-content)属性使用详解
Jul 31 HTML / CSS
CSS3混合模式mix-blend-mode/background-blend-mode简介
Mar 15 HTML / CSS
纯CSS实现聊天框小尖角、气泡效果
Apr 04 HTML / CSS
css3进阶之less实现星空动画的示例代码
Sep 10 HTML / CSS
CSS3实现红包抖动效果
Dec 23 HTML / CSS
纯CSS3实现圆圈动态发光特效动画的示例代码
Mar 08 HTML / CSS
html5跨域通讯之postMessage的用法总结
Nov 07 HTML / CSS
深入探究HTML5的History API
Jul 09 HTML / CSS
HTML5标签使用方法详解
Nov 27 HTML / CSS
基于html5绘制圆形多角图案
Apr 21 HTML / CSS
如何避免常见的6种HTML5错误用法
Nov 06 HTML / CSS
浅谈html5与APP混合开发遇到的问题总结
Mar 20 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
将二维数组转为一维数组的2种方法
2014/05/26 PHP
laravel dingo API返回自定义错误信息的实例
2019/09/29 PHP
php 使用expat方式解析xml文件操作示例
2019/11/26 PHP
jquery 新手学习常见问题解决方法
2010/04/18 Javascript
IE和Firefox的Javascript兼容性总结[推荐收藏]
2011/10/19 Javascript
JS鼠标事件大全 推荐收藏
2011/11/01 Javascript
JS 屏蔽键盘不可用与鼠标右键不可用的方法
2013/11/18 Javascript
IE下Ajax缓存问题的快速解决方法(get方式)
2014/01/09 Javascript
jquery基础教程之deferred对象使用方法
2014/01/22 Javascript
jquery如何判断表格同一列不同行input数据是否重复
2014/05/14 Javascript
使用原生JS实现弹出层特效
2014/12/22 Javascript
使用javascript实现json数据以csv格式下载
2015/01/09 Javascript
javascript实现汉字转拼音代码分享
2015/04/20 Javascript
Jquery Mobile 自定义按钮图标
2015/11/18 Javascript
Angularjs 实现分页功能及示例代码
2016/09/14 Javascript
JQuery PHP图片在线裁剪实例
2020/07/27 Javascript
jQuery Ajax前后端使用JSON进行交互示例
2017/03/17 Javascript
jQuery UI Draggable + Sortable 结合使用(实例讲解)
2017/09/07 jQuery
vue中如何动态绑定图片,vue中通过data返回图片路径的方法
2018/02/07 Javascript
vue弹出框组件封装实例代码
2019/10/31 Javascript
Vue如何实现监听组件原生事件
2020/07/03 Javascript
通过实例解析json与jsonp原理及使用方法
2020/09/27 Javascript
[04:32]DOTA2著名解说配音敌法师 现场专访海涛怒切假腿
2013/12/20 DOTA
[27:53]2014 DOTA2华西杯精英邀请赛 5 24 NewBee VS iG
2014/05/26 DOTA
[01:02:05]LGD vs Mineski 2018国际邀请赛小组赛BO2 第一场 8.19
2018/08/21 DOTA
python 实现分页显示从es中获取的数据方法
2018/12/26 Python
一步步教你用python的scrapy编写一个爬虫
2019/04/17 Python
python爬虫开发之使用python爬虫库requests,urllib与今日头条搜索功能爬取搜索内容实例
2020/03/10 Python
浅析图片上传及canvas压缩的流程
2020/06/10 HTML / CSS
英国领先的葡萄酒专家:Majestic Wine
2017/05/30 全球购物
毕业生自我鉴定范文
2013/11/08 职场文书
初中政治教学反思
2014/01/17 职场文书
运动会100米解说词
2014/01/23 职场文书
会务接待方案
2014/02/27 职场文书
解析目标检测之IoU
2021/06/26 Python
Python实现为PDF去除水印的示例代码
2022/04/03 Python