Home > Software engineering >  I'm writing a c mandelbrot generator but I need to work with HSV
I'm writing a c mandelbrot generator but I need to work with HSV

Time:09-05

I'm starting with a black cv::Mat image but I would like to add HSV to it. How do I achieve this??

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);
    
    }
    
};

This is what I have so far! I dont know if I need to convert it or assign the HSV value at the pixel location.

  • I've added floating point division
  • I've added norm(z) into mandelbrot

The image output is now:

IMAGE OUTPUT

Expected output:

EXPECTED OUTPUT

CodePudding user response:

There were numerous issues in you original code, and there are still quite a few in your current one. To name some:

  1. cv::Mat constructor expects first the height, then the width.
  2. cv::Mat::at method expects first the y coordinate, then the x.
  3. The final color conversion should be COLOR_HSV2BGR not COLOR_BGR2HSV.
  4. mandelbrot should better accept the parameter by const& to avoid copy (an efficiency issue).
  5. Instead of checking abs(z) <= 2, it's better to use norm(z) <= 4 since it avoids calculating the sqrt (an efficiency issue).
  6. Since your main calculations are in doubles, I swapped all the floats to doubles.
  7. There's no need to initialize the cv::Mat to a zero value upon construction, because later on we fill all the pixel values anyway.

See fixed version:

#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);
}

Output: enter image description here

  • Related