【기계 학습】 화상의 패스화 같은 것을 해 보았다

안녕하세요. 안도 勇輝( @holiholiday1173 )입니다.

이번 기사에서는, 전회의 기사에서 소개한 K-means법이라고 불리는 클러스터링 수법의 일종을 이용해, Illustrator등에서 사용하는 것이 많은, 화상의 패스화 (벡터화) 같은 것을 해 보았습니다.

개요



마지막 기사에서 한 일은 다음과 같습니다.
  • K-means를 사용하여 이미지의 픽셀 당 픽셀 값을 클러스터링
  • 각 클러스터에 클러스터 내 평균 픽셀 값을 할당하고 색상 수를 줄여 그립니다

  • 마지막 기사 → 【기계 학습】색의 양자화를 해설

    실제로 처리를 실시한 결과가 이쪽.
    (왼쪽: 처리 전, 오른쪽: 처리 후)


    클러스터 수를 9로 K-means 처리를 한 결과가 오른쪽 이미지가됩니다. 클러스터 수 = 색의 수이므로 처리 후의 이미지는 9 색만으로 그려져 있습니다.
    조금 뻔뻔한 색칠하기 책 같은 이미지가 되고 있네요.

    이전 기사에서는 픽셀값만을 K-means의 입력으로 사용하고 있었기 때문에, 색이 비슷하면 이미지내의 조금 떨어진 영역에 있는 픽셀에서도 같은 클러스터로 나누어져 버렸습니다.

    그래서, 픽셀값에 비해 픽셀 좌표의 정보도 맞추어 클러스터링해 주면, 패스화한 벡터 같은 이미지를 얻을 수 있는 것이 아닐까 생각하고, 해 보았습니다.

    결과



    사용한 코드는 이쪽입니다.
    import os
    import argparse
    import numpy as np
    import cv2
    
    
    if __name__ == "__main__":
        # 引数でパスを指定
        parser = argparse.ArgumentParser()
        parser.add_argument('--img', '-i', help='処理したい画像のパス')
        parser.add_argument('--output', '-o', help='結果画像を出力するディレクトリ')
        args = parser.parse_args()
    
        # 画像の読み込み
        img = cv2.imread(args.img)
    
        # 画像をそのままk-meansにかけることはできないので、shapeを(ピクセル数, 3(BGR))に変換
        Z1 = img.reshape((-1, 3))
    
        """
        ピクセルごとのxy座標を取得
        """
        # 画像の縦横幅
        h, w = img.shape[:-1]
        # 画像のxy座標を2次元リスト化
        Z2 = [[i, j] for i in range(h) for j in range(w)]
    
        # RGB + xy座標を連結
        Z = np.hstack((Z1, Z2))
        # np.float32型に変換
        Z = np.float32(Z)
    
        # k-meansの終了条件
        # デフォルト値を使用
        criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 10, 1.0)
        # 分割後のグループの数
        for K in range(5, 21, 3):
            # K = 10
            # k-means処理
            _, label, center = cv2.kmeans(
                Z, K, None, criteria, 10, cv2.KMEANS_RANDOM_CENTERS)
    
            # np.uint8型に変換
            center = np.uint8(center)
            # グループごとにグループ内平均値を割り当て
            res = center[label.flatten()]
            res = res[:, :-2]
            # 元の画像サイズにもどす
            res2 = res.reshape((img.shape))
    
            output_path = os.path.join(args.output, 'Parrots_K{:02}.png'.format(K))
            # 画像の保存
            cv2.imwrite(output_path, res2)
    

     전회의 코드에 추가한 주된 처리는 이쪽입니다.
    """
    ピクセルごとのxy座標を取得
    """
    # 画像の縦横幅
    h, w = img.shape[:-1]
    # 画像のxy座標を2次元リスト化
    Z2 = [[i, j] for i in range(h) for j in range(w)]
    

      이 부분의 처리로, 픽셀 마다의 xy 좌표를 취득합니다. 여기서 취득할 수 있던 xy 좌표를, 픽셀치의 리스트와 결합하는 것으로, RGB+xy 좌표를 결합한 리스트를 생성합니다.
    우선 img의 세로폭(h), 가로폭(w)을 취득합니다.
    Z2 = ~ 의 행으로 [[0, 0], [0, 1], [0, 2] ... ] 가 되는 xy 좌표 리스트를 만들고 있습니다.
    # RGB + xy座標を連結
    Z = np.hstack((Z1, Z2))
    

    이 행에서 픽셀값과 xy 좌표의 리스트를 결합해, K-means에 입력하는 데이터의 완성입니다.

     
      이하가 그 결과입니다.
    원본 이미지


    K = 5


    K = 8


    K = 11


    K = 14


    K = 17


    K = 20


    화소치 뿐만이 아니라, 위치도 고려해 클러스터 나누고 있으므로, 패스화 같을 수 있어요!

    참고



  • 이미지
    이번에 사용하고 있는 이미지 데이터는 아래 링크에서 다운로드할 수 있습니다.
    h tp // w w. 엣 s. i c. 가나가와이 t. 아 c. jp / 아 p_ 속눈썹 s_j. HTML
  • 좋은 웹페이지 즐겨찾기