ELAS库计算双目视差图

news2025/5/28 3:05:40

ELAS源码下载:https://www.cvlibs.net/download.php?file=libelas.zip
代码结构目录
在这里插入图片描述
修改/src/main.cpp如下:

/*
Copyright 2011. All rights reserved.
Institute of Measurement and Control Systems
Karlsruhe Institute of Technology, Germany

This file is part of libelas.
Authors: Andreas Geiger

libelas is free software; you can redistribute it and/or modify it under the
terms of the GNU General Public License as published by the Free Software
Foundation; either version 3 of the License, or any later version.

libelas is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with
libelas; if not, write to the Free Software Foundation, Inc., 51 Franklin
Street, Fifth Floor, Boston, MA 02110-1301, USA 
*/

// Demo program showing how libelas can be used, try "./elas -h" for help

#include <iostream>
#include "elas.h"
#include "image.h"
#include<opencv2/core.hpp>
#include<opencv2/highgui.hpp>
#include<opencv2/videoio.hpp>
#include<opencv2/opencv.hpp>
#include<string>
#include "opencv2/imgproc/imgproc_c.h"

using namespace std;

// compute disparities of pgm image input pair file_1, file_2
void process (const char* file_1,const char* file_2) {

  cout << "Processing: " << file_1 << ", " << file_2 << endl;

  // load images
  image<uchar> *I1,*I2;
  I1 = loadPGM(file_1);
  I2 = loadPGM(file_2);

  // check for correct size
  if (I1->width()<=0 || I1->height() <=0 || I2->width()<=0 || I2->height() <=0 ||
      I1->width()!=I2->width() || I1->height()!=I2->height()) {
    cout << "ERROR: Images must be of same size, but" << endl;
    cout << "       I1: " << I1->width() <<  " x " << I1->height() << 
                 ", I2: " << I2->width() <<  " x " << I2->height() << endl;
    delete I1;
    delete I2;
    return;    
  }

  // get image width and height
  int32_t width  = I1->width();
  int32_t height = I1->height();

  // allocate memory for disparity images
  const int32_t dims[3] = {width,height,width}; // bytes per line = width
  float* D1_data = (float*)malloc(width*height*sizeof(float));
  float* D2_data = (float*)malloc(width*height*sizeof(float));

  // process
  Elas::parameters param;
  param.postprocess_only_left = false;
  Elas elas(param);
  elas.process(I1->data,I2->data,D1_data,D2_data,dims);

  // find maximum disparity for scaling output disparity images to [0..255]
  float disp_max = 0;
  for (int32_t i=0; i<width*height; i++) {
    if (D1_data[i]>disp_max) disp_max = D1_data[i];
    if (D2_data[i]>disp_max) disp_max = D2_data[i];
  }

  // copy float to uchar
  image<uchar> *D1 = new image<uchar>(width,height);
  image<uchar> *D2 = new image<uchar>(width,height);
  for (int32_t i=0; i<width*height; i++) {
    D1->data[i] = (uint8_t)max(255.0*D1_data[i]/disp_max,0.0);
    D2->data[i] = (uint8_t)max(255.0*D2_data[i]/disp_max,0.0);
  }

  // save disparity images
  char output_1[1024];
  char output_2[1024];
  strncpy(output_1,file_1,strlen(file_1)-4);
  strncpy(output_2,file_2,strlen(file_2)-4);
  output_1[strlen(file_1)-4] = '\0';
  output_2[strlen(file_2)-4] = '\0';
  strcat(output_1,"_disp.pgm");
  strcat(output_2,"_disp.pgm");
  savePGM(D1,output_1);
  savePGM(D2,output_2);

  // free memory
  delete I1;
  delete I2;
  delete D1;
  delete D2;
  free(D1_data);
  free(D2_data);
}

