728x90
반응형

 

 

 

 

바보같은 질문일 수도 있지만... Object Detector를 개발하다가 문득 궁금한 점이 생겼다.

 

Object Detection 구현들을 살펴보면 scale 값과 max size 값을 제한해두는 경우가 있다. 

아래 예시는 FPN pytorch 구현의 res50-lg.yml 파일이며, scale 값은 800으로, max size 값은 1333으로 정해져있다. 

 

SCALES: [800] 

MAX_SIZE: 1333 

EXP_DIR: res50-lg
TRAIN:
  HAS_RPN: True
  IMS_PER_BATCH: 1
  BBOX_NORMALIZE_TARGETS_PRECOMPUTED: True
  RPN_POSITIVE_OVERLAP: 0.7
  RPN_BATCHSIZE: 256
  PROPOSAL_METHOD: gt
  BG_THRESH_LO: 0.0
  DISPLAY: 20
  BATCH_SIZE: 64
  DOUBLE_BIAS: False
  SNAPSHOT_PREFIX: res50_faster_rcnn_fpn
  SCALES: [800]
  MAX_SIZE: 1333
TEST:
  HAS_RPN: True
  SCALES: [800]
  MAX_SIZE: 1333
  RPN_POST_NMS_TOP_N: 1000
POOLING_MODE: crop
ANCHOR_SCALES: [2,4,8,16,32]
RPN_CHANNELS: 256
FPN: True

 

 

 

 

 

이 값들은 train 또는 test 할 때 신경망의 입력으로 image blob을 생성하기 위한 resize 과정에서 사용된다. 

 

1. 입력 이미지의 해상도 값인 w, h 값들 중에서 제일 작은 값을 im_size_min, 제일 큰 값을 im_size_max로 설정한다.

2. target_size 즉 config 파일에서 설정한 800 값을 im_size_min 값으로 나누어 im_scale 값을 설정한다.

3. 그 다음 im_scale 값과 im_size_max 값을 곱하여 큰 값을 구하게 되는데, 이 값이 만일 cfg.TEST.MAX_SIZE 즉 1333 값 보다 크다면 1333 값을 im_size_max 로 나누어 im_scale 을 설정한다.

이것은 가장 큰 축 값이 MAX_SIZE 보다 커지는 것을 방지하기 위함이다. 

4. 마지막으로 im_scale 값을 이용하여 cv2.INTER_LINEAR 보간법으로 resize 해줌으로써 image blob을 완성한다. 

 

관련된 코드는 아래와 같다. 

 

https://github.com/yxgeee/pytorch-FPN/blob/828d1e5188e78181b05e010b62ac91b2585c2bde/lib/model/test.py#L47

 

def _get_image_blob(im):
  """Converts an image into a network input.
  Arguments:
    im (ndarray): a color image in BGR order
  Returns:
    blob (ndarray): a data blob holding an image pyramid
    im_scale_factors (list): list of image scales (relative to im) used
      in the image pyramid
  """
  im_orig = im.astype(np.float32, copy=True)
  im_orig -= cfg.PIXEL_MEANS

  im_shape = im_orig.shape
  im_size_min = np.min(im_shape[0:2])
  im_size_max = np.max(im_shape[0:2])

  processed_ims = []
  im_scale_factors = []

  for target_size in cfg.TEST.SCALES:
    im_scale = float(target_size) / float(im_size_min)
    # Prevent the biggest axis from being more than MAX_SIZE
    if np.round(im_scale * im_size_max) > cfg.TEST.MAX_SIZE:
      im_scale = float(cfg.TEST.MAX_SIZE) / float(im_size_max)
    im = cv2.resize(im_orig, None, None, fx=im_scale, fy=im_scale,
            interpolation=cv2.INTER_LINEAR)
    im_scale_factors.append(im_scale)
    processed_ims.append(im)

  # Create a blob to hold the input images
  blob = im_list_to_blob(processed_ims)

  return blob, np.array(im_scale_factors)

 

 

 

그런데 왜 ? 신경망의 입력으로 Image Blob을 생성할 때 이미지의 크기 범위를 왜 (800, 1333)으로 제한하는 것인지 궁금해졌다.

 

Issue : https://github.com/open-mmlab/mmdetection/issues/2428

 

나와 똑같은 생각을 하였군...

 

 

Fast R-CNN 및 Faster R-CNN (without FPN) 에서는 이미지의 가장 짧은 축을 600 으로 설정하고, 

