当前位置:首页 > 代码·功能电脑·技巧 > 正文

使用Canvas把照片转换成素描画

今天看到腾讯前端开发团队以前发的文章,感觉很有用处,就分享给大家啦

0208516qY

一、引子

话说前阵子想把一张照片转换成素描,然后发个微博。结果发现mac上没找到能直接转换素描的软件(PS不算,可要好几步呢),坑爹啊~~google 了下,Web上竟然也是没有直接把照片转换成素描的东西,连让我包含期望的美图秀秀(Web版)竟然都没有素描功能,T_T。

手机上是有很多这类app,但是我只是想一键转换下,发个微博嗟,至于这么折腾么……

所以自己动手整一个在线版的吧,没怎么用过canvas,正好可以顺道熟悉下。等不及的童鞋可以先到这里看看效果(http://appx.imatlas.com/sketching/)。

二、怎么转换

刚冒出这个想法的时候,简直是一头雾水诶~数学不行、PS不懂、图形学忘光了……

还好有万能的google,翻了几页,找到一个ps制作素描图片的步骤——虽然我不懂,但是如果按照这个步骤用PS能做成素描,我用代码也一定可以的。嗯,一定是的。

PS里面最简单的一个转换素描的步骤为:

  1. 去色(黑白化)
  2. 复制一份,反相
  3. 把复制后的图层叠加方式设为颜色减淡
  4. 高斯模糊

PS里面的具体步骤我就不详说了,可以看这篇文章。既然知道了实现步骤,我只要用JS把这些算法都实现了就行啦,哇哈哈哈~

三、原理什么的

去色:把图片变成黑白图,只要把每个像素的R、G、B设为亮度(Y)的值就行了。关于R、G、B、Y的关系可以看到这里看看,这里只要记住这条公式:Y = 0.299R + 0.587G + 0.114B。

反相:就是将一个颜色换成它的补色。补色就是用255(8位通道模式下,255即2的8次方,16位要用65535去减,即2的16次方)减去它本身得到的值:R(补) = 255 – R。

颜色减淡:其计算公式是:结果色 = 基色 + (混合色 * 基色) / (255 – 混合色),在这里找到的这条公式,原理我就不多说了,因为我也不大懂(^_^,图形学睡过去了……)。

高斯模糊:嗯,这个是最让我抓头摸脑的。一开始没怎么理解到这个算法,纠结了两天。最后终于灵光一闪,想通了(还好没晕过去大睡三天~.~)!网上有很多C++的实现,但是基本没找到JS的。一开始不想去理解高斯模糊,就尝试把C++代码改成JS的,改了半天,终于放弃了~想明白之后,自己照原理写了个,想不到还挺容易的,呃……具体的高斯模糊原理,就在这里这里这里看吧,老衲就不误人子弟了。

本项目已经托管到了Github(https://github.com/iazrael/sketching),这几个方法的源码可以到上面查看。稍微提下实现素描的一个注意事项:去色之后需要拷贝一份像素数组备用,开始是用数组的slice方法来拷贝像素数组的,结果经常需要800ms左右的时间;后来尝试了直接用canvas,putImageData之后再调用getImageData来“曲线救国”,结果只用10几毫秒就可完成,简直让老衲老泪纵横诶~其代码如下:

JavaScript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
/**
 * 素描
 * @param  {Object} imgData 
 * @param  {Number} radius 取样区域半径, 正数, 可选, 默认为 3.0
 * @param  {Number} sigma 标准方差, 可选, 默认取值为 radius / 3
 * @return {Array}
 */
function sketch(imgData, radius, sigma){
    var pixes = imgData.data,
        width = imgData.width,
        height = imgData.height,
        copyPixes;
    discolor(pixes);//去色
    canvas.width = width, canvas.height = height;
    //复制一份
    ctx.clearRect(0, 0, width, height);
    ctx.putImageData(imgData, 0, 0);
    copyPixes = ctx.getImageData(0, 0, width, height).data;
    // 拷贝数组太慢
    // copyPixes = Array.prototype.slice.call(pixes, 0);
    invert(copyPixes);//反相
    gaussBlur(copyPixes, width, height, radius, sigma);//高斯模糊
    dodgeColor(pixes, copyPixes);//颜色减淡
    return pixes;
}

说起用法啊,那你可以问对人了,哈哈。狠狠的敲入app的网址:http://appx.imatlas.com/sketching/(注意只能用现代浏览器(Chrome,Firefox,Opera,Safari等)打开哦,IE9以前的老古董就甭来啦),然后拖拽一张图片到画布区(就是下面打开的灰色地带~),然后……就没有然后啦,最多2秒之后自动生成素描画。点击download按钮可以下载生成的图片。

如果感觉效果不太好,可以改下取样的半径(Sample size),为正整数,最小为1。如果你一定要填负数、小数,也会被取正取整(抠鼻)。之后点下action按钮,生成新的素描图。如果你还不明白,下面来看图说明

sketching 图示

sketching 图示

斋说都没益啦,实牙实齿效果才是王道,看看下面的原图:

 

原图

原图

转换后的素描图:

素描

素描

怎么样,效果是不是还不错咧,嘎嘎嘎。当然,这个算法未必是最好的,欢迎各位童鞋踊跃拍砖,^_^

PS:真的没有想到,腾讯的程序猿居然说“数学不行、PS不懂、图形学忘光了……”这么说让我们情何以堪啊,还用不用活了,做人哪,不能太谦虚,会害死别人的

标签:
上一篇: 下一篇:

9 条评论

评论加载中...
  1. 6楼
    来自天朝的朋友 未知浏览器 Unknow Os
    小容  

    飘雪好漂亮呀

    2015年2月6日 16:53 评论
  2. 其实直接用毁图秀秀可以做到 老实交代镇楼图是哪个妹子

    2015年2月6日 16:38 评论
  3. 4楼
    来自天朝的朋友 未知浏览器 Unknow Os
    中国历史  

    效果挺不错

    2014年11月5日 20:41 评论
  4. 地板
    来自天朝的朋友 谷歌浏览器 Windows 7
    星空、悔  

    还可以,就是没软件方便

    2014年8月6日 11:31 评论
  5. 板凳
    来自天朝的朋友 未知浏览器 Unknow Os
    吴尼玛  

    你的多说是怎样在首页调用留言数量的?

    2014年7月25日 15:39 评论
    • 直接安装多说的插件,然后评论合并就可以了

      2014年7月25日 19:36 评论
  6. 沙发
    来自天朝的朋友 未知浏览器 Unknow Os
    吴尼玛  

    支持一下

    2014年7月25日 14:04 评论

发表评论

不理你。不要啊!吃饭。吃惊。吃西瓜。飞吻!恭喜!Hi纠结!膜拜!OK抛媚眼。泡泡糖。抛钱。忍!生闷气!调皮。偷看。委屈。献花。疑问?抓狂!

小提示:Ctrl+Enter快速提交助您一臂之力~
加载中……