codemonkey
codemonkey

Reputation: 489

OpenCV - Matching Keypoints Found from a Custom Algorithm

Suppose I found keypoints and their descriptors in 2 images.

def create_SIFT_points(filename):
    img = cv.imread(filename)
    sift = cv.xfeatures2d.SIFT_create()
    return sift.detectAndCompute(img,None)
img1_file = 'image_1.png'
img2_file = 'image_2.png'
kp1, des1 = create_SIFT_points(img1_file)
kp2, des2 = create_SIFT_points(img2_file)

And suppose that I used a custom algorithm to found the matches. Then I want to see these matches on kp1 and kp2 visually. For example, if I matched the 7th keypoint on kp1 and 3th keypoint on kp2 I want to see it in a picture. NOTE THAT I am using my own algorithm to find these and holding them in a list.

How can I achieve this? in the documentation there is a drawMatches() method. https://docs.opencv.org/3.4/d4/d5d/group__features2d__draw.html

But how to fill this?

const std::vector< DMatch > &   matches1to2,

https://docs.opencv.org/3.4/d4/de0/classcv_1_1DMatch.html

How can I fill this attributes?

float distance
int imgIdx
int queryIdx
int trainIdx

Upvotes: 1

Views: 695

Answers (1)

Grillteller
Grillteller

Reputation: 941

I already did this in C++ but it is easily transferable to Python.

I am using files (matches.txt) which hold the feature point coordinates (x1, y1, x2, y2) such as trainIdx and queryIdx are similar:

x1 y1 x2 y2 (row 1 - trainIdx 0, queryIdx 0)
x1 y1 x2 y2 (row 2 - trainIdx 1, queryIdx 1)
...

In your example you would have to assing the correct trainIdx and queryIdx to the std::vector<cv::DMatch>.
Then I read the file and the images and fill the overloaded std::vector<cv::DMatch> with queryIdx, trainIdx and distance (which is irrelevant for drawing, so I set it to 1).

Here is the relevant piece of code in C++:

// Read images
cv::Mat img_1 = cv::imread(name_img1);
cv::Mat img_2 = cv::imread(name_img2);

// Create match_file and output_file
std::vector<cv::DMatch> matches_12;
cv::Mat output_image;

// Read keypoints
std::vector<cv::KeyPoint> kp1, kp2;
int counter = 0;

// Read matches file
std::ifstream matches_files;
matches_files.open("matches.txt")

std::string line_of_matches;
while (std::getline(matches_files, line_of_matches))
    {
    std::istringstream iss_matches(line_of_matches);
    float x1, y1, x2, y2;
            

    if (!(iss_matches >> x1 >> y1 >> x2 >> y2)) {break; }
    
    // Store keypoints in appropriate format
    kp1.push_back(cv::KeyPoint(cv::Point2f(x1, y1), 1));
    kp2.push_back(cv::KeyPoint(cv::Point2f(x2, y2), 1));

    // Store matches in appropriate format
    matches_12.push_back(cv::DMatch(counter, counter, 1));

    counter++;
    }
// Draw matches and save the file
cv::drawMatches(img_1, kp1, img_2, kp2, matches_12, output_image, cv::Scalar::all(-1), 
cv::Scalar::all(-1)); 
cv::imwrite("My_own_matching_method.bmp", output_image);
       

Upvotes: 1

Related Questions