int main (int argc, char** argv) {

  // run demo
  if (argc==2 && !strcmp(argv[1],"demo")) {
    process("img/cones_left.pgm",   "img/cones_right.pgm");
    process("img/aloe_left.pgm",    "img/aloe_right.pgm");
    process("img/raindeer_left.pgm","img/raindeer_right.pgm");
    process("img/urban1_left.pgm",  "img/urban1_right.pgm");
    process("img/urban2_left.pgm",  "img/urban2_right.pgm");
    process("img/urban3_left.pgm",  "img/urban3_right.pgm");
    process("img/urban4_left.pgm",  "img/urban4_right.pgm");
    cout << "... done!" << endl;

  // compute disparity from input pair
  } else if (argc==3) {


    string argv1 = string(argv[1]);
    string argv2 = string(argv[2]);
    string extension1 = argv1.substr(argv1.find_last_of('.'), argv1.length());
    string extension2 = argv1.substr(argv2.find_last_of('.'), argv2.length());

    if (extension1 == ".pgm" || extension2 == ".pgm")
    {
      process(argv[1],argv[2]);
      cout << "... done!" << endl;

      string name = argv1.substr(argv1.find_last_of('/')+1, argv1.length());
      name = name.substr(0, name.find_last_of('.')) + "_disp";

      cv::Mat img = cv::imread("../img/" + name + ".pgm");
      cv::normalize(img, img, 0, 255, cv::NORM_MINMAX);
      cv::imshow("Disp Image window",img);
      cv::waitKey(0);
      cv::imwrite("../img/" + name + ".png", img);

    }
    else if (extension1 == ".png" || extension2 == ".png")
    {
      //参考:https://blog.csdn.net/dulingwen/article/details/104128503
      cv::Mat left = cv::imread(argv[1]);
      cv::Mat right = cv::imread(argv[2]);
      // cv::imshow("Left Image",left);
      // cv::imshow("Right Image",right);
      // cv::waitKey(0);
      if (left.size != right.size) 
      {
        cerr << "左右视图必须拥有相同的尺寸" << endl;
        return -1;
      }
      if (left.channels() == 3)
      cvtColor(left, left, cv::COLOR_RGB2GRAY);
	    if (right.channels() == 3)
      cvtColor(right, right, cv::COLOR_RGB2GRAY);

      int width = left.cols;
      int height = left.rows;
      int dim[3] = { width, height, width };
    
      cv::Mat disp_left = cv::Mat::zeros(cv::Size(width, height), CV_32FC1);
      cv::Mat disp_right = cv::Mat::zeros(cv::Size(width, height), CV_32FC1);
    
      // 参数设置	
      Elas::parameters param;
      param.disp_min = 0;                                     // 最小视差	
      param.disp_max = 256;                                // 最大视差	
      param.support_threshold = 0.85;              // 比率测试:最低match VS 次低match
      param.support_texture = 10;                     // 支持点的最小纹理
      param.candidate_stepsize = 5;                  // 用于支持点的sobel特征匹配的邻域半径
      param.incon_window_size = 5;                  // 不连续性窗口的尺寸
      param.incon_threshold = 5;                       // 不连续性窗口内的视差范围阈值
      param.incon_min_support = 5;                 // 不连续性窗口内的最低支持点数量
      param.add_corners = true;                        // 是否添加角点
      param.grid_size = 20;                                  // 网格尺寸
      param.beta = 0.02;                                      // 图像相似性度量的参数
      param.gamma = 3;                                      // 先验概率常数
      param.sigma = 1;                                         // 先验概率的标准差
      param.sradius = 3;                                       // 标准差半径
      param.match_texture = 1;                         // 最低纹理
      param.lr_threshold = 1;                             // 左右一致性检验阈值
      param.speckle_sim_threshold = 1;          // 连通域判断阈值
      param.speckle_size = 200;                        // 连通域噪声尺寸判断阈值
      param.ipol_gap_width = 3;                       // 空洞宽
      param.filter_median = false;                     // 是否中值滤波
      param.filter_adaptive_mean = true;        // 是否自适应中值滤波
      param.postprocess_only_left = true;     // 是否只对左视差图后处理,设置为True可以节省时间
      param.subsampling = false;                     // 每个两个像素进行视差计算,设置为True可以节省时间,但是传入的D1和D2的分辨率必须为(w/2) x (h/2)
    
      clock_t start = clock();
      Elas elas(param);
      elas.process(left.data, right.data, disp_left.ptr<float>(0), disp_right.ptr<float>(0), dim);
      clock_t end = clock();
      cout << "running time: " << (double)(1000 * (end - start) / CLOCKS_PER_SEC) << endl;
    
      disp_left = disp_left * 3;

      string name = argv1.substr(argv1.find_last_of('/')+1, argv1.length());
      name = name.substr(0, name.find_last_of('.')) + "_disp";
      cout << "../img/" + name + ".png" << endl;
      cv::imwrite("../img/" + name + ".png", disp_left);
      cout << "... done!" << endl;

    }

  // display help
  } else {
    cout << endl;
    cout << "ELAS demo program usage: " << endl;
    cout << "./elas demo ................ process all test images (image dir)" << endl;
    cout << "./elas left.pgm right.pgm .. process a single stereo pair" << endl;
    cout << "./elas -h .................. shows this help" << endl;
    cout << endl;
    cout << "Note: All images must be pgm greylevel images. All output" << endl;
    cout << "      disparities will be scaled such that disp_max = 255." << endl;
    cout << endl;
  }

  return 0;
}

