双目立体视觉匹配算法-----SAD匹配算法、BM算法、SGBM算法、GC算法_liulina603的博客-程序员信息网_stereobm算法原理

技术标签: 双目  

一、 SAD算法

1.算法原理
        SAD(Sum of absolute differences)是一种图像匹配算法。基本思想:差的绝对值之和。此算法常用于图像块匹配,将每个像素对应数值之差的绝对值求和,据此评估两个图像块的相似度该算法快速、但并不精确通常用于多级处理的初步筛选。
2.基本流程

输入:两幅图像,一幅Left-Image,一幅Right-Image

对左图,依次扫描,选定一个锚点:

(1)构造一个小窗口,类似于卷积核;
(2)用窗口覆盖左边的图像,选择出窗口覆盖区域内的所有像素点;
(3)同样用窗口覆盖右边的图像并选择出覆盖区域的像素点;
(4)左边覆盖区域减去右边覆盖区域,并求出所有像素点灰度差的绝对值之和;
(5)移动右边图像的窗口,重复(3)-(4)的处理(这里有个搜索范围,超过这个范围跳出);
(6)找到这个范围内SAD值最小的窗口,即找到了左图锚点的最佳匹配的像素块。


参考代码: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];
					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;
}

二、BM算法:速度很快,效果一般

SGBM算法 Stereo Processing by Semiglobal Matching and Mutual Information

GC算法 算法文献:Realistic CG Stereo Image Dataset with Ground Truth Disparity Maps

参考:http://blog.csdn.net/wqvbjhc/article/details/6260844

void BM()
{
  IplImage * img1 = cvLoadImage("left.png",0);
    IplImage * img2 = cvLoadImage("right.png",0);
    CvStereoBMState* BMState=cvCreateStereoBMState();
    assert(BMState);
    BMState->preFilterSize=9;
    BMState->preFilterCap=31;
    BMState->SADWindowSize=15;
    BMState->minDisparity=0;
    BMState->numberOfDisparities=64;
    BMState->textureThreshold=10;
    BMState->uniquenessRatio=15;
    BMState->speckleWindowSize=100;
    BMState->speckleRange=32;
    BMState->disp12MaxDiff=1;

    CvMat* disp=cvCreateMat(img1->height,img1->width,CV_16S);
    CvMat* vdisp=cvCreateMat(img1->height,img1->width,CV_8U);
    int64 t=getTickCount();
    cvFindStereoCorrespondenceBM(img1,img2,disp,BMState);
    t=getTickCount()-t;
    cout<<"Time elapsed:"<<t*1000/getTickFrequency()<<endl;
    cvSave("disp.xml",disp);
    cvNormalize(disp,vdisp,0,255,CV_MINMAX);
    cvNamedWindow("BM_disparity",0);
    cvShowImage("BM_disparity",vdisp);
    cvWaitKey(0);
    //cvSaveImage("cones\\BM_disparity.png",vdisp);
    cvReleaseMat(&disp);
    cvReleaseMat(&vdisp);
    cvDestroyWindow("BM_disparity");
}


三、SGBM算法

作为一种全局匹配算法,立体匹配的效果明显好于局部匹配算法,但是同时复杂度上也要远远大于局部匹配算法。算法主要是参考Stereo Processing by Semiglobal Matching and Mutual Information。

opencv中实现的SGBM算法计算匹配代价没有按照原始论文的互信息作为代价,而是按照块匹配的代价。

参考:http://www.opencv.org.cn/forum.php?mod=viewthread&tid=23854

