今回はベンハムの独楽と言われる錯視動画を作ります.
特定の模様を持つ白黒の画像を回転させると,実際には存在しない色が見えると言う錯視現象をpythonで作りましょう.
軽くどうでもいい世間話を少し.
2020年は長雨のせいか野菜が高いですね.
お盆でナスビとキュウリを串刺しにして走り回らせたいのですが,高くて中々手が出せません.
安い期間に買い込んだキャベツをひたすら食ってます.
ベンハムの独楽(コマ)は,このような動画になります.
www.youtube.com
そういえば動画保存倉庫用のyoutube channel作りました.
これから何か作業しながら動画をアップロードしたりすることもあるかと思います.
それでは,このベンハムの独楽を作成するコードを載せましょう.
このコードは加速度的に回転するベンハムの独楽です.
import numpy as np import math as mt import cv2 #br is Black R, mw is Mesh Width, st is Start Theta, et is End Theta def drawArc(img, r, R, sth, eth): h, w = img.shape[0], img.shape[1] for i in range(w): for j in range(h): x = i-w/2 y = h/2-j rr = x*x+y*y rr = mt.sqrt(rr) if (y < 0 and rr < 400): img[i][j] = 0 if (x == 0 and y == 0): continue if (x == 0 and y > 0): th = 90 elif (x == 0 and y < 0): th = 270 else: th = mt.atan(y/x) th = mt.degrees(th) if (x > 0 and y < 0): th = 360+th if(x < 0 and y > 0): th = 90+(90+th) if (x < 0 and y < 0): th = 180+th if (sth < eth): if (r <= rr and rr <= R and sth <= th and th <= eth): img[i][j] = 0 if (eth < sth): if (r <= rr and rr <= R and ((sth <= th and th <= 360) or (0 <= th and th <= eth))): img[i][j] = 0 return(img) def imgRotation(img,angle): h,w = img.shape[0], img.shape[1] center = (w/2,h/2) scale = 1.0 trans = cv2.getRotationMatrix2D(center, angle*(-1), scale) img = cv2.warpAffine(img, trans, (w, h)) img = np.array(img,np.uint8) return(img) w = 1000 #画像の横幅 h = 1000 #画像の縦幅 blank = np.zeros((h, w, 1), np.uint8) #黒の画像を作成 img = cv2.circle(blank, (h//2,w//2), 400, 255, -1) #画像の中心に白い円を描画 img = np.array(img, np.uint8) mw = 2 #描画する黒い線の太さ for i in range(400//mw): sth = (i*10) % 240 #黒い線の描画開始の角度 eth = sth+60 #黒い線の描画終了の角度 if (sth >= 120): eth = 180 - (eth % 180) sth = eth - 60 if i%2 == 1: #毎回黒線を描画すると線同士の隙間ができない.線の隙間がCharles Benhamで重要. continue else: img = drawArc(img, 400-i*mw, 400-i*mw+mw, sth=sth, eth=eth) #黒い線を描画 alsec = 10 fp = 100.0 hz = 5 frame = int(alsec*fp) fourcc = cv2.VideoWriter_fourcc('m', 'p', '4', 'v') video = cv2.VideoWriter('test.mov', fourcc, fp, (w, h)) sDv = 0 #開始時の回転速度 eDv = hz*360/fp #終了時の回転速度 Da = (eDv-sDv)/frame #回転加速度 for i in range(frame): Dx = Da*i*i #変位=加速度*(時間)^2 oimg = imgRotation(img,Dx) print("now process is ",i,"/",frame) cv2.imwrite("gray.png",oimg) oimg = cv2.imread("gray.png") video.write(oimg) video.release()
このコードで注意したい点として,初期画像を作成した後に,初期画像に変更は加えないで,回転後の画像はoimgという別の変数に格納している点です.
一枚の画像に対して,cv2.getRotationMatrix2Dを何度も行うと,初めの数回は画像の劣化は乏しいのですが,回数を重ねるごとに非常に劣化していきます.
そのため,初期画像と回転後の画像は別の変数として保存しました.
この他にも色々なパターンのベンハムの独楽が存在します.
それぞれの模様で色が変わるかどうかを調べてみようと思って,趣味で作ってみました.