当前位置: 首页 > news >正文

翘首以盼的抗锯齿

Antialiasing

实际的图形学中是怎么实现反走样的呢?

我们不希望实际产出的图形有锯齿效果,那怎么办呢?

06fdde0120ff4b10b8382294479640bc.png

从采样的理论开始谈起吧 

Simpling theory

照片也是一种采样,把景象打散成像素放到屏幕上的过程:

9952d87c436040e4ac2145087fd29437.png

还可以在不同的时间(视频):

272da95e35814a6c97b3e1f3bf009cfc.png

 动画是定义在帧数上的

一个专业术语:Artifacts(瑕疵)

采样会产生很多问题,一个是锯齿:

b50e8204e72241589ddf39bd76711e93.png

还有问题比如说摩尔纹:

dc1451b6590e4724ae9dc31f87a8d43c.png

它怎么产生的呢?

 比如说把左边的奇数行奇数列都去掉变成小图,显示成和大图一样大,就能看到摩尔纹了(拿手机拍电脑显示器)

还有一种有意思的叫车轮效应,也是采样中出现的问题,比如人肉眼的采样速度跟不上高速旋转的物体:

6b3c2dc4fdd54addaa0c21deb03de848.png

我们如何反走样呢?

在采样之前做一个模糊(滤波),做一个模糊再采样就可以反走样:

 2b257c213daf49a287aa0bdef6a6e06a.png

d6d6b0f41c144d05adb178c102df534c.png

注意顺序是不能颠倒的,要先模糊再采样,如果先采样再模糊就变成了Blurred Aliasing:

9cd27af2f07e497696799203b1013178.png 那为什么采样的速度跟不上信号变换的速度就会走样?

Antialiasing in practice

Frequency Domain

先来看看频率吧:

f9c0fb9ce108460cb893a0a58b975e2c.png

调整前面的系数会得到不同的余弦波(频率不同) 

介绍正余弦波:

d3920e2a7baf465596ee1c2fcff63bda.png

为了介绍傅里叶级数展开(任何周期函数可以将其写成正余弦函数的线性组合)

还有个东西叫傅里叶变换:

c99a0ff7c92a414c8ed2b777bca86891.png

傅里叶变换:把函数变成不同频率的段并且显示出来:

64b12b35bb8d49e09c9f9bcfd6df205a.png 采样还原出的函数在不同频率下有出入,走样本质是信号变化的太快导致采样跟不上

 时域相乘,频域卷积,必须要到达两倍才不会走样

b0a8b08442f54108a4acebe365c71520.png

上面的结果就是采样两种频率完全不同的信号但是采样结果完全一样!

 这就是走样。

Filtering

把某个特定的频率给抹掉,说出对应信号如何变化

傅里叶变换就是从时域变到频域:

27c5158195f94a93ba1afc3a4fb6dcf0.png

 中心把其定义成低频的区域,周围全都是高频的区域,在不同频率的信息多少通过亮度表示

信息多集中在低频段

水平和竖直方向有道,我们在分析信号的时候我们会认为它是周期性重复的信号,那么对于不周期性重复的信号怎么办呢?

比如上图哪里重复了,并不重复对吧,我们通过右边界在重复左边界的内容,在边界会产生剧烈的变化从而产生极其高的高频,头顶位置和衣服下边缘位置的图像变化剧烈,导致高频区域为白色

滤波是去掉一些频率的内容,把低频信号抹掉,高频信号有意义:图像内容的边界

687f916495fc4d32a48906e67ab82b10.png

这种滤波叫高通滤波 (通过滤波器使只有高频的滤波可通过)

为什么高频信息就对应边界呢?

是不是变化很剧烈的才叫边界?

那就是高频信息呀,我们如果过滤掉高频只留下低频呢?

a416f17a78e34218a99add2139b4cddb.png

会发现边界模糊勒 

还可以做另外的实验:去掉高频。去掉低频,留下中庸之道,就可以提取到一些不是很明显的边界特征(中通滤波):

5bc40c182eed4e97bc4f64ee136d0255.png

卷积(Convolution)和滤波有关系,本质是一种点乘:

4fd0d143595e4a59935ee9e013badac8.png

这是要做一个卷积操作(加权平均):

7e46c9f66c2e48ea8a2408679e65e135.png

卷积定理: 时域卷积等于频域相乘,在时域上的乘积相当于在频域上的卷积:

29bd8929930c46a7b94e535ed931c9dc.png

1d14176bfb8242308d5cb929ddcbfa41.png

 卷积操作进行均值模糊,时域的卷积等于频域的乘积

滤波器本身是一个3×3的盒子,再×eq?%5Cfrac%7B1%7D%7B9%7D是为了不让图像整体的颜色值发生变化:

9b8904cab66a459cb8e8d9a423023f8b.png

 上面的例子显示出的结果是这个盒子是一个低通滤波器

bba02e0dc5b3421994d157bc40680891.png

时域上的一个小格子转换成频域,如果盒子在时域上变大了,那在频域上该如何变化呢?

盒子在时域上变大,反而在频域上变小:

9702e794d2634d618f186698dd1c44c3.png

 用越大的box做卷积会越来越模糊,如果用一个超级小的box就相当于根本没有做滤波,也就是说所有东西都被留了下来

采样是什么?是在重复频域上的内容(×另外一个函数):

d81836510fa24e6eb20e99457a07a78d.png

根据卷积定理,时域上的乘积对应到频域上为卷积,时域卷积等于频域乘积

采样就是在重复原始信号的频谱

1、左侧一列的中间是一个周期冲激序列,它在t=nT上纵坐标为无穷大,且频域(右中)仍是一个冲激序列,若用其与原信号相乘进行采样,采样的过程就不是让左边上中两图简单相乘就行了,它需要再进行一个过程将其转化为离散时间序列

2、实际采样时一个常用的办法是用一个在t=nT上纵坐标为1的采样序列乘信号源,这样可以直接得到采样信号

3、右上和右中卷积得到右下是可证的

为什么会产生走样就很显然了:采样的不同间隔会引起频谱以另外一个不同的间隔移动:

9bd0dc2fbb574112a7505f961fe3dcdc.png

 采样不够快,冲击函数频率低,卷积结果频率低(原始信号和复制粘贴的信号重合在一起了:发生走样,频谱搬移发生混合)

提升分辨率走样就会好很多(进行多的采样)

Reduce Alising

怎么改善走样呢?

052ab591386845a6a3458c8b175432f1.png

1.提高分辨率

2.先去模糊再去采样(模糊:低通滤波):

d1efd7ed0bb74310ae4a4a6b2beb6cb4.png

e4f54afed9644ba3a245dc940106d311.png 那么在实际的操作中,我们采用什么样的滤波器来进行卷积操作呢?

用一定大小的低通滤波器对其进行卷积:

07b7215b996146199b75bf29815c1954.png

 对像素覆盖的面积求平均:

27b2b40d0f3a44dd9a40a9bdc27b4d24.png

MSAA 

对更多采样点进行反走样(对反走样的近似,不能严格意义上解决反走样的问题),对大覆盖的点的近似:

18dc03b1cd43479095ffe36b7e87f78b.png

cc12082c4a31447eadeb2c30359a6d9d.png 

028ba31ba6304e08b10fb8a03bbccfca.png 

d09aa9ffb07049a89b0ae46935f0276f.png 

通过更多的样本进行反走样的第一步:模糊

 676864ff15fc47598a13ce2f1ee2020b.png

 MSAA是采样时提升了计算精度:

df2c91dd8fc449c68941c55ae88b1cd8.png

05a5a744f48c49f1a8a180ae2618a084.png 

通过增大计算量抗锯齿,还有其他抗锯齿的方法:FXAA(Fast Approximate AA:替换成没有锯齿的边界)、TAA(Temporal AA:找上一帧的信息)

Tips:Super resolution,超分辨率,把小图放大看到的全是锯齿,怎样把采样不够的图变得没有锯齿呢?可以通过深度学习的方法:DLSS(猜测)

Visibility/occlusion

