跳转到内容

分形/扫描

来自维基教科书,开放世界中的开放书籍

扫描,采样

采样

  • 从函数、映射、图像中获取有限数量的值的过程。[1][2]
  • 在统计学、质量保证和调查方法学中,抽样是从统计总体中选择个体子集(统计样本)以估计整个总体的特征。统计学家试图收集代表所讨论总体的样本。抽样比测量整个总体成本更低,数据收集速度更快,并且可以在无法测量整个总体的情况下提供见解。


分类标准:

  • 遍数(单遍、多遍)
  • 网格(规则=均匀/不规则或自适应)
  • 随机(随机)/非随机
  • 有分解或无分解



按范围划分的采样类型

  • 点采样=点采样方法。种子是一个定义的、有理复杂的数字,它代表一个像素=像素中心。请注意,可以在一个像素内找到无限多个点,而许多这样的点可能具有与像素中心不同的颜色/行为。
  • 空间采样(样本之间发生了什么?):一个手动定义的同质网格=均匀采样
  • 1 像素近似=图像显示“平面上距离填充的朱利亚集至多为像素直径的点的集合”[3]
    • 超采样[4]=亚像素近似(分辨率)[5]


按自适应划分的采样

  • 规则、均匀(非自适应)采样
  • 自适应(非均匀)采样=自适应网格细化 (AMR)
    • 基于梯度局部分形分析的细节增强:分形图像模型的关键概念是分形维数能够稳健地表示图像的内在结构信息。[6][7]
    • 对复平面进行四叉树分解,并进行自适应细化,可以得到自适应近似
      • 自适应细分
      • “Mathematica 在需要时自动采样更多点以创建平滑的函数可视化”[8]
      • 自适应采样用于精确绘制数学曲线[9]





步骤

  • 预览
  • 最终渲染


变换或平面类型(参数或动态)划分的类型

扫描平面

  • 所有像素(平面逐像素扫描)一次通过
  • 相同的像素大小(规则、均匀网格)

它还取决于平面描述

int SetPlane(complex double center, double radius, double a_ratio){

	ZxMin = creal(center) - radius*a_ratio;	
	ZxMax = creal(center) + radius*a_ratio;	//0.75;
	ZyMin = cimag(center) - radius;	// inv
	ZyMax = cimag(center) + radius;	//0.7;
    double PixelWidth = (ZxMax-ZxMin)/iWidth;
    double PixelHeight = (ZyMax-ZyMin)/iHeight; // pixel_size = PixelWidth = PixelHeight
	return 0;

}

这里在Lisp

; common lisp. Here float values can be used,  there is no mapping
(loop for y from -1.5 to 1.5 by 0.1 do
      (loop for x from -2.5 to 0.5 by 0.05 do
            (princ (code-char 42))) ; print char
      (format t "~%")) ; new line

以及在C

/* c */
/* screen coordinate = coordinate of pixels */      
int iX, iY, 
iXmin=0, iXmax=1000,
iYmin=0, iYmax=1000,
iWidth=iXmax-iXmin+1,
iHeight=iYmax-iYmin+1;

/* world ( double) coordinate = parameter plane*/
const double ZxMin=-5;
const double ZxMax=5;
const double ZyMin=-5;
const double ZyMax=5;

/* */
double PixelWidth=(ZxMax-ZxMin)/iWidth;
double PixelHeight=(ZyMax-ZyMin)/iHeight;
double Zx, Zy,    /* Z=Zx+Zy*i   */
       Z0x, Z0y,  /* Z0 = Z0x + Z0y*i */

 for(iY=0;iY<iYmax;++iY)
      { Z0y=ZyMin + iY*PixelHeight; /* mapping from screen to world; reverse Y  axis */
        if (fabs(Z0y)<PixelHeight/2) Z0y=0.0; /* Zy = 0 is a special value  */    
        for(iX=0;iX<iXmax;++iX)
         {    /* initial value of orbit Z0 */
           Z0x=ZxMin + iX*PixelWidth;
          }
      }


