#0.はじめに
今回作るものがどういう感じで動くのか見てみたい、この記事を読むのが面倒くさい方はこちら(Youtubeの動画)をご覧ください。
#1.実装
fractal_tree.py
import pygame
import math
import random
pygame.init()
win = pygame.display.set_mode((750, 650))
def drawTree(a, b, pos, deepness):
if deepness:
branch1 = random.randint(1,10)
branch2 = random.randint(1,10)
c = a + int(math.cos(math.radians(pos)) * deepness * branch1)
d = b + int(math.sin(math.radians(pos)) * deepness * branch2)
pygame.draw.line(win, (255,255,255), (a, b), (c, d), 1)
drawTree(c, d, pos - 20, deepness - 1)
drawTree(c, d, pos + 20, deepness- 1)
else:
pygame.draw.circle(win,(0,255,0),(a,b),2,0)
drawTree(370, 650, -90,10)
pygame.display.flip()
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
ここでは、まず棒を描き、そこから一定の角度を引いたり足したりして三角関数を使って次の棒まで距離を縦横求め元の棒にそれを足してというのを繰り返しています。pygameでは下に行くほどyの値が大きくなり、木は上に伸ばしたいので角度はマイナスからスタートしています。また、ここではリアルな感じにするためにランダムにbranch1とbranch2を作っていますがそこを両方10にすると普通のフラクタルツリーになります。
#2.OpenCVを使って木の形を変えてみる
FractalTree.py
import cv2
import math
import numpy as np
def nothing(x):
pass
def drawTree(a, b, pos, deepness,angle,img):
if deepness:
c = a + int(math.cos(math.radians(pos)) * deepness * 10.0)
d = b + int(math.sin(math.radians(pos)) * deepness * 10.0)
cv2.line(img,(a, b), (c, d),(255,255,255),1)
drawTree(c, d, pos - angle, deepness - 1,angle,img)
drawTree(c, d, pos + angle, deepness- 1,angle,img)
def draw(event,x,y,flags,param):
global img
img = np.zeros((800,800,3),np.uint8)
b = cv2.getTrackbarPos('bar','image')
drawTree(370, 650, -90,10,angle=b,img=img)
img = np.zeros((800,800,3),np.uint8)
cv2.namedWindow('image')
cv2.createTrackbar('bar','image',0,360,nothing)
cv2.setMouseCallback('image',draw)
while True:
k = cv2.waitKey(1) & 0xFF
if k == ord('q'):
break
cv2.imshow('image',img)
cv2.destroyAllWindows()
細かい説明はしませんが、ここでは、OpenCVを使ってトラックバーを作り、最初から引いたり足したりする角度を変えることで色々な木の形を作れるようにしています。動作が重くなってしまいましたが、なんとかできました。
#最後に
今回作ったものはYoutubeでも解説しているのでそちらも良かったらご覧ください。質問、アドバイスがあればぜひコメントをよろしくお願いします。