打开终端

cd ~/Documents/projects/libelas/
mkdir build
cd /build
cmake ..
make

编译通过后

# 输入pgm格式图片得到的视差图
./elas ../img/cones_left.pgm ../img/cones_right.pgm

输入pgm格式图片得到的视差图

# 输入png格式图片得到的视差图
./elas ~/Documents/data/MyEuRoC/cam0/data/1694603839467.png ~/Documents/data/MyEuRoC/cam1/data/1694603839467.png 

请添加图片描述

参考:
[1] 双目立体匹配算法:ELAS
[2] VS2019下cmake项目:利用ELAS方法计算双目视差

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1010370.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

三分钟学会一个新技能——使用Java操作Redis

目录 1、前置准备操作 1.1、为什么要进行前置准备操作 1.2、本地如何访问到云服务上Redis的6379端口号 1.3、配置步骤&#xff1a; 2、配置后本地主机如何操作 3、常用命令举例 3.1、通用命令举例 3.2、string相关命令举例 3.3、hash相关命令举例 3.4、list相关命令…

Pytorch从零开始实战03

Pytorch从零开始实战——天气识别 本系列来源于365天深度学习训练营 原作者K同学 文章目录 Pytorch从零开始实战——天气识别环境准备数据集模型选择模型训练数据可视化总结 环境准备 本文基于Jupyter notebook&#xff0c;使用Python3.8&#xff0c;Pytorch2.0.1cu118&…

【Linux学习笔记】 - 常用指令学习及其验证(上)

前言&#xff1a;本文主要记录对Linux常用指令的使用验证。环境为阿里云服务器CentOS 7.9。关于环境如何搭建等问题&#xff0c;大家可到同平台等各大资源网进行搜索学习&#xff0c;本文不再赘述。 由于本人对Linux学习程度尚且较浅&#xff0c;本文仅介绍验证常用指令的常用…

Writesonic:博客和内容创作者的终极写作助手

【产品介绍】 产品名称 Writesonic 上线时间 成立于2020年 具体介绍 Writesonic是一个强大的人工智能写作助手&#xff0c;它使用自然语言处理&#xff08;NLP&#xff09;和机器学习算法来生成内容&#xff0c;这些内容不仅写得好&#xff0c;而且还为SEO和转…

MFC中嵌入显示opencv窗口

在MFC窗体中建立一个Picture Control控件,用于显示opencv窗口 在属性中设置图片控件的资源ID为IDC_PIC1 主要的思路: 使用GetWindowRect可以获取图片控件的区域 使用cv::resizeWindow可以设置opencv窗口的大小,适合图片控件的大小 使用cvGetWindowHandle函数可以获取到ope…

30天入门Python(基础篇)——第3天:【变量】与【输出】与【转义符】(万字解析,建议收藏)

文章目录 专栏导读作者有话说&#xff1a;上一节课补充(Pychaem界面认识)①编写代码区域②运行代码&#xff08;多种方法&#xff0c;随便选一种&#xff0c;开心就好&#xff09; 什么是变量&#xff08;变量的定义&#xff09;①较标准的回答(引用AI)②大白话解释图文并茂(我…

嵌入式Linux驱动开发(I2C专题)(一)

一、I2C协议 1.1、硬件连接 I2C在硬件上的接法如下所示&#xff0c;主控芯片引出两条线SCL,SDA线&#xff0c;在一条I2C总线上可以接很多I2C设备。 1.2、IIC传输数据的格式 1.2.1、写操作 流程如下&#xff1a; 主芯片要发出一个start信号然后发出一个设备地址(用来确定是…

Java作业-模拟扎金花

要求 实现扑克牌的创建、洗牌、发牌、大小对比&#xff0c;输出赢家牌。 前提条件 首先需要创建三个集合&#xff0c;用于存储牌面值、牌号与比较规则&#xff0c;再创建一个类作为牌。 其次还需要了解到一个工具类&#xff0c;就是Collections类&#xff0c;该类的所有方法…

python,迪卡尔象限中画点

import numpy as np import matplotlib.pyplot as plt circleNum 30 # 同时圆刻度值 pointNum 20 # 点的数量 theta np.linspace(0.0, 2*np.pi, pointNum, endpointFalse) s circleNum * np.random.rand(pointNum) # plt.polar(theta, s, linestyleNone, marker*) # 无连接…

