<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          計算機視覺方向簡介 | 半全局匹配SGM

          共 9440字,需瀏覽 19分鐘

           ·

          2021-08-05 23:34


          點擊上方小白學(xué)視覺”,選擇加"星標"或“置頂

          重磅干貨,第一時間送達

          前言

          • 目標讀者:對密集匹配,三維重建等有基本概念并感興趣的人群。
          • 文章及代碼資源:
          網(wǎng)盤中包含有論文以及代碼,論文包括經(jīng)典文章《Stereo Processing by Semi-Global Matching and Mutual Information》,以及兩篇個人認為比較有意思的相關(guān)論文,一篇提出了物方的SGM,另一篇則將SGM與深度學(xué)習(xí)相結(jié)合,代碼是筆者從網(wǎng)上找的開源代碼,供讀者參考。
          鏈接:
          https://pan.baidu.com/s/1CmWd4EQE9VtXbLRnVSvb3w
           提取碼:ypda
          • 導(dǎo)讀:
          相信了解過密集匹配/立體匹配的讀者對“SGM”不會感到陌生,SGM全名為semi-global matching,即半全局匹配,顧名思義,即為一種介于局部匹配與全局匹配之間的匹配算法,其較好的中和了局部匹配和全局匹配的優(yōu)缺點,在精度和效率上有較好的平衡,現(xiàn)在已經(jīng)較為廣泛的應(yīng)用于許多商業(yè)軟件中,尤其在航空遙感影像上有許多應(yīng)用。
          SGM源于經(jīng)典文章《Stereo Processing by Semi-Global Matching and Mutual Information》,谷歌學(xué)術(shù)上顯示被引率已高達2536次,若讀者希望對該算法有較為深刻的理解,該文章幾乎是不可不讀。opencv也有基于該算法的開源實現(xiàn),名為sgbm。
          就Heiko Hirschmuller的經(jīng)典文章而言,其核心為分層互信息的代價計算,多方向一維近似二維的代價聚集,以及其他的一些精化的后處理部分,比如左右一致性處理,亞像素求精等等。但實際上在代價計算步驟中,分層互信息的應(yīng)用并沒有想象中的那么廣泛,比如opencv開源的sgbm所用的代價函數(shù)就不是分層互信息,而是效率更高的BT,個人認為,或許根據(jù)影像情況自行選擇測度會是一個更好的選擇,比如就遙感影像而言,將相關(guān)系數(shù)作為測度的選擇就非常多。
          同時,SGM依賴懲罰參數(shù)來適應(yīng)視差連續(xù)與斷裂等情況,故而懲罰參數(shù)的設(shè)置較為重要,并且需要預(yù)先給定視差范圍,在opencv中的sgbm實現(xiàn)中還需要給定許多其他優(yōu)化參數(shù),如果希望獲取較好的匹配效果,合理設(shè)置參數(shù)非常重要。
          以下將基于個人理解,分別從SGM的核心公式,代價計算步驟,代價聚集,視差計算及精化進行介紹,文章重點將落在代價聚集部分。由于筆者學(xué)識所限,如有錯漏或者理解錯誤的地方,敬請批評。
          1. 核心公式


          SGM雖然名字上稱為半全局匹配,但實際上還是采用的全局匹配算法中最優(yōu)化能量函數(shù)的思想,即尋找每個像素的最優(yōu)視差來使得整張影像的全局能量函數(shù)最小,下式為SGM所采用的能量函數(shù):

          上式中能量函數(shù)的最優(yōu)化是一個NP問題,故而SGM提出了一個思路,即將像素所有視差下的匹配代價進行像素周圍所有路徑(比如8或者16)上的一維代價聚合,然后再將所有的一維代價聚合值相加,以近似二維的最優(yōu),這不僅可以取得和全局算法相媲美的結(jié)果,還大大的增加了效率。
          下式為某像素p沿著某一條路徑r的路徑代價計算公式:
          第一項還是數(shù)據(jù)項,第二項是平滑項,取r方向上視差不變,變化為1,變化大于1三種情況下代價最小的值,第三項則保證
          Lr不超過數(shù)值上限,具體理解可見下文中的代價聚合步驟。
          在代碼中,可以用一個結(jié)構(gòu)體來表示路徑,通過變化rowDiff,colDiff來表明路徑的方向。
          struct path {
              short rowDiff;
              short colDiff;
              short index;
          };
          實際上讀者可以將所謂的路徑理解為像素P(x,y)領(lǐng)域中的某一個特定位置的像素點。比如下圖中的path1可設(shè)為(rowDiff = 0,colDiff = -1,index = 1),path2可設(shè)為(rowDiff = -1,colDiff = 0, index = 2)等。
          本文提供的開源代碼分兩次進行代價聚合的掃描,第一次為上圖中紅色的路徑,第二次為圖中黑色的路徑。

          2. 代價計算


          在視差計算之前,首先需要定義大小為W×H×D(W為影像寬度,H為影像高度,D則為事先給定的視差范圍)的三維矩陣C來存儲每個像素在視差范圍內(nèi)每個視差下的匹配代價值。矩陣C通常稱為DSI(Disparity Space Image),這個長方塊也是我們常說的視差空間。下圖為DSI的示意圖:

          C(x, y, d)代表像素(x,y)在視差為d時的匹配代價,匹配代價越小說明相似度越高。代價函數(shù)或者說測度的選擇有很多,比如說Heiko Hirschmuller文章中的互信息,分層互信息,還有opencv中sgbm所選擇的BT,以及相關(guān)系數(shù)等。匹配測度各自有各自的優(yōu)勢,建議根據(jù)具體數(shù)據(jù)的特性來選擇合適的匹配測度。
          3. 代價聚合


          感性上來講,SGM能夠揚名的一個很重要的點就是它將一個NP的全局優(yōu)化問題簡化成了一個多方向的代價問題,即用多個一維路徑代價聚合的方式來近似二維的最優(yōu)。雖然還是在全局的框架下,但是整體的計算效率已相較于全局算法有了很大提升。

          上一步代價計算步驟中所計算出來的代價僅僅是能量函數(shù)中的數(shù)據(jù)項,在經(jīng)過聚合步驟后的代價才會被用來計算最優(yōu)視差。所謂的代價聚合實質(zhì)上是對上一步的代價矩陣進行全局優(yōu)化,得到一個存有聚集后代價的新的矩陣,用三維矩陣S來表示。
          就路徑聚合,以下將簡要介紹三個示意圖。
          第一個示意圖,也即原論文中路徑聚合的示意圖如下圖所示,做出了一個感性的十六方向代價聚合示意。
          第二個示意圖為許多介紹SGM博客中所用到的示意圖,如下圖所示,紅色箭頭方向代表四路徑聚集,紅色和黑色箭頭方向共同代表八路徑聚集,白色聚合方向則代表十六方向路徑聚集,路徑數(shù)越多時間開銷則會愈多,但相對而言效果也會更好,路徑數(shù)自行權(quán)衡即可。
          第三個示意圖為解釋本文提供的開源代碼所畫的示意圖,如下圖所示,紅色數(shù)字為第一次掃描的路徑index,黑色數(shù)字為第二次掃描的路徑index。
          以第一次掃描為例,代碼如下:
              for (int row = 0; row < rows; ++row) 
              {
                  for (int col = 0; col < cols; ++col) 
                  {
                      for (unsigned int path = 0; path < firstScanPaths.size(); ++path) 
                      {
                          for (int d = 0; d < disparityRange; ++d) 
                          {
                              S[row][col][d] += aggregateCost(row, col, d, firstScanPaths[path], rows, cols, disparityRange, C, A[path]);
                          }
                      }
                  }
                  lastProgressPrinted = printProgress(row, rows - 1, lastProgressPrinted);
              }
          即對于每一個像素點,對其第一次掃描序列中的每一條路徑,對其視差范圍內(nèi)的每一個視差,求取單路徑聚集后的代價,再進行累加,存到S[rol][col][d]中,最后用于WTA視差計算。
          此處關(guān)鍵的函數(shù)為aggregateCost(row, col, d, firstScanPaths[path], rows, cols, disparityRange, C, A[path])。輸入的參數(shù)中(row,col,d)相當于確定了視差空間中三維點的位置,firstScanPaths[path]則確定了是哪條路徑,或者可以更直觀的理解為是像素領(lǐng)域內(nèi)哪個相鄰像素,(rows,cols,disparityRange)則確定了視差空間的范圍,C為上一步代價計算得到的三維代價矩陣,最后的A[path]也是一個三維矩陣,用來存儲對應(yīng)方向的聚集代價,返回值則是A[row][col][d]。以下為該函數(shù)的實現(xiàn):
          unsigned short aggregateCost(int row, int col, int d, path &p, int rows, int cols, int disparityRange, unsigned short ***C, unsigned short ***A) 
          {
              unsigned short aggregatedCost = 0;
              aggregatedCost += C[row][col][d]; //像素匹配的 cost 值

              // 1. 邊界條件,直接為C 
              if (row + p.rowDiff < 0 || row + p.rowDiff >= rows || col + p.colDiff < 0 || col + p.colDiff >= cols) 
              {
                  A[row][col][d] += aggregatedCost;               
                  return A[row][col][d];
              }

              // 2. 若未超出邊界 ,則進行相應(yīng)方向的代價聚合  
              unsigned short minPrev, minPrevOther, prev, prevPlus, prevMinus;
              prev = minPrev = minPrevOther = prevPlus = prevMinus = MAX_SHORT;    
              //設(shè)置初始代價為最大值
              //minPrev: 對應(yīng)路徑的視差代價最小值

              // 對于該路徑方向上,上一個像素,在其視差范圍內(nèi)進行循環(huán)
              for (int disp = 0; disp < disparityRange; ++disp) 
              {
                  unsigned short tmp = A[row + p.rowDiff][col + p.colDiff][disp];
                  //找到這個路徑下,前一個像素取不同視差值時最小的A,即為最后減去的那一項,minPrev
                 if(minPrev > tmp){minPrev = tmp;}     

                  //前一個像素視差取值為d時,即和當前像素的視差相等時,最小的A.        
                  if(disp == d)   
                  { prev = tmp;}
                  //前一個像素視差取值為d+1時,即和當前像素的視差相差1時,最小的A,最后將加懲罰系數(shù)P1.
                  else if(disp == d + 1)  
                  { prevPlus = tmp;}
                  //前一個像素視差取值為d-1時,即和當前像素的視差相差1時,最小的A,最后將加懲罰系數(shù)P1.      
                  else if (disp == d - 1
                  {  prevMinus = tmp;}
                  //前一個像素視差與當前像素的視差相差大于等于2時,最小的A,最后將加懲罰系數(shù)P2.             
                  else 
                  { minPrevOther = tmp;}              
              } 

              /* 計算四種情況下的代價最小值 */
              aggregatedCost += std::min(std::min((int)prevPlus + SMALL_PENALTY, (int)prevMinus + SMALL_PENALTY), std::min((int)prev, (int)minPrevOther + LARGE_PENALTY));
              aggregatedCost -= minPrev; //避免值過大,減小內(nèi)存
              A[row][col][d] += aggregatedCost;
              return A[row][col][d];
          }
          第二次掃描及其他代碼細節(jié)具體見網(wǎng)盤資源。
          4. 視差計算及精化


          視差計算步驟其實非常簡單,通常直接利用贏家通吃(WTA)算法,即選擇某一個像素在所有視差值中最小的那一個即可,這也間接說明上一步,也即代價聚集步驟后所得到的視差空間中的代價值需要非常準確,那將直接決定算法的準確度。視差優(yōu)化則是對計算得到的視差圖進行進一步的優(yōu)化,包括剔除粗差,亞像素插值,平滑等等。比如經(jīng)常使用的左右一致性檢查,可用來剔除遮擋點所產(chǎn)生的錯誤匹配,對視差圖的改進比較大,有時候甚至可以成為許多算法的“遮羞布”。亞像素插值是對WTA得到的整像素進行精化,通常使用二次曲線擬合來獲得子像素的視差。平滑則是使用一些平滑算子對視差圖進行平滑處理。


          結(jié)語


          本文簡要介紹了SGM的思想,并輔以部分代碼以助于理解。近年來深度學(xué)習(xí)大熱,SGM與深度學(xué)習(xí)的結(jié)合逐漸成為趨勢,網(wǎng)盤中所提供的文章與開源代碼可供讀者參考,若有錯漏,歡迎批評與不吝賜教。


          下載1:OpenCV-Contrib擴展模塊中文版教程
          在「小白學(xué)視覺」公眾號后臺回復(fù):擴展模塊中文教程即可下載全網(wǎng)第一份OpenCV擴展模塊教程中文版,涵蓋擴展模塊安裝、SFM算法、立體視覺、目標跟蹤、生物視覺、超分辨率處理等二十多章內(nèi)容。

          下載2:Python視覺實戰(zhàn)項目52講
          小白學(xué)視覺公眾號后臺回復(fù):Python視覺實戰(zhàn)項目即可下載包括圖像分割、口罩檢測、車道線檢測、車輛計數(shù)、添加眼線、車牌識別、字符識別、情緒檢測、文本內(nèi)容提取、面部識別等31個視覺實戰(zhàn)項目,助力快速學(xué)校計算機視覺。

          下載3:OpenCV實戰(zhàn)項目20講
          小白學(xué)視覺公眾號后臺回復(fù):OpenCV實戰(zhàn)項目20講即可下載含有20個基于OpenCV實現(xiàn)20個實戰(zhàn)項目,實現(xiàn)OpenCV學(xué)習(xí)進階。

          交流群


          歡迎加入公眾號讀者群一起和同行交流,目前有SLAM、三維視覺、傳感器自動駕駛、計算攝影、檢測、分割、識別、醫(yī)學(xué)影像、GAN算法競賽等微信群(以后會逐漸細分),請掃描下面微信號加群,備注:”昵稱+學(xué)校/公司+研究方向“,例如:”張三 + 上海交大 + 視覺SLAM“。請按照格式備注,否則不予通過。添加成功后會根據(jù)研究方向邀請進入相關(guān)微信群。請勿在群內(nèi)發(fā)送廣告,否則會請出群,謝謝理解~


          瀏覽 72
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  免费在线无毒av毛片久 | 亚州人妻偷拍成人理伦 | 楪可怜Av一区二区三区 | 国产精品秘 欧美丨欧美捆绑精品 | 午夜精品久久久99热蜜桃的推荐系统 |