상세 컨텐츠

본문 제목

Faster R-CNN implementation (FurkanOM Github)

Coding/Image

by linguana 2021. 4. 20. 11:21

본문

본격적으로 Faster-RCNN을 구현하기 전에,

용어 정리부터하고 가자:

RPN (Region Proposal Network): CNN 모델로, 객체가 있을만한 영역을 예측하는 용도로 사용. (object localization에 활용)

  • IoU (Intersection over Union): region proposal된 bounding box와 ground-truth box가 겹치는 정도로 해당 바운딩박스의 정확도를 알려주는 지표. 용어 그대로 분자는 region proposal과 gt-box가 겹치는 교집합, 분모는 두 영역의 합집합.
  • bbox regression (바운딩 박스 회귀): RPN이 내세운 region proposal들의 positive example과 negative example에 대한 좌표를 보고 바운딩박스의 좌표에 대해 회귀를 하는 것. (좌표 값은 float이므로 분류 아닌 회귀로 처리)
  • NMS (Non-Maxima Suppression): RPN의 알고리즘 특성 상 한 객체의 gt-box에 걸치는 다수의 bbox가 region proposal로 제안되는데, 한 객체에 한 bbox만 있게 하도록 정확도가 낮은 bbox를 제거해주는 과정. 
  • ROI (Region of Interest): 말 그대로 '관심영역'. IoU, bbox regression, NMS를 거친 bbox는 ROI로 불려지는 듯함.
  • alternating training: faster RCNN의 학습되는 방식. 4단계로 나뉨.

Faster RCNN 아키텍처

핵심요소: RPN, end-to-end

1faster rcnn overall architecture


이 FurkanOM 깃헙이 구현할만한 소스인 것 같다.

github.com/FurkanOM/tf-faster-rcnn

 

FurkanOM/tf-faster-rcnn

Tensorflow 2 Faster-RCNN implementation from scratch supporting to the batch processing with MobileNetV2 and VGG16 backbones - FurkanOM/tf-faster-rcnn

github.com

tf-faster-rcnn-master.zip
0.03MB

 


Table of Contents

  • faster_rcnn_trainer.py
  • io_utils.py
  • data_utils.py
  • bbox_utils.py
  • train_utils.py

파악해야할 소스 10개 내외

top-down 방식으로 파악해보자. 가장 먼저 볼 코드는 전체 wrapper인 faster_rcnn_trainer.py이다.


1. faster_rcnn_trainer.py [80 lines]

faster_rcnn_trainer.py

1-1. configuration [1, 22]

라인 내용 dependency
[1, 4] 필요한 모듈 임포팅 utils, models
[6, 8] args 불러오고 gpu로 돌리는 거 가능한지 확인 io_utils
[10, 15] constants 설정 (args.backbone 사용) io_utils
[17, 20] mobilenet_v2 or vgg16 선택 models
[22] 하이퍼 파라미터 불러오기 train_utils

faster_rcnn_trainer.py

1-2. prepare input data [24, 50]

라인 내용 dependency
[24, 27] 훈련 및 검증 데이터 불러오기, item 개수는 이후 step size에 활용됨 (default: voc 2007) -> X 데이터 data_utils.get_dataset 등
[29, 33] voc 2012의 경우, 데이터 불러오기 data_utils
[35] labels 불러오기 -> Y 데이터 data_utils.get_labels
[37] backbone의 hyper-parameter 말고 현재 데이터에 맞게 설정 line [22]
[39, 41] 전처리 (사이즈 조정 등) data_utils.preprocessing
[43, 46] 데이터 사이즈 파악하고 패딩 입히기 data_utils
[48, 50] 앵커 생성, 데이터와 앵커 매핑
(frcnn에 feed될 형식으로 완성됨)
bbox_utils, train_utils

1-3. modeling [52, 80]

faster_rcnn_trainer.py

라인 내용 dependency
[52] rpn model 로딩 라인 [18] 혹은 [20]
[53] frcnn model 객체 생성 models.faster_rcnn
[54, 56] 모델 컴파일 및 초기화 models.faster_rcnn
[59, 62] rpn 사전훈련된 거 있으면 가중치 가져오기 (optional) 라인 [12], io_utils
[64, 67] frcnn model 경로 불러오고, 가중치 불러올 수 있으면 가져옴 io_utils, models.faster_rcnn
[68, 71] 각종 콜백 정의 io_utils, ModelCheckpoint
[73, 80] 모델 스텝 정의 및 훈련 실시 train_utils.get_step_size

이제 각종 utils에 대해서 알아보자. (순서: io_utils, data_utils, bbox_utils, train_utils)

2. io_utils.py [59 lines]

함수 5개 정의됨

2-1. get_log_path 함수 [1, 15]

io_utils.py

라인 내용
[1, 4] 각종 모듈 임포팅
[7, 14] 텐서보드에 로그 그릴 목적인 함수
인자 설명,
(1) 모델은 rpn 혹은 faster_rcnn
(2) 백본: vgg16 혹은 mobilenet_v2
(이하 생략)

