用canvas 实现个图片三角化(LOW POLY)效果
之前无意中看到Ovilia 用threejs做了个LOW POLY,也就是图片平面三角化的效果,觉得很惊艳,然后就自己花了点时间尝试了一下。
我是没怎么用过threejs,所以就直接用canvas的2d绘图API来做,因为感觉似乎这效果也用不上threejs。
直接上demo先:http://whxaxes.github.io/canvas-test/src/Funny-demo/lowpoly/index.html (也可以在移动端看,不过因为计算量比较大,移动设备计算起来会比PC要多花些时间。)
做这种效果主要需要把图片三角化,以及对图片进行边缘化检测。这两个,第一个用到的delaunay三角化算法,第二个用到的sobel边缘检测算法。听起来偷挺高大上的,索性两个算法都有相应的开源组件可以直接拿来用:ironwallaby的delaunay组件 以及 Miguel Mota的sobel组件。
这两个算法sobel还好一点,delaunay就有点复杂了,待日后可以研究一下。不过目前只为做出个效果的话,还是可以用这些组件的。
两个最重要的组件都有了,剩下的事就很简单了:
先将图片绘制到canvas上:
canvas.width = (img.width > 800) ? 800 : img.width;
canvas.height = img.height * canvas.width/img.width; ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
然后获取到canvas的imgData,再通过sobel计算返回新的imgData
var imgData = ctx.getImageData(0, 0, canvas.width, canvas.height); var newImgData = Sobel(imgData);
如果我们把newImgData放到canvas上,就会发现,彩色图片变成了这样的灰度图片:
由于上面说的那个Sobel组件不是很适合自己的用法,同时代码也有不恰当的地方,所以自己做了适当修改和优化,优化了循环方法,加快了运算速度,同时加入了回调函数。详见该项目github中的sobel.js文件
在Sobel方法中对imgData.data进行遍历的时候,会调用回调函数,在回调中把颜色值大于40(也就是灰度为rgb(40,40,40)以上的)的坐标点记录下来。然后随机获取一部分边缘点,再加入一些随机出来的坐标 以及 四个边角的坐标值。这样,我们就可以获取到我们需要的坐标点了
var imgData = ctx.getImageData(, , canvas.width, canvas.height); // 收集色值大于40的边缘像素点
var collectors = [];
Sobel(imgData , function(value , x , y){
if(value > ){collectors.push([x , y]);}
}); // 添加一些随机点
for(var i=;i<;i++){particles.push([Math.random()*canvas.width , Math.random()*canvas.height]);} // 添加随机边缘点,数量为边缘点数量除于50
var length = ~~(collectors.length/), random;
for(var l=;l<length;l++){
random = (Math.random()*collectors.length)<<;
particles.push(collectors[random]);
collectors.splice(random , );
} // 添加四顶点坐标
particles.push([,] , [,canvas.height] , [canvas.width,] , [canvas.width,canvas.height]);
获取到坐标点后,就可以通过delaunay组件计算,获取到拍好次序的三角坐标数组,对这些数组里的点进行连线,就可以出现这样的效果:
当然,我们要的效果不是连线,而是对所有三角形进行颜色填充,也就是获取三角形的三个坐标,然后计算出中心点的坐标,再根据中心点坐标在imgData里获取到相应的rgb的颜色值,然后填充到三角区域就可以了:
// 使用delaunay三角化获取三角坐标
var triangles = Delaunay.triangulate(particles); var x1,x2,x3,y1,y2,y3,cx,cy;
for(var i=0;i < triangles.length; i+=3) {
x1 = particles[triangles[i]][0];
x2 = particles[triangles[i+1]][0];
x3 = particles[triangles[i+2]][0];
y1 = particles[triangles[i]][1];
y2 = particles[triangles[i+1]][1];
y3 = particles[triangles[i+2]][1]; // 获取三角形中心点坐标
cx = ~~((x1 + x2 + x3) / 3);
cy = ~~((y1 + y2 + y3) / 3); // 获取中心点坐标的颜色值
index = (cy*imgData.width + cx)*4;
var color_r = imgData.data[index];
var color_g = imgData.data[index+1];
var color_b = imgData.data[index+2]; // 绘制三角形
ctx.save();
ctx.beginPath();
ctx.moveTo(x1, y1);
ctx.lineTo(x2, y2);
ctx.lineTo(x3, y3);
ctx.closePath();
ctx.fillStyle = "rgba("+color_r+","+color_g+","+color_b+",1)";
ctx.fill();
ctx.restore();
}
上面有一点要注意,获取到的中心点坐标一定要取整,才能够获取到正确的颜色参数,如果想着不取整,而是在获取rgb索引的时候再取整,获取到的颜色值就是错的。因为这样获取到的那个像素点就不是我们要的中心像素点。
颜色也获取到后,就是简单的连线,然后填充操作了,最后出来的效果就是:
虽然没有设计师手动描出来的好看,不过也方便很多,做来玩玩还是挺有意思的。
源码地址,有兴趣的可以一看哈:
https://github.com/whxaxes/canvas-test/tree/gh-pages/src/Funny-demo/lowpoly
用canvas 实现个图片三角化(LOW POLY)效果的更多相关文章
- 基于HTML5 Canvas实现的图片马赛克模糊特效
效果请点击下面网址: http://hovertree.com/texiao/html5/1.htm 一.开门见山受美国肖像画家Chuck Close的启发,此脚本通过使用HTML5 canvas元素 ...
- canvas生成遮罩图片
首先我们知道css3中增加了不少好用.好玩的css3样式可以使用.今天我们要说到是遮罩. 它的使用方式也不复杂,和background使用方式差不多.使用mask-image就 ...
- Canvas + JavaScript 制作图片粒子效果
首先看一下源图和转换成粒子效果的对比图: 左侧图片为源图,右侧图片为粒子效果图.该效果是在Canvas画布上制作的.将图片制作成粒子效果相对而言是比较简单的.重点了解两个知识点即可 1:图 ...
- [js高手之路] html5 canvas系列教程 - 图片操作(drawImage,clip,createPattern)
接着上文[js高手之路] html5 canvas系列教程 - 文本样式(strokeText,fillText,measureText,textAlign,textBaseline)继续,本文介绍的 ...
- 微信小程序--canvas画布实现图片的编辑
技术:微信小程序 概述 上传图片,编辑图片大小,添加文字,改变文字颜色等 详细 代码下载:http://www.demodashi.com/demo/14789.html 概述 微信小程序--ca ...
- canvas 2.0 图片绘制
绘制图片drawImage 2013.02.21 by 十年灯·一条评论 本文属于<html5 Canvas画图系列教程> 这里的绘制图片是指把一张现成的图片,绘制到Canvas上面. 有 ...
- HTML5 Canvas前台压缩图片并上传到服务器
1.前台代码: <input id="fileOne" type="file" /> <input id="btnOne" ...
- 基于canvas图像处理的图片展示demo
图片展示网页往往色彩繁杂,当一个网页上有多张图片的时候用户的注意力就很不容易集中,而且会造成网站整个色调风格的不可把控. 能不能把所有的预览图变成灰度图片,等用户激活某张图片的时候再上色呢? 以前,唯 ...
- 用canvas给视频图片添加特效
Canvas制作视频图片特效 1. Canvas介绍 1.1Canvas是html5上的一个画布标签,功能有点类似java的swing.可以在canvas上画线条 弧线, 文字 就是画布的功能. 具体 ...
随机推荐
- java学习之 反射
以前学习java只是学习了基本语法操作,各种常用方法的使用,随着慢慢学习,很多大神都觉得要想成为大神,就必须把java的反射给理解透,这样我就带着好奇的心去学习到底反射是什么玩意,所以就上网找资料学习 ...
- putty-不输入密码直接登陆
在桌面建立新的快捷方式,命令行填写如下: d:\soft\putty.exe -pw 你的口令 用户名@服务器地址注意更换你的putty.exe的路径,为了避免出错,这里有个窍门,你可以找到putty ...
- 磁盘配额-----quota
为什么要使用磁盘配额:为了限制普通用户使用普通磁盘的空间与创建文件的个数等. 不至于个别人的浪费影响所有人的使用. 需要安装quota的软件包. mount -o usrquota,grpquota ...
- RCP常见问题
1.NoClassDefFoundError 解决办法: 查下依赖和插件启动情况 (manifest的requires和Import.osgi console插件启动情况) manifest的runt ...
- [译] 企业级 OpenStack 的六大需求(第 2 部分):开放架构和混合云兼容
全文包括三部分: 第一部分:API 高可用和管理以及安全模型 第二部分:开放架构和混合云兼容 第三部分:弹性架构和全球交付 在本系列的第一部分,我介绍了企业级 OpenStack 的六大需求.现在,我 ...
- 给深度学习入门者的Python快速教程 - numpy和Matplotlib篇
始终无法有效把word排版好的粘贴过来,排版更佳版本请见知乎文章: https://zhuanlan.zhihu.com/p/24309547 实在搞不定博客园的排版,排版更佳的版本在: 给深度学习入 ...
- 第18章 图元文件_18.2 增强型图元文件(emf)(2)
18.2.7 增强型图元文件的查看和打印程序 (1)传递EMF到剪贴板,剪贴板类型应为:CF_ENHMETAFILE (2)CopyEnhMetaFile用于复制图元文件 (3)剪贴板中的图元文件会自 ...
- 在Ubuntu14.04下安装vsftp服务器
猜想在Ubuntu下搭建ftp服务器来实现windows和ubuntu下文件互传是一件很简单的事儿,但是在网上找了好几篇文章都不行,故自己在这里总结一下方法. 首先安装vsftp服务器 sudo ap ...
- [No000030]程序员节发点别的:中国教育整个把人脑子搞坏了-易中天
导读 在易中天看来,中国教育和中国文化的问题一样,是弱智化.搞坏的原因是什么?是我们的教育评价目标就是"成王败寇"四个字.他明确提出反对励志,反对培优,反对成功学,反对望子成龙.他 ...
- git的两本推荐书
1. pro git, 可以网页直接看 http://iissnan.com/progit/?spm=5176.100239.blogcont5843.18.nUJDcK 2. Git权威指南 < ...