[Computer Vision/OpenCV] 22. Feature Descriptor(3) - SIFT & FLANN+Lowe’s Ratio Test

2025. 5. 28. 17:50ยท๐Ÿฆ„AI/Computer Vision

https://he-kate1130.tistory.com/151

 

[Computer Vision/OpenCV] 21. Feature Descriptor(2) - SIFT

https://he-kate1130.tistory.com/150 [Computer Vision/OpenCV] 20. Feature Descriptor(1)์˜ค๋Š˜์€ Feature Descriptor๊ฐ€ ๋ฌด์—‡์ธ์ง€, ์–ด๋–ค ์•Œ๊ณ ๋ฆฌ์ฆ˜์ด ์žˆ๋Š”์ง€ ํฐ ํ‹€์—์„œ ์•Œ์•„๋ณด๋„๋กํ•œ๋‹ค.Feature Descriptor๋Š” ์ด๋ฏธ์ง€์˜ ํŠน์ง•์ ์„ ์ˆ˜์น˜

he-kate1130.tistory.com

 

SIFT์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ์ง์ ‘ ์ ์šฉํ•ด๋ณด๋ฉฐ, ํ‚คํฌ์ธํŠธ๋ฅผ ๊ฒ€์ถœํ•˜๊ณ  ๋‘ ์ด๋ฏธ์ง€ ๊ฐ„์˜ ๋งค์นญ์„ ์ˆ˜ํ–‰ํ•ด๋ณด์ž.

 

 

ํ‚คํฌ์ธํŠธ ์ถ”์ถœ

๋จผ์ € ๋‘ ์ด๋ฏธ์ง€๋ฅผ ๋ถˆ๋Ÿฌ์˜จ ํ›„, SIFT ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ์ด์šฉํ•ด ๊ฐ๊ฐ์˜ ์ด๋ฏธ์ง€์—์„œ ํ‚คํฌ์ธํŠธ๋ฅผ ์ถ”์ถœํ•œ๋‹ค.

์•„๋ž˜๋Š” drawKeypoints() ํ•จ์ˆ˜๋ฅผ ์ด์šฉํ•ด ์‹œ๊ฐํ™”ํ•œ ๊ฒฐ๊ณผ์ด๋‹ค

 

 

Brute-Force ๋งค์นญ

๊ฐ€์žฅ ๋‹จ์ˆœํ•œ ๋ฐฉ์‹์˜ ๋งค์นญ์ธ Brute-Force Matcher๋ฅผ ์ด์šฉํ•ด ๋‘ ์ด๋ฏธ์ง€์˜ ํŠน์ง•์ ๋“ค์„ ๋งค์นญํ•ด๋ณด๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค

๋„ˆ๋ฌด ๋งŽ์€ ๋งค์นญ์ด ์ƒ๊ฒจ์„œ ์ด๋ฏธ์ง€๊ฐ€ ์ž˜ ์•ˆ๋ณด์ธ๋‹ค.. ๋ฌด์—‡๋ณด๋‹ค ์ •ํ™•ํ•˜์ง€ ์•Š์€ ๋งค์นญ๊ฒฐ๊ณผ๊ฐ€ ๋„ˆ๋ฌด ๋งŽ์•„๋ณด์ธ๋‹ค. 

 

FLANN + Lowe’s Ratio Test

์•ž์„œ ์†Œ๊ฐœํ•œ SIFT๋Š” ์ด๋ฏธ์ง€ ๋‚ด์—์„œ ๊ฐ•๊ฑดํ•œ ํ‚คํฌ์ธํŠธ๋ฅผ ๊ฒ€์ถœํ•˜๊ณ , ๊ฐ ํ‚คํฌ์ธํŠธ์˜ ์ง€์—ญ ํŠน์„ฑ์„ ๋ฒกํ„ฐ๋กœ ๊ธฐ์ˆ (descriptor)ํ•จ์œผ๋กœ์จ ์„œ๋กœ ๋‹ค๋ฅธ ์ด๋ฏธ์ง€ ๊ฐ„ ์œ ์‚ฌํ•œ ์ง€์ ์„ ๋Œ€์‘(matching)์‹œํ‚ฌ ์ˆ˜ ์žˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ๊ธฐ์ˆ ์ž ๊ฐ„์˜ ์ง์ ‘์ ์ธ ๊ฑฐ๋ฆฌ ๋น„๊ต๋Š” ๊ณ„์‚ฐ๋Ÿ‰์ด ๋งค์šฐ ํฌ๋ฉฐ, ์˜ค์ฐจ๊ฐ€ ํฌํ•จ๋œ ์ž˜๋ชป๋œ ๋งค์นญ ์—ญ์‹œ ๋‹ค์ˆ˜ ํฌํ•จ๋  ์ˆ˜ ์žˆ๋‹ค๋Š” ๋‹จ์ ์ด ์žˆ๋‹ค. ์ด๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•œ ๋Œ€ํ‘œ์ ์ธ ๊ธฐ๋ฒ•์ด FLANN๊ณผ Lowe์˜ Ratio Test์ด๋‹ค.

