@ utkarsh:我同意SIFT描述符需要關鍵點的方向和尺度信息。 David G. Lowe的原始論文(來自比例不變關鍵點的獨特圖像特徵)說,「爲了實現方向不變性,描述符的座標和梯度方向相對於關鍵點方向旋轉」。而比例尺信息用於在計算描述符期間選擇圖像的高斯模糊水平。
但是,這個帖子中的問題是關於計算給定像素的描述符。請注意,給定的像素位置不是使用所需程序計算的SIFT關鍵點。因此,在這種情況下,方向和比例信息不可用。因此,在先前回答中提到的code以默認比例(即1)和默認取向(不旋轉鄰域的梯度方向)在給定像素處計算SIFT描述符。
@Teng Long:在另外一個筆記中,我認爲用於匹配兩個圖像(原始圖像和旋轉圖像)中的關鍵點的方法在某種程度上是不明確的。您應該分別在兩個圖像上運行SIFT關鍵點檢測並分別計算其對應的描述符。然後,您可以使用Brute Force匹配這兩組關鍵點。
以下代碼計算圖像及其45度旋轉版本上的SIFT關鍵點,然後使用蠻力部件匹配計算SIFT關鍵點描述符。
# include "opencv2/opencv_modules.hpp"
# include "opencv2/core/core.hpp"
# include "opencv2/features2d/features2d.hpp"
# include "opencv2/highgui/highgui.hpp"
# include "opencv2/nonfree/features2d.hpp"
# include "opencv2\imgproc\imgproc.hpp"
# include <stdio.h>
using namespace cv;
int main(int argc, char** argv)
{
Mat img_1, img_2;
// Load image in grayscale format
img_1 = imread("scene.jpg", CV_LOAD_IMAGE_GRAYSCALE);
// Rotate the input image without loosing the corners
Point center = Point(img_1.cols/2, img_1.rows/2);
double angle = 45, scale = 1;
Mat rot = getRotationMatrix2D(center, angle, scale);
Rect bbox = cv::RotatedRect(center, img_1.size(), angle).boundingRect();
rot.at<double>(0,2) += bbox.width/2.0 - center.x;
rot.at<double>(1,2) += bbox.height/2.0 - center.y;
warpAffine(img_1, img_2, rot, bbox.size());
// SIFT feature detector
SiftFeatureDetector detector;
std::vector<KeyPoint> keypoints_1, keypoints_2;
detector.detect(img_1, keypoints_1);
detector.detect(img_2, keypoints_2);
// Calculate descriptors
SiftDescriptorExtractor extractor;
Mat descriptors_1, descriptors_2;
extractor.compute(img_1, keypoints_1, descriptors_1);
extractor.compute(img_2, keypoints_2, descriptors_2);
// Matching descriptors using Brute Force
BFMatcher matcher(NORM_L2);
std::vector<DMatch> matches;
matcher.match(descriptors_1, descriptors_2, matches);
//-- Quick calculation of max and min distances between Keypoints
double max_dist = 0; double min_dist = 100;
for(int i = 0; i < descriptors_1.rows; i++)
{ double dist = matches[i].distance;
if(dist < min_dist) min_dist = dist;
if(dist > max_dist) max_dist = dist;
}
// Draw only "good" matches (i.e. whose distance is less than 2*min_dist,
//-- or a small arbitary value (0.02) in the event that min_dist is very
//-- small)
std::vector<DMatch> good_matches;
for(int i = 0; i < descriptors_1.rows; i++)
{ if(matches[i].distance <= max(2*min_dist, 0.02))
{ good_matches.push_back(matches[i]); }
}
//-- Draw only "good" matches
Mat img_matches;
drawMatches(img_1, keypoints_1, img_2, keypoints_2,
good_matches, img_matches, Scalar::all(-1), Scalar::all(-1),
vector<char>(), DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS);
//-- Show detected matches
imshow("Good Matches", img_matches);
waitKey(0);
return 0;
}
這裏是結果:
SIFT計算中尺度空間的關鍵點和desctriptors確保不同地縮放圖像仍然會產生相同的關鍵點和相同的描述符。所以關鍵點的大小將決定關鍵點周圍描述符窗口的大小。同樣,角度將確保旋轉的圖像將產生相同的描述符。所以你是否需要選擇特殊的尺寸和角度取決於你的特殊問題。 – Micka
看看這個,也是:http://stackoverflow.com/questions/8561352/opencv-keypoint-information-about-angle-and-octave – Micka
嗨米卡我現在面臨的問題是,我有3D模型。我可以從一個視圖拍攝模型的快照並計算圖像的關鍵點和描述符。旋轉後,我可以計算一組不同的關鍵點和I可以計算出關鍵點和3D點的這些位置的3D位置可以然後轉化到UV在第一視圖中的座標。我想對這兩組關鍵點進行蠻力匹配,以找出每個模型的SIFT和Daisy描述符的視圖不變性。 –