Delaunay and Voronoi portrait
コード
Opencvでどちらも描画できるらしいのでコピペする。
note.nkmk.me
自分で実装したりもしたけどそれなりに計算に時間がかかるので却下した(ドロネー図実装の参考にしたサイトの方法だとO(n^2), 木をうまく使うとO(nlogn))。
qiita.com
ボロノイ図についてはここが面白い。
ysmr-ry.hatenablog.com
import numpy as np import cv2 def main(): img = make_delaunay(path/to/image) cv2.imshow("result", img) cv2.waitKey(0) def make_subdiv(img): n_point = 10000 blur = cv2.GaussianBlur(img, (5, 5), 0) _, th = cv2.threshold(blur, 0, 255, cv2.THRESH_BINARY+cv2.THRESH_OTSU) result = np.zeros((img.shape[0], img.shape[1])) rand_xy = [] cnt = 0 while True: x = np.random.randint(1, img.shape[1]) y = np.random.randint(1, img.shape[0]) if th[y][x] == 0: rand_xy.append([x, y]) result[y][x] = 1 cnt += 1 if cnt >= n_point: break def make_delaunay(path): img = cv2.imread(path) img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) subdiv = make_subdiv(img_gray) triangles = subdiv.getTriangleList() pols = triangles.reshape(-1, 3, 2) img_draw = np.zeros((img.shape[0], img.shape[1])) cv2.polylines(img_draw, pols.astype(int), True, 1, thickness=1) img_draw = post_pro(img_draw) cv2.imwrite("delaunay_cv2.png", img_draw) return img_draw def make_voronoi(path): img = cv2.imread(path) img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) subdiv = make_subdiv(img_gray) facets, centers = subdiv.getVoronoiFacetList([]) img_draw = np.zeros((img.shape[0], img.shape[1])) cv2.polylines(img_draw, [f.astype(int) for f in facets], True, 1, thickness=1) img_draw = post_pro(img_draw) cv2.imwrite("voronoi_cv2.png", img_draw) return img_draw def post_pro(img): img = (img*255).astype(np.uint8) # img = 255-img return img if __name__ == "__main__": main()
点群は大津の二値化した画像の黒い方に点を10000個ランダムでうつ。輝度で分けたりいろいろなやり方があるっぽい。
結果
タイトルを英語にすると伸びることに気づいて味を占めてます...