본문 바로가기
Deep Learning/3D Reconstruction

[논문 리뷰] 3DFaceNet: CNN-based Real-time Dense Face Reconstruction via Synthesizing Photo-realistic Face Images

by kail9974 2021. 8. 31.

Figure 1. 전체 Pipeline, 비디오의 첫프레임은 Single Image CoarseNet, 이후 Tracking CoarseNet, 각 프레임 결과를 FineNet으로 고품질 결과물을 얻음.

3DFaceNet은 단일 이미지가 아닌 비디오에 대한 실시간 3D Reconstruction 모델이다.

Microsoft의 Deep3DFaceRecon(논문 리뷰)에서 BFM에는 없는 Expression에 대한 정보를 가져오기 위해서 이 논문의 표정에 대한 PCA 결과물을 이용했기에 읽어보게 되었다.

 

저자가 내세운 Contributions은 다음 5가지다.

  • Optimization방식의 Inverse Rendering
    단일 이미지에서 정확한 Shape, Albedo, Lighting을 추정함
  • Inverse Rendering 방식으로 많은 양의 사실적인 2D-3D Dataset 생성 (github에 있음)
    이 데이터셋을 통해 Single-image CoarseNet을 학습하며 표정과 Pose에 강건한 모델을 만들 수 있게 함
  • 실제 비디오로 학습한 통계를 통해 이전 프레임을 시뮬레이션하여 Single-image CoarseNet 학습용 데이터를 확장하여 많은 양의 Dataset 생성 (비공개)
    이 데이터셋을 통해 Tracking CoarseNet을 학습함
  • 논문에서 제안한 얼굴 세부 묘사 전이법을 통해 세부 묘사가 있는 많은 양의 2D-3D Dataset 생성 (github에 있음)
    이 데이터셋을 통해 FineNet을 학습함
  • 다양한 크기의 다양성이 높은 합성 데이터를 통해 미세한 부분까지 표현하는 shape, albedo, lighting을 실시간으로 생성하는 3DFaceNet 제안.

Paper: https://arxiv.org/abs/1708.00980 (TPAMI 2018)

Github: https://github.com/Juyong/3DFace (데이터 공개, Code 비공개)

참조 1. Demo Video

 

Introduction

전체 Pipeline은 첫 프레임을 위한 Single image CoarseNet, 다음 프레임을 위한 Tracking CoarseNet, 그리고 FineNet으로 이루어져 있는데 CoarseNet을 통해 중간 데이터를 만들어내고 FineNet으로 최종 결과물을 얻는다.

다른 모델들은 고화질의 세밀한 묘사를 가진 데이터가 적어서 비지도 학습을 사용했지만, 3DFaceNet은 세부 묘사를 가진 데이터에서 shape을 추정한 후 그 세부 묘사를 다른 이미지에서 얻은 shape에 전이한 후 그것을 다시 2D 이미지로 만들어 세부 묘사를 가진 데이터 쌍을 만들어내고 지도학습 통해 FineNet을 학습한다.

FineNet 이전에 CoarseNet 학습에도 데이터의 Pose 등을 바꿔 데이터를 생성해서 학습하는데 이러한 방식들은 일종의 augmentation을 적용한 것으로 볼 수 있으며 이후 자세히 설명하겠다.

 

Inverse Rendering

Figuer 2. Inverse Rendering pipeline. CoarseNet을 통한 초기결과물 얻기, 세밀한 shape 수정, albedo blending의 3 stage로 구성

3D Reconstruction에는 rendering이 필수적인데 optimization 기반은 시간이 오래 걸리기 때문에 CNN 기반 CoarseNet과 FineNet의 renderer를 만들었다.

Inverse Rendering은 이 CNN 기반 renderer를 학습하기 위한 사전 준비 단계이며 optimization 기반의 방법을 사용하여 데이터를 만들어 CNN 기반 renderer를 학습했다.

3DFaceNet의 Inverse Rendering은 parameter 공간에서 조잡한 shape, albedo, lighting, pose를 추정한 후 픽셀 공간에서 세밀한 결과물을 얻고 albedo를 blending 하는 3 stage의 과정으로 이루어져 있다.

 

Stage 1

가장 먼저 진행하는 것은 Differentiable renderer를 통해서 얼굴을 rendering 하기 위한 변수 shape, albedo, lighting, pose를 반복적 최적화로 추정하는 과정이며 변수 각각에 대해서 먼저 설명하겠다.

