SAD算法原理及其实现

一。算法原理。

   SAD(Sum of absolute differences)是图像立体匹配中常用的初级块匹配算法,其基本运算思想是求取相对应的左右两个像素块内像素值之差的绝对值之和。

二。计算流程。

前期准备:某物体在同一时刻左右相机拍摄得到的左右图像。left_image,right_image.

!!!强调一点:在进行立体匹配之前,两幅图像处于经过立体校正之后的行对准状态。

(1)设定SAD窗口的大小,left_image中开始匹配的位置,(p,q)以及在right_image中SAD窗口移动的范围D。

(2)在left_image图像中,确定待匹配的像素点的位置(x,y),并以此位置作为SAD窗口的锚点,用SAD窗口覆盖left_image中以(x,y)为锚点的区域regionl。

(3)在right_image图像中,选取匹配的开始点,位置为(m,n),并以该点作为SAD窗口的锚点,用SAD窗口去覆盖,在right_iamge中形成以(m,n)为锚点的图像区域regionr.

(4)定义differernce=regionr-regionl。计算difference中的和。

(5)在right_image图像中沿行方向移动SAD(移动次数为匹配的范围大小),重复步骤(3),(4),并将每次得到的difference记录在mat矩阵中。

(6)找到mat矩阵中difference最小的值,则其所在位置就是right_image和left_image的视差。

三。代码实现

SAD.h
#include"iostream"
#include"opencv2/opencv.hpp"
#include"iomanip"
using namespace std;
using namespace cv;
 
class SAD
{
	public:
		SAD():winSize(7),DSR(30){}
		SAD(int _winSize,int _DSR):winSize(_winSize),DSR(_DSR){}
		Mat computerSAD(Mat &L,Mat &R); //计算SAD
	private:
		int winSize; //卷积核的尺寸
		int DSR;     //视差搜索范围
	
};
 
 Mat SAD::computerSAD(Mat &L,Mat &R)
	{
		int Height=L.rows;
	    int Width=L.cols;
		Mat Kernel_L(Size(winSize,winSize),CV_8U,Scalar::all(0));
	    Mat Kernel_R(Size(winSize,winSize),CV_8U,Scalar::all(0));
	    Mat Disparity(Height,Width,CV_8U,Scalar(0)); //视差图
 
/*实际匹配时,左图没有从最左侧区域开始,是因为在实际应用中,物体在左右两幅图像中,左边图像相对于右侧的图像而言,更靠近图像的左侧区域。这样会造成左侧的图像的最左侧区域在右图像中找不到实际的匹配点。*/	
for(int i=0;i<Width-winSize;i++)  //左图从DSR开始遍历
		{
			for(int j=0;j<Height-winSize;j++)
			{
				Kernel_L=L(Rect(i,j,winSize,winSize));
			    Mat MM(1,DSR,CV_32F,Scalar(0)); //
 
				for(int k=0;k<DSR;k++)
				{
					int x=i-k;
					if(x>=0)
					{
					Kernel_R=R(Rect(x,j,winSize,winSize));
					Mat Dif;
			        absdiff(Kernel_L, Kernel_R, Dif);//
					Scalar ADD=sum(Dif);
					float a=ADD[0];
				//以视差作为Dif的位置标记,下一步通过查找最小Dif的位置即可得到视差。
                    MM.at<float>(k)=a;
					}
					
				}
				Point minLoc;
                minMaxLoc(MM, NULL, NULL,&minLoc,NULL);
			    
				int loc=minLoc.x;//视差值。
				//int loc=DSR-loc;
				Disparity.at<char>(j,i)=loc*16;
				
			}
			double rate=double(i)/(Width);
			cout<<"已完成"<<setprecision(2)<<rate*100<<"%"<<endl; //处理进度
		}
		return Disparity;
	}




// MySAD.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include"SAD.h"
int _tmain(int argc, _TCHAR* argv[])
{
	Mat Img_L=imread("imL.png",0);
	Mat Img_R=imread("imR.png",0);
    Mat Disparity;    //视差图
    
	//SAD mySAD;
	SAD mySAD(7,30);
	Disparity=mySAD.computerSAD(Img_L,Img_R);
 
	imshow("Img_L",Img_L);
	imshow("Img_R",Img_R);
	imshow("Disparity",Disparity);
	waitKey();
	return 0;
}

实际处理效果如下:

参考链接:https://blog.csdn.net/liulina603/article/details/53302168

  • 8
    点赞
  • 75
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
C++实现SAD(Sum of Absolute Differences)算法的步骤如下: 1. 读取原始图像和模板图像,并将它们转换为灰度图像。 2. 定义模板的大小,即要在原始图像中匹配的模板的大小。 3. 在原始图像上滑动模板,计算每个模板和原始图像匹配区域的SAD值。 4. 找到SAD值最小的匹配区域,即为找到的模板位置。 下面是一个简单的示例代码,演示如何实现SAD算法: ```c++ #include <iostream> #include <opencv2/opencv.hpp> using namespace cv; using namespace std; int main() { Mat srcImage = imread("original.jpg", IMREAD_GRAYSCALE); Mat tplImage = imread("template.jpg", IMREAD_GRAYSCALE); // 定义模板的大小 int tplWidth = tplImage.cols; int tplHeight = tplImage.rows; // 在原始图像上滑动模板,计算每个模板和原始图像匹配区域的SAD值 double minSAD = DBL_MAX; int minX = 0, minY = 0; for (int y = 0; y < srcImage.rows - tplHeight; y++) { for (int x = 0; x < srcImage.cols - tplWidth; x++) { double SAD = 0; for (int j = 0; j < tplHeight; j++) { for (int i = 0; i < tplWidth; i++) { SAD += abs(srcImage.at<uchar>(y+j, x+i) - tplImage.at<uchar>(j, i)); } } if (SAD < minSAD) { minSAD = SAD; minX = x; minY = y; } } } // 找到SAD值最小的匹配区域,即为找到的模板位置 Point matchLoc(minX, minY); rectangle(srcImage, matchLoc, Point(minX + tplWidth, minY + tplHeight), Scalar(0, 0, 255), 2, 8, 0); imshow("Match result", srcImage); waitKey(0); return 0; } ``` 在上面的示例代码中,我们首先读取了原始图像和模板图像,并将它们转换为灰度图像。然后,我们定义了模板的大小,并在原始图像上滑动模板,计算每个模板和原始图像匹配区域的SAD值。最后,找到SAD值最小的匹配区域,即为找到的模板位置。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值