由 Robert Munafo 完成的正常网格扫描绘图[10]

  /* Plot a single pixel, row i and column j

   NOTE:
     itmax is the maximum number of Mandelbrot iterations
     min_r is the real coordinate of the left edge of the image
     max_i is the imaginary coordinate of the top of the image
     px_spacing = pixel size  is the width of the image (in real coordinates) divided by the number of pixels in a row
     image aspect ratio = 1:1
  */
  void pixel_53(int i, int j, int itmax)
  {
    double cr, ci;

    ci = max_i - ((double) i) * px_spacing;
    cr = min_r + ((double) j) * px_spacing;
    evaluate_and_plot(cr, ci, itmax, i, j);
  }
  // modified code using center and radius to scan the plane 
  int height = 720;
  int width = 1280;
  double dWidth;
  double dRadius = 1.5;
  double complex center= -0.75*I;
  double complex c;
  int i,j;

  double width2; // = width/2.0
  double height2; // = height/2.0
  
  width2 = width /2.0;
  height2 = height/2.0;

complex double coordinate(int i, int j, int width, int height, complex double center, double radius) {
  double x = (i - width /2.0) / (height/2.0);
  double y = (j - height/2.0) / (height/2.0);
  complex double c = center + radius * (x - I * y);
  return c;
}

for ( j = 0; j < height; ++j) {
    for ( i = 0; i < width; ++i) {
      c = coordinate(i, j, width, height, center, dRadius);
      // do smth 
       }
     }

另一个版本

int main()
{
  int aa = 4;
  int w = 800 * aa;
  int h = 800 * aa;
  
  #pragma omp parallel for schedule(static, 1)
  for (int j = 0; j < h; ++j)
  {
    double y = (h/2 - (j + 0.5)) / (h/2) * r;
    for (int i = 0; i < w; ++i)
    {
      double x = (i + 0.5 - w/2) / (h/2) * r;
      double _Complex c = x + I * y;
      // proceed
    }
  }
  
  return 0;
}

平面分解

[编辑 | 编辑源代码]

四叉树

[编辑 | 编辑源代码]

四叉树类型

  • 区域四叉树
  • 点四叉树




// Quad-tree by Naoki Tsutae in Processing
// https://openprocessing.org/sketch/1769288
quadTree = (x, y, size) => {
 if (size < minRectSize) return;
 const n = noise((x + posx) * 0.001, (y + posy) * 0.001, variation);
 if (abs(n - 0.45) > size / maxRectSize) {
   rect(x, y, size);
 } else {
   size /= 2;
   const d = size / 2;
   quadTree(x + d, y + d, size);
   quadTree(x + d, y - d, size);
   quadTree(x - d, y + d, size);
   quadTree(x - d, y - d, size);
 }
};

区域四叉树

[编辑 | 编辑源代码]

区域四叉树表示空间划分,通过将区域分解为四个相等的象限、子象限等等,每个叶节点包含与特定子区域相对应的数据。树中的每个节点要么具有

  • 正好四个子节点
  • 或者没有子节点(叶节点)。

遵循这种分解策略的四叉树的高度(即,只要在子象限中有感兴趣的数据,就细分子象限)对正在分解的空间中感兴趣区域的空间分布敏感且依赖于此。区域四叉树是一种trie

深度为 n 的区域四叉树可用于表示包含 2n × 2n 个像素的图像,其中每个像素值均为 0 或 1。根节点表示整个图像区域。如果任何区域中的像素并非完全为 0 或 1,则将其细分。在此应用中,每个叶节点表示一个像素块,这些像素块均为 0 或 1。请注意,当这些树用于存储图像时,在空间方面可能会有潜在的节省;图像通常有许多大小可观的区域,在整个区域中具有相同的颜色值。与其存储图像中每个像素的二维数组,不如使用四叉树来捕获可能比我们否则需要像素分辨率大小的单元高出许多划分级别的相同信息。树分辨率和整体大小受像素大小和图像大小的限制。

区域四叉树还可以用作数据场的可变分辨率表示。例如,区域中的温度可以存储为四叉树,每个叶节点存储其表示的子区域的平均温度。

