2012-09-22 19 views
2

我正在使用opencv進行攝像機標定。我使用的是「烹飪書籍編程」中給出的相同代碼。在OpenCV攝像機標定過程中出錯

我從我的智能手機的棋盤上拍照。然後我使用opencv程序爲我做相機校準。當我有非常大的棋盤時,程序只能處理一組圖像。它不爲另一組圖像的工作,我得到運行時錯誤「斷言失敗enter image description here

我不知道在我的代碼出錯的代碼如下: - 。

int main() 
{ 
CameraCalibrator calibrateCam; 
std::vector<std::string> filelist; 
char buff[100]; 

for(int i=0;i<21;i++) 
{ 
    sprintf(buff,"..\\Train\\3\\%d.jpg",i+1); 
    filelist.push_back(buff); 
} 
cv::Size boardSize(4,3); 
double calibrateError; 
int success; 
success = calibrateCam.addChessboardPoints(filelist,boardSize); 
} 

class CameraCalibrator{ 
public: 
    std::vector<std::vector<cv::Point3f>> objectPoints; 
    std::vector<std::vector<cv::Point2f>> imagePoints; 
    //Square Lenght 
    float squareLenght; 
    //output Matrices 
    cv::Mat cameraMatrix; //intrinsic 
    cv::Mat distCoeffs; 
    //flag to specify how calibration is done 
    int flag; 
    //used in image undistortion 
    cv::Mat map1,map2; 
    bool mustInitUndistort; 
public: 
    CameraCalibrator(): flag(0), squareLenght(36.0), mustInitUndistort(true){}; 
    int addChessboardPoints(const std::vector<std::string>& filelist,cv::Size& boardSize){ 
     std::vector<std::string>::const_iterator itImg; 
     std::vector<cv::Point2f> imageCorners; 
     std::vector<cv::Point3f> objectCorners; 
     //initialize the chessboard corners in the chessboard reference frame 
     //3d scene points 
     for(int i = 0; i<boardSize.height; i++){ 
      for(int j=0;j<boardSize.width;j++){ 
       objectCorners.push_back(cv::Point3f(float(i)*squareLenght,float(j)*squareLenght,0.0f)); 
      } 
     } 
     //2D Image points: 
     cv::Mat image; //to contain chessboard image 
     int successes = 0; 

     for(itImg=filelist.begin(); itImg!=filelist.end(); itImg++){ 
      image = cv::imread(*itImg,CV_LOAD_IMAGE_GRAYSCALE); 
      std::cout<<*itImg<<"\n"; 

      bool found = cv::findChessboardCorners(image, boardSize, imageCorners); 

      cv::drawChessboardCorners(image, boardSize, imageCorners, found);      
      cv::cornerSubPix(image, imageCorners, cv::Size(5,5),cv::Size(-1,-1), 
       cv::TermCriteria(cv::TermCriteria::MAX_ITER+cv::TermCriteria::EPS,30,0.1)); 
      //if we have a good board, add it to our data 
      if(imageCorners.size() == boardSize.area()){ 
       addPoints(imageCorners,objectCorners); 
       successes++; 
      } 
     } 

     return successes; 
    } 
    void addPoints(const std::vector<cv::Point2f>& imageCorners,const std::vector<cv::Point3f>& objectCorners){ 
     //2D image point from one view 
     imagePoints.push_back(imageCorners); 
     //corresponding 3D scene points 
     objectPoints.push_back(objectCorners); 
    } 
    double calibrate(cv::Size &imageSize){ 
     mustInitUndistort = true; 
     std::vector<cv::Mat> rvecs,tvecs; 
     return 
      cv::calibrateCamera(objectPoints, //the 3D points 
       imagePoints, 
       imageSize, 
       cameraMatrix, //output camera matrix 
       distCoeffs, 
       rvecs,tvecs, 
       flag); 

    } 
    void remap(const cv::Mat &image, cv::Mat &undistorted){ 
     std::cout << cameraMatrix; 
     if(mustInitUndistort){ //called once per calibration 
      cv::initUndistortRectifyMap(
       cameraMatrix, 
       distCoeffs, 
       cv::Mat(), 
       cameraMatrix, 
       image.size(), 
       CV_32FC1, 
       map1,map2); 
      mustInitUndistort = false; 
     } 
     //apply mapping functions 
     cv::remap(image,undistorted,map1,map2,cv::INTER_LINEAR); 
    } 
}; 

在攝像機標定類,它會成功打開圖像,但它在findChessboardCorners行上失敗......

Plz在這方面幫了我一個樣本棋盤圖像如下:該算法在第一張圖像上找不到角落。 。 - enter image description here

+0

您尚未提供足夠的信息。算法在上面的圖像中失敗了嗎?如果沒有,那麼當算法失敗時應該發佈一些圖像加上您的實際校準代碼,而不僅僅是這部分。你畫出檢測到的點嗎?另外,爲什麼你的黑色方塊周圍有紅色邊框? – Sassa

+0

我已經更新了我的答案。 PLZ看看,讓我知道。 。 。 – user1388142

回答

2

首先,在cv::findChessboardCorners您的boardSize是錯誤的,您應將其定義爲cv::Size boardSize(4,3);cv::Size boardSize(5,4);,因爲您的主板每行有5個內角和每列有4個角。


此外,你應該增加一個檢查的情況下,都沒有發現的角落。在你的代碼,後

bool found = cv::findChessboardCorners(image, boardSize, imageCorners); 

你繼續和呼叫功能,如cv::drawChessboardCornerscv::cornerSubPix如果沒有彎道,這將無法正常工作。這部分應該是:

for(itImg=filelist.begin(); itImg!=filelist.end(); itImg++) 
{ 
    image = cv::imread(*itImg,CV_LOAD_IMAGE_GRAYSCALE); 
    std::cout<<*itImg<<"\n"; 

    bool found = cv::findChessboardCorners(image, boardSize, imageCorners); 

    if (found) // continue only if corners have been found 
    { 
     cv::drawChessboardCorners(image, boardSize, imageCorners, found);      
     cv::cornerSubPix(image, imageCorners, cv::Size(5,5),cv::Size(-1,-1), cv::TermCriteria(cv::TermCriteria::MAX_ITER+cv::TermCriteria::EPS,30,0.1)); 

     //if we have a good board, add it to our data 
     if(imageCorners.size() == boardSize.area()) 
     { 
      addPoints(imageCorners,objectCorners); 
      successes++; 
     } 
    } 
    else // if no corners found 
    { 
     std::cout<<"No corners found in image"<<std::endl; 

     // Do anything else you want here 
    } 
} 


而且,爲什麼會出現在你的黑色正方形紅色邊框?我還沒有看到cv::findChessboardCorners究竟是如何檢測到角點的,但是這很可能導致算法失敗。你可以嘗試一下沒有它的新板嗎?雖然我們在上面,但上角的光線反射也會起到一定作用,因爲黑色的亮度值非常淺。您是否在OpenCV提供的示例圖像中嘗試了算法?

+0

非常感謝您的建議。我會這樣做,並會讓你知道。 。 。 – user1388142