상세 컨텐츠

본문 제목

#OpenCV 4로 배우는 컴퓨터 비전과 머신 러닝 - 19

Programing/OpenCV

by CouqueD'asse 2022. 8. 2. 15:44

본문

14장 지역 특징점 검출과 매칭

 

14.1 코너 검출

 

14.1.1 해리스 코너 검출 방법

템플릿 매칭은 영상의 크기가 바뀌거나 회전이 되면 제대로 동작하지 않는 한계가 있음

두 영상 사이에 기하학적 변환이 있어도 효과적으로 사용할 수 있는 지역 특징점 기반 매칭 방법

특징 : 영상으로부터 추출할 수 있는 유용한 정보를 의미 (평균 밝기, 히스토그램, 에지, 직선 성분, 코너 등)

지역 특징 : 에지, 직선 성분, 코너처럼 영상 전체가 아닌 일부 영역에서 추출할 수 있는 특징

코너 : 에지의 방향이 급격하게 변하는 부분으로서 삼각형의 꼭지점이나 연필 심처럼 뾰족하게 튀어나와 있는 부분이 코너가 될 수 있음. 직선 성분 등의 다른 지역 특징에 비해 분별력이 높고 대체로 영상 전 영역에 골고루 분포하기 때문에 영상을 분석하는 데 유용한 지역 특징으로 사용됨

특징점 (키포인트 또는 관심점) : 코너처럼 한 점의 형태로 표현할 수 있는 특징

// 해리스 코너 검출
void corner_harris()
{
	Mat src = imread("building.jpg", IMREAD_GRAYSCALE);

	if (src.empty())
	{
		return;
	}

	Mat harris;
	cornerHarris(src, harris, 3, 3, 0.04);

	Mat harris_norm;
	normalize(harris, harris_norm, 0, 255, NORM_MINMAX, CV_8U);

	Mat dst;
	cvtColor(src, dst, COLOR_GRAY2BGR);

	for (int j = 1; j < harris.rows - 1; j++)
	{
		for (int i = 1; i < harris.cols - 1; i++)
		{
			if (harris_norm.at<uchar>(j, i) > 120)
			{
				if (harris.at<float>(j, i) > harris.at<float>(j - 1, i) && // 비최대 억제 수행 : (i, j)위치에서 
					harris.at<float>(j, i) > harris.at<float>(j + 1, i) && // 주변 네 개의 픽셀을 비교하여 지역 최대인 경우에만 빨간원 표시
					harris.at<float>(j, i) > harris.at<float>(j, i - 1) &&
					harris.at<float>(j, i) > harris.at<float>(j, i + 1))
				{
					circle(dst, Point(i, j), 5, Scalar(0, 0, 255), 2);
				}
			}
		}
	}

	imshow("src", src);
	imshow("harris_norm", harris_norm);
	imshow("dst", dst);

	waitKey();
	destroyAllWindows();
}

 

4.1.2 FAST 코너 검출 방법

해리스 코너 검출 방법 : 영상의 코너 특성을 수학적으로 잘 정의하고, 복잡한 수식을 잘 전개하여 수치적으로 코너를 검출하지만 복잡한 연산을 필요로 하기 때문에 연산 속도가 느림

FAST 코너 검출 방법 : 단순한 픽셀 값 비교 방법을 통해 코너를 검출하여 매우 빠르게 동작함

특정 코너 점 주변 픽셀들도 함께 코너로 검출하는 경우가 많기 때문에 주변 코너 픽셀 중에서 가장 코너에 적합한 픽셀을 선택하는 비최대 억제 작업을 추가적으로 수행하는 것이 좋음 (그레이스케일 영상만 사용)

// FAST 코너 검출
void corner_fast()
{
	Mat src = imread("building.jpg", IMREAD_GRAYSCALE);

	if (src.empty())
	{
		return;
	}

	vector<KeyPoint> keypoints;
	FAST(src, keypoints, 60, true); // 임계값 60, 비최대 억제 수행

	Mat dst;
	cvtColor(src, dst, COLOR_GRAY2BGR);

	for (KeyPoint kp : keypoints)
	{
		Point pt(cvRound(kp.pt.x), cvRound(kp.pt.y));
		circle(dst, pt, 5, Scalar(0, 0, 255), 2);
	}

	imshow("src", src);
	imshow("dst", dst);

	waitKey();
	destroyAllWindows();
}

 

14.2 크기 불변 특징점 검출과 기술

 

14.2.1 크기 불변 특징점 알고리즘

코너는 영상이 회전되어도 여전히 코너로 검출됨 -> 회전 불변 특징점

영상의 크기가 변경될 경우 코너는 더 이상 코너로 검출되지 않을 수 있음

ORB 알고리즘 : 입력 영상의 크기를 점진적으로 축소한 피라미드 영상을 구축하여 특징점을 추출. 그리고 각 특징점에서 주된 방향 성분을 계산하고, 방향을 고려한 BRIEF 알고리즘으로 이진 기술자를 계산

BRIEF 알고리즘 : 특징점 주변의 픽셀 쌍을 미리 정하고, 해당 픽셀 값 크기를 비교하여 0 또는 1로 측징을 기술

τ(x, y) = 1 (I(x) < I(y)) or 0

이진 기술자 : 특징점 주변 정보를 이진수 형태로 표현하는 기술자

FAST 기반의 방법으로 특징점을 구한 후, 각 특징점에서 픽셀 밝기 값 분포를 고려한 코너 방향 성분을 계산. 그리고 이 방향 성분을 이용하여 BRIEF 계산에 필요한 점들의 위치를 보정함으로써 회전에 불변한 BRIEF 기술자를 계산

기본적으로 256개의 크기 비교 픽셀 쌍을 사용하여 이진 기술자를 구성하며, 결과적으로 하나의 특징점은 256비트로 표현

이진 기술자로 표현된 특징점 사이의 거리 계산은 주로 해밍 거리 방법을 사용

해밍 거리 : 이진수로 표현된 두 기술자에서 서로 값이 다른 비트의 개수를 세는 방식으로 계산

해밍 거리 계산 : 두 기술자의 비트 단위 배타적 논리합(XOR) 연산 후, 비트 값이 1인 개수를 세는 방식으로 빠르게 계산 가능

 

14.2.2 OpenCV 특징점 검출과 기술

// 키포인트 검출
void detect_keypoints()
{
	Mat src = imread("box_in_scene.png", IMREAD_GRAYSCALE);

	if (src.empty())
	{
		return;
	}

	Ptr<Feature2D> feature = ORB::create();

	vector<KeyPoint> keypoints;
	feature->detect(src, keypoints); // 키포인트 검출

	Mat desc;
	feature->compute(src, keypoints, desc); // 키포인트 기술자 계산

	cout << "keypoints.size() : " << keypoints.size() << endl;
	cout << "desc.size() : " << desc.size() << endl;

	Mat dst;
	drawKeypoints(src, keypoints, dst, Scalar::all(-1), DrawMatchesFlags::DRAW_RICH_KEYPOINTS);
    // 키포인트 위치, 크기, 방향 정보

	imshow("src", src);
	imshow("dst", dst);

	waitKey();
	destroyAllWindows();
}

관련글 더보기