Koebe 四分之一定理:

Once b [the exterior distance estimate for c] is found, by the Koebe 1/4-theorem, we know there's no point of the Mandelbrot set with distance from c smaller than b/4. 
// code in Haskell by Claude Heiland-Allen https://mathr.co.uk/blog/2010-10-30_distance_estimation.html
exterior :: Square -> Bool
exterior s@(Square a b c d) = fromMaybe False $ do
  lb <- distance a
  lt <- distance b
  rb <- distance c
  rt <- distance d
  let k = 4 * sqrt 2 * size s
  return $ and
    [ lb + rb > k
    , lt + rt > k
    , lb + lt > k
    , rb + rt > k
    ]

抗锯齿和超采样

[编辑 | 编辑源代码]
计算最终颜色值

超采样超采样抗锯齿 (SSAA) 是一种空间抗锯齿方法,即用于从计算机游戏中渲染的图像或生成图像的其他计算机程序中消除锯齿(锯齿状和像素化边缘,俗称“锯齿”)的方法。锯齿的出现是因为与具有连续平滑曲线和线条的现实世界物体不同,计算机屏幕向观看者显示大量的小方块。这些像素大小相同,每个像素都有单一颜色。线条只能显示为像素集合,因此除非它是完全水平或垂直的,否则看起来会很锯齿。超采样的目的是减少这种效果。在像素内部的多个实例(而不仅仅是在中心,像正常情况一样)进行颜色采样,然后计算平均颜色值。这是通过以比要显示的分辨率高得多的分辨率渲染图像,然后将其缩小到所需大小,并使用额外的像素进行计算来实现的。结果是降采样的图像,在物体边缘的像素行之间具有更平滑的过渡。

样本数量决定了输出质量

超级采样,其他名称

  • 抗粒几何
  • 超级采样(下采样)[13][14]
  • 缩小尺寸
  • 缩小比例[15]
  • 亚像素精度

计算成本和自适应超级采样

[edit | edit source]

超级采样在计算上很昂贵,因为它需要更大的显卡内存和内存带宽,因为使用的缓冲区大小要大得多。[16] 解决这个问题的一种方法是使用称为自适应超级采样的技术,它只对物体边缘的像素进行超级采样。

最初,每个像素内只取几个样本。如果这些值非常相似,则只使用这些样本确定颜色。如果不是,则使用更多样本。这种方法的结果是,只有在必要的地方才会计算更多样本,从而提高性能。

类型

[edit | edit source]

在像素内取样时,必须以某种方式确定样本位置。虽然这样做的方法数量是无限的,但有一些方法是常用的。[16][17]

网格

[edit | edit source]

最简单的算法。像素被分成几个子像素,每个子像素的中心都会取一个样本。它快速且易于实现。但是,由于采样的规律性,如果使用的子像素数量较少,仍然会发生锯齿。

随机

[edit | edit source]

也称为随机采样,它避免了网格超级采样的规律性。但是,由于模式的不规则性,样本在像素的某些区域会变得不必要,而在其他区域则会缺失。[18]

泊松圆盘

[edit | edit source]

泊松圆盘采样算法[19] 将样本随机放置,然后检查任何两个样本是否过于接近。最终结果是均匀但随机的样本分布。但是,该算法所需的计算时间过长,不适合用于实时渲染,除非采样本身在计算上比样本点的定位更昂贵,或者样本点不会为每个像素重新定位。[18]


Poisson-disk sampling (blue noise) is the best sampling pattern. It maximizes the uniformity of the samples in addition to the randomness of their placement, which gets you the most bang for your buck with respect to the contribution of each sample. quaz0r on FF


链接

抖动

[edit | edit source]

对网格算法的修改,以近似泊松圆盘。像素被分成几个子像素,但样本不是从每个子像素的中心取的,而是从子像素内的随机点取的。聚集仍然可能发生,但程度较小。[18] 抖动也被推荐用于避免莫尔纹。

旋转网格

[edit | edit source]

