ORB图像匹配

最近在看图像匹配方面的资料,图像匹配的主要步骤是:

1.提取特征点:在两张待匹配的图像中寻找最容易识别的像素点,如角点或者纹理丰富的物体边缘点。

2.特征点描述子:对于检测出的特征点,用一些数学上的特征对其进行描述。常 用的描述子类型有FAST,SIFT,SURF,ORB,HARRIS,FREAK。

3.特征点之间的匹配:计算两幅图像中特征点的相似度,如欧氏距离、Hausdoff、马氏距离等。

4.去除错误匹配的点:对匹配上的点进行筛选,保留正确匹配点。常用的方法:Ransac,GTM。

用了SIFT做匹配,发现匹配的效果不理想,并且在cv里是nonfree的,找到的keypoint非常多,需要对找到的关键点进行筛选。继续找资料发现了ORB和FREAK,听说FREAK比SURF和ORB更牛X,模拟的是人眼的视网膜成像原理。ORB论文资料还没仔细看,博友的说法是:用FAST作为特征点提取的算法,FAST提取特征点的速度是很快,并在此基础上添加特征点的主方向,使得ORB具有旋转不变性。在匹配上ORB采用贪婪穷举的方法得到相关性较低的随机点对,通过阅读代码知道,ORB采用暴力方式测试Keypoints的距离,用到的是海明距离(Hamming Distance)。另一个改进是对于随机点对,ORB不在使用像素点的直接比较,而是选择该像素为中心的一个小patch作为比较对象,提高了抗噪能力。

unsigned int hamdist(unsigned int x, unsigned int y) 
{ 
	unsigned int dist = 0, val = x ^ y;   
	// Count the number of set bits 
	while(val) 
	{ 
		++dist; 
		val &= val - 1; 
	}   
	return dist; 
} 

unsigned int hamdist2(unsigned char* a, unsigned char* b, size_t size) 
{ 
	HammingLUT lut;  
	unsigned int result;
	result = lut((a), (b), size); 
	return result; 
}  
这段代码是计算海明距离的,第一个函数计算了两个unsigned int类型数据的海明距离,与第二个函数的区别是,后者是计算两个unsigned char 类型数组之间总的距离。

ORB图像匹配_第1张图片




void naive_nn_search2(vector& keys1, Mat& descp1, vector& keys2, Mat& descp2, vector& matches) 
{ 
	for( int i = 0; i < (int)keys2.size(); i++)
	{
		unsigned int min_dist = INT_MAX; 
		unsigned int sec_dist = INT_MAX; 
		int min_idx = -1, sec_idx = -1;
		unsigned char* query_feat = descp2.ptr(i); 
		for( int j = 0; j < (int)keys1.size(); j++)
		{
			unsigned char* train_feat = descp1.ptr(j);
			unsigned int dist =  hamdist2(query_feat, train_feat, 32); 
			//最短距离
			if(dist < min_dist)
			{ 
				sec_dist = min_dist; 
				sec_idx = min_idx;
				min_dist = dist; 
				min_idx = j; 
			}
			//次短距离
			else if(dist < sec_dist)
			{ 
				sec_dist = dist; sec_idx = j; 
			} 
		}   
		if(min_dist <= (unsigned int)(sec_dist * 0.8) && min_dist <=50)
		{ 
			matches.push_back(DMatch(i, min_idx, 0, (float)min_dist)); 
		} 
	} 
}   

当满足最近距离与次近距离的比值小于80%且最短距离必须在一定范围内(50)时,就定义找到一个匹配点,存放在matchs里。

int main(int argc, char* argv[])
{
	
	Mat img1 = imread(image_filename1, 1); 
	Mat img2 = imread(image_filename2, 1); 
	//GaussianBlur(img1, img1, Size(5, 5), 0); 
	//GaussianBlur(img2, img2, Size(5, 5), 0);   
	ORB orb1(100 /*ORB::CommonParams(1.2, 1)*/); 
	ORB orb2(10 /*ORB::CommonParams(1.2, 1)*/);   
	vector keys1, keys2;
	Mat descriptors1, descriptors2;
	int64 st, et; 

	//提取ORB特征;
	orb1(img1, Mat(), keys1, descriptors1, false); 
	printf("tem feat num: %d\n", keys1.size());
	st = cvGetTickCount();
	orb2(img2, Mat(), keys2, descriptors2, false);
	et = cvGetTickCount(); 
	printf("orb2 extraction time: %f\n", (et-st)/(double)cvGetTickFrequency()/1000.); 
	printf("query feat num: %d\n", keys2.size());   

	// find matches 
	vector matches;   
	st = cvGetTickCount(); 
	for(int i = 0; i < 10; i++)
	{  
		naive_nn_search2(keys1, descriptors1, keys2, descriptors2, matches); 
	} 
	et = cvGetTickCount();   
	printf("match time: %f\n", (et-st)/(double)cvGetTickFrequency()/1000.); 
	printf("matchs num: %d\n", matches.size());   

	Mat showImg;  
	drawMatches(img2, keys2, img1, keys1, matches, showImg, CV_RGB(0, 255, 0), CV_RGB(0, 0, 255)); 
	string winName = "Matches"; 
	namedWindow( winName, WINDOW_AUTOSIZE ); 
	imshow( winName, showImg ); 
	waitKey(0);   
	
}

运行结果为:

ORB图像匹配_第2张图片


 

你可能感兴趣的:(ORB图像匹配)