사용하는 3D shape topology의 평균 형태의 얼굴에 개인의 특징과 표정의 변화를 더하여 target shape이 만들어진다.

3DFaceNet은 3DMM으로 BFM topology를 사용하며 shape $p$와 albedo $b$를 수식으로 나타내면 다음과 같다.

$$p=\bar{p}+A_{id}\alpha_{id}+A_{exp}\alpha_{exp}$$

$$b=\bar{b}+A_{alb}\alpha_{alb}$$

 $A_{id}, A_{alb}$는 BFM의 무표정을 PCA 한 값이며 $A_{exp}$ Facewarehouse 데이터로부터 얻은 표정 shape과 중립 shape간의 차이값을 PCA한 값이다.

각 $A$값에 CoarseNet으로 얻는 parmaeter인 $\alpha$를 곱하여 3D shape의 각각의 정점이 x, y, z로 어느 정도 움직여야 하는지, albedo의 픽셀 색상이 어떻게 변화해야 하는지 계산된다.

카메라나 lighting, pose 등 다른 부분은 Deep3DFaceRecon과 동일하며 $\chi=\{\alpha_{id}, \alpha_{exp}, \alpha_{alb}, s, pitch, yaw, roll, t, \mathrm{r}\}$가 CoarseNet의 출력이다.

$s$는 scale, $t$는 카메라의 위치, $\mathrm{r}$은 RGB의 각 채널에 맞는 구면 조화 함수 계수로 parameter $\chi$를 특징에 맞게 그룹 지으면 다음과 같다.

$$shape=\{\alpha_{id}, \alpha_{exp}\}$$

$$albedo=\{\alpha_{alb}, \mathrm{r}\}$$

$$pose=\{pitch, yaw, roll\}$$

$$translation=\{s, t\}$$

 

$\chi$를 추정하기 위한 loss function $E$는 사진과 같은지($E_{con}$), 랜드마크가 일치하는지($E_{lan}$)와 regularization($E_{reg}$)으로 구성되어 있으며 수식은 아래와 같다.

$$E_{con}(\chi) = \frac{1}{|F|} \lVert I_{ren} - I_{in} \rVert^2$$

$F$는 얼굴 영역의 픽셀, $I_{in}$은 입력 이미지, $I_{ren}$은 결과물을 2D로 투영한 후 $I_in$위에 overlay 한 것이다.

$$E_{lan}(\chi) = \frac{1}{L} \sum_{i \in L} \lVert q_i - (\Pi Rp_i + t) \rVert^2$$

$L$은 랜드마크, $q_i$는 입력 이미지의 랜드마크 좌표, $p_i$는 3D 정점 그 자체의 좌표, $\Pi$는 scaling 행렬로 $s$를 포함하며, $R$은 회전 행렬, $t$는 평행이동 값이다.

$$E_{reg}(\chi) = \sum_{i=1}^{100} \left[ \left( \frac{\alpha_{id,i}}{\sigma_{id,i}} \right)^2 + \left( \frac{\alpha_{alb,i}}{\sigma_{alb,i}} \right)^2 \right] + \sum_{i=1}^{79} \left( \frac{\alpha_{exp,i}}{\sigma_{exp,i}} \right)^2$$

$\sigma$는 표준편차이며 100은 사람의 수(100명의 identity), 79는 표정의 수다.

 

Stage 2

추정한 parameter로부터 얻은 3D shape을 세세하게 다듬는 과정이다.

표현력이 부족한 저차원의 변수들을 사용하여 parameter optimization을 했기 때문에 얼굴의 주름과 같은 세부적인 부분은 최적화하지 못했으며 잠재 공간이 아닌 픽셀 공간에서 이를 최적화해야 한다.

픽셀 공간에서 처리하기 때문에 3D shape의 정점으로 만들어진 삼각면에 포함되는 픽셀에 삼각면 무게중심 좌표를 할당하여 깊이 값 $z$에 디테일 깊이 정보 $d$를 더한 $\tilde{z}$을 얻으며 $d$를 최적화하는 함수는 다음과 같다.

$$E(d) = E_{con} + \mu_1 \lVert d \rVert_2^2 + \mu_2 \lVert \triangle d \rVert_1$$

