四种Block Match算法

块匹配Block Match算法常用于双目立体匹配和帧间距离匹配上,特点是实现步骤简单,这里介绍四种基本的Block Match算法:

1.Sum of Absolute Differencse(sad)公式如下:


C++实现代码:

Mat funcSADR2L(Mat leftImage, Mat rightImage, int windowSize, int dispMin, int dispMax, int STEP = 1)
{
	CV_Assert(leftImage.rows == rightImage.rows && leftImage.cols == rightImage.cols);
	CV_Assert(windowSize % 2 == 1);
	CV_Assert(dispMax > dispMin);
	int nrLeft = leftImage.rows - 1;
	int ncLeft = leftImage.cols - 1;
	int win = (windowSize - 1) / 2;
	Mat dispMap = Mat::zeros(nrLeft, ncLeft, CV_8UC1);
	for (int i = 0 + win; i <= nrLeft - win; i = i + STEP)
	{
		for (int j = 0 + win; j <= ncLeft - win - dispMax; j = j+STEP)
		{
			double prevSAD = 65532;
			double temp = 0.0;
			int bestMatchSoFar = dispMin;
			for (int dispRange = dispMin; dispRange <= dispMax; dispRange++)
			{
				double sad = 0.0;
				for (int a = -win; a <= win; a++)
				{
					for (int b = -win; b <= win; b++)
					{
						if (j + b + dispRange <= ncLeft)
						{
							temp = (double)rightImage.at<uchar>(i + a, j + b) - (double)leftImage.at<uchar>(i + a, j + b + dispRange);
							if (temp < 0.0)
							{
								temp = temp*(-1.0);
							}
							sad = sad + temp;
						}
					}
				}
				if (prevSAD > sad)
				{
					prevSAD = sad;
					bestMatchSoFar = dispRange;
				}
			}
			dispMap.at<uchar>(i, j) = bestMatchSoFar;
		}
	}
	normalize(dispMap, dispMap, 0, 255, CV_MINMAX);
	return dispMap;
}

2.Sum of Squared Differences(ssd)公式如下:


C++实现代码:

Mat funcSSDR2L(Mat leftImage, Mat rightImage, int windowSize, int dispMin, int dispMax, int STEP = 1)
{
	CV_Assert(leftImage.rows == rightImage.rows && leftImage.cols == rightImage.cols);
	CV_Assert(windowSize % 2 == 1);
	CV_Assert(dispMax > dispMin);
	int nrLeft = leftImage.rows - 1;
	int ncLeft = leftImage.cols - 1;
	int win = (windowSize - 1) / 2;
	Mat dispMap = Mat::zeros(nrLeft, ncLeft, CV_8UC1);
	for (int i = 0 + win; i <= nrLeft - win; i = i + STEP)
	{
		for (int j = 0 + win; j <= ncLeft - win - dispMax; j = j + STEP)
		{
			double prevSDD = 65532;
			double temp = 0.0;
			int bestMatchSoFar = dispMin;
			for (int dispRange = dispMin; dispRange <= dispMax; dispRange++)
			{
				double ssd = 0.0;
				for (int a = -win; a <= win; a++)
				{
					for (int b = -win; b <= win; b++)
					{
						if (j + b + dispRange <= ncLeft)
						{
							temp = (double)rightImage.at<uchar>(i + a, j + b) - (double)leftImage.at<uchar>(i + a, j + b + dispRange);
							temp = temp*temp;
							ssd = ssd + temp;
						}
					}
				}
				if (prevSDD > ssd)
				{
					prevSDD = ssd;
					bestMatchSoFar = dispRange;
				}
			}
			dispMap.at<uchar>(i, j) = bestMatchSoFar;
		}
	}
	normalize(dispMap, dispMap, 0, 255, CV_MINMAX);
	return dispMap;
}

3.Sum of Hamming Distances(shd)公式如下:


bit()的含义是像素转为二进制后含有多少个1,整个公式意思就是两张局部图先异或一下,然后统计所有像素二进制化后1的个数,取最少的那个就行了。

c++实现代码:

