見出し画像

OpenCVでマンデルブロ集合を描く実験

こちらの記事を見て、マンデルブロ集合は意外に短いコードで描ける事を知りOpenCVの勉強を兼ねて表示させてみました。
開発環境は、こちらの記事を見てVisual Studio 2022を使用。
OpenCVには、点を描画する専用の関数はなさそうだった為、こちらの記事を見てポインタを使用。全部調べて組み合わせただけですね。
以下タイトルの画像を表示させたコードです。
ポインタが使いやすい様にxとyのループの順番を入れ替えて、計算回数の偶数奇数の色分けを追加してみました。

// マンデルブロ集合 v002 (1000 x 1000pix, 計算回数50, 計算回数を偶数奇数で色分け)
#include <opencv2/opencv.hpp>
#include <iostream>

int main(void)
{   
  // 定数データ
  double size = 4;                        // 描く領域の一辺の長さ
  int pixel = 1000;                       // 描く領域の一辺のピクセル数
  int kaisuu = 50;                        // 計算回数

  // 変数データ
  double x, y, a, b, _a, _b;

  //空の画像生成(1000ピクセルの正方形の画像)
  cv::Mat image = cv::Mat::zeros(cv::Size(pixel, pixel), CV_8UC3);

  // マンデルブロ集合を描く
  for (int j = 0; pixel > j; j++) {       // y(虚部)方向のループ
    y = j * size / pixel - size / 2;      // 定数Cの虚部
    cv::Vec3b *src = image.ptr<cv::Vec3b>(j); //j行目の先頭画素のポインタを取得
    for (int i = 0; pixel > i; i++) {     // x(実部)方向のループ
      x = i * size / pixel - size / 2;    // 定数Cの実部
      a = 0;                              // くり返し計算に使う複素数zの実部
      b = 0;                              // くり返し計算に使う複素数zの虚部
      for (int k = 0; kaisuu > k; k++) {  // 上限を50回とするくり返し計算
        _a = a * a - b * b + x;           // z^2+Cの計算(実部)
        _b = 2 * a * b + y;               // z^2+Cの計算(虚部)
        a = _a;                           // zの値を更新(実部)
        b = _b;                           // zの値を更新(虚部)
        if (a * a + b * b > 4) {          // もし絶対値が2を(絶対値の2乗が4を)超えていたら
          //src[i] = cv::Vec3b(255, 0, 0);  // (i,j)の位置のピクセルを「マンデルブロ集合でない色」で塗りつぶして
          if ((k & 0x01) == 0)  src[i] = cv::Vec3b(255, 0, 0);    // 偶数(青色)
          else                  src[i] = cv::Vec3b(0, 127, 127);  // 奇数(黄色)
          break;                          // 次の点の計算へ
        }
      }
    }
  }

  //画像の表示
  cv::imshow("showing",image);
  cv::waitKey(0);
    
  return 0;
}

今回は以上になります。


この記事が気に入ったらサポートをしてみませんか?