1항은 stage 1의 것과 동일하고 2항은 작은 오차를 줄이는 것이며 3항은 오차의 Laplacian으로 오차값을 부드럽게 만들기 위한 것이다.

stage 1과 마찬가지로 이 수식을 반복적으로 적용하여 최적 shape을 만들어낸다.

이때 최적화 과정은 stage 1에서 얻어낸 shape을 바꾸는 것이 아니라 추가로 displacement map $d$를 얻는 것이다.

 displacement map $d$는 나중에 FineNet을 학습할 때 사용된다.

참조 2. Fine Dataset의 afw_134212_1의 displacement map에 해당하는 정점 좌표를 plot한 것. 실제 정점에 해당하는 것이 아닌 픽셀 좌표에 해당하며 회전시켰을 때 사진에서 보이지 않는 부분은 표현되지 않음.

그런데 stage 2의 결과물은 2D 사용에서는 훌륭하지만 3D로 사용하기에는 어렵다.

3D 공간이 아닌 픽셀 공간의 displacement map은 3D modeling에서 사용하는 normal map과 유사하다.

normal map은 texture와 같이 3D mesh 위에 입혀 vertex 사이를 채우는 울퉁불퉁함을 표현하는 데 사용한다.

그런데 3D mesh 전체 표면을 덮지 못하는 2D 공간의 displacement map은 게임이나 시뮬레이션 등 다른 곳에 활용할 수 없는 이 모델에서만 쓸 수 있다.

저자는 이 displacement map을 사용하여 다른 얼굴 mesh 위에 입혀 Augment 하여 사용한다.

참조 2는 직접 데이터를 받아 plot 한 결과물인데 보다시피 입력 사진에 보이지 않는 부분은 displacement map에서 표현되지 않는다.

아래 Figure 5를 보면 $d$를 시각화한 것을 볼 수 있는데 3D model 표면에 맞춘 것처럼 생기긴 했다.

방향을 잘 맞춘다면 충분히 다른 mesh 위에 입힐 수 있어 보인다.

 

Stage 3

마지막으로 완성된 shape에 맞게 albedo 또한 수정한 후 blending 하는 단계다.

stage 1의 출력으로 만든 albedo $b_c$와 stage 2에서 계산된 shape의 normal vector $n$에 대해 수정된 albedo $b_f$는 다음과 같다.

$$b_c = (\bar{b} + A_{alb}\alpha_{alb}) \cdot \mathrm{r}^T \phi(n_{stage1})$$

$$b_f = I_{in}/(\mathrm{r}^T \phi(n_{stage2}))$$

여기서 $\mathrm{r}$은 구면 조화 함수 계수, $\phi$는 구면 조화 함수다.

수식을 보면 stage 1에서 굳이 $b_c$를 만들지 않아도 $b_f$를 얻을 수 있는 것으로 보이는데 stage 2의 shape 정보가 완벽하지 않기 때문에 shape의 오차가 albedo에 포함되어 $b_f$가 왜곡될 수 있다.
$b_c$는 이 현상을 완화하기 위해서 만드는 것이며 결과적으로 얻는 albedo $b$는 다음과 같다.

$$b = \beta b_c + (1-\beta) b_f$$

Linear interpolation 하는 것이며 beta는 얼굴의 영역마다 다른 값을 사용하는데, 이마나 눈꼬리 같이 주름이 많은 부분은 albedo에 shape 정보가 포함되기 쉽기 때문에 0.65로 $b_c$가 크게 반영되고 볼 등의 다른 부분에서는 0.35로 $b_f$가 크게 반영되도록 한다. 영역 간의 경계 부분은 0.35~0.65로 연속적으로 설정한다.

 

CNN-based Rendering

시간이 걸리는 Optimization 기법의 Inverse Rendering을 통해서 2D-3D 쌍의 dataset을 만들고 이 dataset으로 한 번에 결과물을 얻을 수 있는 CNN-based renderer를 학습한다.

Single-image CoarseNet, Tracking CoarseNet, FineNet의 3개의 네트워크로 구성되어 있으며 하나씩 설명하겠다.

 

Single-image CoarseNet

 

Figure 3. Single-image CoarseNet에 사용하기 위한 dataset 생성 과정. Inverse Rendering으로 shape을 얻고 표정과 pose를 augmentation 한다.

