Opencv SIFT特征提取

来源:互联网 发布:淘宝可以改好评吗 编辑:程序博客网 时间:2024/05/16 13:47

Opencv里面,特征提取可以分为两步进行:detection + computation,具体为detection后,得要一些keypoints,然后在这些keypoints上应用相应的描述符。

SIFT是一个比较常用的特征,下面就以SIFT特征为例,在Opencv进行SIFT提取(SIFT detection + SIFT description)。具体代码如下:

static inline voidunpackOctave(const KeyPoint& kpt, int& octave, int& layer, float& scale){octave = kpt.octave & 255;layer = (kpt.octave >> 8) & 255;octave = octave < 128 ? octave : (-128 | octave);scale = octave >= 0 ? 1.f / (1 << octave) : (float)(1 << -octave);}string strfixedLength(const int i, const int length){ostringstream oss;if (i < 0){oss << '-1';}oss << setfill('0') << setw(length) << (i < 0 ? -i : i);return oss.str();}int main(){initModule_nonfree();int nImages = 1;string image_path = "D:\\Datasets\\ukbench\\ukbench_test\\ukbench";//string image_path = "D:\\Datasets\\ukbench\\ukbench_imgs\\full\\ukbench";Mat img;vector<KeyPoint> keypoints;vector<KeyPoint>::iterator itr_keypoints;Ptr<FeatureDetector> detector = FeatureDetector::create("SIFT");Ptr<DescriptorExtractor> extractor = DescriptorExtractor::create("SIFT");Mat sift_tmp;ofstream img_sift_info("sift_info.txt", ofstream::out);ofstream img_sift("sift.txt", ofstream::out);string img_name = "ukbench";for (int i = 0; i < nImages; ++i){img_name = "ukbench";img_name = img_name + strfixedLength(i, 5) + ".jpg";cout << img_name << endl;img = imread(image_path + strfixedLength(i, 5) + ".jpg", CV_LOAD_IMAGE_GRAYSCALE);// SIFT detectiondetector->detect(img, keypoints);// SIFT descriptionextractor->compute(img, keypoints, sift_tmp);if (keypoints.size() != sift_tmp.rows){cout << "Error: number of keypoints should matched the number of descriptor matrix rows!" << endl;return -1;}// sift file format: "x y:octave:angle:sift descriptor"int octave;int layer;float scale;for (int i = 0; i < sift_tmp.rows; ++i){unpackOctave(keypoints[i], octave, layer, scale);img_sift << keypoints[i].pt.x << " " << keypoints[i].pt.y << ":" <<octave << ":" << keypoints[i].angle << ":";for (int j = 0; j < sift_tmp.cols - 1; ++j){img_sift << *(float *)(sift_tmp.data + sift_tmp.step[0] * i + sift_tmp.step[1] * j) << " ";}img_sift << *(float *)(sift_tmp.data + sift_tmp.step[0] * i + sift_tmp.step[1] * (sift_tmp.cols - 1)) << endl;}// sift info file format: "image_name:num. of sift"img_sift_info << img_name << ":" << keypoints.size() << endl;keypoints.clear();}img_sift.close();img_sift_info.close();system("pause");return 0;}

与SIFT特征相关的几个参数是octave,scale,angle等,其中octave要特别注意。

Opencv里面把octave,scale,layer等都编码到keypoint的octave中,具体可以看https://stackoverflow.com/questions/17015995/opencv-sift-descriptor-keypoint-radius

上面特征提取代码里面的unpackOctave(const KeyPoint& kpt, int& octave, int& layer, float& scale)函数就是用来将keypoint octave解码成对应的参数的(copy from sift.cpp)。

此外,还需注意的是,不同的detection方法(SIFT、SURF、MSER等),keypoint不同成员变量(octave、size等)的具体含义是不尽相同的,使用时需要小心。

0 0
原创粉丝点击