Mat funcSHDR2L(Mat leftImage, Mat rightImage, int windowSize, int dispMin, int dispMax,int STEP = 1)
{
	CV_Assert(leftImage.rows == rightImage.rows && leftImage.cols == rightImage.cols);
	CV_Assert(windowSize % 2 == 1);
	CV_Assert(dispMax > dispMin);
	int nrLeft = leftImage.rows - 1;
	int ncLeft = leftImage.cols - 1;
	int win = (windowSize - 1) / 2;
	Mat dispMap = Mat::zeros(nrLeft, ncLeft, CV_8UC1);
	for (int i = 0 + win; i <= nrLeft - win; i = i + STEP)
	{
		for (int j = 0 + win; j <= ncLeft - win - dispMax; j = j + STEP)
		{
			int min = 0;
			int position = 0;
			Rect rightRect = Rect(j - win, i - win, 2 * win + 1, 2 * win + 1);
			Mat rightWindow = rightImage(rightRect);
			for (int dispRange = dispMin; dispRange <= dispMax; dispRange++)
			{
				if (j + win + dispRange <= ncLeft)
				{
					Rect leftRect = Rect(j - win + dispRange, i - win, 2 * win + 1, 2 * win + 1);
					Mat leftWindow = leftImage(leftRect);
					Mat bloc3 = Mat::zeros(leftWindow.rows, leftWindow.cols, CV_8UC1);
					for (int m = 0; m < leftWindow.rows; m++)
					{
						for (int n = 0; n < leftWindow.cols; n++)
						{
							bloc3.at<uchar>(m, n) = leftWindow.at<uchar>(m, n) ^ rightWindow.at<uchar>(m, n);
						}
					}
					int dis = 0;
					for (int m = 0; m < leftWindow.rows; m++)
					{
						for (int n = 0; n < leftWindow.cols; n++)
						{
							dis += BitCount(bloc3.at<uchar>(m, n));
						}
					}
					if (dispRange == 0)
						min = dis;
					else if (min > dis)
					{
						min = dis;
						position = dispRange;
					}
				}
			}
			dispMap.at<uchar>(i, j) = position;
		}
	}
	normalize(dispMap, dispMap, 0, 255, CV_MINMAX);
	return dispMap;
}

4.Normalized Cross Correlation(ncc)公式如下:

c++实现代码:

Mat funcNCCR2L(Mat leftImage, Mat rightImage, int windowSize, int dispMin, int dispMax, int STEP = 1)
{
	CV_Assert(leftImage.rows == rightImage.rows && leftImage.cols == rightImage.cols);
	CV_Assert(windowSize % 2 == 1);
	CV_Assert(dispMax > dispMin);
	int nrLeft = leftImage.rows - 1;
	int ncLeft = leftImage.cols - 1;
	int win = (windowSize - 1) / 2;
	Mat dispMap = Mat::zeros(nrLeft, ncLeft, CV_8UC1);

	for (int i = 0 + win; i <= nrLeft - win; i = i + STEP)
	{
		for (int j = 0 + win; j <= ncLeft - win - dispMax; j = j + STEP)
		{
			double prevNCC = 0.0;
			int bestMatchSoFar = dispMin;
			for (int dispRange = dispMin; dispRange <= dispMax; dispRange++)
			{
				double ncc = 0.0;
				double nccNumberator = 0.0;
				double nccDenominator = 0.0;
				double nccDenominatorRightWindow = 0.0;
				double nccDenominatorLeftWindow = 0.0;
				for (int a = -win; a <= win; a++)
				{
					for (int b = -win; b <= win; b++)
					{
						nccNumberator += rightImage.at<uchar>(i + a, j + b)*leftImage.at<uchar>(i + a, j + b + dispRange);
						nccDenominatorRightWindow += rightImage.at<uchar>(i + a, j + b)*rightImage.at<uchar>(i + a, j + b);
						nccDenominatorLeftWindow += leftImage.at<uchar>(i + a, j + b + dispRange)*leftImage.at<uchar>(i + a, j + b + dispRange);
					}
				}
				nccDenominator = sqrt(nccDenominatorRightWindow*nccDenominatorLeftWindow);
				ncc = nccNumberator / nccDenominator;
				if (prevNCC < ncc)
				{
					prevNCC = ncc;
					bestMatchSoFar = dispRange;
				}
			}
			dispMap.at<uchar>(i, j) = bestMatchSoFar;
		}
	}
	normalize(dispMap, dispMap, 0, 255, CV_MINMAX);
	return dispMap;
}


  • 3
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值