FPN 에서는 가장 짧은 축을 800으로 설정한다고 한다. 그러니까 왜...

 

 

 

 

 

 

 

 

그래서 Fast R-CNN 논문에서 관련된 내용을 찾아보았다. 

In this section, all experiments use single-scale training and testing (s = 600; see Section 5.2 for details).

아.. 모든 실험에서 single-scale training and testing 을 수행했고, 이 때 s 값을 600으로 사용하였구나. 당연히 600 pixel 은 최적의 값이니까 그렇게 사용하였겠지?... 자세한 내용은 5.2에 있다 하여 관련된 내용을 살펴보았다.

 

Fast R-CNN 에서는 scale-invariant를 달성하기 위해 brute-force learning(single scale)과 image pyramids(multi-scale)을 비교하였다. 두 경우 모두 이미지의 스케일을 가장 짧은 길이를 정의하게 되며, 모든 실험은 s = 600 pixel 을 사용한다.

 

single scale 실험에서는 가장 긴 축은 1000 pixel로 제한하고, 이미지의 종횡비(aspect ratio)를 유지하기 때문에 일부 이미지의 경우 s 가 600 pixel 보다 작아질 수 있다. 이 값은 VGG16 fine-tuning 과정 중에 GPU 메모리에 맞도록 설정되었다. single scale 설정은 일반적으로 이미지를 1.6배 up-sampling 하게 된다. RoI Pooling 레이어의 stride 는 평균적으로  ≈ 10 정도로 설정한다. 

 

multi-scale 실험에서는 SPPNet(Spatial Pyramid Pooling in Deep Convolutional Networks for Visual Recognition) 논문에서 설정한 5개의 scale 값인 s ∈ {480, 576, 688, 864, 1200} 를 설정한다. 그러나 GPU 메모리 초과를 방지하기 위해 가장 긴 축을 2000 pixel 로 제한하게 된다.

 

참고로 SPPNet 에서 multi scale 값들을 설정한 이유는 CNN들은 고정 크기의 이미지를 사용하는데, 이는 입력 이미지의 비율과 크기를 제한한다. 임의의 크기의 이미지에 적용할 경우 현재의 방법은 대개 입력 이미지를 crop하거나 warp하여 고정 크기로 맞추는데 crop 영역은 전체 object를 포함하지 못할 수 있고 warp 이미지는 원치않는 기하학적 왜곡을 유발시키게 된다. 

 

 

아래 표를 살펴보면, 1개 또는 5개의 스케일로 학습 및 테스트 했을 때의 모델 S와 M 결과를 보여준다. 이 표에서 single scale 과 multi scale 로 실험된 결과가 거의 동등하다는 것을 알 수 있다. 각 mAP 1.2 / 1.3 / 1.5 차이, 속도는 single scale이 거의 2 ~ 4배 정도 빠르다. L 모델은 GPU 메모리 문제로 multi scale 실험을 진행하지 못했다고 한다. 

VGG16 모델 L의 경우 구현 세부 사항에 따라 단일 스케일 사용에 제한이 있다. 그러나 R-CNN의 각 proposal 이 canonical size 로 wrap 된다는 의미에서 "infinite" scale 을 사용하더라도 기존의 알려진 R-CNN의 mAP 66.0% 보다 약간 높은 mAP 66.9% 를 달성한다고 한다. 따라서 single-scale 처리는 특히 매우 깊은 모델의 경우 속도와 정확도 간의 최상의 균형을 제공하기 때문에 모든 실험은 s = 600 pixel 로 single-scale 학습 및 테스트를 진행한다. 

 

결론은 즉, multi scale을 사용하여 학습 및 테스트 하는 것 보다 single scale 을 사용하는 것이 경제성(속도, 정확도) 측면에서 더 이득이기 때문에 single scale 을 사용하게 되었고, single scale 사용 시 그 값은 VGG 16 모델 기준 GPU 메모리가 초과하지 않는 수준에서 s = 600 pixel 이라는 값을 설정하게 되었으며, 이 때 가장 긴 축의 max size 를 제한하여 종횡비를 유지하게 되었다는 것이다.

 

따라서 이것이 일반적인 관행이 되어버린 것이였다. 결국 이미지의 최대 크기를 [1333, 800] 범위로 제한해두는 것도 실험적으로 최적의 해상도라고 판단했기 때문이 아닐까 싶다. 여러 논문들을 찾아봐도 통상적으로 최대 [1333, 800] 크기를 사용한다고 한다.

 