전체 pipeline에서 가장 앞부분의 네트워크다. 먼저 이 네트워크를 학습하기 위한 데이터 생성법을 살펴보자.

기존의 다른 모델에서 데이터를 생성한 경우는 주름과 같은 피부의 세세한 정보가 사라진 경우가 많아 사실적이지 않은 결과물을 보여줬다.

앞서 설계한 Inverse Rendering으로 2D 이미지의 3D GT를 만들 경우에는 피부의 고주파 정보까지 포함할 수 있으므로 기존 모델들보다 훨씬 좋은 품질의 데이터를 만들 수 있다.

이를 이용하여 입력 이미지의 rendering parameter $\chi$를 연산하고 pose $pitch, yaw, roll$과 표정 $\alpha_{exp}$를 조정한 $\tilde{\chi}$를 만든다.

이후 입력 이미지의 배경을 $\tilde{\chi}$로 만든 shape의 normal vector에 맞게 warping 해서 사실적인 shape과 texture를 갖는 새로운 이미지를 만들어낸다.

참조 3. 3D Shape의 좌표를 RGB로 나타낸 것. (a) 3D 그대로인 텍스쳐만 RGB값으로 입힌 NCC. (b) 2D로 투영한 PNCC.
참조 4. 3D shape에 맞추어 2D 이미지를 warping한 것의 예시. (a) original (b) yaw + 20 degree (c) yaw + 30 degree (d) yaw + 40 degree

이 방법은 3DDFA(Face Alignment Across Large Poses: A 3D Solution, github)에서 제시한 Projected Normalized Coordinate Code(PNCC)를 이용하여 2D 이미지를 3D 구조에 맞추어 warping 하는 방법을 변형한 것이다.

참조 4가 3DDFA의 결과물을 보여준 것이며 3DFaceNet은 얼굴 부분을 3D shape과 albedo를 2D로 투영하여 사용하는 점이 차이점으로 좀 더 사실적인 결과를 만들어 낼 수 있다.

Figure 3의 맨 오른쪽 이미지가 그 결과물이며 300W dataset에서 4,000장의 얼굴 사진을 골라내고 각각 20장의 augmentation을 만들어 총 80,000장의 dataset을 만들었다.

 

이렇게 만든 dataset을 이용하여 Single-image CoarseNet을 지도학습하며 albedo는 추정하지 않고 $\mathcal{T} = \{ \alpha_{id}, \alpha_{exp}, s, pitch, yaw, roll, t_x, t_y \}$를 추정한다.

CoarseNet은 Resnet-18의 출력만 185 node로 바꾼 모델이며 224 해상도의 이미지 입력을 받는다.

(185 = 100 identity + 79 expression + 3 rotation + 2 translation + 1 scale)

 

$\mathcal{T}$를 추정하기 위한 loss는 일반적으로 사용하는 3D shape의 정점 간의 MSE가 아닌 GT parameter $\mathcal{T}_g$를 이용한 픽셀 공간의 loss를 사용한다.

우선 이 과정을 이해하기 위해서 2D 이미지와 3D shape의 관계를 살펴보자.

3D shape은 얼굴의 표면을 만들어주는 N개의 정점으로 이루어져 있고 일반적으로 3개의 정점으로 구성된 삼각면을 갖는데, 이 정점을 2D로 투영했을 때 모든 픽셀마다 정점이 존재하지는 않으며 픽셀 수보다 정점이 훨씬 적기 때문에 픽셀 공간에서의 loss를 적용하기는 어렵다.

픽셀 공간의 loss를 적용하려면 모든 픽셀마다 해당하는 3D shape에 대한 정보가 있어야 하기 때문에 각 픽셀이 어떤 삼각면에 포함되는지와 그 삼각면의 무게중심을 3D shape 정보로 사용한다.

 

$\mathcal{T}$를 2D 픽셀 공간으로 투영한 것은 다음과 같으며 loss $D(\mathcal{T}_g, \mathcal{T}_n)$은 다음과 같이 정의한다.

$$Proj(\mathcal{T}) = \Pi R (\bar{p}_q + A_{q,id}\alpha_{id} + A_{q,exp}\alpha_{exp}) + t$$

$$D(\mathcal{T}_g, \mathcal{T}_n) = \lVert Proj(\mathcal{T}_g) - Proj(\mathcal{T}_n) \rVert_2^2$$

