【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为例介绍如何保存股票数据到本地. 一.大致思路:我们先获取 ...
随机推荐
- [ZJOI 2010]count 数字计数
Description 题库链接 问你 \([l,r]\) 区间内所有整数中各个数码出现了多少次. \(1\leq a\leq b\leq 10^{12}\) Solution 数位 \(DP\) . ...
- [HNOI 2014]道路堵塞
Description A国有N座城市,依次标为1到N.同时,在这N座城市间有M条单向道路,每条道路的长度是一个正整数.现在,A国 交通部指定了一条从城市1到城市N的路径,并且保证这条路径的长度是所有 ...
- POJ1222熄灯问题
千年老题,以前用枚举做,现在用高斯消元做 自由元直接做成0即可 #include<cstdio> #include<cstdlib> #include<algorithm ...
- 【vijos1943】上学路上
题目戳这里 描述 小雪与小可可吵架了,他们决定以后互相再也不理对方了.尤其是,他们希望以后上学的路上不会再相遇. 我们将他们所在城市的道路网视作无限大的正交网格图,每一个整数点 (x,y) 对应了一个 ...
- 配置mysql使其允许外部ip进行登录
这两天在做一个数据库的项目,用到了mysql,需要通过外部的ip远程访问mysql,发现默认的mysql是不允许远程访问的,需要做简单的配置. 如下: 1. 打开一个终端(cmd)输入 mysql - ...
- git日常使用经验积累
1 git merge origin/develop 将远程分支合并到本地,一般先执行合并,解决冲突,然后再git commit合入新建的分支,推送到远程分支里面,最后码云上找pl pull requ ...
- 如何导入python中的模块
作为一名新手Python程序员,你首先需要学习的内容之一就是如何导入模块或包.但是我注意到,那些许多年来不时使用Python的人并不是都知道Python的导入机制其实非常灵活.在本文中,我们将探讨以下 ...
- Delphi 日期时间函数
DateUtils.IncYear();DateUtils.IncMonth();DateUtils.IncWeek();DateUtils.IncDay();DateUtils.IncHour(); ...
- Linux 查看系统硬件信息汇总 (部份实例详解Centoso为例)
1.cpu #lscpu命令,查看的是cpu的统计信息.(部分旧版本不支持) Disk /dev/sda: bytes heads, sectors/track, cylinders Units = ...
- 单选、多选框根据value值设置选中
$("input:checkbox[value='video']").parent().addClass('checked'); $("input:radio[value ...