FLANN (Fast Library for Approximate Nearest Neighbors)

FLANN์€ ๊ณ ์ฐจ์› ๊ณต๊ฐ„์—์„œ์˜ ํšจ์œจ์ ์ธ ์ตœ๊ทผ์ ‘ ์ด์›ƒ ํƒ์ƒ‰(Nearest Neighbor Search)์„ ์œ„ํ•œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋กœ, ์ •ํ™•ํ•œ ๋งค์นญ๋ณด๋‹ค๋Š” ๊ทผ์‚ฌ์ (approximate) ์ตœ๊ทผ์ ‘ ์ด์›ƒ์„ ๋น ๋ฅด๊ฒŒ ์ฐพ๋Š” ๊ฒƒ์„ ๋ชฉํ‘œ๋กœ ํ•œ๋‹ค. ์ด๋Š” ์ด๋ฏธ์ง€ ๋‚ด ๋‹ค์ˆ˜์˜ ํ‚คํฌ์ธํŠธ ๊ฐ„ ํŠน์ง• ๋ฒกํ„ฐ๋ฅผ ๋น„๊ตํ•  ๋•Œ ๊ณ„์‚ฐ ๋ณต์žก๋„๋ฅผ ์ค„์ด๋Š” ๋ฐ ์œ ๋ฆฌํ•˜๋‹ค.

OpenCV์—์„œ๋Š” DescriptorMatcher::create(DescriptorMatcher::FLANNBASED)๋ฅผ ํ†ตํ•ด FLANN ๊ธฐ๋ฐ˜ ๋งค์นญ๊ธฐ๋ฅผ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ๊ณ , ๋‚ด๋ถ€์ ์œผ๋กœ๋Š” KD-Tree ํ˜น์€ KMeans Tree ๋“ฑ์˜ ์•Œ๊ณ ๋ฆฌ์ฆ˜์ด ์ž๋™์œผ๋กœ ์„ ํƒ๋˜์–ด ์‚ฌ์šฉ๋œ๋‹ค.

Lowe’s Ratio Test

FLANN๊ณผ ๊ฐ™์€ ๊ทผ์‚ฌ ๋งค์นญ ๊ธฐ๋ฒ•์„ ์‚ฌ์šฉํ•  ๊ฒฝ์šฐ, ์ž˜๋ชป๋œ ๋งค์นญ์„ ํ•„ํ„ฐ๋งํ•˜๋Š” ํ›„์ฒ˜๋ฆฌ ๋‹จ๊ณ„๊ฐ€ ํ•„์ˆ˜์ ์ด๋‹ค.

์ด์— ๋Œ€ํ•ด David Lowe๋Š” ๊ทธ์˜ SIFT ๋…ผ๋ฌธ์—์„œ ๋‹ค์Œ๊ณผ ๊ฐ™์€ Ratio Test๋ฅผ ์ œ์•ˆํ•˜์˜€๋‹ค.

 

