NCC归一化相关匹配算法,这个时间比较久

原作者

对于非线性迭代优化方案,有多种方法可以获得初始猜测。最常见和公认的方法是快速归一化互相关(NCC)[4]。该方法使用公式5中的相关系数,并以计算效率高的方式计算当前配置中每个像素位置处的相关系数。它利用FFT计算分子中不可预计算的部分,然后利用求和面积表计算分母中不可预计算的部分。FFT可以通过获得参考子集内的灰度值,然后用与当前图像相同大小的零填充这些值来使用(参见图6的左下角)。在该过程的最后,获得一组相关系数;最高相关系数值的坐标将产生当前配置中子集的位置。需要注意的是,NCC方法只能确定整数位移(即整数u和v),因此不能为p中的其他四个参数提供初始猜测。因此,归一化互相关法最适合于在变形相对较低的区域(即没有大的旋转或应变)提供初始猜测。该过程如图6所示;有关NCC实施的更详细和更出色的处理见 ---J P Lewis, “Fast Normalized Cross-Correlation.” Industrial Light & Magic (1995). 。

#include <opencv2/opencv.hpp>

using namespace cv;

//纯粹的归一化相关匹配算法,没有用到任何提速手段,纯ncc函数运行时间大约在23秒左右

void ncc(Mat& srcImage, Mat& templImage, Mat& result)
{
	int rows = srcImage.rows - templImage.rows + 1;
	assert(templImage.rows <= srcImage.rows);
	int cols = srcImage.cols - templImage.cols + 1;
	assert(templImage.cols <= srcImage.cols);
	result.create(rows, cols, CV_32FC1);

	Mat src, templ;
	cvtColor(srcImage, src, COLOR_BGR2GRAY);
	cvtColor(templImage, templ, COLOR_BGR2GRAY);

	double sum_templ = 0.;
	for (int i = 0; i < templ.rows; i++)
	{
		uchar* templ_ptr = templ.ptr<uchar>(i);
		for (int j = 0; j < templ.cols; j++)
		{
			sum_templ += (double)(templ_ptr[j] * templ_ptr[j]);
		}
	}

	double num = 0., den = 0.;
	for (int i = 0; i < result.rows; i++)
	{
		float* result_ptr = result.ptr<float>(i);                       //因为result的类型是CV_32FC1,所以其对应的指针所指向的类型为float,用uchar和double都会出错
		for (int j = 0; j < result.cols; j++)
		{

			for (int m = 0; m < templ.rows; m++)
			{
				uchar* templ_ptr = templ.ptr<uchar>(m);
				uchar* src_ptr = src.ptr<uchar>(i+m);
				for (int n = 0; n < templ.cols; n++)
				{
					num += (double)(templ_ptr[n] * src_ptr[j + n]);
					den += (double)(src_ptr[j + n] * src_ptr[j + n]);
				}
			}
			result_ptr[j] = (float)(num / (sqrt(sum_templ)*sqrt(den)));
			num = 0.;
			den = 0.;
		}
	}
}

int main()
{
	Mat srcImage = imread("C:\\Users\\LIUU\\Pictures\\src.jpg");
	Mat templImage = imread("C:\\Users\\LIUU\\Pictures\\roi_1.jpg");

	double time = static_cast<double>(getTickCount());
	Mat resultMap;
	ncc(srcImage, templImage, resultMap);

	normalize(resultMap, resultMap, 0, 1,NORM_MINMAX);                 //一般归一化常用NORM_MINMAX,即将每个元素限制在一定范围内,但这个函数默认的模式是归一化二范数
	imshow("bb", resultMap);
	time = ((double)getTickCount() - time) / getTickFrequency();
	std::cout << time;                                                            //只记录ncc算法所花费的时间,对于我用的模板和原图,耗时23秒左右
	

	double minVal, maxVal;
	Point minPos, maxPos;
	minMaxLoc(resultMap, &minVal, &maxVal, &minPos, &maxPos);

	rectangle(srcImage, maxPos, Point(maxPos.x + templImage.cols, maxPos.y + templImage.rows),Scalar(0,0,255));
	imshow("aa", srcImage);
	waitKey(0);
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值