1. 程式人生 > >雙目立體視差圖計算

雙目立體視差圖計算

clc;
clear;


%% 載入2張立體影象
left = imread('left.png');
right = imread('right.png');
sizeI = size(left);


% 顯示覆合影象
zero = zeros(sizeI(1), sizeI(2));
channelRed = left(:,:,1);
channelBlue = right(:,:,3);
composite = cat(3, channelRed, zero, channelBlue);


figure(1);
subplot(2,2,1);
imshow(left);
axis image;
title('Left Image');


subplot(2,2,2);
imshow(right);
axis image;
title('Right Image');


subplot(2,2,3);
imshow(composite);
axis image;
title('Composite Image');


%% 基本的塊匹配


% 通過估計子畫素的塊匹配計算視差
disp('執行基本的塊匹配~');


% 啟動定時器
tic();


% 平均3個顏色通道值將RGB影象轉換為灰度影象
leftI = mean(left, 3);
rightI = mean(right, 3);




% SHD
bitsUint8 = 8;
leftI = im2uint8(leftI./255.0);
rightI = im2uint8(rightI./255.0);




% DbasicSubpixel將儲存塊匹配的結果,元素值為單精度32位浮點數
DbasicSubpixel = zeros(size(leftI), 'single');


% 獲得影象大小
[imgHeight, imgWidth] = size(leftI);


% 視差範圍定義離第1幅影象中的塊位置多少畫素遠來搜尋其它影象中的匹配塊。對於大小為450x375的影象,視差範圍為50是合適的
disparityRange = 50;


% 定義塊匹配的塊大小
halfBlockSize = 5;
blockSize = 2 * halfBlockSize + 1;


% 對於影象中的每行(m)畫素
for (m = 1 : imgHeight)
   
% 為模板和塊設定最小/最大塊邊界
% 比如:第1行,minr = 1 且 maxr = 4
    minr = max(1, m - halfBlockSize);
    maxr = min(imgHeight, m + halfBlockSize);

    % 對於影象中的每列(n)畫素
    for (n = 1 : imgWidth)
        
        % 為模板設定最小/最大邊界
        % 比如:第1列,minc = 1 且 maxc = 4
minc = max(1, n - halfBlockSize);
        maxc = min(imgWidth, n + halfBlockSize);
        
        % 將模板位置定義為搜尋邊界,限制搜尋使其不會超出影象邊界 
% 'mind'為能夠搜尋至左邊的最大畫素數;'maxd'為能夠搜尋至右邊的最大畫素數
% 這裡僅需要向右搜尋,所以mind為0
% 對於要求雙向搜尋的影象,設定mind為max(-disparityRange, 1 - minc)
mind = 0; 
        maxd = min(disparityRange, imgWidth - maxc);


% 選擇右邊的影象塊用作模板
        template = rightI(minr:maxr, minc:maxc);

% 獲得本次搜尋的影象塊數
numBlocks = maxd - mind + 1;

% 建立向量來儲存塊偏差
blockDiffs = zeros(numBlocks, 1);
        
% 計算模板和每塊的偏差
for (i = mind : maxd)

%選擇左邊影象距離為'i'處的塊
block = leftI(minr:maxr, (minc + i):(maxc + i));