2-2. get_model_path 함수 [17, 29]

io_utils.py

h5 파일이 있는 경로를 반환하는 함수

(만약 "trained"라는 폴더가 없으면 만들어줌)


2-3. handle_args 함수 [31, 43]

io_utils.py

cmd 아규먼트 파싱해주는 함수 (gpu, backbone을 설정해줌)


2-4. is_valid_backbone 함수 [45, 50]

io_utils.py

assert condition

조건이 참이 아니라면 AssertionError을 발생시킨다.

즉, backbone은 vgg16이거나 mobilenet_v2 둘 중에 하나여야 한다.


2-5. handle_gpu_compatibility 함수 [52, 59]

io_utils.py

gpu 호환성 검사하는 함수, 에러 발생하면 print해줌


3. data_utils.py [157 lines]

총 12개 함수 있음


3-0. 필요한 모듈 임포팅 [1, 5]

data_utils.py

모듈 임포팅하는 라인 [1, 5]에서 다른 특별할 것은 없는데

라인 [3]의 tfds는 voc 데이터셋을 이미 제공하고 있다, (아래 링크 참고)

voc  |  TensorFlow Datasets

faster_rcnn_trainer.py 라인[25]에서 "voc/2007" 데이터를 불러오는데, 다음과 같은 형태로 로딩된다.

tfds voc


3-1. preprocessing 함수 [7, 29]

data_utils.py

말 그대로 전처리하는 함수이다. 이미지와 타겟 사이즈를 입력값으로 주면 해당 사이즈로 만들고, 해당 이미지에 매핑된 바운딩박스와 레이블을 반환함. 데이터 증강이나 평가도 가능함.


3-2. get_random_bool 함수 [31, 36]

data_utils.py

랜덤한 불리언 값 반환함, 아래 randomly_apply_operation 함수에 활용됨


3-3. randomly_apply_operation 함수 [38, 52]

data_utils.py

인자: 호출할 수 있는 함수, 이미지, 정답 박스

tf.cond  |  TensorFlow Core v2.4.1

tf.cond(pred, true_fn=None, false_fn=None, name=None) 참이면 true_fn 반환, 거짓이면 false_fn 반환


3-4. flip_horizontally 함수 [54, 68]

data_utils.py

말 그대로 수평으로 돌림 (이미지뿐만 아니라 정답 박스도)


3-5. get_dataset 함수 [70, 82]

data_utils.py

tsdf에서 테이터셋 불러와줌 (voc 2007, voc 2012 등)


3-6. get_total_item_size 함수 [84, 95]

data_utils.py

주어진 split (i.e. train 혹은 validation)으로 요소들의 개수를 반환해줌. (step size를 알기 위해 필요한 preliminary 정보)


3-7. get_labels 함수 [97, 104]

data_utils.py

wrapper 파일 (faster_rcnn_trainer.py) 라인 [35]에서 레이블을 얻기 위해 사용됨.


3-8 & 3-9. get_custom_imgs & custom_data_generator 함수 [106, 136]

data_utils.py

tensorflow dataset에서 가져오지 않고 따로 커스텀 데이터를 불러오는 경우 사용하는 함수


3-10 & 3-11 & 3-12. get_data_types & get_data_shape & get_padding_values 함수

data_utils.py

각각 가져오라는 거 가져와주는 함수 (데이터 타입, 데이터 모양, 패팅 값)

약간 기타 잡동사니 함수 느낌


4. bbox_utils.py [182 lines]

함수 8개

4-1. generate_base_anchors 함수 [3, 21]

bbox_utils.py

임포트하는 것은 tensorflow뿐이다.

generate_anchors 함수를 완성시키기 위해 사용되는 재료 함수. 일단 기본 앵커 만들어주는 함수이다. 

하이퍼 파라미터에 들어있는 이미지 사이즈, 앵커 ratios 및 scales가 활용된다.


4-2. generate_anchors 함수 [23, 46]

bbox_utils.py

주어진 이미지의 하이퍼파라미터대로 모든 앵커 박스를 만들어주는 함수.

[line 36] tf.cast("조건"): 조건에 대해 True면 1, False면 0을 반환함

[line 38] tf.meshgrid: 2차원 또는 삼차원 변수의 격자점 좌표를 생성하는 명령어

[line 40] tf.stack(values, axis=0, name='stack'): Stacks a list of rank-R tensors into one rank-(R+1) tensor

[line 46] tf.clip_by_value(t, clip_value_min, clip_value_max, name=None): Clips tensor values to a specified min and max. 텐서에서 clip_value_min 보다 작은 값은 clip_value_min이 되고, clip_value_max 보다 큰 값은 clip_value_max이 됨. 즉, 정한 최소값 최대 값 사이 바깥의 값은 짜른다.


4-3. non_max_suppression 함수 [48, 70]

