blog.monophile.net

Takaaki Yamamoto

東京工業大学において計算機科学と応用数学を学び、 情報科学芸術大学院大学[IAMAS]においてメディア表現を専攻し修了。 digitiminimi Inc. において、インフラエンジニアとして生計をたててている。

各種環境の構築と管理を承ります。

  • 仮想環境: Openstack, GCP, AWS, Azure, ...
  • アプリケーション: WordPress, GitLab, Redmine, ...

List

特徴点検出とDelaunay三角形分割による画像の分解

画像を三角形に分割するための画像フィルタをPythonとOpenCVで作りました。

コーディング

以下のテキストファイルをdelaunay.pyとします。 必要なモジュールはscipy,numpy,cv2です。

import sys
import scipy as sp
import numpy as np
import scipy.misc
import cv2

detector = cv2.FeatureDetector_create("SURF")
surf = lambda f_grayed: detector.detect(f_grayed, mask=f_grayed)
gray = lambda frame: cv2.cvtColor(frame, cv2.COLOR_RGB2GRAY)

def delaunay(f):
    surf_dats = surf(gray(f))
    np_surf_dats = np.array(map(lambda dat: dat.pt, surf_dats))
    div = 20
    w, h = f.shape[0], f.shape[1]
    wint , hint = w / div , h / div
    souths  = [(h - 1, wint * i)    for i in range(div + 1)]
    norths  = [(0, wint * i)        for i in range(div + 1)]
    easts   = [(hint * i  , w - 1)  for i in range(div + 1)]
    wests   = [(hint * i  , 0)      for i in range(div + 1)]
    if len(np_surf_dats) > 0:
        points = np.vstack((np_surf_dats, souths, norths, easts, wests))
    else:
        return None
    from scipy.spatial import Delaunay
    triangles = Delaunay(points)
    return triangles

def draw_delaunay_triangles(f, radius=2, line_color=(255, 255, 255)):
    triangles = delaunay(f)
    if triangles is None:
        return None
    dst = np.zeros(f.shape, dtype=np.uint8)
    for tri in triangles.vertices:
        poly = np.array(map(lambda i:np.array(triangles.points[i], dtype=np.int32), tri))
        xave , yave = np.sum(poly[:, 0]) / 3 , np.sum(poly[:, 1]) / 3
        color = np.array(f[yave, xave], dtype=np.float)
        cv2.fillPoly(dst, [poly], tuple(color), lineType=cv2.CV_AA)
        cv2.polylines(dst, [poly], True, (255, 255, 255), 1)
    for c in triangles.points:
        cv2.circle(dst, (int(c[0]), int(c[1])), radius, line_color, -1)
    return dst

if __name__ == "__main__" :
    print sys.argv
    if len(sys.argv) == 3:
        filename = sys.argv[1]
        frame = cv2.imread(filename)
        dst = draw_delaunay_triangles(frame)
        cv2.imwrite(sys.argv[2], dst)
        sys.exit()
    else:
        print "ex: \n\t $ python delaunay.py src.png triagnled.png"
        sys.exit(1)

example

以下のコマンド打つことによって新しいファイルが生成されます。

$ python delaunay.py lena.png triangled_lena.png
lena.png

lena.png

lena_triangled.png

lena_triangled.png