【问题标题】:Smooth coloring algorithm平滑着色算法
【发布时间】:2015-05-16 02:12:09
【问题描述】:

这个问题已经发布了很多,但我已经阅读了这里发布的问题,并在不久前构建了我自己的实现。在挖掘了一些旧项目并再次遇到它之后,我放弃了这个项目并决定再试一次。但是,我仍然无法弄清楚smooth coloring algorithm 的这种实现有什么问题。

但是,对于平滑条带和“图像”(tkinter 画布)的着色,我有一个错误(可能?)。我想说这只是我定义的 RGB 调色板的结果,以及我要去的深度,但我对此并不是 100% 肯定的。在大多数情况下,它似乎是平滑的,稍后会详细介绍。我会尽量做到这一点。

我已经定义了以下 RGB 调色板(137 种颜色)here,这是我在计算集合时获得的相当不错的缩放级别和 5,000 深度的结果。

现在,这里看起来很奇怪。这是在一两个缩放级别之后,我想说这只是为了保持乐观的前景而存在如此多不同颜色的像素的结果。它看起来像在更远的缩放级别,虽然自然不那么突出。

这是我递归计算集合并为其着色的相关函数

def mandel(self, x, y, z, iteration):

    mod_z = math.sqrt((z.real * z.real) + (z.imag * z.imag))

    #If its not in the set or we have reached the maximum depth
    if  mod_z >= 100.0 or iteration == DEPTH:
        if iteration < DEPTH:
            if iteration > MAX_COLOR:
                iteration = iteration % MAX_COLOR
            nu = math.log2(math.log2(abs(mod_z)) / math.log2(2)) / math.log2(2)
            value = iteration + 5 - nu
            print(iteration)
            color_1 = RGB_PALETTE[math.floor(value)]
            color_2 = RGB_PALETTE[math.floor(value) + 1]
            fractional_iteration = value % 1

            color = self.linear_interp(color_1, color_2, fractional_iteration)

            self.canvas.create_line(x, y, x + 1, y + 1,
                                    fill = self.rgb_to_hex(color))

    else:

        z = (z * z) + self.c
        self.mandel(x, y, z, iteration + 1)

    return z

def create_image(self):
    begin = time.time() #For computing how long it took (start time)
    diam_a = self.max_a - self.min_a
    diam_b = self.max_b - self.min_b
    for y in range(HEIGHT):
        for x in range(WIDTH):
            self.c =  complex(x * (diam_a / WIDTH) + self.min_a, 
                              y * (diam_b / HEIGHT) + self.min_b)

            constant = 1.0
            z = self.c

            bound = 1 / 4
            q = (self.c.real - bound)**2 + (self.c.imag * self.c.imag)
            x1 = self.c.real
            y2 = self.c.imag * self.c.imag
            sixteenth = 1 / 16

            #See if its in p2-bulb for different coloring schema between the main bulb and other bulbs of the set
            if not (q*(q + (x1 - bound)) < y2 / (constant * 4) or 
                    (x1 + constant)**2 + y2 < sixteenth): 
                #value of the recursive call while it is not in the set
                z = self.mandel(x, y, z, iteration = 0)

            if self.progress_bar != None:
                self.progress_bar["value"] = y

    self.canvas.update() #Update the progress bar
    print("Took %s Minutes to Render" % ((time.time() - begin) / MINUTE))

如果以上内容还不够,则将发布与计算和绘制集合有关的完整代码here

【问题讨论】:

  • 平滑只能在相邻像素之间的颜色梯度较低的情况下起作用。在函数非常参差不齐且具有高梯度的情况下,不会显示平滑:例如,如果您确定“平滑”的米色,当相邻像素的颜色值(无论是否平滑)为红色时,结果看起来会很嘈杂和青色。维基百科文章中比较带状和平滑渲染的图像在分支中也有噪声部分。
  • 您可能可以调整调色板及其限制,但我认为您可以仅针对图像的某些部分进行优化,就像您只能为照片的某些部分选择一个好的焦点一样。
  • 这是有道理的,我已经玩了一段时间试图获得更好的结果,这似乎基本上和它在尝试实现这种特定的平滑着色时一样好,假设我确实正确地实现了它,我不得不承认这有点令人失望,因为我通过基本的线性插值获得了更好的着色。我将如何调整调色板及其限制?我对颜色渐变和操作它们的经验很少。
  • 好吧,例如,您可以使用 RGB[math.floor(c * value + v0) % NRGB] 代替 RGB[math.floor(value)] 并尝试使用因子 c 和偏移量 v0。模 % NRGB 应该将索引带入一个允许的范围,如果它超出范围。 'NRGB' 是调色板的长度。

标签: python algorithm python-3.x colors mandelbrot


【解决方案1】:

您要消除的是混叠。所以解决方案(显然)是抗锯齿。分形的有效解决方案是自适应超级采样。请参阅此adaptively super sampled mandelbrot sequenceSupersampling 只是意味着输出中的每个像素都是像素区域中几个样本的平均值(请记住,您的像素不是无限小的点 - 它们有区域)。可以使用不同的模式,它们在美学、运行时和实现复杂性之间有不同的权衡。

诸如 mandelbrot 或 julia 集之类的分形具有使自适应超级采样成为一个不错选择的特性:存在值变化不大的大区域(并且会浪费额外的计算),而其他区域的值改变很多。它们需要在图片变化很大的部分(即图像中的嘈杂部分)中采集大量样本。您可以使用几种方法来确定需要大量采样的内容。但是两个容易想到的方法是:

  • 多次通过图像
    • 在每次连续遍历中,如果某个像素的颜色与其相邻像素的颜色变化超过阈值,则在该像素的区域中执行进一步采样并取平均值
  • 总是为每个像素做几个样本(比如 4 个)
    • 如果这些样本差异很大,请采取更多措施
    • 这将在值相对相似的区域浪费计算

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-05-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-03-06
    • 2014-03-17
    相关资源
    最近更新 更多