% 計算塊的基於1的索引放進'blockDiffs'向量
blockIndex = i - mind + 1;
   
            %{
            % NCC(Normalized Cross Correlation)
            ncc = 0;
            nccNumerator = 0;
            nccDenominator = 0;
            nccDenominatorRightWindow = 0;
            nccDenominatorLeftWindow = 0;
            %}
            
            % 計算模板和塊間差的絕對值的和(SAD)作為結果
            for (j = minr : maxr)
                for (k = minc : maxc)
                    %{
                    % SAD(Sum of Absolute Differences)
                    blockDiff = abs(rightI(j, k) - leftI(j, k + i));
                    % SSD(Sum of Squared Differences)
                    % blockDiff = (rightI(j, k) - leftI(j, k + i)) * (rightI(j, k) - leftI(j, k + i));
                    blockDiffs(blockIndex, 1) = blockDiffs(blockIndex, 1) + blockDiff;
                    %}
                    
                    %{
                    % NCC
                    nccNumerator = nccNumerator + (rightI(j, k) * leftI(j, k + i));
                    nccDenominatorLeftWindow = nccDenominatorLeftWindow + (leftI(j, k + i) * leftI(j, k + i));
                    nccDenominatorRightWindow = nccDenominatorRightWindow + (rightI(j, k) * rightI(j, k));
                    %}
                end
            end
            %{
            % SAD
            blockDiffs(blockIndex, 1) = sum(sum(abs(template - block)));
            %}
            
            %{
            % NCC
            nccDenominator = sqrt(nccDenominatorRightWindow * nccDenominatorLeftWindow);
            ncc = nccNumerator / nccDenominator;
            blockDiffs(blockIndex, 1) = ncc;
            %}
            


            % SHD(Sum of Hamming Distances)
            blockXOR = bitxor(template, block);
            distance = uint8(zeros(maxr - minr + 1, maxc - minc + 1));
            for (k = 1 : bitsUint8)
                distance = distance + bitget(blockXOR, k);
            end
            blockDiffs(blockIndex, 1) = sum(sum(distance));


end

% SAD值排序找到最近匹配(最小偏差),這裡僅需要索引列表


        % SAD/SSD/SHD
        [temp, sortedIndeces] = sort(blockDiffs, 'ascend');


        %{
        % NCC
        [temp, sortedIndeces] = sort(blockDiffs, 'descend');
        %}
        % 獲得最近匹配塊的基於1的索引
bestMatchIndex = sortedIndeces(1, 1);

        % 將該塊基於1的索引恢復為偏移量
% 這是基本的塊匹配產生的最後的視差結果
d = bestMatchIndex + mind - 1;

        %{
% 通過插入計算視差的子畫素估計
% 子畫素估計要求用左右邊的塊, 所以如果最佳匹配塊在搜尋窗的邊緣則忽略估計
if ((bestMatchIndex == 1) || (bestMatchIndex == numBlocks))
% 忽略子畫素估計並儲存初始視差值
DbasicSubpixel(m, n) = d;
else
% 取最近匹配塊(C2)的SAD值和最近的鄰居(C1和C3)
C1 = blockDiffs(bestMatchIndex - 1);
C2 = blockDiffs(bestMatchIndex);
C3 = blockDiffs(bestMatchIndex + 1);

% 調整視差:估計最佳匹配位置的子畫素位置
DbasicSubpixel(m, n) = d - (0.5 * (C3 - C1) / (C1 - (2 * C2) + C3));
        end
        %}
        DbasicSubpixel(m, n) = d;
    end


% 每10行更新過程
if (mod(m, 10) == 0)
fprintf('影象行:%d / %d (%.0f%%)\n', m, imgHeight, (m / imgHeight) * 100);
    end
end


% 顯示計算時間
elapsed = toc();
fprintf('計算視差圖花費 %.2f min.\n', elapsed / 60.0);


%% 顯示視差圖
fprintf('顯示視差圖~\n');


% 切換到影象4
subplot(2,2,4);
% 第2個引數為空矩陣,從而告訴imshow用資料的最小/最大值,並且對映資料範圍來顯示顏色
imshow(DbasicSubpixel, []);


% 去掉顏色圖會顯示灰度視差圖
colormap('jet');
colorbar;


% 指定視差圖的最小/最大值
%caxis([0 disparityRange]);


%設定顯示的標題
title(strcat('Basic block matching, Sub-px acc., Search left, Block size = ', num2str(blockSize)));


%% 誤匹配畫素的百分比


thresh = 1;


computedDisparityMap = double(DbasicSubpixel);
groundTruthDisparityMap = double(imread('disp6.png'));


scale = max(max(groundTruthDisparityMap)) / max(max(computedDisparityMap));
computedDisparityMap = computedDisparityMap * scale;


numPixels=0;
perBADMatch=0.0;


