2020-iuc-sw-skku / LSC-Systems

산학협력프로젝트: 머신러닝 기반 Wafer Map Defect Pattern Identification
8 stars 3 forks source link

Rotation-Invariant Features #12

Open Jinu-Lee opened 4 years ago

Jinu-Lee commented 4 years ago

Wafer Map Defect Pattern Recognition Using Rotation-Invariant Features - Rui Wang and Nan Chen 원본 / 요약본

1

Rotation-Invariant Feature: 회전해도 변하지 않는 Feature

Jinu-Lee commented 4 years ago
  1. Polar Mask
def polar_mask(N_a, N_c, size=32):
    A = [[2 ** N_a - 1], [(1 << (N_a // 2)) - 1], []]
    C = [[] for i in range(N_c)]

    bit_mask = 2 ** N_a - 1
    #a_1,*
    for i in range(1, N_a):
        if i == N_a // 2:
            continue
        A[0].append((A[0][0] << i) & bit_mask)

    #a_2,*
    for i in range(1, N_a // 2):
        A[1].append((A[1][0] ^ (A[1][0] << i)) & bit_mask)

    A = [list(map(lambda x: list(map(int, bin(x)[2:].zfill(N_a))), arr)) for arr in A]

    #a_3,*
    A[2] = [list(map(lambda x: 2 * x - 1, arr)) for arr in A[1]]

    #c
    for i in range(N_c):
        C[i].append(2 ** (i + 1) - 1)
        for j in range(1, N_c - i):
            C[i].append(C[i][0] << j)

    C = [list(map(lambda x: list(map(int, bin(x)[2:].zfill(N_c))), arr)) for arr in C]

    #flatten
    A = [a for arr in A for a in arr]
    C = [c for arr in C for c in arr]

    weight_matrix = np.array([np.matmul(np.array([a]).T, np.array([c])) for a in A for c in C])

    #make mask
    R = size // 2
    rad = np.linspace(0, R, num=N_c, endpoint=False)
    angle = np.linspace(0, 2*np.pi, num=N_a, endpoint=False)
    dist = lambda y, x: np.sqrt((x - R) ** 2 + (y - R) ** 2)

    mask = np.zeros((size, size))    
    for i in range(size):
        for j in range(size):
            d = dist(i, j)
            if d > R:
                continue

            theta = np.arctan2(R - i, j - R)
            if theta < 0:
                theta += 2 * np.pi

            mask[i][j] = np.argmax(angle[angle <= theta]) * N_c + np.argmax(rad[rad <= d]) + 1

    #apply weight on mask
    masks = []
    for weight in weight_matrix:
        weighted_mask = mask.copy()
        for i in range(N_a):
            for j in range(N_c):
                weighted_mask[weighted_mask == (N_c * i + j + 1)] = weight[i][j]
        masks.append(weighted_mask)

    return masks

논문에 나와있는 예시인 N_a=4, N_c=3를 넣으면 아래와 같은 Master Mask가 나온다. 1

논문에서 실제 사용한 값인 N_a=4, N_c=5, N_t=16을 이용해 추출 -> 추출되는 개수는 (2*N_a-1)(1+N_c)(N_c)/2=105 polar_mask.zip

Jinu-Lee commented 4 years ago

(3개의 feature 공통) 하나의 master mask에서 feature 추출하기 -> 여러 각도로 돌린 결과 중 최댓값

img -> 변형 필요

img[img != 2] = 0
img[img == 2] = 1
def extract_features(img, mask, N_t, size=32):
    result = []
    for angle in np.linspace(0, 360, num=N_t, endpoint=False):
        rotation_matrix = cv2.getRotationMatrix2D((size / 2, size / 2), angle, 1)
        rotated_mask = cv2.warpAffine(mask, rotation_matrix, (size, size))

        masked_img = img * rotated_mask
        result.append(masked_img.sum(dtype=np.int32))

    return max(result)
Jinu-Lee commented 4 years ago
  1. Line Mask
def line_mask(N_l, size=32):
    R = size // 2
    dist = lambda y, x: np.sqrt((x - R) ** 2 + (y - R) ** 2)
    rad = np.linspace(0, R, num=N_l, endpoint=False)

    mask = np.zeros((size, size))
    for i in range(size):
        for j in range(size):
            d = dist(i, j)
            if d > R:
                continue

            theta = np.arctan2(R - i, j - R)
            if -np.pi / 2 <= theta <= np.pi / 2:
                mask[i][j] = np.argmax(rad[rad <= (j - R)]) + 1

    masks = []
    for i in range(1, N_l + 1):
        weighted_mask = mask.copy()
        weighted_mask[weighted_mask != i] = 0
        weighted_mask[weighted_mask == i] = 1
        masks.append(weighted_mask)

    return masks

논문에 사용된 N_l=7 2 line_mask.zip

Jinu-Lee commented 4 years ago
  1. Arc Mask
def arc_mask(N_r, R_l, R_h, N_o, R_c, size=32):   
    R_l, R_h, R_c = [(size / 2) * i for i in (R_l, R_h, R_c)]

    dist = lambda y, x, c: np.sqrt((x - c - size / 2) ** 2 + (y - size / 2) ** 2)

    rad = np.linspace(R_l, R_h, num=N_r, endpoint=False)
    center = np.linspace(R_c, 0, num=N_o, endpoint=False)

    masks = []
    for c in center:
        mask = np.zeros((size, size))

        for i in range(size):
            for j in range(size):
                d = dist(i, j, c)
                if d < R_l or d > R_h:
                    continue

                mask[i][j] = np.argmax(rad[rad <= d]) + 1

        for i in range(1, N_r + 1):
            weighted_mask = mask.copy()
            weighted_mask[weighted_mask != i] = 0
            weighted_mask[weighted_mask == i] = 1
            masks.append(weighted_mask)

    return masks

논문에 나온대로 N_o=12, N_r=6, R_c=1.2R, R_l=0.5R, R_h=R 주석 2020-07-17 162952 arc_mask.zip

Jinu-Lee commented 4 years ago

D: Density / G: Geometry / R: Radon P: Polar / L: Line / A: Arc

image

image