bbox_utils.py

내부 알고리즘 같은 자세한 내용은 tf.image.combined_non_max_suppression  |  TensorFlow Core v2.4.1 참고.

NMS 적용해주는 함수.

cf> *args 파라미터를 몇 개 받을지 모르는 경우 사용하고 형태는 튜플; **kwargs: keyword arguments의 줄임말, 딕셔너리 형태


4-4. get_bboxes_from_deltas 함수 [72, 96]

bbox_utils.py

models.faster_rcnn.py에서 활용됨.

anc 는 anchor의 줄임말, ctr는 center의 줄임말.

[line 81] The ellipsis (three dots) indicates "as many ':' as needed". This makes it easy to manipulate only one dimension of an array, letting numpy do array-wise operations over the "unwanted" dimensions. (ScyPy Cookbook Indexing)

[line 86] tf.exp: Computes exponential of x element-wise. e^x. e denotes Euler's number and is approximately equal to 2.718281.


4-5. get_deltas_from_bboxes 함수 [98, 124]

bbox_utils.py

[line 119] tf.where(condition, x=None, y=None, name=None): Return the elements where condition is True (multiplexing x and y). tf.where  |  TensorFlow Core v2.4.1

  • x and y are not provided --> retrieves indices of True elements.
  • x and y are provided --> multiplex btwn x and y.
    1. Choose an output shape from the shapes of condition, x, and y that all three shapes are broadcastable to.
    2. Then, if condition is True, choose corresponding element / row from x; if condition is False, choose corresponding element / row from y.

[line 119] tf.math.equal(x, y, name=None): Returns the truth value of (x == y) element-wise.

[line 119] tf.zeros_like(input, dtype=None, name=None): Creates a tensor with all elements set to zero. 받은 인풋과 같은 크기로 0으로 이루어진 텐서를 만들어줌.

[line 119] tf.math.truediv(x, y, name=None): Divides x / y elementwise (using Python 3 division operator semantics).

[line 121] tf.math.log(x, name=None): Computes natural logarithm of x element-wise.


4-6. generate_iou_map 함수 [126, 150]

bbox_utils.py

배치마다 IoU (Intersection over Union) 계산. gt는 ground_truth의 줄임말. 

[line 135] tf.split(value, num_or_size_splits, axis=0, num=None, name='split'): 바운딩박스들(bboxes)을 자동의 축(axis=-1)에 따라 4개씩 잘라라.

[line 141] tf.transpose(a, perm=None, conjugate=False, name='transpose'): 예시 perm=[0, 2, 1] 참고 

더보기
x = tf.constant([[[ 1,  2,  3],
                  [ 4,  5,  6]],
                 [[ 7,  8,  9],
                  [10, 11, 12]]])
# x.shape=(2, 2, 3)

tf.transpose(x, perm=[0, 2, 1])
# <tf.Tensor: shape=(2, 3, 2), dtype=int32, numpy=
# array([[[1, 4],
#         [2, 5],
#         [3, 6]],
#         [[7, 10],
#         [8, 11],
#         [9, 12]]], dtype=int32)>

4-7 & 4-8. normalize_bboxes & denormalize_bboxes 함수 [152, 182]

bbox_utils.py

정규화(normalize) 함수는 0-1 사이의 값으로 만들어주고, 비정규화 함수는 원래의 값으로 돌려준다


5. train_utils.py [225 lines]

함수 9개

5-0. configuration

train_utils.py

필요한 모듈 임포팅. 여기서 주목할 점은 bbox_utils를 사용한다는 점이다. 또한 RPN은 vgg16 혹은 mobilenet_v2에 따라 feature map의 크기가 다르다.


5-1. get_hyper_params 함수 [20, 42]

train_utils.py

동적으로 하이퍼파라미터를 생성한다. 


5-2. get_step_size 함수 [44, 52]

train_utils.py

총 아이템 개수와 배치 사이즈를 알아서 스텝 사이즈를 구한다. (단순히 나누는 작업이다.)


5-3. randomly_select_xyz_mask 함수 [54, 69]

train_utils.py

아래의 calculate_rpn_actual_outputs 함수에 활용되는 서브 함수.

[line 64] tf.random.uniform(shape, minval=0, maxval=None, dtype=tf.dtypes.float32, seed=None, name=None): Outputs random values from a uniform distribution.

[line 65] tf.cast(x, dtype, name=None): Casts a tensor to a new type.


5-4. faster_rcnn_generator 함수 [71, 86]

train_utils.py

 

 

 

 

 

 

 

 

 

'Coding > Image' 카테고리의 다른 글

Removing Duplicate Images  (0) 2021.05.04
Faster RCNN (PyTorch implementation)  (0) 2021.04.22
Weakly Supervised Learning  (0) 2021.04.19
Bank Check OCR  (0) 2021.04.19
RCNN Miscellaneous Repository  (0) 2021.04.15

관련글 더보기