YOLO(Object Detection)

jaegoo1199·2021년 8월 5일
0

Deep Learning

목록 보기
10/12
post-thumbnail

YOLO(You Only Look Once)


욜로(YOLO) 알고리즘은 실시간으로 물체의 둘레 상자(bounding box)를 찾는데 쓰인다. 욜로 알고리즘의 결과값은 (pc,bx,by,bh,bw,c)(p_c, b_x, b_y, b_h, b_w, c)로 표현이 된다.

Output

  • pcp_c: 물체가 존재하는지에 대한 값을 판별한다. 11이면 물제가 존재한다는 의미를 갖는다.
  • bxb_x, byb_y: 둘레 박스의 중앙 좌표로 그리드의 양 변을 11이라고 설정하였을 때, 상대적인 좌표로 나타나게 된다. 즉, 1보다 작은 값을 가진다.
  • bhb_h, bwb_w: 둘레 박스의 높이와 너비 길이를 나타내는 요소로 그리드의 길이 대비 상대적인 길이 값을 가지게된다. 즉, 중앙값과 다르게 11보다 큰 값을 가질 수 있다.
  • cc: 물체의 종류를 상징하는 벡터를 저장한다.

Anchor Boxes

같은 그리드 안에 다른 클래스의 둘레 상자가 있을 수 있기 때문에 이를 고정 상자(ancor boxes)를 이용해서 표현을 한다. 이후 비최댓값 제거(non-max suppresion)를 이용해서 가장 정확한 박스의 필터링 과정을 거친다.

위의 그림은 5개의 고정 박스를 인코딩한 결과이다. 위의 방식을 평탄화 과정을 통해서 (19,19,5,85)(19, 19, 5, 85)에서 (19,19,425)(19, 19, 425)로 변경을 시켜주도록 하자.

Class Score

욜로 알고리즘에서의 점수 할당은 위의 그림과 같이 pcp_c의 각 클래스에 곱(elementwise)을 실행하고, 최댓값에 해당하는 요소가 점수로 기록된다. 최댓값이 위치해있던 위치의 클래스가 욜로 알고리즘을 통해 도출된 클래스의 결과이다.

def yolo_filter_boxes(boxes, box_confidence, box_class_probs, threshold = .6):
    # Step 1: Compute box scores
    box_scores = box_class_probs * box_confidence

    # Step 2: Find the box_classes using the max box_scores
    box_classes = tf.math.argmax(box_scores, -1) # shape = (19, 19, 5)
    box_class_scores = tf.math.reduce_max(box_scores, -1) # shape = (19, 19, 5)
    
    # Step 3: Create a filtering mask
    filtering_mask = box_class_scores >= threshold # shape = (19, 19, 5)
    
    # Step 4: Apply the mask to box_class_scores, boxes and box_classes
    scores = tf.boolean_mask(box_class_scores, filtering_mask)
    boxes = tf.boolean_mask(boxes, filtering_mask)
    classes = tf.boolean_mask(box_classes, filtering_mask)
    
    return scores, boxes, classes

결국 클래스 점수가 가장 높은 대상을 그 둘레 상자의 클래스로 설정을 하는 과정이다. 위의 결과로 반환값은 다음과 같은 차원을 가진다.

  • scores: (17789, )
  • boxes: (17789, 4)
  • classes: (17789, )

모든 박스에 대한 데이터와 관련된 내용이 순서대로 정리되어있는 형태로 반환이 되는 모습을 볼 수 있다.

Non-max Suppression

지금까지는 결과값에서 가장 높은 점수를 기록하고 있는 클래스로 둘레 상자를 설정한 상태이다. 하지만 욜로 알고리즘에서 우리는 한 그리드에서 중복될 수 있는 박스(anchor boxex)를 5개로 설정하였기 때문에 실제로 같은 대상을 가리키는 여러개의 박스가 나올 수 있다. 비최댓값 제거를 통해서 가장 정확도가 높은 박스를 제외한 나머지 박스들을 제거할 필요가 있다.

  • 설정한 점우(threshold score)보다 낮은 박스를 우선적으로 제거한다.
  • 한 물체에 대해서 겹쳐진 박스(IoU)를 찾아 하나만 남기고 제거한다.

비최댓값 제거를 위해서는 합집합에서 교집합이 차지하는 비율(Intersection over Union)을 계산을 통해 둘레 상자의 정확도를 측정할 수 있다.

위의 IoU값을 바탕으로 알고리즘의 결과 중, 가장 정확한 값을 추출해 낼 수 있게 된다. 욜로 알고리즘에서 비최댓값 제거를 사용하는 예시는 다음과 같다.

  1. 가장 높은 확률의 상자를 구한다.
  2. 확률이 가장 높은 상자 주변의 상자와 IoU를 구하고 이 값이 설정한 임계값보다 높을 경우 그 값을 제거한다.
  3. 1의 과정을 현재 상자와 같은 대상을 가리키고 있는 상자가 없을 때까지 반복한다.
def yolo_non_max_suppression(scores, boxes, classes, max_boxes = 10, iou_threshold = 0.5):    
    max_boxes_tensor = tf.Variable(max_boxes, dtype='int32')
    nms_indices = tf.image.non_max_suppression(boxes, scores, max_boxes, iou_threshold)
    
    scores = tf.gather(scores, nms_indices)
    boxes = tf.gather(boxes, nms_indices)
    classes = tf.gather(classes, nms_indices)
    
    return scores, boxes, classes

실제로는 프레임워크의 함수를 이용하여 비최댓값 제거를 할 수 있다. non_max_suppression()을 이용하여 욜로 알고리즘으로 필터링된 상자의 정보를 인자값으로 넘겨주면 처리가 진행된다. 기본적인 알고리즘의 흐름의 위의 순서와 같다. 위의 함수는 인자값으로 넣어준 변수들을 색인으로 등록하게 되는데 결과값을 gather()과 색인의 이름을 통해서 얻을 수 있다.

YOLO Evaluation

욜로 모델을 통해 나온 결과는 각 그리드당 4개의 텐서를 가지게 된다.

  • box_xy: (None, 19, 19, 5, 2)
  • box_wh: (None, 19, 19, 5, 2)
  • box_confidence: (None, 19, 19, 5, 1)
  • box_class_probs: (None, 19, 19, 5, 80)

기본적으로 19×1919\times 19의 그리드 안에서 둘레 상자에 대한 인식이 이뤄지며 위에서 서술한 과정을 이용해서 둘레 상자를 필터링하게 된다.

def yolo_eval(yolo_outputs, image_shape = (720, 1280), max_boxes=10, score_threshold=.6, iou_threshold=.5):
    box_xy, box_wh, box_confidence, box_class_probs = yolo_outputs
    
    boxes = yolo_boxes_to_corners(box_xy, box_wh)
    
    scores, boxes, classes = yolo_filter_boxes(boxes, box_confidence, box_class_probs, score_threshold)
    
    boxes = scale_boxes(boxes, image_shape)
    
    scores, boxes, classes = yolo_non_max_suppression(scores, boxes, classes, max_boxes, iou_threshold)

    return scores, boxes, classes

scale_box()를 하는이유는 사용하는 모델이 인식하는 사진의 크기와 실제 적용하려는 사진의 크기가 다르기 때문이다. 이를 통해 실제 사용하려는 사진의 크기에 맞추어 둘레 상자를 표시해야 하기 때문이다.

Reference

profile
아직 거북이지만 곧 앞질러 갈겁니다.

0개의 댓글