matlab opencv 计算视差disparity

0.前言 
视差与深度的关系戳这里。在opencv里应该有三种求视差的方法和一些问题集锦,可参考:http://blog.csdn.net/chenyusiyuan/article/details/5967291/ 
1.代码

void saveDisp(const char* filename, Mat mat);
int main()
{
    char* filename = "../disparity_value.txt";

    Mat left = imread("../image/left_199.png",CV_LOAD_IMAGE_GRAYSCALE);
    Mat right = imread("../image/right_199.png",CV_LOAD_IMAGE_GRAYSCALE);
    double t = (double)getTickCount();
    Mat disp;
    StereoBM bm;  
    CvStereoBMState *BMState = cvCreateStereoBMState();
    bm.state->SADWindowSize = 15;  
    bm.state->minDisparity = 0;  
    bm.state->numberOfDisparities = 80;  
    bm.state->textureThreshold = 10;  
    bm.state->uniquenessRatio = 8;  
    bm.state->speckleWindowSize = 10;  
    bm.state->speckleRange = 32;  
    bm.state->disp12MaxDiff = -1;  
    /*防止左侧黑边*/
    copyMakeBorder(left, left, 0, 0, 80, 0, IPL_BORDER_REPLICATE);  
    copyMakeBorder(right, right, 0, 0, 80, 0, IPL_BORDER_REPLICATE);  

    bm.operator()(left,right,disp,CV_32F);
    disp = disp.colRange(80, left.cols);  

    t = ((double)getTickCount() - t)/getTickFrequency();
    cout<<"time:"<<t<<endl;
    imshow("disp",disp);
    saveDisp(filename,disp);
    cvWaitKey(0);
    return 0;
}

/**
将视差保存到txt,用于MATLAB读取
**/
void saveDisp(const char* filename,  Mat mat)       
{
    int ih = mat.type();
    //float disp = mat.at<float>(0,0); 
    FILE* fp = fopen(filename, "wt");
    fprintf(fp, "%02d\n", mat.rows);
    fprintf(fp, "%02d\n", mat.cols);
    for(int y = 0; y < mat.rows; y++)
    {
        for(int x = 0; x < mat.cols; x++)
        {
            float disp = mat.at<float>(y, x); // 这里视差矩阵是CV_16S 格式的,故用 short 类型读取
            fprintf(fp, "%f\n", disp); // 若视差矩阵是 CV_32F 格式,则用 float 类型读取
        }
    }
    fclose(fp);
}
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
相应的Matlab代码为:
function img = txt2img(filename)
data = importdata(filename);
r = data(1);    % 行数
c = data(2);    % 列数
disp = data(3:end); % 视差
vmin = min(disp);
vmax = max(disp);
disp = reshape(disp, [c,r])'; % 将列向量形式的 disp 重构为 矩阵形式
%  OpenCV 是行扫描存储图像,Matlab 是列扫描存储图像
%  故对 disp 的重新排列是首先变成 c 行 r 列的矩阵,然后再转置回 r 行 c 列
img = uint8( 255 * ( disp - vmin ) / ( vmax - vmin ) );
mesh(disp);
set(gca,'YDir','reverse');  % 通过 mesh 方式绘图时,需倒置 Y 轴方向
axis tight; % 使坐标轴显示范围与数据范围相贴合,去除空白显示区


http://blog.csdn.net/u010025211/article/details/53197337

https://cn.mathworks.com/help/vision/ref/reconstructscene.html

http://www.visionbib.com/bibliography/contents.html

http://docs.opencv.org/3.0-beta/doc/py_tutorials/py_calib3d/py_depthmap/py_depthmap.html

http://docs.opencv.org/trunk/d3/d14/tutorial_ximgproc_disparity_filtering.html

https://dzone.com/articles/computing-disparity-map-opencv


看求disparity的算法挺简单的,本来想自己实现下,

先用matlab写个简单的,就是http://vision.deis.unibo.it/~smatt/Seminars/StereoVision.pdf里面的1领域的window search

clear
clc
img1 = rgb2gray(imread('left1.jpg'));
img2 = rgb2gray(imread('right1.jpg'));
[n,m] = size(img1);


sigma = 1;
gausFilter = fspecial('gaussian', [5,5], sigma);
img1= imfilter(img1, gausFilter, 'replicate');
img2= imfilter(img2, gausFilter, 'replicate');


LARGE = 10000000;
max = 60;
d = zeros(n,m);


