opencv - OpenCV 中相机标定期间出错

标签 opencv camera-calibration

我正在使用 opencv 进行相机校准。我使用的是“Cook bookprogramming”中给出的相同代码。

我正在用智能手机拍摄棋盘的照片。然后我使用 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 行上失败。 。 。

请帮助我。一张棋盘图像示例如下。该算法在第一张图像上无法找到角点。 。 。 。 :-enter image description here

最佳答案

首先,在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
    }
}


另外,为什么黑色方 block 周围有红色边框?我还没有研究过 cv::findChessboardCorners 到底是如何检测角点的,但这很可能会导致算法失败。您可以尝试使用没有它的新板吗?当我们这样做时,上角的光反射也可以发挥一些作用,因为黑色的强度值是非常浅的灰色。您是否在 OpenCV 提供的示例图像中尝试过您的算法?

关于opencv - OpenCV 中相机标定期间出错,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12541783/

相关文章:

c++ - openCV 3.0:如何保存/加载 cv::ml::boost 模型

c# - 寻找等高线之间的最小距离

opencv - 校准彼此面对的 2 个相机? (打开简历)

c# - 像素坐标到 3D 线(opencv)

python - 使用 OpenCV 进行相机校准 - 如何调整棋盘正方形的大小?

java - 固定方向时获取屏幕方向

python - 如何保存大型Python numpy数据集?

c++ - 校准相机时 opencv 错误 : assertion failed in convert. cpp (opencv)

opencv - 使用opencv跟踪车辆轨迹

matlab - 给定焦距和相机位置/旋转的正确透视图像