使用 2×2 网格布局,但样本模式被旋转,以避免样本与水平或垂直轴对齐,这极大地提高了最常见情况下的抗锯齿质量。为了获得最佳模式,旋转角度为 arctan (1/2)(约 26.6 度),正方形被拉伸了倍。[20] [citation needed]

具有极端伪随机锯齿的图像示例

[edit | edit source]

因为分形具有无限的细节,并且除了算术舍入误差之外没有噪声,所以它们比照片或其他测量数据更清晰地说明了锯齿。逃逸时间(它们在像素的精确中心转换为颜色)在集合的边界处趋于无穷大,因此,由于锯齿,靠近边界的中心的颜色是不可预测的。此示例在其大约一半的像素中都有边缘,因此它显示出许多锯齿。第一张图像以其原始采样率上传。(由于大多数现代软件都会进行抗锯齿处理,因此可能需要下载完整尺寸的版本才能看到所有锯齿。)第二张图像以五倍的采样率进行计算,然后使用抗锯齿进行下采样。假设人们真的想要每个像素的平均颜色,那么这张图像就更接近了。它明显比第一张图像更有序。

为了正确比较这些图像,有必要以全尺寸查看它们。

在这种情况下,碰巧有额外的信息可用。通过使用“距离估计器”算法重新计算,识别出了非常靠近集合边缘的点,因此,集合边缘附近快速变化的逃逸时间会将异常精细的细节混叠进来。从这些计算出的点得出的颜色已被识别为其像素的异常不具有代表性。集合在那里变化得更快,因此单个点样本不能代表整个像素。在第三张图像中,这些点被替换为周围点的插值。这减少了图像的噪点,但也有使颜色变亮的副作用。因此,此图像与通过更大的计算点集获得的图像不完全相同。为了显示被丢弃了什么,第四张图像显示了被拒绝的点,这些点被混合到灰色背景中。

最后,“发芽涡轮机”非常规则,因此在向下取样以获取最近的像素时,在主“涡轮轴”附近可以清楚地看到系统性的(莫尔)混叠。第一张图像中的混叠看起来是随机的,因为它来自像素大小以下的所有细节级别。当抑制较低级别的混叠以制作第三张图像,然后再次对第三张图像进行降采样(无抗锯齿)以制作第五张图像时,第三张图像尺度上的顺序在第五张图像中表现为系统性的混叠。

图像的纯降采样具有以下效果(建议全尺寸查看)



代码

[edit | edit source]
 // subpixels finished -> make arithmetic mean
 char pixel[3];
 for (int c = 0; c < 3; c++)
   pixel[c] = (int)(255.0 * sum[c] / (subpix * subpix)  + 0.5);
 fwrite(pixel, 1, 3, image_file);
 //pixel finished
  • Ned Batchelder[21] 的 Aptus 命令行版本(python 和 c 代码)(参见 aptuscmd.py)使用通过 PIL 函数 resize[22] 的高质量降采样滤波器
  • Josef Jelinek 编写的 Java 代码:[23] 使用网格算法进行超采样,计算 4 个新点(角点),产生的颜色是每个颜色分量的平均值
 //Created by Josef Jelinek
 // http://java.rubikscube.info/
 Color c0 = color(dx, dy); // color of central point
 // computation of 4 new points for antialiasing
 if (antialias) { // computes 4 new points (corners)
   Color c1 = color(dx - 0.25 * r, dy - 0.25 * r);
   Color c2 = color(dx + 0.25 * r, dy - 0.25 * r);
   Color c3 = color(dx + 0.25 * r, dy + 0.25 * r);
   Color c4 = color(dx - 0.25 * r, dy + 0.25 * r);
  // resulting color; each component of color is an avarage of 5 values (central point and 4 corners)
   int red = (c0.getRed() + c1.getRed() + c2.getRed() + c3.getRed() + c4.getRed()) / 5;
   int green = (c0.getGreen() + c1.getGreen() + c2.getGreen() + c3.getGreen() + c4.getGreen()) / 5;
   int blue = (c0.getBlue() + c1.getBlue() + c2.getBlue() + c3.getBlue() + c4.getBlue()) / 5;
   color = new Color(red, green, blue);
 }
  • 可以创建大图像(例如 10 000 x 10 000),并将其转换/调整大小(缩小)。例如使用 ImageMagick
convert big.ppm -resize 2000x2000 m.png


降采样和插值本质上是压缩,低频分量,即

  • 变化速度低于采样频率一半的缓慢变化颜色将被保留
  • 高频细节将丢失

区间算术

[edit | edit source]

如何优化搜索最近的点?

[edit | edit source]

另请参阅

[edit | edit source]

参考资料

[edit | edit source]
  1. 来自塔尔图大学的纹理和采样:
  2. fractalforums.org : 采样
  3. “您可以信赖的 Julia 集图像” - Luiz-Henrique de Figueiredo、Diego Nehab、Jofge Stolfi、Joao Batista Oliveira - IEE 2015
  4. 维基百科中的超采样
  5. 维基百科中的亚像素分辨率
  6. researchgate : 基于梯度的局部分形分析的单图像超分辨率和细节增强 - HONGTENG Xu、Xiaokang Yang、Guangtao Zhai
  7. Hongteng Xu: 基于分形的图像处理
  8. wolfram mathematica: AdaptiveSamplingOfSurfaces
  9. 自适应采样,绘制数学曲线 By Xah Lee. Date: 2016-05-01. Last updated: 2016-05-07.
  10. 来自 Mandelbrot 集合词汇表和百科全书,作者:Robert Munafo,(c) 1987-2020. 由 Robert P. Munafo 于 2010 年 12 月 5 日编写的指数映射。
  11. 维基百科中的空间抗锯齿
  12. fractalforums 讨论:抗锯齿分形 - 最佳方法?
  13. 维基百科中的超采样
  14. ImageMagick v6 示例 - 重采样滤波器
  15. 哪个图像降采样算法的质量最好?
  16. a b "抗锯齿技术比较". sapphirenation.net. 2016-11-29. 检索于 2020-04-19. 一般来说,SSAA 提供卓越的图像质量,但性能损失很大,因为场景是在非常高的分辨率下渲染的。
  17. "什么是超采样?". everything2.com. 2004-05-20. 检索于 2020-04-19.
  18. a b c Allen Sherrod (2008). 游戏图形编程. Charles River Media. p. 336. ISBN 978-1584505167.
  19. Cook, R. L. (1986). "计算机图形中的随机采样". ACM 图形学报. 5 (1): 51–72. doi:10.1145/7529.8927. S2CID 8551941.
  20. "超采样抗锯齿分析" (PDF). Beyond3D.com. 检索于 2020-04-19.
  21. Aptus (python 和 c 代码) by Ned Batchelder
  22. Pil 函数 resize
  23. Java 代码 by Josef Jelinek
  24. 你可以信任的 Julia 集图像 Luiz Henrique de Figueiredo
  25. 关于复杂动力系统双曲结构的数值构建 by Jennifer Suzanne Lynch Hruska
  26. "你可以信任的 Julia 集图像" by Luiz Henrique de Figueiredo 和 Joao Batista Oliveira
  27. 生成 Julia 集保证图像的自适应算法 by Luiz Henrique de Figueiredo
  28. 用区间算术绘制分形 - 第 1 部分 by Dr Rupert Rawnsley
  29. 用区间算术绘制分形 - 第 2 部分 by Dr Rupert Rawnsley
  30. Fractint 绘制方法
  31. 同步轨道算法 by R Munafo
  32. 杏仁面包主页 by Michael R. Ganss
  33. 粗略的 Mandelbrot 集 by Neural Outlet.. 发表于 2014 年 11 月 23 日
  34. 你可以信任的 Julia 集图像 by Luiz Henrique de Figueiredo, Diego Nehab, Jorge Stolfi 和 Joao Batista Oliveira
  35. 多项式 Julia 集的严格边界 by Luiz Henrique de Figueiredo
  36. 你可以信任的 Julia 集图像 by LUIZ HENRIQUE DE FIGUEIREDO 和 DIEGO NEHAB
  37. 距离估计 by Claude Heiland-Allen
华夏公益教科书