우노
[DL] Object Detection (Sliding Windows, YOLO) 본문
Object Detection에는 여러가지 Algorithm이 존재합니다.
- Sliding Windows Detection
- YOLO Detection
하나하나 다뤄보겠습니다.
Sliding Windows Detection
자동차 감지 알고리즘을 만들고 싶다고 가정해봅시다.
그렇다면, Sliding Windows Detection은 다음과 같은 순서로 진행됩니다.
1) 우선 X와 y로 Training Set를 만듭니다.
- 이 때, X는 자동차만 표현하도록 딱 맞게 자른 이미지입니다.
2) Training Set이 다 만들어졌다면, Training Set의 X를 Input으로 주는 ConvNet을 학습시킵니다.
- ConvNet은 y를 출력하며, y는 자동차인지 아닌지를 0 또는 1로 나타냅니다.
3) ConvNet 학습이 끝났다면, Test 이미지를 통해 성능을 Test 합니다.
- Test 이미지를 입력 받은 뒤, Training 시 사용한 Window 크기 만큼 이미지를 잘라, 학습한 ConvNet의 입력으로 넣습니다.
- ConvNet은 해당 Window에 Car가 있는지 없는지 판단하며, 결과를 0 또는 1로 나타냅니다.
- 이는, Window가 이미지의 끝에 도착할 때까지 Sliding하며 반복됩니다.
- 이를 완료하면, Test 이미지 내부의 잘라진 Window 각각은, 0 또는 1로 분류될 것입니다.
- Window 중 1이 있다면 해당 Test 이미지에는 Car가 있는 것입니다.
- 이를 Sliding Window 라고 부릅니다.
하지만, Sliding Windows Detection 에는 커다란 단점이 하나 있습니다.
바로 계산 비용입니다.
Sliding Windows Detection은 이미지에 있는 많은 사각 영역들을 잘라내고, ConvNet을 통해 각각을 독립적으로 실행시키기 때문에 계산 비용이 많이 듭니다.
만약, 여러분이 아주 큰 스트라이드나 아주 큰 Window를 사용해 Sliding 한다면, ConvNet에 보내야할 Window의 숫자는 줄어들게 돼 계산 비용은 줄어들게 되지만,
수행력에 안 좋은 영향을 줄 수도 있습니다.
이러한, 계산 비용 문제는 다행이도 좋은 해결책을 가지고 있습니다.
따라서 해결책 중 하나인, Convolutional Implementation of Sliding Windows에 대해서 알아보겠습니다.
Convolutional Implementation of Sliding Windows
위에서 다룬 Sliding Windows Detection은, 이미지의 Window 크기마다 ConvNet을 실행하며,
Window가 이미지 끝에 도달할 때 까지 반복해야하므로, 매우 느리다는 단점을 가지고 있었습니다.
하지만 Convolutional Implementation of Sliding Windows는 각각의 Window에 ConvNet을 실행할 필요 없이, 전체 Window에 한 번의 ConvNet만 실행 할 수 있습니다.
예제를 통해 알아보겠습니다.
아래 그림은, Sliding Windows Detection에서 사용되는 기존의 ConvNet 구조입니다.
- 입력(Window)을 받아 4가지 객체 중 하나로 분류하는 예제이며
- 기존의 ConvNet 구조에는 Fully Connected Layer가 존재합니다.
아래 그림은, Convolutional Implementation of Sliding Windows에서 사용되는 ConvNet의 구조입니다.
- 기존 ConvNet 구조에서 Fully Connected Layer를 Convolution Layer로 변환한 구조입니다.
- Fully Connected Layer를 Convolution Layer로 변환함으로써, 해당 ConvNet을 전체 이미지에 적용할 수 있게 됩니다.
변환한 ConvNet이 왜 효율적인지 자세히 알아보겠습니다. (아래 그림은 2차원만 표현한 그림입니다.)
- 위 그림의 상단 예시는 14x14x3 이미지를 변환한 ConvNet을 사용해 Convolution한 결과입니다.
- 14 x 14 x 3 이미지를 ConvNet을 통해 Convolution하니 1 x 1 x 4 의 결과가 나옵니다.
- 하단 예시는, 16x16x3 이미지를 변환한 ConvNet을 사용해 Convolution한 결과입니다.
- 16 x 16 x 3 이미지를 ConvNet을 통해 Convolution하니 2 x 2 x 4 의 결과가 나옵니다.
- 이는, 전체 이미지에 대해 4개의 Label을 얻은 것과 동일합니다.
- 만약, 기존의 ConvNet 방식이었다면 위와 같이 4개의 Label을 얻기 위해선
- 16x16x3 이미지를 4가지 Window로 나눈 뒤, 각 Window 영역에서 ConvNet을 독립적으로 실행해 4개의 Label을 얻었을 것입니다.
- 하지만, 위처럼 변환된 ConvNet을 이미지 전체에 사용한다면, 한 번의 Covolution을 통해 4개의 라벨값이 나오게 됩니다.
- 이러한 방법은 공통 이미지 영역에 있는 많은 계산을 공유하기 때문에 빠릅니다.
- 위 그림의 상단 예시는 14x14x3 이미지를 변환한 ConvNet을 사용해 Convolution한 결과입니다.
따라서, 아래 그림과 같이 28 x 28 x 3 이미지가 들어왔을 때, 한번의 Convolution으로 64(8x8)개 영역의 label 값을 얻을 수 있게 됩니다.
- 하지만, 이러한 방법에도 각 Bounding Box가 객체를 정확하게 표현하지 못한다는 단점이 존재합니다.
YOLO Detection
지금까지 Sliding Windows Detection 및 Convolutional Implementation of Sliding Windows에 대해서 알아보았습니다.
하지만, Sliding Window로 이미지 영역을 한 칸씩 밀면서 객체를 감지하다보면, Bounding Box와 객체가 완벽하게 일치하지 않을 수 있다는 단점이 있었습니다.
또한, Bounding box는 보통 정사각형이 아닌 직사각형입니다.
따라서, Bounding Box 예측을 보다 정확히 하기 위해 YOLO 알고리즘이 사용됩니다.
- YOLO는 You Only Look Once의 약자입니다.
YOLO의 기본 아이디어는, 아래 그림과 같이 이미지 분류 및 객체 위치 측정을 Sliding Window가 아닌 Grid로 나누어 적용하는 것입니다.
또한, YOLO는 Training Set을 위한 Target Label y도 Sliding Window Detection 방법과 다르게 정의됩니다.
예시를 통해 Target Label y에 대해서 알아보겠습니다.
위 그림과 같이, Input X에 대한 Target Label y는 각 그리드 셀에 대해 Class Label(c1, c2, c3) 과 Bounding Box(bx, by, bh, bw) 로 구성됩니다.
각 그리드 셀을 구체적으로 보면, 위 예제를 기준으로 [Pc, bx, by, bh, bw, c1, c2, c3]가 됩니다.
Pc (Probability of Class) : 이미지 내에 "객체가 있는가?"를 의미합니다.
- Pc = 1이면 Object가 존재한다는 뜻이며
- Pc = 0이면 Object가 없는 background라는 뜻입니다.
bx, by, bh, bw : 이미지 내 객체의 Bounding Box 좌표를 의미합니다.
- bx : bounding box의 중심점 x좌표
- by : bounding box의 중심점 y좌표
- bh : bounding box의 높이
- bw : bounding box의 너비
c1, c2, c3 : 어떤 객체로 분류되는가를 의미합니다.
- Class1(Pedestrian), Class2(Car), Class3(Motorcycle)
따라서, YOLO Detection은 다음과 같은 순서로 진행됩니다.
1) 우선 X와 y로 Training Set를 만듭니다.
- 객체를 탐지한 그리드 셀은, y = [1, bx, by, bh, bw, 0, 1, 0] 으로 구성할 수 있습니다.
- 객체를 탐지한 그리드 셀의 벡터는
- Pc = 1 이 되고, 객체에 해당하는 Class만 1이 됩니다.
- 그 다음으로는, 객체의 Bounding Box 좌표(bx, by, bh, bw)가 할당됩니다.
- 객체를 탐지한 그리드 셀은, y = [0, ?, ?, ?, ?, ?, ?, ?] 으로 구성할 수 있습니다.
- 그리드 셀 내에 객체가 없기 때문에 Pc = 0 이 되고 나머지 원소는 어떤 값이 와도 의미가 없습니다.
- 각각의 그리드 셀은 객체 Bounding box의 중심점을 가지고 있을 때만, Pc 가 1이 됩니다.
- 따라서, 객체는 전체 그리드 셀 중 하나의 그리드 셀에만 할당되게 됩니다.
- 객체를 탐지한 그리드 셀은, y = [1, bx, by, bh, bw, 0, 1, 0] 으로 구성할 수 있습니다.
2) Training Set이 다 만들어졌다면, Training Set의 X를 Input으로 주는 ConvNet을 학습시킵니다.
- YOLO의 ConvNet은 Convolutional Implementation을 사용하기 때문에,
- 각 그리드 셀마다 ConvNet을 학습하지 않고, 전체 그리드에 대해 한 번의 학습을 진행합니다.
- 이러한 연산은 각 그리드 간 많은 연산이 공유되므로 효율적인 알고리즘이 됩니다.
3) ConvNet 학습이 끝났다면, Test 이미지를 통해 성능을 Test 합니다.
- 위 그림에서는, 3 x 3 grid로 Test 하고 있지만, 보통 19 x 19 grid 같은 미세한 그리드를 사용해, 동일한 그리드 셀 안에 여러 객체가 할당 될 가능성을 줄여줍니다.
- 따라서, 위와 같은 이미지로 테스트 한다면, 각 그리드 셀에 대한 Label이 총 9개 나올 것이며, 각 Label은 8차원 벡터값을 가지고 있을 것입니다.
- 각 라벨 벡터는
- 객체를 탐지한 그리드 셀은 y = [1, bx, by, bh, bw, 0, 1, 0] 가 될 것이며
- 객체를 탐지하지 못한 그리드 셀은 y = [0, ?, ?, ?, ?, ?, ?, ?] 가 될 것 입니다.
- 각각의 그리드 셀은 객체 Bounding box의 중심점을 가지고 있을 때만, Pc 가 1이 됩니다.
- 따라서, 객체는 전체 그리드 셀 중 하나의 그리드 셀에만 할당되게 됩니다.
- 또한, 각 그리드 마다 해당 그리드 셀의 좌측 상단 좌표를 (0,0) 우측 하단 좌표를 (1,1)로 사용하기 때문에, bx, by는 0과 1사이의 값을 가지며
- 객체의 Bounding Box는 해당 그리드 셀을 넘어갈 수 있기 때문에, bh, bw는 1보다 클 수 있습니다.
Intersection Over Union
객체 탐지 알고리즘이 잘 작동하는지 확인하기 위해선 IOU 방법을 사용합니다.
위 그림에서, 빨간색이 실제 객체의 Bounding Box이며, 보라색이 예측한 객체의 Bounding Box라면
IOU는 아래 그림과 같이, [ 두 Bounding Box의 교집합 / 두 Bounding Box의 합집합 ] 으로 계산할 수 있습니다.
IOU가 높을수록 성능이 좋은 것이며, 낮을수록 성능이 안 좋은 것입니다.
Non-max Suppression
지금까지 배운 Object Detection의 문제는, 알고리즘이 동일한 객체에 대해 다수의 탐지체를 찾을 수 있다는 것입니다.
- Training 시에는 객체의 중심점에 있는 그리드 셀만 Pc = 1로 설정해 객체를 인식한 것으로 다뤘지만
- Test 시에는 각 그리드 셀 마다 객체의 중심점을 가지고 있다고 인식할 수 있습니다.
따라서, Non-max Suppression은 다수의 객체로 인식한 결과에 대해, 동일한 객체를 인식한 것으로 정리하는 방법입니다.
19 x 19 입력에 대해, 그리드를 사용해 객체를 탐지하는 예시를 들어보겠습니다.
- 그림에서 각각의 객체는 중간 지점이 하나뿐이므로, 정상적이라면 객체마다 그리드 셀 하나가 할당되는 것이 맞습니다.
- 하지만, 실제로는 361개의 그리드 셀 모두 각각 이미지를 분류하고 있기 때문에,
- 각각의 그리드가 "여기에 객체가 있다"라고 인식할 확률이 큽니다.
- 따라서, Non-max Suppression을 통해 다수의 객체로 인식된 결과에 대해 동일한 객체를 인식한 것으로 정리하는 과정이 필요합니다.
Non-max Suppression이 어떻게 진행되는지 알아보겠습니다.
- 우선, 19 x 19 그리드 셀을 사용해 객체 탐지가 끝나면, 361개의 그리드 셀은 각각 아래와 같은 Label vector를 가지고 있을 것입니다.
- [Pc, bx, by, bh, bw]
- 이 때, Pc는 해당 그리드 셀이 객체를 가지고 있을 확률을 의미하며, bx, by, bh, bw는 객체로 예측한 바운딩박스 좌표를 의미합니다.
- 따라서, 위 그림의 왼쪽 객체를 탐지한 그리드 셀들은 0.8, 0.7의 Pc 값을 가지고 있으며
- 오른쪽 객체를 탐지한 그리드 셀들은 0.6, 0.9, 0.7의 Pc 값을 가지고 있게 됩니다.
- 이후, Non-max Suppression은 다음과 같은 순서로 진행됩니다.
- 우선, 전체 그리드 셀에 대해, Pc 값이 특정 임계값보다 작은 예측은 제거합니다.
- 남은 그리드 셀에 대해, Pc 값이 가장 큰 그리드 셀을 고릅니다.
- 위 예제에서는, 오른쪽 객체의 0.9 그리드 셀이 골라질 것입니다.
- Pc 값이 가장 큰 그리드 셀과 전체 그리드 셀의 IOU를 구해, IOU 값이 높은 그리드 셀들은 동일한 객체를 탐지하고 있는걸로 간주하고 제거합니다.
- 위 예제에서는, 오른쪽 객체의 0.6 그리드 셀과 0.7 그리드 셀이 제거될 것입니다.
- 남은 그리드 셀에 대해, Pc 값이 가장 큰 그리드 셀을 고릅니다.
- 위 예제에서는, 왼쪽 객체의 0.7 그리드 셀이 골라질 것입니다.
- Pc 값이 가장 큰 그리드 셀과 전체 그리드 셀의 IOU를 구해, IOU 값이 높은 그리드 셀들은 동일한 객체를 탐지하고 있는걸로 간주하고 제거합니다.
- 위 예제에서는, 왼쪽 객체의 0.6 그리드 셀이 제거될 것입니다.
- 이와 같은 과정을 반복하면, 결국 동일한 객체에 대해 하나의 그리드 셀만 탐지한 것처럼 정리될 것입니다.
- 우선, 19 x 19 그리드 셀을 사용해 객체 탐지가 끝나면, 361개의 그리드 셀은 각각 아래와 같은 Label vector를 가지고 있을 것입니다.
위와 같은 알고리즘이 non-max suppression 이며
위 예제에서는, 단 하나의 객체만 탐지하는 알고리즘을 설명했습니다.
하지만 만약, 보행자, 오토바이 등 여러 객체를 추가로 탐지한다면
Label Vector에는 c1, c2, c3와 같은 추가적인 구성 요소가 생깁니다.
이 땐, 각 class 당 non-max suppression을 독립적으로 수행하면 됩니다.
Anchor Boxes
지금까지 다룬 객체 탐지 문제 중 하나는, 각 그리드 셀이 하나의 객체만 감지 할 수 있다는 것입니다.
하지만 객체 탐지 시, 각 그리드 셀 안에는 여러 객체가 포함되어 있을 수도 있습니다.
예제를 통해 살펴보겠습니다.
이 예제에서는 3 x 3 그리드를 계속 사용하겠습니다.
위 그림을 보시면, 보행자의 중심점과 차량의 중심점이 거의 같은 위치에 있으며, 둘 다 동일한 그리드 셀에 속해 있는 것을 볼 수 있습니다.
만약, 해당 그리드 셀이 기존의 Label Vector [Pc, bx, by, bh, bw, c1, c2, c3] 를 사용한다면, 우리는 두 가지 객체를 탐지할 수 없습니다.
- [Pc, bx, by, bh, bw, c1, c2, c3] Vector를 사용한다면, 1개의 Bounding Box 좌표만 할당할 수 있으므로 1개의 객체만 탐지할 수 있습니다.
따라서, Anchor Boxes라는 개념이 나타났습니다.
Anchor Boxes는 아래 그림과 같이, 탐지하려는 객체의 모양을 미리 정의해놓고 객체가 탐지되었을 때 어떤 Anchor box와 유사한지 비교해 Vector 값을 할당하는 방식입니다.
- Anchor Boxes는 5개 또는 그 이상 사용할 수 있지만
- 설명을 쉽게 하기 위해 2개의 Anchor Box만 사용하겠습니다.
예제를 통해 Anchor Boxes 과정을 살펴보겠습니다.
위 그림과 같이 2가지 Anchor Boxes를 사용한다면, 각 그리드 셀은 2가지 객체에 대한 Target Label y 값을 가질 수 있으며 2개의 Vector를 이어붙인 형태가 됩니다.
우선, Test 과정에서 각 그리드 셀은 객체를 탐지하며, 탐지한 객체의 Bounding Box가 Anchor box 1과 유사한지 Anchor box2와 유사한지 IOU를 통해 계산합니다.
IOU 계산 후, 높은 Anchor box Vector 자리에 값을 할당합니다.
따라서, 아래 그림과 같이 각 그리드 셀이 무엇을 인식하느냐에 따라 Targe Label y 값이 할당됩니다.
- 사람과 차를 인식했을 경우에는 [1, bx, by, bh, bw, 1, 0, 0, 1, bx, by, bh, bw, 0, 1, 0] 이며
- 차만 인식했을 경우에는 [0, ?, ?, ?, ?, ?, ?, ?, 1, bx, by, bh, bw, 0, 1, 0] 입니다.
'AI > Deep Learning' 카테고리의 다른 글
[DL] Neural Style Transfer (1) | 2021.02.10 |
---|---|
[DL] One Shot Learning, Siamese Network, Triplet Loss, Binary Loss (1) | 2021.02.10 |
[DL] Landmark Detecting (1) | 2021.02.09 |
[DL] Object Localization (객체 위치 식별) (3) | 2021.02.09 |
[DL] Convolution, Padding, Stride, Pooling in CNN (1) | 2021.02.03 |