【NPR】铅笔画
写在前面
今天打算写一篇跟Unity基本无关的文章。起因是我上个星期不知怎么的搜到了一个网站 ,里面实现的效果感觉挺好的,后来发现是2012年的NPAR会议的最佳论文。看了下文章,觉得不是很难,就想着实现一下。后来发现国内有两个博主有相关的文章,一个是风吹夏天的文章,一个是Imageshop的文章。通过读论文和两位博主的文章基本对算法就走通了,剩下的就是编码了。原论文作者给出了算法第一个部分的代码,风吹夏天的文章在其基础上又给出了笔画部分的代码,但都不全。
我这篇文章就不赘述算法了,有兴趣的可以看论文或上面两个博主的文章,讲得都比较清楚。我把我实现的代码上传到了github的PencilDrawing项目中,包含了全部代码,基本可以实现论文中的效果,只是由于没有论文中使用的铅笔纹理,因此做不到100%一样。有兴趣的可以去下载下来玩玩看 :)
代码:我的github的PencilDrawing项目(Matlab代码)。
相关论文:Lu C, Xu L, Jia J. Combining sketch and tone for pencil drawing production[C]//Proceedings of the Symposium on Non-Photorealistic Animation and Rendering. Eurographics Association, 2012: 65-73.
概述
这篇文章想要做的事情就是,输入一张图像,输出一张铅笔画风格的图像。你可能会说,这不是PS的滤镜么?恩,的确PS有类似的功能,但效果不够好,当然技术好的童鞋可以通过多步加工得到更好的效果,但这篇文章的算法可以对输入图像一次就生成效果比较的铅笔画效果。比如下面的图像:
仔细观察的话,会发现这篇论文实现的效果有几个特点,一个是图像轮廓会有手绘的线条感,而不是像之前很多算法那样仅仅是进行边缘检测;另一个特点是它的图像整体色调更符合铅笔画的特征,比如有一些铅笔的笔触感,色调也更倾向于真实的铅笔画。
算法
非常详细的算法我就不再说明了,有兴趣的可以去看原论文和之前提到的两篇文章。这里大致讲一下算法流程:
首先需要生成笔画图像:
这是通过对图像计算梯度后,对像素进行方向分类,再对每个方向的像素分别和对应的算子进行滤波后得到的。
生成色调图像:
这一步是使用了论文里所谓的“基于模型的色调转换”,实际就是对真实的铅笔画的直方图进行分析,把整个直方图分成了三块:最亮的部分,中间灰度过渡部分和最暗的部分。作者使用了三个方程分别对这三个部分进行建模,再使用一组权重混合它们,得到目标直方图。这些权重是实验学习得到的,论文里提到了三组不同的权重,我在github的项目页也有所说明。最后,根据这个目标直方图对图像进行直方图匹配即可得到需要的色调图像。这一步总是无法得到和论文里完全一样的结果,没办法,论文总会有一些参数和小修改不会写进去,我猜想大概是进行了一些图像平滑的操作。
生成铅笔画风格的图像:
这一步会使用一张铅笔画纹理,例如:
然后使用这张纹理来模拟上一步得到的色调图,这是通过对铅笔画纹理进行指数运算+保证局部平滑求最优解来得到的。这一步使用的纹理对最后得到的画面效果很重要,无奈作者没有给出他们论文里使用的各个铅笔画纹理,因此我就只能从网上找喽,所以效果也不完全一样。这一步局部平滑度越低,得到的结果图像的铅笔笔触越明显。
最后,我们只需要把第1步得到的笔画图像和第3步得到的图像进行相乘,即可得到最终的图像:
对彩色图像的处理需要先把图像从RGB空间变换到YUV空间,然后只对Y分量进行上述处理,最后再重新变换会RGB空间即可。
结果
这个算法健壮性还是不错的,作者在他们的网站上给出了非常多的例子!不过通过我的实践,我认为很多图像要想得到比较好的效果还是要不断调整参数的,比较重要的参数有生成色调图时使用的三个混合权重(我一般使用最亮的那一组);笔画的长度,一些小图(例如400x400)要使用比较小的算子,例如6或7,大图可以适当使用10以上大小的算子,这会影响生成的图像中轮廓的铅笔笔画长度;还有就是尽管作者没有说明,但我觉得一些比较暗的图像需要最后有一个类似伽马的计算,把画面整体提亮。
下面给出一些效果:
这个是作者给出的众多测试图之一:
下面这个是武汉大学的落叶(来自于昨天我的朋友圈中某个武大美铝的照片,虽然一张落叶看不出什么,但不得不说武大真的是太美了…):
当当当,最后当然是我的母校,交大啦~下面这个是上海交大徐汇小区的图书馆:
其他的就不贴了,有兴趣的可以直接去github上下载。最后,have fun~
【NPR】铅笔画的更多相关文章
- 关于Cewu Lu等的《Combining Sketch and Tone for Pencil Drawing Production》一文铅笔画算法的理解和笔录。
相关论文的链接:Combining Sketch and Tone for Pencil Drawing Production 第一次看<Combining Sketch and Tone f ...
- Little Sympathy for Bear Stearns : NPR
Little Sympathy for Bear Stearns : NPR Little Sympathy for Bear Stearns
- 【NPR】卡通渲染
写在前面 我的博客讲过好几篇卡通渲染了,比如[Unity Shader实战]卡通风格的Shader(一).[Unity Shader实战]卡通风格的Shader(二).[NPR]漫谈轮廓线的渲染.[S ...
- 【NPR】非真实感渲染实验室
写在前面 前几天在知乎看到一个问题--关于非实感图形学或者风格化渲染有哪些好的书或者paper,我刚好接触过一些就去里面回答了一下.答完以后突然想在Unity里搞一个这样的集锦,把一些简单的NPR论文 ...
- 【NPR】漫谈轮廓线的渲染
写在前面 好久没写文章.最近在看<Real Time Rendering, third edition>这本书,看到了NPR这一章就想顺便记录下一些常见的轮廓线渲染的方法. 在非真实感渲染 ...
- python 爬虫下载英语听力新闻(npr news)为mp3格式
想通过听实时新闻来提高英语听力,学了那么多年的英语,不能落下啊,不然白费背了那么多年的单词. npr news是美国国家公共电台,发音纯正,音频每日更新,以美国为主,世界新闻为辅,比如最近我国武汉发生 ...
- Unity Shader NPR 卡通渲染
卡通渲染的主要原理包含两个方面: 1.轮廓线的描边效果 2.模型漫反射离散和纯色高光区域的模拟 描边: 描边的实现方法采用将模型的轮廓线顶点向法线(或顶点)的方向扩展一定的像素得到.也可通过边缘检测( ...
- ASP.NET_各个币种之间的汇率转换(实时)使用Yahoo汇率。
近期开发支付平台的时候有运用到各国的实时汇率之间的转换问题,于是在往上找了很多相关资料,以下就是一些参考网址: 1.提供API接口的网站:https://www.showapi.com:这个网站有提供 ...
- Python使用TuShare将股票数据保存到Oracle数据
TuShare是个获取股票数据的模块包,我们进行分析,需要将股票数据保存到本地,避免每次都从网上获取,由于本机装有ORCALE,以ORACLE为例介绍如何保存股票数据到本地. 一.大致思路:我们先获取 ...
随机推荐
- POJ 3590 The shuffle Problem
Any case of shuffling of n cards can be described with a permutation of 1 to n. Thus there are total ...
- SAC E#1 - 一道神题 Sequence1
题目背景 小强和阿米巴是好朋友. 题目描述 小强很喜欢数列.有一天,他心血来潮,写下了一个数列. 阿米巴也很喜欢数列.但是他只喜欢其中一种:波动数列. 一个长度为n的波动数列满足对于任何i(1 < ...
- 【LSGDOJ1383】修改回文 dp
题目描述 为了跟踪所有的牛,农夫JOHN在农场上装了一套自动系统. 他给了每一个头牛一个电子牌号 当牛走过这个系统时,牛的名字将被自动读入. 每一头牛的电子名字是一个长度为M (1 <= M & ...
- ●BZOJ 1531 [POI2005]Bank notes
题链: http://www.lydsy.com/JudgeOnline/problem.php?id=1531 题解: 单调队列优化多重背包DP (弱弱的我今天总算是把这个坑给填了...) 令V[i ...
- 文本分类学习 (五) 机器学习SVM的前奏-特征提取(卡方检验续集)
前言: 上一篇比较详细的介绍了卡方检验和卡方分布.这篇我们就实际操刀,找到一些训练集,正所谓纸上得来终觉浅,绝知此事要躬行.然而我在躬行的时候,发现了卡方检验对于文本分类来说应该把公式再变形一般,那样 ...
- 利用maven install jar到项目当中
接着上面利用maven打好的jar包.把刚刚打好的包放入其他项目当中怎么办? 只需要在相同的目录下执行mvn install,maven会自动把jar放到本地仓库中. 这样,原先maven项目中缺少依 ...
- JS中怎样判断undefined(比较不错的方法)
最近做项目碰到的问题.拿出来跟大家分享一下吧. 用servlet赋值给html页面文本框值后,用alert来弹出这个值.结果显示"undefined".所以我就自然的用这个值和字符 ...
- RxSwift 系列(八) -- Error Handing Operators
前言 本篇文章我们将学习RxSwift中的错误处理,包括: catchErrorJustReturn catchError retry retry(_:) catchErrorJustReturn 遇 ...
- js中对象的自定义排序
//并返回一个可以用来对包含该成员的对象数组进行排序的比较函数 var compareAsc = function (prop) { return function (obj1, obj2) { va ...
- jdk1.7和jdk1.8区别
转自:http://www.2cto.com/kf/201307/225968.html 本文是我学习了解了jdk7和jdk8的一些新特性的一些资料,有兴趣的大家可以浏览下下面的内容. 官方文档:ht ...