tic;
for (i = 1 + halfBlockSize : imgHeight - halfBlockSize)
    for(j = 1 + halfBlockSize : imgWidth - halfBlockSize - disparityRange)
        if(groundTruthDisparityMap(i,j) ~= 0)
            if(abs(computedDisparityMap(i,j) - groundTruthDisparityMap(i,j)) > thresh)
                perBADMatch = perBADMatch + 1;
            end
            numPixels = numPixels + 1;
        end
    end
end
perBADMatch = perBADMatch / numPixels


timeTaken = toc;
fprintf('計算誤匹配畫素的百分比花費 %.2f min.\n', elapsed / 60.0);

相關推薦

雙目立體視差計算

clc; clear; %% 載入2張立體影象 left = imread('left.png'); right = imread('right.png'); sizeI = size(left); % 顯示覆合影象 zero = zeros(sizeI(1), sizeI

用VS+Opencv3.1從雙目立體視差中重建三維點雲

基本原理 基本流程 程式碼 本程式碼執行需要在VS上配置好opencv3.1+openNI+PCL,opencv3.1的配置可以在網上找到很多資料,openNI和PCL的配置可以參看上一篇博文下http://blog.csd

雙目立體視覺匹配演算法之視差disparity計算——SAD演算法、SGBM演算法

一、SAD演算法 1.演算法原理         SAD(Sum of absolute differences)是一種影象匹配演算法。基本思想:差的絕對值之和。此演算法常用於影象塊匹配,將每個畫素對應數值之差的絕對值求和,據此評估兩個影象塊的相似度。該演

雙目立體匹配經典演算法之Semi-Global Matching(SGM)概述:視差計算視差優化

文章目錄 視差計算 視差優化 剔除錯誤匹配 提高視差精度 抑制噪聲 視差計算   在SGM演算法中,視差計算採用贏家通吃(WTA)演算法,每個畫素選擇最小聚

雙目立體匹配經典演算法之Semi-Global Matching(SGM)概述:匹配代價計算之Census變換(Census Transform,CT)

  基於互資訊的匹配代價計算由於需要初始視差值,所以需要通過分層迭代的方式得到較為準確的匹配代價值,而且概率分佈計算稍顯複雜,這導致代價計算的效率並不高。學者Zabih和Woodfill 1 提出的基於Census變換法也被廣泛用於匹配代價計算。Census變換是使用畫素鄰域內的區域性灰

雙目立體匹配經典演算法之Semi-Global Matching(SGM)概述:匹配代價計算之互資訊(Mutual Information,MI)

  半全域性立體匹配演算法Semi-Global Matching,SGM由學者Hirschmüller在2005年所提出1,提出的背景是一方面高效率的區域性演算法由於所基於的區域性視窗視差相同的假設在很多情況下並不成立導致匹配效果較差;而另一方面全域性演算法雖然通過二維相鄰畫素視差之間

雙目立體匹配(Stereo Matching)獲取深度

  雙目立體匹配一直是雙目視覺的研究熱點,雙目相機拍攝同一場景的左、右兩幅視點影象,運用立體匹配匹配演算法獲取視差圖,進而獲取深度圖。而深度圖的應用範圍非常廣泛,由於其能夠記錄場景中物體距離攝像機的距離,可以用以測量、三維重建、以及虛擬視點的合成等。   但

真實場景的雙目立體匹配(Stereo Matching)獲取深度詳解

  雙目立體匹配一直是雙目視覺的研究熱點,雙目相機拍攝同一場景的左、右兩幅視點影象,運用立體匹配匹配演算法獲取視差圖,進而獲取深度圖。而深度圖的應用範圍非常廣泛,由於其能夠記錄場景中物體距離攝像機的距離,可以用以測量、三維重建、以及虛擬視點的合成等。   但是對於想自己嘗試拍攝雙目圖片進行立體匹配獲取深度

雙目視覺探索路2】獲取視差(未完待續)

如前所述,本系列首先通過視差圖的實現,從直觀的角度對雙目立體視覺首先進行個大概的瞭解。 立體視覺的整體概述: 雙目立體視覺測物體空間資訊的流程順序應為: 如前一講所述,整個雙目立體視覺的實現流程可分為標定以及立體視覺的實現。 標定: 標定的目的為獲得相機的內外參,其基本原

【bzoj3630】[JLOI2014]鏡面通道 對偶+計算幾何+網絡流最小割

log ros font eof ext 理學 最小 bool type 題目描述 在一個二維平面上,有一個鏡面通道,由鏡面AC,BD組成,AC,BD長度相等,且都平行於x軸,B位於(0,0)。通道中有n個外表面為鏡面的光學元件,光學元件α為圓形,光學元件&b

HDU 4370 0 or 1(spfa+思維建+計算最小環)

inf 計算 最小 star while arch mes targe space 題目鏈接:http://acm.hdu.edu.cn/showproblem.php?pid=4370 題目大意:有一個n*n的矩陣Cij(1<=i,j<=n),要找到矩陣Xi

Spark學習之路 (二十八)分布式計算系統

尺度 內存 底層 mapr 分區 ces 兩個 傳遞方式 cat 一、引言   在了解GraphX之前,需要先了解關於通用的分布式圖計算框架的兩個常見問題:圖存儲模式和圖計算模式。 二、圖存儲模式   巨型圖的存儲總體上有邊分割和點分割兩種存儲方式。2013年,Gra

雙目立體視覺

矩陣 com sad 因此 ssd 視差 形式 技術分享 行號 1.簡介: 雙目視覺是模擬人類視覺原理,使用計算機被動感知距離的方法。從兩個或者多個點觀察一個物體,獲取在不同視角下的圖像,根據圖像之間像素的匹配關系,通過三角測量原理計算出像素之間的偏移來獲取物體的三維信息。

OpenCV——積分計算

col com stream image using alt pan not sqs 1 #include <opencv2/opencv.hpp> 2 #include <iostream> 3 #include "math.h

雙目立體視覺三維重建

雙目立體視覺的整體流程包括:影象獲取、雙目標定、雙目矯正、立體匹配、三維重建。 影象獲取 雙目相機拍攝獲取 左右目影象 雙目標定 內參 外參 相機矩陣

雙目立體匹配——歸一化互相關(NCC)

  歸一化相關性,normalization cross-correlation,因此簡稱NCC,下文中筆者將用NCC來代替這冗長的名稱。   NCC,顧名思義,就是用於歸一化待匹配目標之間的相關程度,注意這裡比較的是原始畫素。通過在待匹配畫素位置p(px,py)構建3*3鄰域匹配視窗,

【深度相機系列三】深度相機原理揭祕--雙目立體視覺

本文已經首發在個人微信公共號:計算機視覺life(微訊號CV_life),歡迎關注! 導讀 為什麼非得用雙目相機才能得到深度? 雙目立體視覺深度相機的工作流程 雙目立體視覺深度相機詳細工作原理   &

1. 雙目立體視覺演算法

流程圖 矯正 矯正兩個相機之間的R t和畸變,使兩個相機的成像平面滿足: 兩幅圖嚴格的行對應 兩幅影象的對極線恰好在同一水平線上 極線約束 與 極線匹配 極線約束:空間中任意一點在影象平面上的投影點,必然處於該點和兩個攝像頭光心組成的對極平面上

計算:一張秒級洞察千億級複雜關係

在資料規模越來越大、資料結構越來越複雜的大資料時代,傳統的關係型資料暴露出了建模缺陷、水平伸縮等問題,於是具有更強大表達能力的圖資料受到業界極大的重視。如果把關係資料模型比做火車的話,那麼現在的圖資料建模可比做高鐵。 什麼是圖呢? 圖(Graph),將資訊中的實體,以及實體之間的關係,

雙目立體匹配經典演算法之Semi-Global Matching(SGM)概述:代價聚合(Cost Aggregation)

  由於代價計算步驟只考慮了局部的相關性,對噪聲非常敏感,無法直接用來計算最優視差,所以SGM演算法通過代價聚合步驟,使聚合後的代價值能夠更準確的反應畫素之間的相關性,如圖1所示。聚合後的新的代價值儲存在與匹配代價空間C同樣大小的聚合代價空間S中,且元素位置一一對應。 圖1:代價聚合