#include <highgui.h>
#include <cv.h>
#include <cxcore.h>
#include <iostream>
using namespace std;
using namespace cv;
int main()
{

    IplImage * img1 = cvLoadImage("left.png",0);
    IplImage * img2 = cvLoadImage("right.png",0);
    cv::StereoSGBM sgbm;
    int SADWindowSize = 9;
    sgbm.preFilterCap = 63;
    sgbm.SADWindowSize = SADWindowSize > 0 ? SADWindowSize : 3;
    int cn = img1->nChannels;
    int numberOfDisparities=64;
    sgbm.P1 = 8*cn*sgbm.SADWindowSize*sgbm.SADWindowSize;
    sgbm.P2 = 32*cn*sgbm.SADWindowSize*sgbm.SADWindowSize;
    sgbm.minDisparity = 0;
    sgbm.numberOfDisparities = numberOfDisparities;
    sgbm.uniquenessRatio = 10;
    sgbm.speckleWindowSize = 100;
    sgbm.speckleRange = 32;
    sgbm.disp12MaxDiff = 1;
    Mat disp, disp8;
    int64 t = getTickCount();
    sgbm((Mat)img1, (Mat)img2, disp);
    t = getTickCount() - t;
    cout<<"Time elapsed:"<<t*1000/getTickFrequency()<<endl;
    disp.convertTo(disp8, CV_8U, 255/(numberOfDisparities*16.));

    namedWindow("left", 1);
    cvShowImage("left", img1);
    namedWindow("right", 1);
    cvShowImage("right", img2);
    namedWindow("disparity", 1);
    imshow("disparity", disp8);
    waitKey();
    imwrite("sgbm_disparity.png", disp8);   
    cvDestroyAllWindows();
    return 0;
}


四、GC算法 效果最好,速度最慢


void GC()
{
    IplImage * img1 = cvLoadImage("left.png",0);
    IplImage * img2 = cvLoadImage("right.png",0);
    CvStereoGCState* GCState=cvCreateStereoGCState(64,3);
    assert(GCState);
    cout<<"start matching using GC"<<endl;
    CvMat* gcdispleft=cvCreateMat(img1->height,img1->width,CV_16S);
    CvMat* gcdispright=cvCreateMat(img2->height,img2->width,CV_16S);
    CvMat* gcvdisp=cvCreateMat(img1->height,img1->width,CV_8U);
    int64 t=getTickCount();
    cvFindStereoCorrespondenceGC(img1,img2,gcdispleft,gcdispright,GCState);
    t=getTickCount()-t;
    cout<<"Time elapsed:"<<t*1000/getTickFrequency()<<endl;
    //cvNormalize(gcdispleft,gcvdisp,0,255,CV_MINMAX);
    //cvSaveImage("GC_left_disparity.png",gcvdisp);
    cvNormalize(gcdispright,gcvdisp,0,255,CV_MINMAX);
    cvSaveImage("GC_right_disparity.png",gcvdisp);


    cvNamedWindow("GC_disparity",0);
    cvShowImage("GC_disparity",gcvdisp);
    cvWaitKey(0);
    cvReleaseMat(&gcdispleft);
    cvReleaseMat(&gcdispright);
    cvReleaseMat(&gcvdisp);
}



版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/liulina603/article/details/53302168

智能推荐

CentOS7配置Nginx服务_weixin_34270865的博客-程序员信息网

为什么80%的码农都做不了架构师?&gt;&gt;&gt; ...

阿里逆天级调优方案,内部这套Java性能调优实战宝典,堪称教科书_倾听铃的声的博客-程序员信息网

随着互联网的发展,高可靠、高并发以及降本增效,已成为各大公司面临的现实挑战,性能优化需求愈发迫切,大到分布式系统,小到代码块的算法优化,都已经成为你日常工作中必须要面对的事情。对于开发者而言,性能优化也从加分项变为一个热门技能,缺乏相关知识将很难在面试或工作中脱颖而出。俗话说,知己知彼百战百胜,想要克服“性能优化”这一难题,先要了解性能优化的特点,并抓住其关键和本质。作为面试必考内容,很多应聘者反映说面试官的一些问题会让其陷入模棱两可的境地,不知如何作答,比如很多人就搞不懂缓冲与缓存的区别。这种问题

NSFileManager文件和文件夹的操作_chase_cc的博客-程序员信息网