不知道有用没用的Api

encodeURIComponent(https://www.baidu.com/?name啊啊啊) decodeURIComponent(https%3A%2F%2Fwww.baidu.com%2F%3Fname%3D%E5%95%8A%E5%95%8A%E5%95%8A) encodeURI(https://www.baidu.com/?name啊啊啊) decodeURI(https://www.baidu.com/?name%E5%95%8A%E5%95%8A%E5%95%8A) …

​LeetCode解法汇总1222. 可以攻击国王的皇后

目录链接&#xff1a; 力扣编程题-解法汇总_分享记录-CSDN博客 GitHub同步刷题项目&#xff1a; https://github.com/September26/java-algorithms 原题链接&#xff1a;力扣&#xff08;LeetCode&#xff09;官网 - 全球极客挚爱的技术成长平台 描述&#xff1a; 在一个 8x…

解决虚拟机重启后ifconfig看不到IP的问题

目录 背景 解决方案 背景 虚拟机&#xff0c;桥接模式&#xff0c;启动后一切正常&#xff0c;但重启后发现终端连不上虚机了&#xff0c;也ping不到&#xff0c;最后检查发现&#xff0c;IP消失了&#xff0c;虚机没有IP了。 解决方案 不论是否重启&#xff0c;只要是看不…

2023-09-14 LeetCode每日一题(可以攻击国王的皇后)

2023-09-14每日一题 一、题目编号 1222. 可以攻击国王的皇后二、题目链接 点击跳转到题目位置 三、题目描述 在一个 8x8 的棋盘上&#xff0c;放置着若干「黑皇后」和一个「白国王」。 给定一个由整数坐标组成的数组 queens &#xff0c;表示黑皇后的位置&#xff1b;以及…

关于浅克隆和深克隆入门理解

浅克隆:需要类实现Cloneable,并重写clone()方法 一般在重写clone()方法时,将返回值类型强转为自己类,避免每次克隆之后需要强转 public class Test {public static void main(String[] args) throws CloneNotSupportedException {A a1new A();A a2 a1.clone();//克隆之后 a1…

【搭建私人图床】本地PHP搭建简单Imagewheel云图床,在外远程访问

文章目录 1.前言2. Imagewheel网站搭建2.1. Imagewheel下载和安装2.2. Imagewheel网页测试2.3.cpolar的安装和注册 3.本地网页发布3.1.Cpolar临时数据隧道3.2.Cpolar稳定隧道&#xff08;云端设置&#xff09;3.3.Cpolar稳定隧道&#xff08;本地设置&#xff09; 4.公网访问测…

Linux——(第十章)进程管理

目录 一、概述 二、常用指令 1.ps查看当前系统进程状态 2.kill 终止进程 3.pstree 查看进程树 4.top 实时监控系统进程状态 5.netstat 监控网络状态 一、概述 &#xff08;1&#xff09;进程是正在执行的一个程序或命令&#xff0c;每一个进程都是一个运行的实体&#…

Redis 常用命令

目录 全局命令 1&#xff09;keys 2&#xff09;exists 3) del(delete) 4&#xff09;expire 5&#xff09;type SET命令 GET命令 MSET 和 MGET命令 其他SET命令 计数命令 redis-cli&#xff0c;进入redis 最核心的命令&#xff1a;我们这里只是先介绍 set 和 get 最简单的操作…

IP地址,子网掩码,默认网关,DNS讲解

IP地址&#xff1a;用来标识网络中一个个主机&#xff0c;IP有唯一性&#xff0c;即每台机器的IP在全世界是唯一的。 子网掩码&#xff1a;用来判断任意两台计算机的ip地址是否属于同一子网络的根据。最为简单的理解就是两台计算机各自的ip地址与子网掩码进行and运算后&#x…

常用排序算法

一、插入排序1、直接插入排序2、折半插入排序3、希尔排序 二、交换排序1、冒泡排序2、快速排序 三、选择排序1、简单选择排序2、堆排序&#xff08;1&#xff09;调整堆&#xff08;2&#xff09;创建堆 四、归并排序五、基数排序六、各种排序方法的比较 将一组杂乱无章的数据按…

Zookeeper应用场景和底层设计

一、什么是zookeeper Zookeeper是一个开源的分布式协调服务框架&#xff0c;它是服务于其它集群式框架的框架。 【简言之】 有一个服务A&#xff0c;以集群的方式提供服务。只需要A专注于它提供的服务就可以&#xff0c;至于它如何以多台服务器协同完成任务的事情&#xff0c…