[英]Keep only the good keypoints panoramic images stitching opencv
I am working on a project regarding the matching of consecutive images in order to find the panoramic image.我正在研究一个关于匹配连续图像以找到全景图像的项目。
I found the keypoints with SIFT and the matches between couple of images using BFMatcher, but after removing the bad matches I am not able to keep the corresponding keypoints, or even to display the matches using cv::drawMatches because the program crashes.我发现了 SIFT 的关键点和使用 BFMatcher 的几个图像之间的匹配,但是在删除了错误的匹配之后,我无法保留相应的关键点,甚至无法使用 cv::drawMatches 显示匹配,因为程序崩溃了。
The inital part of the code is the following, and it works.代码的初始部分如下,它可以工作。
("image" is a vector containing all the images) (“图像”是包含所有图像的向量)
cv::Mat descriptors;
std::vector<cv::KeyPoint> keypoints;
std::vector<cv::Mat> descriptors_array;
std::vector<std::vector<cv::KeyPoint>> keypoints_array, reduced_keypoints_array;
cv::Ptr<cv::Feature2D> sift = cv::xfeatures2d::SIFT::create();
for(int i=0; i<N_images; i++){
sift->detectAndCompute(image.at(i), cv::Mat(), keypoints, descriptors);
keypoints_array.push_back(keypoints);
descriptors_array.push_back(descriptors);
}
std::vector<std::vector<cv::DMatch>> matches_array,
std::vector<cv::DMatch> matches, good_matches;
cv::Ptr<cv::BFMatcher> matcher = cv::BFMatcher::create(cv::NORM_L2, true);
for(int i=0; i<N_images-1; i++){
matcher->match(descriptors_array.at(i), descriptors_array.at(i+1), matches, cv::Mat());
for(int j=0; j<matches.size(); j++){
if (min_distance > matches.at(j).distance){
min_distance = matches.at(j).distance;
}
}
for( int k = 0; k <descriptors_array.at(i).rows; k++) {
if( matches[k].distance < 3*min_distance) {
good_matches.push_back(matches[k]);
}
}
matches_array.push_back(good_matches);
}
I am having problem with this code, when i want to just keep the good keypoints, which corresponds to the matches_array.当我只想保留与matches_array相对应的好的关键点时,我遇到了这段代码的问题。
for(int i=0; i<keypoints_array.size()-1; i++){
reduced_keypoints_array.push_back(std::vector<cv::KeyPoint>());
for(int j=0; j<matches_array.at(i).size(); j++){
reduced_keypoints_array.at(i).push_back(cv::KeyPoint());
reduced_keypoints_array.at(i).at(j) = keypoints_array.at(i).at(matches_array.at(i).at(j).queryIdx);
}
}
And here i wanted to display the matches, but it also crashes because my matches are more than the keypoints since I couldn't reduce the number of keypoints.在这里我想显示匹配,但它也崩溃了,因为我的匹配超过了关键点,因为我无法减少关键点的数量。
cv::Mat out;
for(int i=0; i<keypoints_array.size()-1; i++){
cv::drawMatches(image.at(i), keypoints_array.at(i), image.at(i+1), keypoints_array.at(i+1),matches_array.at(i), out2, cv::Scalar::all(-1), cv::Scalar::all(-1), std::vector< char >(), cv::DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS );
cv::imshow("matches", out);
cv::waitKey(0);
}
How can i keep only the corresponding keypoints?我怎样才能只保留相应的关键点? Or just draw the matches without removing the keypoints?
或者只是在不删除关键点的情况下绘制比赛?
I edited some parts that I will mark in the code.我编辑了一些我将在代码中标记的部分。 I would not recommend the data structures you are using, since it is very hard to read them.
我不推荐您使用的数据结构,因为它们很难阅读。 Consider creating
typedefs
or structs
when you have multiple vectors of vectors.当您有多个向量向量时,请考虑创建
typedefs
或structs
。 I used ORB since I did not install SIFT at the moment.我使用 ORB,因为我目前没有安装 SIFT。 Here is an example for three images:
这是三个图像的示例:
int main(int argc, char** argv)
{
// Reading my images and insert them into a vector
std::vector<cv::Mat> image;
cv::Mat img1 = cv::imread("1.png", cv::IMREAD_GRAYSCALE);
cv::Mat img2 = cv::imread("2.png", cv::IMREAD_GRAYSCALE);
cv::Mat img3 = cv::imread("3.png", cv::IMREAD_GRAYSCALE);
image.push_back(img1);
image.push_back(img2);
image.push_back(img3);
int N_images = (int)image.size();
cv::Mat descriptors;
std::vector<cv::KeyPoint> keypoints;
std::vector<cv::Mat> descriptors_array;
std::vector<std::vector<cv::KeyPoint>> keypoints_array, reduced_keypoints_array;
// Here I used ORB
cv::Ptr<cv::ORB> orb = cv::ORB::create();
for (int i = 0; i < N_images; i++) {
orb->detectAndCompute(image.at(i), cv::Mat(), keypoints, descriptors);
keypoints_array.push_back(keypoints);
descriptors_array.push_back(descriptors);
}
std::vector<std::vector<cv::DMatch>> matches_array;
std::vector<cv::DMatch> matches, good_matches;
cv::Ptr<cv::BFMatcher> matcher = cv::BFMatcher::create(cv::NORM_L2, true);
// I created a vector of pairs of keypoints to push them into an array similar to the good matches
std::vector<std::pair<cv::KeyPoint, cv::KeyPoint>> good_keypoint_pairs_array;
std::vector<std::vector<std::pair<cv::KeyPoint, cv::KeyPoint>>> keypoint_pairs_array;
float min_distance = 1000;
for (int i = 0; i < N_images-1 ; i++) {
matcher->match(descriptors_array[i], descriptors_array.at(i + 1), matches, cv::Mat());
// I left that part out since I got always a number of 0 matches, no matter which min_distance I used
/*for (int j = 0; j < matches.size(); j++) {
if (min_distance > matches.at(j).distance) {
min_distance = matches.at(j).distance;
}
}*/
for (int k = 0; k < descriptors_array.at(i).rows; k++) {
if (matches[k].distance < 3 * min_distance) {
good_keypoint_pairs_array.push_back(std::make_pair(keypoints_array.at(i).at(k), keypoints_array.at(i + 1).at(k)));
good_matches.push_back(matches[k]);
}
}
keypoint_pairs_array.push_back(good_keypoint_pairs_array);
matches_array.push_back(good_matches);
}
cv::Mat out;
// I create my keypoint vectors to use them for the cv::drawMatches function
std::vector<cv::KeyPoint> kp_1, kp_2;
for (int i = 0; i < keypoint_pairs_array.size(); ++i) {
for (int j = 0; j < keypoint_pairs_array[i].size(); ++j) {
kp_1.push_back(keypoint_pairs_array[i][j].first);
kp_2.push_back(keypoint_pairs_array[i][j].second);
}
cv::drawMatches(image.at(i), kp_1, image.at(i + 1), kp_2, matches_array.at(i), out, cv::Scalar::all(-1), cv::Scalar::all(-1), std::vector< char >(), cv::DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS);
cv::imshow("matches", out);
cv::waitKey(0);
kp_1.clear();
kp_2.clear();
}
}
I am having problem with this code, when i want to just keep the good keypoints, which corresponds to the matches_array.
当我只想保留与matches_array相对应的好的关键点时,我遇到了这段代码的问题。
As you already mentioned, it is very important that the size of the std::vector<cv::DMatch>
is always similar to the size of the std::vector<cv::KeyPoint>
So you have to save your keypoints in the same loop where you use your number of matches as shown.正如您已经提到的,
std::vector<cv::DMatch>
的大小始终与std::vector<cv::KeyPoint>
的大小相似非常重要,因此您必须将关键点保存在如图所示,您使用匹配数量的相同循环。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.