本文是《Unreal Engine 4 手绘风滤镜(Paint Filter)即 桑原滤镜(Kuwahara Filter)教程》的下半部分,上半部分请见《Unreal Engine 4 手绘风滤镜(Paint Filter)即 桑原滤镜(Kuwahara Filter)教程(上)》
作者|Tommy Tran May 1 2018 | 翻译 开发游戏的老王

文章目录

  • 选择方差最低的核
  • 方向性桑原滤镜(Directional Kuwahara filter)
  • 索贝尔是如何工作的
  • 获取局部走向
  • 什么是矩阵
  • 旋转核
  • 构造旋转矩阵

选择方差最低的核

添加如下代码获得方差最低的核

// 1
float3 FinalColor = MeanAndVariance[0].rgb;
float MinimumVariance = MeanAndVariance[0].a;// 2
for (int i = 1; i < 4; i++)
{if (MeanAndVariance[i].a < MinimumVariance){FinalColor = MeanAndVariance[i].rgb;MinimumVariance = MeanAndVariance[i].a;}
}return FinalColor;

解释一下上述代码:

  1. 创建了两个变量保存最终的颜色和最小方差(都是用第一个核的平均值和方差作为初始值)。
  2. 遍历其余的三个核,如果当前核的方差小于最小方差,就意味着找到了新的FinalColorMinimumVariance。遍历完毕以后所输出FinalColor当热就是方差最低的核的平均值了。

然后找到 Materials\PostProcess文件夹,打开PP_Kuwahara,点击应用,再回到主编辑界面就可以看到效果了。

效果看起来不错,但是如果你贴近一看,会发现一些奇怪的“块状斑”。下图中我把它们高亮标注了一下:


这是使用轴向平行核(axis-aligned kernel)产生的副作用。一种除去这种块状斑的方法就是使用改进版的滤镜,我们称之为方向性桑原滤镜(Directional Kuwahara filter)

方向性桑原滤镜(Directional Kuwahara filter)

这种滤镜和之前的很类似,只不过它平行于像素的局部走向。下面是个核大小为3×5的方向性桑原滤镜:

注:因为我们把一个核视为一个矩阵(matrix),所以以Height x Width的形式书写它的维度,而不是像往常一样写成Width x Height。下文中我们会继续介绍矩阵的知识。

核首先要计算出像素边缘的走向,然后将整个核旋转使其平行。

我们使用索贝尔算子(Sobel)进行卷积运算来获得局部走向。如果索贝尔这个词你听起来很熟悉,八成因为它是一非常经典的边缘检测技术。既然它是一种边缘检测技术,我们能用它来获取局部走向么?我们先来了解一下索贝尔的工作原理,你就明白了。

索贝尔是如何工作的

索贝尔使用2个核

Gx用于获取水平方向的梯度;Gy用于获取垂直方向的梯度。我们以下面3×3的灰度图为例:

首先,使用中间的像素核每个核进行卷积。

译者注:对应单元格中的值相乘再相加


如果把每对值都标记到一个2D平面上,那么我们就可以将这个向量所指的方向视为像素的边缘走向

然后我们可以对这个斜度值求反正切(arc tangent 或 atan),然后就可以用这个角度对核进行旋转了。

这就是我们利用索贝尔来计算像素局部走向的方法。

获取局部走向

打开Global.usf将下列代码添加到 GetPixelAngle():

float GradientX = 0;
float GradientY = 0;
float SobelX[9] = {-1, -2, -1, 0, 0, 0, 1, 2, 1};
float SobelY[9] = {-1, 0, 1, -2, 0, 2, -1, 0, 1};
int i = 0;

注意:GetPixelAngle()函数的}一定不要写!!!前面文章讲过的知识点!

解释一下每个变量的意义:

  • GradientX: 保存水平方向的斜度
  • GradientY: 保存垂直方向的斜度
  • SobelX: 将水平索贝尔核存储到一个数组中
  • SobelY: 将垂直索贝尔核存储到一个数组中
  • i: 用于访问SobelX和SobelY数组中的元素

接下来使用SobelX 和 SobelY 实施卷积,代码如下:

