ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 이미지 매칭 코드
    컴공지식/컴퓨터비전 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
Designed by Tistory.