이 loss를 더 좋은 결과를 얻기 위해서 특징에 맞게 $L_{pose}$와 $L_{geo}$로 나누었으며, 이는 GT의 geo를 쓰고 추정한 pose를 써서 투영한 것과 그 반대의 것에 해당한다.

$$L_{pose} = \lVert Proj(\mathcal{T}_g) - Proj(\mathcal{T}_{n,pose},\mathcal{T}_{g,geo}) \rVert_2^2$$

$$L_{geo} = \lVert Proj(\mathcal{T}_g) - Proj(\mathcal{T}_{n,geo},\mathcal{T}_{g,pose}) \rVert_2^2$$

$$w = \frac{L_{geo}}{L_{pose} + L_{geo}}$$

$$\begin{align}L &= w \cdot L_{pose} + (1-w) \cdot L_{geo} \\ &= \frac{2L_{pose}L_{geo}}{L_{pose} + L_{geo}}\end{align}$$

 

Tracking CoarseNet

최초 프레임 이후의 결과물을 얻기 위한 중간 네트워크로 이전 프레임에서 추정한 parameter도 활용하여 현재 프레임의 parameter와 albedo를 추정한다.

설계 과정에서 처음에는 이전 프레임의 모든 parameter를 사용하여 현재 프레임 값을 추론하려 했으나, 너무나도 많은 정보를 사용함에 따라 복잡한 데다 불확실성이 컸기 때문에 수렴하기 어려웠고 불안정한 테스트 결과를 얻었다.

실험을 통해서 이전 프레임의 pose 관련 값($\{s, pitch, yaw, roll, t\}$)만 사용하는 것이 복잡성을 줄여 안정적으로 학습할 수 있었다고 한다.

Figure 4. 다른 프레임에 대한 warping 예시. 좌측은 다른 프레임의 PNCC, 우측은 PNCC로 warping한 현재 프레임 이미지.

그래서 Tracking CoarseNet의 입력은 현재 프레임의 이미지에 이전 프레임의 pose 값을 삽입한 것이다.

정확하게 설명하자면 이전 프레임의 pose값을 사용해서 3D shape을 생성하고 그것을 2D로 투영하고 픽셀 위치에 맞는 3D 상의 정점의 x, y, z 값을 R, G, B 값으로 사용해서 이미지를 만들어낸다.

사실 이것은 사람의 입장에서만 다를 뿐이지 모델의 관점에서 보면 3D 좌표 정보를 2D 좌표에 맞추어 사용하는 것이다.

이를 PNCC라고 하고 PNCC를 사용해 현재 프레임을 왜곡시킨다.

현재 프레임과 이전 프레임의 포즈는 다르므로 Figure 4에서 보듯이 상당히 많이 왜곡된 것을 볼 수 있다.

Tracking CoarseNet은 이런 왜곡된 이미지를 입력으로 받으며, 얼굴 shape에 대한 정보와 함께 얼마나 왜곡됐는지를 추정하는 모델이다.

따라서 이전 프레임과의 차이 $delta$를 추정하며, k번째 프레임에 대해 출력 parameter $\mathcal{T}^k = \{ \alpha_{id}^k, \alpha_{exp}^k, \alpha_{alb}^k, \delta^k(s), \delta^k(pitch), \delta^k(yaw), \delta^k(roll), \delta^k(t), \mathrm{r}^k \}$을 가진다.

 

구조는 Single-image CoarseNet과 동일하며 추가로 albedo와 lighting을 추정하여 312 node로 출력을 갖는다.

(312 = 100 identity + 79 expression + 3 rotation + 2 translation + 1 scale + 100 albedo + 27 lighting)

 

학습에 사용한 loss는 Single-image CoarseNet의 $L_{pose}, L_{geo}$에 color loss인 $L_{col}$이 추가된 것이다.

$$L_{col}=\lVert I_{ren}^k (\alpha_{alb}^k, \mathrm{r}^k) - I_{in}^k \rVert_2^2$$

여기서 $I_{ren}^k (\alpha_{alb}^k, \mathrm{r}^k)$는 GT shape, pose에 추정한 albedo와 lighting을 입힌 결과물이다.

전체 loss는 다음과 같다.

$$w_1 = \frac{L_{geo}+L_{col}}{2(L_{pose}+L_{get}+L_{col})}$$

