Open Jinu-Lee opened 4 years ago
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가 나온다.
논문에서 실제 사용한 값인 N_a=4, N_c=5, N_t=16을 이용해 추출 -> 추출되는 개수는 (2*N_a-1)(1+N_c)(N_c)/2=105 polar_mask.zip
(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)
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 line_mask.zip
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 arc_mask.zip
D: Density / G: Geometry / R: Radon P: Polar / L: Line / A: Arc
Wafer Map Defect Pattern Recognition Using Rotation-Invariant Features - Rui Wang and Nan Chen 원본 / 요약본
Rotation-Invariant Feature: 회전해도 변하지 않는 Feature