컴퓨터비전

NMS(Non Maximum Suppression)

dokpin 2022. 2. 14. 23:59
728x90

겹치는 바운딩 박스(물체 검출 영역)들에 대해서 가장 confidence가 높은 바운딩 박스만 남기는 방법입니다.

 

Yolo같은 경우 아래 그림과 같이 어떤 물체에 대해서 여러 개의 바운딩 박스가 검출됩니다.

 

NMS(Non Maximum Suppression)를 사용하면 중복되는 바운딩 박스들을 없앨 수 있습니다.

겹치는 정도가 바운딩 박스를 제거하는 조건이 됩니다.

어느 정도 겹쳐야 되는가에 대한 판단 중 하나로 IOU(Intersection Over Union)를 사용합니다.

IOU는 두 사각형이 위치상으로 어느 정도 유사한지 알 수 있는 측정 척도 중 하나입니다.

겹치는 정도를 알 수 있습니다.

IOU(Intersection Over Union) (tistory.com)

 

NMS 처리 후 결과입니다.

 

NMS 코드(함수)

struct detectionResult
{
	cv::Rect plateRect;
	double confidence;
	int type;
};

void NMS(std::vector<detectionResult> &vResultRect)
{
	for (int i = 0; i < vResultRect.size() - 1; i++)
	{
		for (int j = i + 1; j < vResultRect.size(); j++)
		{
			double IOURate = (double)(vResultRect[i].plateRect & vResultRect[j].plateRect).area() / (vResultRect[i].plateRect | vResultRect[j].plateRect).area();
			if (IOURate >= 0.5)
			{
				if (vResultRect[i].confidence > vResultRect[j].confidence) {
					vResultRect.erase(vResultRect.begin() + j);
					j--;
				}
				else {
					vResultRect.erase(vResultRect.begin() + i);
					i--;
					break;
				}
			}
		}
	}
}

NMS 함수의 입력은 구조체의 vector입니다.

사각형 위치 정보, confidence, 클래스 분류 번호등을 구조체로 선언했습니다.

NMS 적용할 때 위치 뿐만 아니라 클래스 분류가 일치하는 조건들도 사용할 수 있습니다.

함수 안에서 값이 변경되므로 call of reference로 구현합니다.

 

IOU 값은 double IOURate 변수에 저장이 되는데 OpenCV의 Rect 클래스를 사용하면 간단히 구할 수 있습니다.

코드에서는 반복문에 벡터와 구조체로 복잡해보이는데 Rect 타입 변수 두 개가 주어질 때 두 Rect의 IOU는 아래와 같습니다. 두 사각형의 전체 넓이로 두 사각형의 겹치는 넓이를 나누면 됩니다.

cv::Rect A(0, 0, 100, 50);
cv::Rect B(50. 50, 100, 100);
double IOURate = (double)(A & B).area() / (A | B).area();

IOU 값이 0.5 이상인 두 영역이 있을 때,

더 정확하게 분류한 바운딩 박스만 남기고 나머지 바운딩 박스는 지웁니다.

 

2중 for문을 사용해서 i와 j 두 인덱스가 겹치지 않게 전체 탐색하도록 구현했습니다.

하위 for문인 j가 가리키는 영역이 지워지면 j--로 인덱스를 조정하고 반복문을 계속 진행하고

상위 for문인 i가 가리키는 영역이 지워지면 i--후 하위 for문을 break하여 2중 for문을 다시 실행합니다.