Ratio Test๋Š” ๊ฐ ํ‚คํฌ์ธํŠธ์— ๋Œ€ํ•ด ๊ฐ€์žฅ ๊ฐ€๊นŒ์šด ๋งค์นญ ๋ฒกํ„ฐ(nearest neighbor)์™€ ๋‘ ๋ฒˆ์งธ๋กœ ๊ฐ€๊นŒ์šด ๋งค์นญ ๋ฒกํ„ฐ(second nearest neighbor) ๊ฐ„์˜ ๊ฑฐ๋ฆฌ ๋น„์œจ์„ ์ด์šฉํ•˜์—ฌ ๋ชจํ˜ธํ•œ ๋งค์นญ์„ ์ œ๊ฑฐํ•˜๋Š” ๋ฐฉ๋ฒ•์ด๋‹ค. ๋‘ ๋ฒกํ„ฐ ๊ฐ„์˜ ๊ฑฐ๋ฆฌ๊ฐ€ ์ถฉ๋ถ„ํžˆ ์ฐจ์ด๊ฐ€ ๋‚  ๊ฒฝ์šฐ, ์ฒซ ๋ฒˆ์งธ ๋งค์นญ์ด ์‹ ๋ขฐํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒƒ์œผ๋กœ ๊ฐ„์ฃผํ•œ๋‹ค.

 

์ฝ”๋“œ์—์„œ๋Š” ๋‹ค์Œ์˜ ์กฐ๊ฑด๋ฌธ์„ ํ†ตํ•ด ๊ตฌํ˜„๋œ๋‹ค:

if (knn_matches[i][0].distance < ratio_thresh * knn_matches[i][1].distance)

 

์—ฌ๊ธฐ์„œ ratio_thresh๋Š” ์ผ๋ฐ˜์ ์œผ๋กœ 0.7~0.8 ์‚ฌ์ด์˜ ๊ฐ’์„ ๊ฐ€์ง€๋ฉฐ, ์—ฌ๊ธฐ์—์„œ๋Š” 0.8์„ ์‚ฌ์šฉํ•˜์˜€๋‹ค.

์ด ์ž„๊ณ„๊ฐ’๋ณด๋‹ค ๊ฑฐ๋ฆฌ ์ฐจ์ด๊ฐ€ ํฌ๋ฉด, ํ•ด๋‹น ๋งค์นญ์€ ์‹ ๋ขฐํ•  ์ˆ˜ ์žˆ๋Š”(good match) ๊ฒƒ์œผ๋กœ ๊ฐ„์ฃผํ•œ๋‹ค.

 

 

 

C++ OpenCV Code

#include <iostream>
#include "opencv2/core.hpp"
#include "opencv2/highgui.hpp"
#include "opencv2/features2d.hpp"
#include <opencv2/opencv.hpp>


using namespace cv;
using namespace std;


int main(int argc, const char* argv[])
{
    // ์ด๋ฏธ์ง€ ์ฝ๊ธฐ 
    Mat img_1 = imread("peters_1.jpg", IMREAD_COLOR);
    if (img_1.empty()) {
        std::cerr << "Image load failed!" << std::endl;
        return -1;
    }
    Mat img_2 = imread("peters_2.jpg", IMREAD_COLOR);
    if (img_2.empty()) {
        std::cerr << "Image load failed!" << std::endl;
        return -1;
    }

    //-- Step 1: Detect the keypoints
    Ptr<SIFT> detector = SIFT::create();

    std::vector<KeyPoint> keypoints1, keypoints2;
    Mat descriptors1, descriptors2;
    detector->detectAndCompute(img_1, noArray(), keypoints1, descriptors1);
    detector->detectAndCompute(img_2, noArray(), keypoints2, descriptors2);

    //-- Step 2: Matching descriptor vectors with a brute force matcher
    Ptr<DescriptorMatcher> matcher = DescriptorMatcher::create(DescriptorMatcher::BRUTEFORCE);
    std::vector< DMatch > matches;
    matcher->match(descriptors1, descriptors2, matches);

    //-- Step 2: Matching descriptor vectors with a FLAN
    Ptr<DescriptorMatcher> matcher2 = DescriptorMatcher::create(DescriptorMatcher::FLANNBASED);
    std::vector< std::vector<DMatch> > knn_matches;
    matcher2->knnMatch(descriptors1, descriptors2, knn_matches, 2);
    const float ratio_thresh = 0.7f;
    std::vector<DMatch> good_matches;
    for (size_t i = 0; i < knn_matches.size(); i++)
    {
        if (knn_matches[i][0].distance < ratio_thresh * knn_matches[i][1].distance)
        {
            good_matches.push_back(knn_matches[i][0]);
        }
    }

    //-- Draw keypoints
    Mat img_keypoints_1, img_keypoints_2, img_gray_1, img_gray_2;
    cvtColor(img_1, img_gray_1, COLOR_BGR2GRAY);
    cvtColor(img_2, img_gray_2, COLOR_BGR2GRAY);
    drawKeypoints(img_gray_1, keypoints1, img_keypoints_1);
    drawKeypoints(img_gray_2, keypoints2, img_keypoints_2);

    //-- Draw matches
    Mat img_matches, img_matches_2;
    drawMatches(img_1, keypoints1, img_2, keypoints2, matches, img_matches);
    drawMatches(img_1, keypoints1, img_2, keypoints2, good_matches, img_matches_2, Scalar::all(-1),
        Scalar::all(-1), std::vector<char>(), DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS);

    //-- Show detected matches
    imshow("Matches", img_matches);
    imshow("Good Matches", img_matches_2);

    // ๊ฒฐ๊ณผ ์ €์žฅ ํด๋”
    std::string output_dir = "./output/";
    imwrite(output_dir + "sift_keypoint_1.png", img_keypoints_1);
    imwrite(output_dir + "sift_keypoint_2.png", img_keypoints_2);
    imwrite(output_dir + "sift_matching.png", img_matches);
    imwrite(output_dir + "sift_matching_flan.png", img_matches_2);


    waitKey();
    return 0;
}

 

 