首先需要谈的问题就是关于可见性,很直观的一种想法是先画远处的物体,再画近处的物体(把远处的物体遮挡住),由远到近做光栅化:(Painter's Algorithm)画家算法:

555ac0251ef74c2ab944998019f9a944.png

但是想要定义深度并不简单,需要光栅化排序:

da204d864e344033ac52f835b911a1b7.png

上面这种复杂的情况在深度上存在互相遮挡的关系,也就没办法用亲爱的画家算法,为了解决这个问题,在图形学中引入了一个概念:Z-Buffering

Z-Buffering

深度缓冲84144df9616640509bd52144d7ada7e6.png

 对三角形的覆盖关系不好判断,但是可以面向像素排序,记录像素离我们比较近的距离

最后得到的结果是要渲染出一幅画面:

cd2f42a7ce4f4a2b909567eabae90c14.png

这两幅图永远都是同时生成的,那算法在一开始的时候该如何进行呢?

看像素的具体情况,更新最浅深度:

ac623824a9b94441a2f66c1d5443adb1.png

深度缓存工作实例:

cec161338af1479eababbeafbf69b4a7.png 

涂新颜色、更新最小深度值 

深度缓存算法有一个好处:与顺序无关,不会有两个浮点数的值完全一样(出现深度完全一样的情况),深度缓存算法被广泛的应用于图形学

f68362e6eebb49b7bddfc6f794100c21.png

 

相关文章:

  • 【java 如何将字符串反转?】
  • C++访问越界
  • python 批量ts合并成一个mp4
  • Unity3D 基于YooAssets的资源管理详解
  • Web安全渗透攻防技术
  • 深度解读:Apache Kafka如何超越消息引擎的界限
  • echaerts图例自动滚动并隐藏翻页按钮
  • Android基础-性能优化
  • Iphone自动化指令每隔固定天数打开闹钟关闭闹钟(二)
  • Vue 跨平台性能优化十法
  • HLA高层体系结构1.0.0版本
  • 父组件调用子组件方法(组合式 API版)
  • 浅谈申请小程序地理位置权限的正确打开方式
  • (代码示例)使用setTimeout来延迟加载JS脚本文件
  • yolov5-ros模型结合zed2相机部署在 Ubuntu系统
  • Android 架构优化~MVP 架构改造
  • GraphQL学习过程应该是这样的
  • LeetCode刷题——29. Divide Two Integers(Part 1靠自己)
  • Node 版本管理
  • Promise初体验
  • STAR法则
  • vue和cordova项目整合打包,并实现vue调用android的相机的demo
  • 安卓应用性能调试和优化经验分享
  • 给初学者:JavaScript 中数组操作注意点
  • 观察者模式实现非直接耦合
  • 检测对象或数组
  • 优秀架构师必须掌握的架构思维
  • 远离DoS攻击 Windows Server 2016发布DNS政策
  • 怎么把视频里的音乐提取出来
  • 这几个编码小技巧将令你 PHP 代码更加简洁
  • ​iOS安全加固方法及实现
  • ${factoryList }后面有空格不影响
  • (003)SlickEdit Unity的补全
  • (2)Java 简介
  • (C语言)编写程序将一个4×4的数组进行顺时针旋转90度后输出。
  • (vue)页面文件上传获取:action地址
  • (十一)图像的罗伯特梯度锐化
  • (一)appium-desktop定位元素原理
  • (原創) 人會胖會瘦,都是自我要求的結果 (日記)
  • (最优化理论与方法)第二章最优化所需基础知识-第三节:重要凸集举例
  • .gitignore
  • .net core webapi 大文件上传到wwwroot文件夹
  • .net core 依赖注入的基本用发
  • .net 打包工具_pyinstaller打包的exe太大?你需要站在巨人的肩膀上-VC++才是王道
  • .NET 指南:抽象化实现的基类
  • .NET命名规范和开发约定
  • .py文件应该怎样打开?
  • @kafkalistener消费不到消息_消息队列对战之RabbitMq 大战 kafka
  • @private @protected @public
  • [AAuto]给百宝箱增加娱乐功能
  • [BZOJ1178][Apio2009]CONVENTION会议中心
  • [C进阶] 数据在内存中的存储——浮点型篇
  • [Django 0-1] Core.Email 模块
  • [flask] flask的基本介绍、flask快速搭建项目并运行
  • [Fri 26 Jun 2015 ~ Thu 2 Jul 2015] Deep Learning in arxiv