![見出し画像](https://assets.st-note.com/production/uploads/images/128061399/rectangle_large_type_2_4cbbecebae932d69b56fca068f95c18b.png?width=800)
Pythonは虚数を扱えるらしい
たとえば変数「$${c}$$」に複素数「$${3 + 4i}$$」を入れるとする。
$$
c = 3 + 4i
$$
Pythonではこう書くらしい。
c = complex(3, 4)
print(c)
結果。
(3+4j)
なぜか虚数が「$${j}$$」になっているけれど、電気工学の慣習では電流の「$${i}$$」と区別するために「$${j}$$」と書くらしい。「complex」は複素数「complex number」から。
たとえば先ほどの「$${c}$$」を2乗してみる。手計算だとこうなるけれど、
$$
\begin{align*}
\\
c^2 &= (3 + 4i)^2 \\
&= 3^2 + 2 \times 3 \times 4i + (4i)^2 \\
&= 9 + 24i - 16 \\ &= -7 + 24i
\end{align*}
$$
Pythonはこれだけ。
c = complex(3, 4)
print(c**2)
結果。
(-7+24j)
ちゃんと計算してくれてる!
逆に「$${c}$$」から「実部」や「虚部」を取り出すこともできる。
c = complex(3, 4)
print(c.real)
print(c.imag)
結果。
3
4
ちなみに英語で実部を「real part」、虚部を「imaginary part」と言うらしい。
マンデルブロ集合を描いてみる
こうなると描きたくなるのが「マンデルブロ集合」。これを描くには素数の計算が必要になるけれど、Pythonならすごく簡単に書けるのでは!?
# マンデルブロ集合の画像をPNG形式で保存する
# モジュールをインポート
import numpy as np # 科学計算
from PIL import Image # 画像の読み書きなど
import time # 時間計算
# 開始時刻を記録
start = time.time()
# 画像の解像度、描画する範囲、を設定
width, height = 2000, 2000 # 画像の解像度(px)
a_min, a_max = -2, 1 # 複素数のaの範囲(画像の横軸)
b_min, b_max = -1.5, 1.5 # 複素数のbの範囲(画像の縦軸)
loop_max = 4096 # 再帰回数の最大(256の倍数を推奨)
# マンデルブロ集合の内側なら黒(0)、外側なら再帰回数(n)、を返す
def mandelbrot(c, loop_max):
z = 0 # zの初期値=0
n = 0 # 再帰回数の初期値=0
while abs(z) <= 2 and n < loop_max: # zが距離2を脱出するまで
z = z ** 2 + c # z = z² + c
n = n + 1
if n == loop_max:
return 0 # 集合の内側
else:
return n # 集合の外側
# 画像データ配列(NumPy配列)を作成
image_data = np.zeros((height, width), dtype=np.uint8) # データ型:8bitの符号なし整数(0〜255)
# 全ピクセルについて、マンデルブロ集合の内側か外側かを調べる
for b_index, b in enumerate(np.linspace(b_min, b_max, height)):
for a_index, a in enumerate(np.linspace(a_min, a_max, width)):
c = complex(a, b) # 複素数に変換(c=a+bi)
n = mandelbrot(c, loop_max) # マンデルブロ集合の計算(n=再帰回数)
image_data[b_index, a_index] = 255 - n % 256 # nを画像データ配列に格納(nを0〜255の繰り返しにして、明るさを反転)
# NumPy配列をPillow画像オブジェクトに変換
image = Image.fromarray(image_data) # NumPy→Pillow
image = image.convert('RGB') # RGB形式に変換
# 画像を保存
image.save('mandelbrot.png')
# 終了時刻を記録
end = time.time()
# 実行にかかった時間を表示
print('実行時間 :', format(end - start, '.2f'), '秒')
うん、思ったより短く書けなかったね。😑
描画にかかった時間は7分54秒。
![](https://assets.st-note.com/img/1705574181416-9SutedMqjH.png?width=800)
2000 × 2000ピクセルなので拡大すると粗い。
![](https://assets.st-note.com/img/1705603344964-L6hqsuOZiY.png?width=800)
![](https://assets.st-note.com/img/1705603369737-uKJyv5B7Y6.png?width=800)
![](https://assets.st-note.com/img/1705604311919-aftXkysKbl.png?width=800)
20000 × 20000ピクセルで描画してみた。
![](https://assets.st-note.com/img/1705601055791-MyTG1ihoDc.png?width=800)
![](https://assets.st-note.com/img/1705603393946-YArmUXpQAi.png?width=800)
![](https://assets.st-note.com/img/1705603417602-srEAeOkSHX.png?width=800)
![](https://assets.st-note.com/img/1705604349043-s7OymLQAer.png?width=800)
12時間44分もかかってしまったけれど、中央の粒がマンデルブロ集合の形になっているのがよくわかる。✨
余談だけど、「マンデルブロ集合」は「グレー」の「256階調」で描くのがいいと思う。色は後から付けた方が楽だから。
Photoshopで色を付ける手順
まず、開くときに「カラープロファイル」を埋め込む。これで「カラーモード」になる。
![](https://assets.st-note.com/img/1705585161889-ovsDyACcTF.png?width=800)
「レイヤー」パレットの「調整レイヤー」アイコンをタップし、
![](https://assets.st-note.com/img/1705585843443-Y9va2ftICf.png?width=800)
出てきたメニューから「グラデーションマップ」を選ぶ。
![](https://assets.st-note.com/img/1705586420822-oZsdufBPWk.png?width=800)
「グラデーションマップ」が追加された。
![](https://assets.st-note.com/img/1705586494437-fPfF1j19bH.png?width=800)
たぶん「プロパティ」が表示されていると思う。これが現在のグラデーション。右の「∨」を押すと、色々なグラデーションが表示される。
![](https://assets.st-note.com/img/1705586559018-7JxjgboKsM.png?width=800)
選ぶと色が変わる。
![](https://assets.st-note.com/img/1705586801379-Knmb4eZYKF.png?width=800)
自作することもできる。
![](https://assets.st-note.com/img/1705587053863-7eudq41UnO.png?width=800)
ちなみにこのグラデーションは、Pythonの「cubehelix」というカラーマップに似せて作ったもの。
「逆方向」や「方法」というオプションも調子が変わって面白かった。
フリー素材
20000ピクセルの画像はこちら。ご自由にお使いください。(需要あるかな?)
Python 3
macOS Sonoma 14.1.2
Photoshop 2024 25.3.1
とりにえさをあたえるぼたん