我正在编写一个 C++ Mandelbrot 生成器,但我需要使用 HSV

问题描述 投票:0回答:1

我从黑色

cv::Mat
图像开始,但我想向其中添加 HSV。我怎样才能实现这个目标??

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

int MAX_ITER = 80;

int mandelbrot(std::complex<double> c){
    std::complex<double> z{0,0};
    int n = 0;
    while (abs(z) <= 2 && n < MAX_ITER){
        z = z*z + c;
        n += 1;
    }   
    return n;
}
int m;
int main()
{
    //! [mandelbrot-transformation]
    Mat mandelbrotImg(width, height,CV_8UC3, cv::Scalar(0, 0, 0));
    Mat mandelHSV(width, height,COLOR_BGR2HSV);
    float wid = (float)width;
    float hei = (float)height;
    int count = 0;
    for (int x=0; x < width; x++){
        for (int y=0; y<height; y++){
            
            std::complex<double> c( RE_START + (x / wid) * (RE_END - RE_START),
                    IM_START + (y / hei) * (IM_END - IM_START));

            m = mandelbrot(c);
            
            double hue = (255 * m / (float)MAX_ITER);
            double saturation = 255.0;
            double value;
            if (m < MAX_ITER) {
                value = 255;
            }else {
               value = 0;
            }
            mandelbrotImg.at<cv::Vec3b>(x,y) = ((uchar)hue, (uchar)saturation, (uchar)value);
            
            count++;
            
        }
    }
    cv::cvtColor(mandelbrotImg, mandelbrotImg, COLOR_BGR2HSV);
    imwrite("../img/mandle.png", mandelbrotImg);
    
    }
    
};

这就是我目前所拥有的! 我不知道是否需要转换它或在像素位置分配 HSV 值。

  • 我添加了浮点除法
  • 我已将norm(z) 添加到mandelbrot 中

现在的图像输出是:

IMAGE OUTPUT

预期输出:

EXPECTED OUTPUT

c++ opencv
1个回答
3
投票

您的原始代码中有很多问题,并且您当前的代码中仍然存在不少问题。

举几个例子:

  1. cv::Mat
    构造函数首先需要高度,然后是宽度。
  2. cv::Mat::at
    方法首先需要 y 坐标,然后是 x。
  3. 最终的颜色转换应该是
    COLOR_HSV2BGR
    不是
    COLOR_BGR2HSV
  4. mandelbrot
    应该更好地通过
    const&
    接受参数 避免复制(效率问题)。
  5. 不要检查
    abs(z) <= 2
    ,最好使用
    norm(z) <= 4
    ,因为它可以避免计算 sqrt(效率问题)。
  6. 由于您的主要计算在
    double
    中,因此我将所有
    float
    交换为
    double
  7. 构建时无需将
    cv::Mat
    初始化为零值,因为稍后我们无论如何都会填充所有像素值。

参见修复版本:

#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <complex>


static const int RE_START = -2;
static const int RE_END = 1;
static const int IM_START = -1;
static const int IM_END = 1;
static const int MAX_ITER = 80;


int mandelbrot(std::complex<double> const & c) 
{
    std::complex<double> z{ 0,0 };
    int n = 0;
    while (std::norm(z) <= 4 && n < MAX_ITER) 
    {
        z = z*z + c;
        n += 1;
    }
    return n;
}


int main()
{
    int width = 960;
    int height = 640;

    cv::Mat mandelbrotImg(height, width, CV_8UC3);
    double wid = (double)width;
    double hei = (double)height;
    double reWidth = RE_END - RE_START;
    double imWidth = IM_END - IM_START;
    for (int x = 0; x < width; x++) 
    {
        for (int y = 0; y < height; y++) 
        {
            std::complex<double> c(RE_START + (x / wid) * reWidth, IM_START + (y / hei) * imWidth);
            int m = mandelbrot(c);

            double hue = (255 * m / (float)MAX_ITER);
            double saturation = 255.0;
            double value = (m < MAX_ITER) ? 255.0 : 0;

            mandelbrotImg.at<cv::Vec3b>(y, x) = cv::Vec3b((uchar)hue, (uchar)saturation, (uchar)value);
        }
    }
    cv::cvtColor(mandelbrotImg, mandelbrotImg, cv::COLOR_HSV2BGR);
    cv::imwrite("../img/mandle.png", mandelbrotImg);
}

输出: enter image description here

© www.soinside.com 2019 - 2024. All rights reserved.