-
이미지 매칭 코드컴공지식/컴퓨터비전 2024. 10. 24. 20:38
#include <opencv2/opencv.hpp>
#include <opencv2/core.hpp>
#include <opencv2/features2d.hpp>
#include <opencv2/highgui.hpp>
#include <iostream>
#include <vector>
using namespace cv;
using namespace std;
int main() {
// 이미지와 특징점, 디스크립터 변수 선언
Mat query, image, descriptors1, descriptors2;
Ptr<ORB> orbF = ORB::create(1000); // 최대 1000개의 키포인트 생성
vector<KeyPoint> keypoints1, keypoints2;
vector<vector<DMatch>> matches; // KNN 매칭 결과
vector<DMatch> goodMatches; // 좋은 매칭만 따로 저장
BFMatcher matcher(NORM_HAMMING); // Hamming 거리로 매칭
Mat imgMatches;
int i, k = 2; // KNN 매칭에서 최적의 2개 매칭 찾기
float nndr = 0.6f; // 최근접 이웃 거리 비율 (nn드비율)
// 이미지 읽기
query = imread("assets/query.jpg");
image = imread("assets/input.jpg");
// 이미지 리사이즈 (필요시)
resize(query, query, Size(640, 480));
resize(image, image, Size(640, 480));
// 이미지가 제대로 로드되지 않으면 종료
if (query.empty() || image.empty()) {
cout << "이미지를 불러오지 못했습니다!" << endl;
return -1;
}
// ORB 특징점 검출 및 디스크립터 계산
orbF->detectAndCompute(query, noArray(), keypoints1, descriptors1);
orbF->detectAndCompute(image, noArray(), keypoints2, descriptors2);
// KNN 매칭 수행 (최적의 두 매칭 찾기)
matcher.knnMatch(descriptors1, descriptors2, matches, k);
// 좋은 매칭 찾기: 첫 번째 매칭이 두 번째보다 훨씬 좋을 때만 사용
for (i = 0; i < matches.size(); i++) {
if (matches[i].size() == 2 &&
matches[i][0].distance <= nndr * matches[i][1].distance) {
goodMatches.push_back(matches[i][0]); // 좋은 매칭 저장
}
}
// 좋은 매칭이 너무 적으면 실패 처리
if (goodMatches.size() < 4) {
cout << "매칭 실패!" << endl;
return 0;
}
// 두 이미지의 매칭 결과를 그리기
drawMatches(query, keypoints1, image, keypoints2, goodMatches, imgMatches,
Scalar::all(-1), Scalar::all(-1), vector<char>(),
DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS);
// 매칭 결과 출력
imshow("imgMatches", imgMatches);
waitKey(0); // 아무 키나 누를 때까지 대기
return 0;
}ORB::create(1000)은 ORB(Oriented FAST and Rotated BRIEF) 알고리즘을 사용해서 최대 1000개의 특징점(키포인트)을 찾도록 객체를 생성한다.
그리고 keypoints1과 keypoints2는 각 이미지에서 발견된 특징점을 저장한다.
matches: 특징점 간의 비교 결과가 담긴 벡터. 두 이미지 간의 디스크립터가 얼마나 비슷한지 비교하는 결과다.
goodMatches: 유사도가 높은(즉, 제대로 매칭된) 것들만 따로 모아둔 벡터다.
matcher.knnMatch()가 각 디스크립터에서 가장 가까운 두 개를 찾아준다.
k = 2: 최적의 두 매칭을 찾겠다는 의미
goodMatches가 4개 미만이면 매칭 실패로 간주하고 종료한다. 이거 제대로 안 잡아두면 나중에 디버깅 지옥이다.
마지막으로 drawMatches() 함수로 두 이미지의 매칭 결과를 그려서 시각화한다.
Scalar::all(-1)은 색상을 자동으로 지정하겠다는 의미다.
DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS는 단일 포인트는 그리지 않도록 설정한다.
'컴공지식 > 컴퓨터비전' 카테고리의 다른 글
Face Detection (2) 2024.10.28 객체 탐지 방법 (1) 2024.10.28 CNN이란? (2) 2024.10.24 이미지 매칭(Image Matching)이란? (1) 2024.10.24 ORB란? (1) 2024.10.24