for (int x = -1; x <= 1; x++)
{for (int y = -1; y <= 1; y++){// 1float2 Offset = float2(x, y) * TexelSize;float3 PixelColor = SceneTextureLookup(UV + Offset, 14, false).rgb;float PixelValue = dot(PixelColor, float3(0.3,0.59,0.11));// 2GradientX += PixelValue * SobelX[i];GradientY += PixelValue * SobelY[i];i++;}
}

解释一下代码:

  1. 前2行获取采样像素颜色。第3行对该颜色去色转换成一维灰度值。相较于计算每个颜色通道的灰度这样做更简单。
  2. 对于每一个核,让它乘以对应格子里的像素灰度,然后把值累加到相应的斜度变量中(即GradientX和GradientY),然后i++继续处理下一个核元素。

直接把斜度值代入atan()函数。将下面的代码添加到for循环的下面:

return atan(GradientY / GradientX);

现在我们拥有了获取像素角度的函数,还需要研究一下如何旋转核。一种方法就是使用矩阵(matrix)。

注:实际上你也可以使用基本的三角方法来旋转,只不过我觉得这里是一个学习矩阵的好机会,因为它们实在是好用。

什么是矩阵

矩阵就是一个数字组成的二维数组。例如,下面是一个2×3的矩阵(2行 3列):

矩阵本身看起来没什么意思。但当你用一个向量和矩阵相乘的时候,就会体会到它的强大威力了。它可以让你很方便地进行旋转缩放等操作。如何使用矩阵来实现旋转呢?

在坐标系统中,每个维度都可以用向量表示。我们称之为基向量,它们定义了坐标轴的正方向。

下面是几个不同基向量的例子。红色箭头表示X方向,绿箭头表示Y方向。

我们可以使用基向量构建一个旋转矩阵,来旋转一个向量。简单地说,就是一个包含着旋转后基向量位置的矩阵。举个例子:你有一个向量(橙色箭头所示)(1, 1)

假设我们想顺时针将它旋转90度。首先,我们要把基向量先旋转该角度。

然后,以新的基向量位置构造一个2×2的矩阵。第一列是红色箭头的位置,第二列是绿色箭头的位置

最后,使用橙色向量和旋转矩阵进行矩阵乘法。其结果就是橙色向量的新位置。

注:你没必要知道矩阵如何相乘,因为HLSL已经内置了相关函数。

惊喜不惊喜?更牛X的是你甚至可以使用上面的矩阵将任意二维向量顺时针旋转90度。对于滤镜来讲,这就意味着我们只需为每个像素构造一次旋转矩阵,就可以为整个核所使用。

接下来该使用旋转矩阵旋转核了。

旋转核

首先,修改GetKernelMeanAndVariance()函数使其能够接受2×2的矩阵。这是因为,我们得在Kuwahara.usf 中构建这旋转矩阵并把它传入其中。将GetKernelMeanAndVariance()改为:

float4 GetKernelMeanAndVariance(float2 UV, float4 Range, float2x2 RotationMatrix)

接着把里层for循环的第一行改为:

float2 Offset = mul(float2(x, y) * TexelSize, RotationMatrix);

mul()函数将使用偏移量和RotationMatrix进行矩阵乘法。这样就可以以当前像素旋转了。

接下来,我们要构造旋转矩阵。

构造旋转矩阵

我们使用正弦(sine)和 余弦(cosine)来构造旋转矩阵:

关闭 Global.usf并打开Kuwahara.usf,然后将下面的代码添加到变量列表的底端:

float Angle = GetPixelAngle(UV);
float2x2 RotationMatrix = float2x2(cos(Angle), -sin(Angle), sin(Angle), cos(Angle));

第一行计算出当前像素的角度,第二行使用该角度创建旋转矩阵。

最后,我们将RotationMatrix传给每一个核。把GetKernelMeanAndVariance()改为如下形式:

GetKernelMeanAndVariance(UV, Range, RotationMatrix)

这就是方向性桑原滤镜的全部啦!关闭Kuwahara.usf并回到PP_Kuwahara,点击应用并关闭它。

下面就是原始的桑原滤镜和方向性桑原滤镜的对比。请尤其注意,方向性桑原滤镜不再有那些块状斑了。

注: 我们可以使用PPI_Kuwahara修改滤镜的大小。我建议将滤镜设为X半径大于Y半径。这将提高核沿边缘走向的大小,对于提高方向性有一定好处。

Unreal Engine 4 手绘风滤镜(Paint Filter)即 桑原滤镜(Kuwahara Filter)教程(下)相关推荐

  1. Unreal Engine 4 手绘风滤镜(Paint Filter)即 桑原滤镜(Kuwahara Filter)教程(上)

    原文|<Unreal Engine 4 Paint Filter Tutorial> 作者|Tommy Tran May 1 2018 | 翻译 开发游戏的老王 阅读时长|25分钟 内容难 ...

  2. 大气简洁手绘风商务计划书PPT模板

    今天小编将给大家带来得是主题为大气简洁手绘风商务计划书PPT模板.这份PPT模板的模板样式是以浅色作为模板的主色调,模板整体的制作围绕着手绘风展开,模板的内容也十分丰富多彩.下面就给大家展示该PPT模 ...

  3. 简约手绘风卡通教学课件PPT模板

    模板介绍 精美PPT模板设计,简约手绘风卡通教学课件PPT模板.一套说课PPT幻灯片模板,内含灰色多种配色,精美风格设计,动态播放效果,精美实用. 一份设计精美的PPT模板,可以让你在汇报演讲时脱颖而 ...

  4. 大气欧美彩色手绘风论文答辩PPT模板

    下面这篇文章内容当中,小编将和大家分享得是主题为大气欧美彩色手绘风论文答辩PPT模板.这份PPT模板的模板样式是以白色作为模板背景,可模板内的边框.图案的颜色则为彩色,模板的风格为大气欧美手绘风.下面 ...

  5. 给ggplot2来个「手绘风」

    本文借助xkcd在ggplot2里玩下手绘风,续前两篇: 一行Python代码让图形秒变「手绘风」 一款蠢萌蠢萌的可视化工具 xkcd主要有以下6个属性,详细功能都在后文代码里了- theme_xkc ...

  6. 敲可爱的手绘风可视化库——cutecharts

    作者:陈键冬,Python中文社区专栏作者,开源项目pyecharts核心开发者.pyecharts项目曾上榜 Github Trending in Open Source,目前star数量超过710 ...

  7. sketch 流程图_眼前一亮!2款免费手绘风流程图绘制工具

    我在另外一篇文章:[一款让Python开发效率提升50%的工具包]画了几张手绘风格的流程图,文章发表之后有读者私信我: "这种风格的流程图好漂亮啊,请问是用什么工具画的啊?" 的确 ...

  8. 手绘风 PPT:Google 是如何运作的?

     时间:2015-03-17 14:04 来源:网络 作者:Pearl.Wu <Google 是如何运作的>一书于今年 9 月出版,作者是如雷贯耳的 Google 前 CEO 埃里克· ...

  9. 手绘风 PPT:Google 是如何运作的?-20141116早读课

    <Google 是如何运作的>一书于今年 9 月出版,作者是如雷贯耳的 Google 前 CEO 埃里克·施密特和 Google 高级副总裁乔纳森·罗森伯格.本文中的 54 张插图则是施密 ...

  10. 蓝色手绘风毕业总结PPT模板

    四月中旬了,毕业季快到了,青春洒满了的校园,终究还是要离开了.那人,那事,那景,虽有不舍,万般留恋,但也终究要分离的.或许,这就是成长吧.在相遇,别离中结束一段旅程,又要开始新一段旅程. 即将离开校园 ...

最新文章

  1. Delphi - 数组 详解
  2. 【转】多线程Core Data
  3. 再见,备份——你好,真正的数据保护
  4. 专访英特尔戴金权 | AI和大数据正在这样重塑英特尔
  5. boost::mpi模块reduce() 集合的性能测试
  6. 手把手教你配置VS Code 远程开发工具,工作效率提升N倍
  7. ARM处理器异常处理
  8. 点广告才可以下载的代码
  9. 腾讯云主机安全防护(云镜)/usr/local/qcloud/YunJing/YDEyes/YDService 卸载
  10. python-包机制
  11. 解读——等级保护定级指南
  12. 两台电脑之间使用ntp做时间同步的总结
  13. Gerry-自定义报表组件
  14. 四轴mpu6050姿态角卡尔曼滤波代码分析
  15. 想要创业,却没货源?答应我,别只在阿里妈妈上找了好吗
  16. 如何科学有效地根治肾虚——下篇(如何有效治疗肾虚?)
  17. 对大量文本进行指定内容的批量替换
  18. 项目分享|小师弟手把手教你用蓝牙模块
  19. ANT无线通信技术(1) 简介
  20. AI鸟类识别实现自然生态环境数字化监测

热门文章

  1. java实现gps定位_GPS定位数据的提取与存储系统的设计
  2. Java、Java Web面试题(来源于MLDN、北方网)
  3. 自己动手写操作系统(五)
  4. 硬件开发笔记(二):硬件开发基本流程,制作一个USB转RS232的模块(一):开发基本过程和元器件选型
  5. 计算机三级数据库技术笔记
  6. 计算机操作系统(第四版)课后习题答案(完整版)[转载]
  7. Apache Pulsar 中文社区先锋奖与年度优秀案例出炉!
  8. java实现socket网络编程
  9. Android 高德地图 Native method not found: com.autonavi.amap.mapcore.MapCore.nativeNewInstance:(Ljava/lan
  10. 计算机二级vf相关 书籍,计算机等级考试二级VF笔试教材.doc