当前位置: 首页 > 知识库问答 >
问题:

使用CImg无法使用mandelbrot集获得颜色平滑度

燕正德
2023-03-14

因此,在学习C的一个步骤中,我决定尝试使用CImg实现mandelbrot集。这是我的程序:

#include <cstdlib>
#include <iostream>
#include <complex>

#define cimg_use_png
#include "CImg.h"

using namespace cimg_library;

const int MAX_ITER = 80;
const int WIDTH = 600;
const int HEIGHT = 400;
const int DEPTH = 1;
const int COLOR_SPECTRUM = 3;

const int RE_START = -2;
const int RE_END = 1;
const int IM_START = -1;
const int IM_END = 1;

double mandelbrot(const std::complex<double> &value) {
    std::complex<double> z(0, 0);
    int n = 0;
    while (abs(z) <= 2 && n < MAX_ITER){
        z = (z * z) + value;
        n += 1;
    }

    if(n == MAX_ITER) {
        return n;
    }

    return n + 1 - log(log2(norm(z)));
}

int main() {
    CImg<int> img(WIDTH, HEIGHT, DEPTH, COLOR_SPECTRUM, 0);
    img.RGBtoHSV();

    cimg_forXY(img, x, y) {
        std::complex<double> complex(RE_START + ((double)x / WIDTH) * (RE_END - RE_START),
                                     IM_START + ((double)y / HEIGHT) * (IM_END - IM_START));
        double m = mandelbrot(complex);

        int hue = (255 * m / MAX_ITER);
        int saturation = 255;
        int value = 0;
        if (m < MAX_ITER) {
            value = 255;
        }

        int color[] = { hue, saturation, value };
        img.draw_point(x, y, color);
    }

//    img.HSVtoRGB().display("Mandelbrot");
    img.HSVtoRGB().save_png("output/test.png");

    return 0;
}

我设法画出经典的曼德尔布洛特形状,但后来我试图实现平滑,以摆脱丑陋的带状。但我不能让它真正工作。

说真的,我不知道我在做什么,因为数学很难。

当保存图像时,我也会收到这个警告

[CImg] *** Warning ***[instance(600,400,1,3,0x104800000,non-shared)] 
CImg<int>::save_png(): Instance has pixel values in 
[-1.65164e+07,65025], probable type overflow in file 'output/test.png'.

所以很明显我有一个溢出的地方,但我真的不知道在哪里。

如果有人能帮助我,解释我在做什么,并指出我所做的所有错误的事情,但用一种简单的方式,我将永远感激。

更新

因此,通过添加标准化步骤,我获得了更好的图像:

img.HSVtoRGB()
    .normalize(0, 255)
    .save_png("output/test.png");

溢出错误消失了。

但是HSV和RGB之间的转换似乎有问题。

白色的东西都应该是黑色的。

我写的HSV值255, 255, 0

但它在RGB中被转换为255,255,255,这是错误的。它应该被转换成黑色。

更新2

正如鲍勃告诉我的,色调和饱和度不是介于0之间的数字。。100它由0到之间的数字表示。。1.

这是我的主要失误,也是为什么我的失误让黑人变成了白人。通过纠正这一点并进行Bob建议的小修正,我现在得到:

共有1个答案

南宫炜
2023-03-14

在HSV颜色模型中,色调通常表示为角度[0°、360°),而饱和度和值在[0,1]范围内。

修复发布代码的一种方法是调整存储在img中的值及其类型。

CImg<double> img(WIDTH, HEIGHT, DEPTH, COLOR_SPECTRUM, 0);
//   ^^^^^^ I guess a float could be enough
// img.RGBtoHSV();  Here, is useless. CImg has no notion of the color space

cimg_forXY(img, x, y)
{
    std::complex<double> c(/* Get real and imaginary part from x and y */);

    double m = mandelbrot(c);

    double color[] = {
//  ^^^^^^    
        360.0 * m / MAX_ITER,       // hue
        1.0,                        // saturation
        (m < MAX_ITER) ? 1.0 : 0.0  // value
    };

    img.draw_point(x, y, color);
}

img.HSVtoRGB().normalize(0, 255).save_png("output/test.png");

还要注意,在mandelbrot()中,您可以使用

while (std::norm(z) <= 4 && n < MAX_ITER) // 
{   // ^^^^^^^^^^^^^^^^^ To avoid a sqrt at every iteration

    // See e.g. https://linas.org/art-gallery/escape/smooth.html for this:
    return n + 1 - std::log2( std::log( std::norm(z) ) * 0.5 );       
}
 类似资料:
  • 我正在编写一个Java程序来显示我的入门编程类的Mandelbrot集。我相信我已经正确地设置了所有的数学,但是当我尝试绘制分形时,我得到的只是一种纯色。我已经测试了数学,它似乎应该是有效的。我搜索了一个多小时,但没有找到任何有用的东西。下面是我的复数类,并实际创建了Mandelbrot集:复数 曼德布罗特 我已经做了一些JUnit测试,上面的两个类似乎都可以工作。我的测试中可能有一个缺陷导致了疏

  • 我知道关于这件事,阿雷迪回答了很多问题。然而,我的略有不同。无论何时我们实现平滑着色算法,我都理解它。 其中n是逃逸迭代,2是z的幂,如果我没有弄错,z是该逃逸迭代处复数的模。然后,我们在颜色之间的线性插值中使用这个重整化的逃逸值来生成平滑的带状mandelbrot集。我已经看到了关于这个的其他问题的答案,我们通过HSB到RGB的转换来运行这个值,但是我仍然无法理解这将如何提供平滑的颜色渐变,以及

  • 在过去的几天里,我一直在开发C Mandelbrot集合程序,我设法让它工作得很好,然而,我的最终目标是能够用我的鼠标平稳地放大集合,这是我还没有做到的,所以我可能需要一些帮助! 这是我的部分代码(嗯,完整的mandelbrot函数): 这是输出的图片:(抱歉,它不是很漂亮,颜色不是我的首要任务,但我一定会尽快处理它们,只要我弄清楚变焦!) 曼德布罗特 我希望能够做到的是: 左键单击- (已经有一

  • 我用python编程了Mandelbrot集,但看起来很奇怪,所以我搜索平滑的颜色。我用对数和线性插值编程了一个平滑的着色函数,但是无论我尝试什么,我都得不到我想要的: 这是我的调色板 这里是我的着色功能 这是我得到的 正如你所看到的那样,平滑的颜色是没有连续性的 我想要这样的东西: 理想结果 我们看不到色差

  • 问题内容: 我正在尝试使用pdfbox从pdf中提取包含所有信息的文本。我获得了我想要的所有信息,除了颜色。我尝试了多种获取fontcolor的方法(包括使用PDFBox获取文本颜色)。但是没有用。现在,我从pdfBox的PageDrawer类复制了代码。但是,RGB值也不正确。 我正在使用上面的代码。得到的值是r = 0,g = 0,b = 0,内部cosp对象值为[0.0],内部pd对象数组=

  • 我目前正在使用Cups Version 1.2.4用于打印应用程序。一个强制性功能是读取纸张颜色(白皮书、蓝纸、...)。这是通过使用名为jipsi的旧打印库读取mediaSupport标签来完成的。 打印应用程序现在将使用新的CUPS版本2.0.2和打印库Cups4j进行更新。如果我尝试使用mediaSupport标签读取纸张颜色,结果集会输出像“iso_b4_250x352mm”这样的纸张大小