ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [python] Procrustes shape analysis
    코딩/Python 2020. 10. 20. 15:40

    최근 서로 다른 실루엣의 유사도를 비교하는 방법을 찾던 중 논문에서 Procrustes Shape Analysis라는 서로 다른 두 도형의 유사도를 비교하는 방법을 공부해보았다. 한글로된 설명이 많이 없어 나중에 보기 편하게 포스팅을 남겨본다. 

     

    https://www.mathworks.com/matlabcentral/mlc-downloads/downloads/submissions/23972/versions/22/previews/chebfun/examples/geom/html/Procrustes.html

     

    Procrustes shape analysis

    Procrustes shape analysis Alex Townsend, August 2011 Contents (Chebfun Example geom/Procrustes.m) function procrustes close all Shape analysis on a beach holiday Procrustes shape analysis is a statistical method for analysing the distribution of sets of sh

    www.mathworks.com

    해당 포스팅에서 이미 Procrustes Shape Analysis에 대해서 잘 설명되어 있으나, 최근 많이 사용되고 있는 python 코드로 변환과 동시에 한글로된 설명을 남겨본다. 위 포스팅에서는 두 도형(원반, 조약돌)을 비교하는 예시를 들고 있는데, 이 포스팅에서는 두개의 사각형 모형 유사도를 비교해본다.

     

    import numpy as np
    import matplotlib.pyplot as plt
    import matplotlib.patches as patches

    fig, ax = plt.subplots()
    plt.xlim(-6, 6), plt.ylim(-6, 6)
    plt.plot([6, -6], [0, 0], 'k')
    plt.plot([0, 0], [-6, 6], 'k')

    rect1 = [[-3,-3],[-1,-3],[-1,-1],[-3,-1]]
    rect2 = [[2,0],[4,2],[2,4],[0,2]]

    for i in range(len(rect1)):
       if i != len(rect1)-1:
          plt.plot([rect1[i][0], rect1[i+1][0]], [rect1[i][1], rect1[i+1][1]], 'r')
       else:
          plt.plot([rect1[0][0], rect1[i][0]], [rect1[0][1], rect1[i][1]], 'r')


    for i in range(len(rect2)):
       if i != len(rect2)-1:
          plt.plot([rect2[i][0], rect2[i+1][0]], [rect2[i][1], rect2[i+1][1]], 'b')
       else:
          plt.plot([rect2[0][0], rect2[i][0]], [rect2[0][1], rect2[i][1]], 'b')

    plt.show()

    위 파이썬 코드를 실행 시키면 아래와 같은 두 도형을 확인할 수 있다. 

    Original

    두 정사각형 도형은 (위치, 회전, 크기)라는 특성을 가지고 있는데, 이제부터 Procrustes Shape Analysis 방법을 활용하여 두 도형의 특성(위치, 회전, 크기)을 제외하고 모형이라는 유사도를 확인해본다. Procrustes Shape Analysis방법은 총 4단계로 구성된다. 

     

    def translate_mean_to_center(np_set):
       np_set -= np.mean(np_set, 0)
       return np_set

    # Translate mean to 0.
    rect1 = translate_mean_to_center(rect1)
    rect2 = translate_mean_to_center(rect2)
    print(rect1)
    print(rect2)

    After Translation

    1. 먼저 Translation을 이용하여 두 도형의 중심점을 맞춘다. 

    1. Translate the shapes so they have mean zero.

     

    # scale so RMSD is 1
    rect1 = rect1 / np.linalg.norm(rect1)
    rect2 = rect2 / np.linalg.norm(rect2)
    print(rect1)
    print(rect2)

    After Scaling

    2. Normalization을 통해 두 도형의 크기(Scale)를 맞춘다. 

    2. Scale so the shapes have Root Mean Squared Distance (RMSD) to the origin of one.

     

    from scipy.linalg import orthogonal_procrustes

    R, s = orthogonal_procrustes(rect1, rect2)
    rect2 = np.dot(rect2, R.T) * s
    print(rect1)
    print(rect2)

    After aligning

    3. 회전하여 두 모형을 정렬 시킴

    3. Rotate to align major axis.

    (rect2가 회전하여 rect1을 가릴껄 생각 못했었음;)

     

    disparity = np.sum(np.square(rect1 - rect2))
    print(disparity)

    4. 마지막으로 두 변환된 사각형의 disparity를 구한다. disparity가 0에 가까울 수록 두 도형의 모형이 유사도가 높다는 것을 의미한다. 위 예제의 경우 두 도형이 정사각형이 였기 때문에 코드를 실행해보면 disparity가 0이 나오는것을확인 할 수 있다.

     

    지금까지 두 도형의 특성인(위치, 회전, 크기)와 상관없이 모형의 형태를 비교해보는 Procrustes Shape Analysis방법을 활용해 보았다.

    '코딩 > Python' 카테고리의 다른 글

    python 코딩 관련 공부할 리스트  (0) 2022.11.10

    댓글

Designed by Tistory.