Opencv SIFT特征提取

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

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

static inline void
unpackOctave(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 detection
		detector->detect(img, keypoints);

		// SIFT description
		extractor->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
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值