猫も杓子も構造化

発達障害、特別支援などについて書いています。最近は心理学関係の内容が多めです。

Pythonでお絵かき(エビングハウス錯視編)

以前にPythonでカフェウォール錯視の画像を作った。

nekomosyakushimo.hatenablog.com

今回はカフェウォール錯視に続いてもう少し複雑な感じのお絵かきを試みる。錯視界隈では有名なエビングハウス錯視でいってみよう。

エビングハウスが何だか分からない人はWikipediaを見るとよいでしょう。おそらく1度や2度は見たことがあるはず。

エビングハウス錯視 - Wikipedia

今回のポイントは中心円を囲む外側の円の位置情報である。三角関数を用いてxとy座標を求めるのだが、Python三角関数を使う際には、ライブラリのmathやnumpyが必要になる。今回は行列の処理が必要だったのでnumpyを使っている。

# 左の外円の位置情報
x = [0, 60, 120, 180, 240, 300]
x1 = np.radians(x)  # 弧度法に変換
x2 = np.cos(x1)  # コサインを計算
x3 = x2 * 120  # 外円の作る円の半径をかける
y2 = np.sin(x1)  # サインを計算
y3 = y2 * 120
pos1 = np.c_[x3, y3] + center1


考え方としては、中心円を囲む大きな円があるとして、三角関数を使ってその円周上の座標を求めている。Pythonでsinやcosの計算をする際には、弧度法で値を与えないといけないそうなので、radians()という関数で変換をしてから計算し、大きな円の半径をかけて中心円からの距離を求めている。最後のnp.c_()は、配列を列方向に結合する関数で、こうすることで[x座様, y座標]が6つからなる6×2の行列を得ることができる。

ここで得られた座標は外円の中心点の座標なので、円を描く際にはその座標から外側の円の半径を引いたものと足したものを用意してやれば良い。

完成品が次のもの。色はWikipediaに準じた。

f:id:nekomosyakushimo:20170906011955p:plain


使用したコードは次の通り。

# coding:utf-8
from __future__ import division
from __future__ import unicode_literals
import numpy as np
from PIL import Image
from PIL import ImageDraw

# 描画オブジェクトとか
image = Image.new("RGB", (640, 320), color=(255, 255, 255))
draw = ImageDraw.Draw(image)

# もろもろの情報
center1 = np.array([200, 160])
center2 = np.array([500, 160])
rad1 = 30
rad2 = 50
rad3 = 15

# 左の外円の位置情報
x = [0, 60, 120, 180, 240, 300]
x1 = np.radians(x)  # 弧度法に変換
x2 = np.cos(x1)  # コサインを計算
x3 = x2 * 120  # 外円の作る円の半径をかける
y2 = np.sin(x1)  # サインを計算
y3 = y2 * 120
pos1 = np.c_[x3, y3] + center1

#  右の外円の位置情報
a = [0, 45, 90, 135, 180, 225, 270, 315]
a1 = np.radians(a)
a2 = np.cos(a1)
a3 = a2 * 60
b2 = np.sin(a1)
b3 = b2 * 60
pos2 = np.c_[a3, b3] + center2

#中心の円を描画
draw.ellipse(((tuple(center1 - rad1)), (tuple(center1 + rad1))),
             fill=(228, 127, 66), outline=None)
draw.ellipse(((tuple(center2 - rad1)), (tuple(center2 + rad1))),
             fill=(228, 127, 66), outline=None)

#  左側周りの大きな円を描画
for i in range(6):
    draw.ellipse(((tuple(pos1[i] - rad2)), (tuple(pos1[i] + rad2))),
                 fill=(146, 164, 184), outline=None)

#  右側周りの小さな円を描画
for i in range(8):
    draw.ellipse(((tuple(pos2[i] - rad3)), (tuple(pos2[i] + rad3))),
                 fill=(146, 164, 184), outline=None)

image.save("ebbing.png")