gpt4 book ai didi

c++ - SIFT 匹配给出非常差的结果

转载 作者:塔克拉玛干 更新时间:2023-11-03 01:46:01 35 4
gpt4 key购买 nike

我正在开展一个项目,我将使用单应性作为分类器中的特征。我的问题是自动计算单应性,我使用 SIFT 描述符来找到两个图像之间的点来计算单应性,但是 SIFT 给我的结果很差,因此我不能在我的工作中使用它们。

我正在使用 OpenCV 2.4.3。

起初我使用的是 SURF,但我得到了类似的结果,所以我决定使用速度较慢但更精确的 SIFT。我的第一个猜测是我的数据集中的图像分辨率太低,但我在最先进的数据集 (Pointing 04) 上运行我的算法,我得到了几乎相同的结果,所以问题在于我所做的而不是在我的数据集中。

在每个图像中找到的 SIFT 关键点之间的匹配是使用 FlannBased 匹配器完成的,我尝试了 BruteForce 匹配器,但结果再次几乎相同。

这是我找到的匹配示例(来自 Pointing 04 数据集的图像) Matches of my algorithm

上图显示了与我的程序找到的匹配有多差。只有 1 分是正确的匹配。我需要(至少)4 次正确匹配才能完成我必须做的事情。

这是我使用的代码:

这是从每个图像中提取 SIFT 描述符的函数

void extract_sift(const Mat &img, vector<KeyPoint> &keypoints, Mat &descriptors, Rect* face_rec) {

// Create masks for ROI on the original image
Mat mask1 = Mat::zeros(img.size(), CV_8U); // type of mask is CV_8U

Mat roi1(mask1, *face_rec);
roi1 = Scalar(255, 255, 255);

// Extracts keypoints in ROIs only
Ptr<DescriptorExtractor> featExtractor;
Ptr<FeatureDetector> featDetector;
Ptr<DescriptorMatcher> featMatcher;

featExtractor = new SIFT();
featDetector = FeatureDetector::create("SIFT");

featDetector->detect(img,keypoints,mask1);
featExtractor->compute(img,keypoints,descriptors);

}

这是匹配两个图像描述符的函数

void match_sift(const Mat &img1, const Mat &img2, const vector<KeyPoint> &kp1,
const vector<KeyPoint> &kp2, const Mat &descriptors1, const Mat &descriptors2,
vector<Point2f> &p_im1, vector<Point2f> &p_im2) {

// Matching descriptor vectors using FLANN matcher
Ptr<DescriptorMatcher> matcher = DescriptorMatcher::create("FlannBased");
std::vector< DMatch > matches;
matcher->match( descriptors1, descriptors2, matches );

double max_dist = 0; double min_dist = 100;

// Quick calculation of max and min distances between keypoints
for( int i = 0; i < descriptors1.rows; ++i ){
double dist = matches[i].distance;
if( dist < min_dist ) min_dist = dist;
if( dist > max_dist ) max_dist = dist;
}

// Draw only the 4 best matches
std::vector< DMatch > good_matches;

// XXX: DMatch has no sort method, maybe a more efficent min extraction algorithm can be used here?
double min=matches[0].distance;
int min_i = 0;
for( int i = 0; i < (matches.size()>4?4:matches.size()); ++i ) {
for(int j=0;j<matches.size();++j)
if(matches[j].distance < min) {
min = matches[j].distance;
min_i = j;
}
good_matches.push_back( matches[min_i]);
matches.erase(matches.begin() + min_i);
min=matches[0].distance;
min_i = 0;
}

Mat img_matches;
drawMatches( img1, kp1, img2, kp2,
good_matches, img_matches, Scalar::all(-1), Scalar::all(-1),
vector<char>(), DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS );
imwrite("imgMatch.jpeg",img_matches);
imshow("",img_matches);
waitKey();

for( int i = 0; i < good_matches.size(); i++ )
{
// Get the points from the best matches
p_im1.push_back( kp1[ good_matches[i].queryIdx ].pt );
p_im2.push_back( kp2[ good_matches[i].trainIdx ].pt );
}
}

这些函数在这里被调用:

extract_sift(dataset[i].img,dataset[i].keypoints,dataset[i].descriptors,face_rec);

[...]

//  Extract keypoints from i+1 image and calculate homography
extract_sift(dataset[i+1].img,dataset[i+1].keypoints,dataset[i+1].descriptors,face_rec);
dataset[front].points_r.clear(); // XXX: dunno if clearing the points every time is the best way to do it..
match_sift(dataset[front].img,dataset[i+1].img,dataset[front].keypoints,dataset[i+1].keypoints,
dataset[front].descriptors,dataset[i+1].descriptors,dataset[front].points_r,dataset[i+1].points_r);

dataset[i+1].H = findHomography(dataset[front].points_r,dataset[i+1].points_r, RANSAC);

非常感谢任何有关如何提高匹配性能的帮助,谢谢。

最佳答案

您显然在代码 w.r.t. 中使用了“最佳四点”。火柴的距离。换句话说,如果两个描述符非常相似,您认为匹配是有效的。我相信这是错误的。你试过画出所有的火柴吗?其中许多应该是错误的,但也应该有很多是好的。

匹配的距离只是说明两个点的相似程度。这并不能说明匹配在几何上是否连贯。选择最佳匹配一定要考虑几何形状。

下面是我的做法:

  1. 检测角点(您已经这样做了)
  2. 找到匹配项(您已经这样做了)
  3. 尝试使用匹配项(之前不要过滤它们!)使用findHomography(...)
  4. 找到两个图像之间的单应变换
  5. findHomography(...) 会告诉您哪些是内点。这些是您的good_matches

关于c++ - SIFT 匹配给出非常差的结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17546780/

35 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com