여기서 주의해야 할 점은 당연한 이야기이지만 무조건 저 크기로 Resize 하는 것이 아니라 저 범위 내에서 Resize 하는 것이다. 

 

 

 

 

 

 

 

 

 

또 참고로 object detection 분야에서 multi scale 을 시도하게 된 역사를 다룬 논문이 있다. 

 

An Analysis of Scale Invariance in Object Detection – SNIP

 

관련된 내용을 요약하면 아래와 같다. 

 

최근 여러가지 방법들을 통해 객체 탐지 문제를 개선하는데 크게 도움이 되었지만, 학습과 관련된 많은 중요한 문제들은 해결되지 않은 채 남아있다. 문제들은 아래와 같다. 

 

  • 객체 탐지를 위한 우수한 성능을 얻기 위해 이미지를 up-sampling 하는 것이 중요한가?
  • 객체 탐지 데이터에서 이미지의 일반적인 크기가 480x640 인데도 800x1200 으로 up-sampling 하는 것이 일반적인 관행인 이유가 무엇인가?

 

SNIP(Scale Normalization for Image Pyramids)에서 multi-scale training(MST)은 다음과 같은 문제를 해결한다.

 

  • 각 이미지는 서로 다른 해상도에서 관찰되므로 고해상도(e.g. 1400x2000)에서는 큰 물체를 분류하기 어렵고, 저해상도(e.g. 480x800)에서는 작은 물체를 분류하기가 어렵다.
  • 하지만 다행히 각 객체 인스턴스는 여러 다른 스케일의 형태로 나타나며 이러한 모양 중 일부는 우리가 바라는 scale range에 속하게 된다.

 

위 그림에서는 서로 다른 스케일에서 동일한 레이어 컨볼루션 특징은 다르며, 서로 다른 스케일에서 이미지의 다른 semantic regions 에 매핑된다는 것을 보여준다. 따라서 서로 다른 스케일(S, M, L)을 이용하여 학습하기로 한다. 

 

 

위 그림 3, 4번째 그림을 보면 모든 스케일로 탐지했을 때 여러 스케일을 가지고 있는 객체를 잘 탐지할 수 있다는 것을 알 수 있으며, 가능한 한 객체의 많은 변화를 포착하면서 적절하게 크기가 조정된 객체로 탐지기를 훈련하는 것이 중요하다고 결론을 짓게 된다. 

 

 

 

위 그림은 각 해상도 (480, 800), (800, 1200), (1400,2000) 에서 multi-scale training 을 하는 SNIP train and inference 과정을 보여준다. 여기서 보라색 박스는 각 스케일에서 지정된 범위를 벗어나는 유효하지 않은 ROI를 나타낸다. 이는 학습 및 추론 중에 삭제된다. 학습 중 각 배치는 특정 스케일에서 샘플링된 이미지로 구성된다. 잘못된 GT 상자는 RPN에서 앵커를 무효화하는데 사용된다. 각 스케일로부터의 검출은 NMS를 사용하여 재조정되고 결합된다. 

 

따라서 SNIP에서 너무 크거나 극단적인 스케일을 가진 객체를 제거하기 위해 원하는 스케일 범위에 속하는 객체에 대해서만 학습이 수행되고 나머지는 back-propagation 되는 동안 무시된다. SNIP는 학습 중에 모든 객체 인스턴스를 사용하여 모양과 포즈의 모든 변형을 포착하는데 도움이 되는 동시에 pre-train 된 신경망의 스케일 공간에서 domain-shift 를 줄이게 된다. SNIP를 이용하여 학습된 검출기를 평가한 결과는 아래와 같다. 

 

 

 

 

 

 

 

 

 

 

 

참고자료 1 : https://blog.daum.net/sotongman/7

 

SPPnet

SPPNet ( https://arxiv.org/pdf/1406.4729.pdf ) Abstract 현존하는 CNN은 고정 크기의 입력 이미지를 요구하는데 이는 '인위적'이며 그 이미지나 임의의 크기로 변환된 부분 이미지에 대한 인식 정확도를 해침..

blog.daum.net

 

참고자료 2 : https://www.slideshare.net/jaewonlee79/pr110-an-analysis-of-scale-invariance-in-object-detection-snip

 

PR-110: An Analysis of Scale Invariance in Object Detection – SNIP

paper : https://arxiv.org/abs/1711.08189 youtube : https://youtu.be/nimHWHxjBJ8

www.slideshare.net

 

728x90
반응형