NSFileManager的文件操作上面中简单的介绍了数据存储,但是在获取数据,要存储时,一般需要创建一个单独的文件或者文件夹报保存你要存储的数据,所以要介绍一下NSFileManager,这个很重要,在日常开发中会经常使用到这个类NSFileManager用法NSFileManager使用了单例模式使用defaultManager方法可以获得那个单例对象 objc [NSFileMa...

黑马程序员-File类的常见方法及使用_Sily孤狼的博客-程序员信息网

------- android培训、java培训、期待与您交流! ----------

【环境配置】win10下通过Anaconda安装tensorflow、keras(主要是报错解答)_初出茅庐的程序媛的博客-程序员信息网

【主要分享配置环境中参考的写的比较好的博客,以及问题解答】最近开始研究GAN网络,所以第一步当然还是配置环境的问题。windows下安装tensorflow的步骤有很多,还算简单,一步一步做就好,主要问题就是版本问题,通过一天的安装-卸载-安装,过来人劝大家不要安装最新的版本,否则错误咋解决都不知道!1、安装Anaconda,然后安装tensorflow,参考下面这个链接,基本无雷ht...

网站建设-数据库纵向扩展_吃素的小动物的博客-程序员信息网

对于大型的网站建设,我们之前已经说了如何根据服务器负载量来横向扩展数据库。抛开关于面向服务(SOA)和面向资源(ROA)概念的争论,深入了解它们的基本前提就会发现,至少它们都有一个共同点,都要求架构师和程序员考虑架构中的职责拆分。大体上就是采用动词(服务)和名词(资源)的概念来实现拆分。 首先,我们先看看怎么用动词拆分网站。如果我们的网站是相对简单的电子商务网站,那么可以用动词吧...

随便推点

springboot导包显示不存在_使用spring boot启动项目,死活找不到包,spring boot 扫描原理..._喻毅嘉的博客-程序员信息网

平时spring boot 都是自动扫描,没有注意,当项目分多个工程,并且包名变化后,就遇到找不到Bean的问题了,这时就想起来spring boot扫描的原理了经在网上查找发现:SpringBoot项目的Bean装配默认规则是根据Application类所在的包位置从上往下扫描! “Application类”是指SpringBoot项目入口类。这个类的位置很关键:如果Application类所在...

解决安装了keras报错no moudle ‘keras’_王壹浪的博客-程序员信息网_为什么安装了keras还是报错

安装完了之后更新一下:pip install --upgrade Keras 更新再安装一下:python -m pip install keras 安装问题解决。

自动化测试资料整理包括(python、appium、selenium、RF)_黑夜照亮前行的路的博客-程序员信息网_自动化测试资料

Python教程http://www.liaoxuefeng.com/wiki/001374738125095c955c1e6d8bb493182103fac9270762a000Appium:http://appium.io/slate/en/master/#Appium 中文 Appium API 文档 https://testerhome.com/topics/3144

Linux笔记(二): WIN 10 Ubuntu 双系统_anbipan1507的博客-程序员信息网

(一) 说明记录一次ubuntu安装过程及遇到的问题。环境:WIN 10 单硬盘(二) ubuntu ISO文件下载ubuntu 18.04https://www.ubuntu.com/download/desktopubuntu 官网历史版本下载http://releases.ubuntu.com/?_ga=2.124103118.558040255.1...

华为云桌面---cloudclient安装使用_渊博苑的博客-程序员信息网_cloudclient

今天被华为的人鄙视了,说你都不知道cloudclient?第一次使用华为FusionCompute被华为的深深鄙视了,妈的隔壁我说大哥,给个下载链接吧,被无情回复没有……于是乎,我很不服气的自力更生把问题解决了,特此记录一下。https://obs.myhwclouds.com/obs-workspace-share/AccessClient.msi下载软件,双击运行就行了。这个时候桌面就出现了cloud client然后就开始了愉快的华为云使用了……...

对Hibernate Session做一个简单的包装_Suspend的博客-程序员信息网

在谈包装之前,我们先看一看以下几个论断: 牛人们都说dao是反模式,认为需要取消dao。 以前写个dao,需要一个DAO的基类、spring的注入、泛型,甚至要声明一个dao的接口,比较繁琐。  大多数情况下,我认为我们需要一个简单的实现,既不要程序员为了处理数据,声明dao的实现,做很多事情,又能比较方便的实现对数据操作的解耦。JPA的EntityManager提供了一个很好的例...

推荐文章

热门文章

相关标签