$$w_2 = \frac{L_{pos}+L_{col}}{2(L_{pose}+L_{get}+L_{col})}$$

$$L = w_1 \cdot L_{pose}+w_2 \cdot L_{geo}+(1-w_1-w_2)\cdot L_{col}$$

 

Tracking CoarseNet을 학습하기 위해서도 데이터를 만들어야 했는데 이전에 만든 80,000장의 데이터에 대한 이전 프레임을 만들어서 사용하고 있다.

처음에는 이를 랜덤 pose값을 적용해서 만들었지만 실제 비디오와 차이가 너무 커서 쓸 수가 없었기 때문에 실제 비디오를 분석해서 roll, pitch, yaw, translation의 분포에 맞게 sampling 한 $\delta(\chi)$를 적용하여 만들었다.

이전에 만든 80,000장에 대해서 이전 프레임 80,000장을 만들어 총 160,000장의 dataset으로 학습하였다.

이 데이터셋은 공개되어있지 않다.

 

FineNet

전체 pipeline의 마지막 단계로 최종 출력을 얻는 네트워크다.

FineNet을 학습할 때 입력 이미지에 대한 CoarseNet의 출력 parameter $\mathcal{T}$로 rendering 한 3D shape에서 Inverse Rendering stage 2의 방법으로 displacement map $d$를 만들어 학습 데이터로 사용한다.

CoarseNet 출력을 입력하여 displacement map $d$를 출력하는 U-Net 구조의 모델이다.

Figure 5. FineNet 학습용 데이터 생성과정. 주름이 많은 얼굴에서 displacement map을 가져와 300W 데이터에 전이함.

FineNet을 학습하기 위해서는 얼굴 표면이 많이 변하는 데이터가 필요한데 CoarseNet 학습에 썼던 300W에는 그럼 샘플이 적다.

그래서 인터넷에서 1,000장을 수집하고 displacement map을 연산한 후 300W 데이터 위에 전이하는 방식으로 120,000(장당 임의의 30개의 $d$ 적용)장의 dataset을 구성하였다.

전이하는 방법은 source 이미지와 target 이미지의 CoarseNet 출력 parameter로부터 source displacement map이 target 이미지와 일치하도록 변형하여 $\tilde{d}_t$를 만드는 것이다.

$$\mathrm{w}(i,j)=s_d[d_s(i'+1,j')-d_s(i',j'),d_s(i',j'+1)-d_s(i',j')]^T$$

$$\min_{\tilde{d}_t} \sum_{(i,j)\in \Omega} \lVert \nabla \tilde{d}_t(i,j)-\mathrm{w}(i,j) \rVert^2$$

$$s.t. \tilde{d}_t(i,j) = d_t(i,j)$$

여기서 $i,j$는 얼굴 영역 $\Omega$에 포함되는 2D 픽셀 좌표이며 $s_d$는 $d$의 세기를 조절하는 scale factor다.

 

생성한 데이터를 사용하여 단순하게 l2 loss만 적용하여 지도학습하였다.

 

Experiments

Figure 7. 1행: 입력 이미지, 2행: Single-image CoarseNet 출력, 3행: Tracking CoarseNet 출력.
Figure 9. 1행: 입력, 2행: FineNet 출력. 픽셀 공간에서 깊이 정보를 가져오다 보니 머리카락도 포함된 것을 볼 수 있음.
Figure 10. 1행: 입력, GT mesh, 2행: Inverse Rendering 출력, 3행: FineNet 출력.
Figure 15. 빛이 강해서 표면 정보가 손실된 이미지에 대한 결과. 1열: 입력, 2열: Inverse Rendering 출력, 3열: FineNet 출력.

한계점은 서술하지 않았으며 실험 결과는 모델이 잘 동작하는 모습만 볼 수 있었다.

그래서 따로 설명하지 않고 이미지 첨부로 대체하겠다.

 

결론

  • Dataset 생성에 공헌이 있는 논문
  • 모델 자체는 2Stage로 단순하며 크게 주목할 것은 없음
  • Expression은 FaceWarehouse라는 BFM과 topology가 다른 3DMM이며 이것을 PCA 해서 BFM의 exp를 조절할 수 있음
    Topology가 다르더라도 공통되는(위치가 유사한) 정점을 골라내면 사용 가능함을 뜻함

댓글