'๐Ÿฆ„AI > Computer Vision' ์นดํ…Œ๊ณ ๋ฆฌ์˜ ๋‹ค๋ฅธ ๊ธ€

[Computer Vision/OpenCV] 21. Feature Descriptor(2) - SIFT  (0) 2025.05.28
[Computer Vision/OpenCV] 20. Feature Descriptor(1)  (1) 2025.05.22
[Computer Vision/OpenCV] 19. Corner Detection - Harris Corner Detection  (0) 2025.04.24
[Computer Vision/OpenCV] 18. Edge Detection(2) - Canny Edge Detector  (0) 2025.04.23
[Computer Vision/OpenCV] 17. Edge Detection(1) - Sobel, Laplacian of Gaussian Filter  (0) 2025.04.22
'๐Ÿฆ„AI/Computer Vision' ์นดํ…Œ๊ณ ๋ฆฌ์˜ ๋‹ค๋ฅธ ๊ธ€
  • [Computer Vision/OpenCV] 21. Feature Descriptor(2) - SIFT
  • [Computer Vision/OpenCV] 20. Feature Descriptor(1)
  • [Computer Vision/OpenCV] 19. Corner Detection - Harris Corner Detection
  • [Computer Vision/OpenCV] 18. Edge Detection(2) - Canny Edge Detector
mingyung
mingyung
  • mingyung
    KATE.log
    mingyung
  • ์ „์ฒด
    ์˜ค๋Š˜
    ์–ด์ œ
    • ๋ถ„๋ฅ˜ ์ „์ฒด๋ณด๊ธฐ
      • ๐Ÿฆ„AI
        • Computer Vision
        • Paper
        • ML
        • DL
        • NLP
        • Reinforcement Learning
      • ๐ŸคธGraphics
        • OpenGL
      • ๐ŸAlgorithm
      • ์žก๋™์‚ฌ๋‹ˆ
      • ๐Ÿฅ”Project
        • Reversi Agent
        • Team22
        • [Project] Threepark
      • Computer Science
        • SW Engineering
        • Database
        • Computer Network
        • Compiler
        • Data structures
      • Dev
        • Spring
  • ์ตœ๊ทผ ๊ธ€

  • ์ธ๊ธฐ ๊ธ€

  • ํƒœ๊ทธ

    keypoint
    Gaussian
    ์ปดํ“จํ„ฐ ๋„คํŠธ์›Œํฌ
    feature descriptor
    Filtering
    OSP
    Surf
    loss
    network
    Computer Vision
    Image Processing
    ์ž๋ฃŒ๊ตฌ์กฐ
    localization
    Loss function
    Internet
    CV
    ML
    computer network
    SIFT
    Edge Detection
  • ์ตœ๊ทผ ๋Œ“๊ธ€

  • hELLOยท Designed By์ •์ƒ์šฐ.v4.10.3
mingyung
[Computer Vision/OpenCV] 22. Feature Descriptor(3) - SIFT & FLANN+Lowe’s Ratio Test
์ƒ๋‹จ์œผ๋กœ

ํ‹ฐ์Šคํ† ๋ฆฌํˆด๋ฐ”