充填ジュリア集合を描画する
充填ジュリア集合は漸化式
で定義される複素数列で、n→∞の極限において無限大に発散しないという条件を満たす複素数z0の集合を指します。
フリー百科事典『ウィキペディア(Wikipedia)』>>充填ジュリア集合
マンデルブロ集合と同じ漸化式による定義ですが、マンデルブロ集合がz0を固定しcを複素平面上で変えた場合の集合なのに対して、ジュリア集合はcを固定しz0を複素平面上で変えた場合の集合となります。cを適切な値に設定することで美しい図形を描画できます。
充填ジュリア集合を求めるプログラムは複素平面において、各点cに対する漸化式を計算し発散するか収束するかで判定します。あらかじめ設定した回数まで漸化式を計算しznがある閾値を越える場合には発散と判定、閾値を越えない場合には収束(充填ジュリア集合)と判定します。
関連記事
環境
コード
画像サイズを800x600とし、幅x・高さyの二重ループ内で対応する複素数が収束するか発散するかを調べています。
このように画像の各画素に複素平面上の複素数z0を対応させ、それぞれのz0が発散するか収束するかを判定します。
whileループで漸化式をn30まで計算し、計算が完了されれば(ループ終了後のnが30となれば)収束、znが100000000000000以上となりn=30となる前にwhileループを抜けた場合は発散と判定します。
収束部の輝度を0、発散部の赤の輝度を165+n*3として充填ジュリア集合を図にします。
import numpy as np import cv2 height, width = 600, 800 # ジュリア集合描画用ndarray julia = np.zeros((height, width, 3), np.uint8) div = 200 for y in range(height): for x in range(width): z0 = complex((x-0.5*width)/div, (y-0.5*height)/div) c = complex(-0.8, 0.156) # z0の絶対値が100000000000000を超えるかループが30回になったらwhileループを抜ける n = 0 while abs(z0) < 100000000000000 and n < 30: z0 = z0**2 + c # 漸化式 n += 1 # ループ回数+1 if n == 30: # 漸化式が収束した場合 julia[y, x, :] = 0 else: # 漸化式が発散した場合 julia[y, x, 2] = 165+n*3 # ジュリア集合画像の保存 cv2.imwrite('julia.jpg', julia)
実行結果
充填ジュリア集合(収束部)が黒、それ以外が赤で描画された図形が保存されます。
z0の範囲を変えます。
divの値を200→300に変え、描画位置をずらし、充填ジュリア集合を部分的に拡大します。
コード
#拡大 import numpy as np import cv2 height, width = 600, 600 # ジュリア集合描画用ndarray julia = np.zeros((height, width, 3), np.uint8) div = 300 for y in range(height): for x in range(width): z0 = complex((x-0.2*width)/div, (y-0.5*height)/div) c = complex(-0.8, 0.156) # z0の絶対値が100000000000000を超えるかループが30回になったらwhileループを抜ける n = 0 while abs(z0) < 100000000000000 and n < 30: z0 = z0**2 + c # 漸化式 n += 1 # ループ回数+1 if n == 30: # 漸化式が収束した場合 julia[y, x, :] = 0 else: # 漸化式が発散した場合 julia[y, x, 2] = 165+n*3 # ジュリア集合画像の保存 cv2.imwrite('julia.jpg', julia)
実行結果