werry-chanの日記.料理とエンジニアリング

料理!コーディング!研究!日常!飯!うんち!睡眠!人間の全て!

Pythonでマンデルブロ模様変化の動画作ろうや

久しぶりに何かプログラミングな記事を書こうと思いまして,

そういえば以前,マンデルブロ集合を中途半端に説明して放置してたなぁと

werry-chan.hatenablog.com

↑これですね.ソースコードだけのせて,しかも画像で,これはよろしくない.

今回はちゃんとコード載せますので安心してください.

ほんで今回は,

マンデルブロ集合が動きます.

マンデルブロ集合って複素数座標上の原点スタートが標準なのですが,今回は原点以外から反復関数かけてやると,どのように模様が変化するか見てみます.
www.youtube.com
ゆっくり動くマンデルブロ集合↑

www.youtube.com
早く動くマンデルブロ集合↑


制作過程をtwitterで追っている↑

後半で沢山ウニョウニョしてますね.

M=~~ってのを大きくすると計算するのにかなり時間かかかりますので注意です.

必要なライブラリはnumpyとopencvです.

これがマンデルブロ集合の画像生成プログラムです.↓

import numpy as np
import cv2

def model(X,Y,N,a,b):
     for i in range(N):
         a,b=a**2-b**2+X,2*a*b+Y
         c=a**2+b**2
     c[c<4]=0
     c[c>4]=255
     return(a,b,c)

def mand_plot(a,b,M):
    for N in range(2,20):
     #print("now process is step ",N)
     mdl_tpl=model(X,Y,1,a,b)
     a,b=mdl_tpl[0],mdl_tpl[1]
     if N//5%2==0:
         img[mdl_tpl[2]==255]=N%5*41
     else:
         img[mdl_tpl[2]==255]=255-N%5*41

#1000枚の画像をmand_plptというファイルに保存するのでfilename定義.
filename="./mand_plot/"

#画像の枚数1000枚
img_num=1001
#画像のサイズは1000*1000.後でresizeして良いが,計算中はサイズそのままじゃないとプロットの精度が悪くなるので,保存時にresizeしましょう.
M=1000

#極座標形の長さrの初期値
r=0.0
#極座標形の角度thetaの初期値
theta=0.0
for l in range(1,img_num,1):
    #rとthetaを少しずつ増加させる.thetaは全部で5pi回転する.
    r+=1.0/(img_num-1)
    theta+=5*np.pi/(img_num-1)
    a=r*np.cos(theta)
    b=r*np.sin(theta)
    x,y=[np.linspace(-2,2,M)]*2
    X,Y=np.meshgrid(x,y)
    mdl_tpl=model(X,Y,1,a,b)
    a,b,img=mdl_tpl[0],mdl_tpl[1],mdl_tpl[2]
    mand_plot(a,b,M)
    #画像を保存前にresize
    img=cv2.resize(img,(500,500))
    if l<10:
        cv2.imwrite(filename+"mad"+"00"+str(l)+".png",img)
    elif l<100:
        cv2.imwrite(filename+"mad"+"0"+str(l)+".png",img)
    else:
        cv2.imwrite(filename+"mad"+str(l)+".png",img)
    print("now process is ",l,"\n")

画像を動画に書き出すプログラム.↓

import cv2

fourcc = cv2.VideoWriter_fourcc('m','p','4','v')
#(500,500)は画像のサイズ.
video = cv2.VideoWriter('video_c4_M1000.mov', fourcc, 20.0, (500, 500))

for i in range(1, 1001,1):
    if i<10:
        img = cv2.imread('mad'+"00"+str(i)+'.png')
    elif i<100:
        img = cv2.imread('mad'+"0"+str(i)+'.png')
    else:
        img = cv2.imread('mad'+str(i)+'.png')
    #img = cv2.resize(img, (500,500))
    video.write(img)

video.release()