for i=1:n
    fprintf('processing %d \n', i);
    for j=1:m
        minDiff = LARGE;
        t = -1;
        for k=0:max
            if j+k<=m
                diff = abs(img1(i,j)-img2(i,j+k));
                if diff < minDiff
                    minDiff = diff ;
                    t = k;
                end
            else
                break;
            end
        end
        d(i, j) = t;
    end
end

但是得不到讲义里面的答案,一个基本的形状也得不到(难道是显示数据的问题??转成图片这一步没做好??)

Anyway,用Matlab和opencv自带的函数都OK,自己搞不定就想看下源码,Matlab的源码看着很蛋疼,一下又链到一个不知所云的函数,那就看opencv源码把,找是找到了,可以没什么注释,也咩有说具体算法参考的什么资料,

说不得,还是先看片基础的论文吧,因为网上的博客时候都是讲的差不多,具体讲的也比较少,可找论文又出现问题,根本不知道什么搜索关键字,因为想实现个基本的算法,所以想找最开始提出这种算法的论文,但是年代太久有找不到,真是GG

说不得,看书籍把,一些Computer Vision的书籍有讲这些算法,learning opencv也有讲,但是经历上面的本末倒置后,竟然看不下去,浑浑噩噩过了几天,最好还是找到opencv的sample代码,调用opencv现成的函数


后面也想写全局求disparity矩阵的模拟退火算法,先copy了一个网上可以求极值的模拟退火代码,但是应用不上求disparity矩阵的实际问题,而且速度很慢,估计是哪里想错了吧


教训:明白自己要做什么:是自己写算法还是调用现成的

自己写就要先弄清楚算法步骤,先找简单的博客,先实现简单原始的

调用现成的就可以参考opencv自带的sample例子


  • 3
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 生成视差图可以使用opencv中的StereoSGBM算法,具体步骤如下: 1. 读取左右两张图像,并将其转为灰度图像。 2. 定义StereoSGBM对象,设置其参数,包括最小视差、最大视差、SAD窗口大小等。 3. 调用StereoSGBM对象的compute方法,对两张图像进行匹配计算,得到视差图。 4. 对视差图做一些后处理,比如显示、保存等。 下面是代码示例: ```python import cv2 # 读取左右两张图像 imgL = cv2.imread('left.png', 0) imgR = cv2.imread('right.png', 0) # 定义StereoSGBM对象 stereo = cv2.StereoSGBM_create(minDisparity=0, numDisparities=16, blockSize=3) # 计算视差disparity = stereo.compute(imgL, imgR) # 后处理 disparity = cv2.normalize(disparity, None, alpha=0, beta=255, norm_type=cv2.NORM_MINMAX, dtype=cv2.CV_8U) # 显示和保存视差图 cv2.imshow('disparity', disparity) cv2.imwrite('disparity.png', disparity) cv2.waitKey() cv2.destroyAllWindows() ``` 注意,此处的左右图像应该是同一场景从不同角度拍摄得到的,且应该已经进行了校正。如果没有进行校正,可以使用opencv中的StereoRectify函数对左右图像进行校正。 ### 回答2: OpenCV是一个广泛应用于计算机视觉和图像处理的开源库。它提供了很多函数和工具来处理图像和视频数据。 要生成视差图,首先需要获取两幅视差图像,通常分别表示左眼和右眼观察到的同一个场景。这两幅图像可以通过立体相机或者从不同角度拍摄同一场景获得。 生成视差图的关键在于计算两幅图像之间的视差信息,即同一点在两幅图像中的像素偏移量。一种常用的方法是利用图像的纹理信息,在两幅图像中寻找相似的纹理块。这可以通过计算图像的灰度直方图或者特征向量进行。 OpenCV提供了一些视差计算的函数,如StereoBM和StereoSGBM。StereoBM算法基于块匹配的思想,使用固定大小的窗口在两幅图像中搜索最佳匹配块。而StereoSGBM算法则利用更复杂的信号处理和优化技术来更准确地计算视差。 通过调用这些函数,可以将左右视图的图像作为输入,然后生成视差图。视差图中的每个像素值表示了对应像素在两幅图像中的视差值。生成的视差图可以用于立体匹配、距离估计和三维重建等应用。 需要注意的是,视差图的质量和准确性取决于输入图像的质量、生成视差的算法以及参数设置等因素。因此,在生成视差图之前,需要对图像进行预处理和调参,以确保生成的视差图满足具体应用的需求。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值