Skip to content

Instantly share code, notes, and snippets.

@Po-Jen
Last active October 16, 2015 15:39
Show Gist options
  • Save Po-Jen/374b18af0ad5c2bac3bc to your computer and use it in GitHub Desktop.
Save Po-Jen/374b18af0ad5c2bac3bc to your computer and use it in GitHub Desktop.
PTAM calibrator研究紀錄

標頭檔部份

這檔案引用了幾個之前比較不熟悉的標頭檔,列在下面

gvars3/instances.h

Gvars 3是一個可以讀設定檔的函式庫,在這邊是用來跟GUI綁定在一起,用來讀程式算出的相機參數 http://www.edwardrosten.com/cvd/gvars3.html

cvd/image.h, cvd/byte.h, cvd/rgb.h, cvd/utility.h

libcvd是一個電腦視覺的函式庫,擁有基本的影像處理功能。 http://www.edwardrosten.com/cvd

TooN/SVD.h

TooN是C++的數值方法函式庫,主要可以用來解大量的矩陣運算(例如矩陣分解跟最佳化)。 http://www.edwardrosten.com/cvd/toon.html

全域變數

Vector<NUMTRACKERCAMPARAMETERS> camparams;

在include/ptam/ATANCamera.h裡面,有一行#define NUMTRACKERCAMPARAMETERS 5。另外,Vector是TooN裡面的一個class,所以這個全域變數是一個會儲存5個數字的陣列,這5個數字應該就是PTAM校正完得到的5個內部參數的儲存位置

Set Parser

GUI.StartParserThread()
GV3::get<Vector<NUMTRACKERCAMPARAMETERS> >("Camera.Parameters", ATANCamera::mvDefaultParams, SILENT); 

這是在main裡面第一個看不懂的東西, 根據Gvars的簡單範例,GV3::get("wurble")是把設定檔中wurble=10這行的10parse出來。 合理猜測,現在遇到的這行是把某個設定檔中的Camera.Parameters的值爬出來,指定給ATANCamera::mvDefaultParams。

在ATANCamera.h裡面,發現有這麼一個data member,不過順便看了一下註解後發現,好像沒什麼用

static const Vector<NUMTRACKERCAMPARAMETERS> mvDefaultParams;

重點應該是下面這個data member,註解說他才是真正儲存相機參數的變數

Vector<NUMTRACKERCAMPARAMETERS> mgvvCameraParams;

Init & Run CameraCalibrator

CameraCalibrator c;
c.Run();

CameraCalibrator這個class裡面有一個mCamera(ATANCamera mCamera),在建構子設定了這個成員的一些初始值,此外,訂閱影像也是在這邊開始。

CameraCalibrator::CameraCalibrator() :
      mCamera("Camera"), mbDone(false), mCurrentImage(CVD::ImageRef(752, 480)), mDoOptimize(false), mNewImage(false)
{
  ros::NodeHandle nh; 
  image_transport::ImageTransport it(nh);
  mImageSub = it.subscribe("image", 1, &CameraCalibrator::imageCallback, this);
}

Run的內容因為需要詳細分析,現在先不管,只要知道裡面有個while迴圈維持程式持續運行就好。

Run一開始會做一些初始化的設定,這邊我們就先忽略他,直接切入抓取新的Image和Optimize的部份。

抓取新的Image

      if (mNewImage)
      {   
        mNewImage = false;
        CalibImage c;
        if (c.MakeFromImage(mCurrentImage))
        {   
          if (mbGrabNextFrame)
          {   
            mvCalibImgs.push_back(c);
            mvCalibImgs.back().GuessInitialPose(mCamera);
            mvCalibImgs.back().Draw3DGrid(mCamera, false);
            mbGrabNextFrame = false;
          };  
        }   
      }  

以使用者的觀點來看,每按一次Grabframe就會多儲存一張影像,而且可以在GUI上看到一個很粗糙的,對於Grid位置的猜測。 從程式碼中可以明顯地看出影像會先用來初始化一個新的CalibImage物件,然後塞進mvCalibImgs(std::vector mvCalibImgs是CameraCalibrator的一個data member)裡面。 然後會呼叫CalibImage物件的GuessInitialPose函式,更新mCamera裡面的pose, 最後再用CalibImage物件的Draw3DGrid把粗糙的結果畫出來。

這邊有一個要注意的地方是,MakeFromImage()跟GuessInitialPose()都是相當複雜的函式,我的複雜是說這兩個函式裡面都做了不少事情,如果想要了解PTAM吐出的5個參數的真意,可能還是要進一步跳進去分析到底做了什麼事。

最佳化相機參數

這邊實際用到的程式碼也不多(註解掉的部份只是在抽換GUI顯示的內容而已),最主要用到的就是OptimizeOneStep()。

      if(mDoOptimize)
        OptimizeOneStep();
      //GUI.ParseLine("CalibMenu.ShowMenu Opti");
      //int nToShow = *mgvnShowImage - 1;
      //if (nToShow < 0)
      //  nToShow = 0;
      //if (nToShow >= (int)mvCalibImgs.size())
      //  nToShow = mvCalibImgs.size() - 1;
      //*mgvnShowImage = nToShow + 1;  

      glDrawPixels(mvCalibImgs[nToShow].mim);
      mvCalibImgs[nToShow].Draw3DGrid(mCamera, true);

截至目前,我們已經把大致的流程走過一遍,接下來就要再更深入地理解實際計算相機參數的程式碼了。

一切入這個函式,第一行就看不懂了...

const FixParams& pPars = PtamParameters::fixparams();

找了一下發現FixParams被定義在include/ptam/Params.h裡面,

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment