C++ findChessboardCorners 校准图像失败

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/17665912/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 21:20:23  来源:igfitidea点击:

findChessboardCorners fails for calibration image

c++opencvcomputer-visioncamera-calibration

提问by laurenelizabeth

I am trying to get OpenCV 2.4.5 to recognize a checkerboard pattern from my webcam. I couldn't get that working, so I decided to try to get it working just using a "perfect" image:

我试图让 OpenCV 2.4.5 从我的网络摄像头识别棋盘图案。我无法让它工作,所以我决定尝试使用“完美”图像来让它工作:

checkerboard with white border

带白色边框的棋盘格

but it still won't work--patternFound returns false every time. Does anyone have any idea what I'm doing wrong?

但它仍然不起作用——patternFound 每次都返回false。有谁知道我做错了什么?

#include <stdio.h>

#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/calib3d/calib3d.hpp>
#include <opencv2/highgui/highgui.hpp>

using namespace cv;
using namespace std;

int main(){
    Size patternsize(8,8); //number of centers
    Mat frame = imread("perfect.png"); //source image
    vector<Point2f> centers; //this will be filled by the detected centers

    bool patternfound = findChessboardCorners(frame,patternsize,centers);

    cout<<patternfound<<endl;
    drawChessboardCorners(frame, patternsize, Mat(centers), patternfound);

    cvNamedWindow("window");
    while(1){
        imshow("window",frame);
        cvWaitKey(33);
    }
}

回答by laurenelizabeth

Through trial and error, I realized that patternsize should be 7x7 since it is counting internal corners. This parameter has to be exact--8x8 won't work, but neither will anything less than 7x7.

通过反复试验,我意识到 patternsize 应该是 7x7,因为它计算内角。此参数必须准确--8x8 不起作用,但任何小于 7x7 的参数也不起作用。

回答by Desai

Instead of using

而不是使用

Size patternsize(8,8); 

use

Size patternsize(7,7);  

回答by CTZStef

Width and height of the chessboard can't be of the same length, i.e. it needs to be assymetric. This might be the source of your problem. Hereis a very good tutorial about camera calibration with OpenCV.

棋盘的宽度和高度不能相同,即必须不对称。这可能是您问题的根源。 是一个关于使用 OpenCV 校准相机的非常好的教程。

Just below is the code I use for my calibration (tested and fully functional, HOWEVER I call it in some processing thread of my own, you should call it in your processing loop or whatever you are using to catch your frames) :

下面是我用于校准的代码(经过测试且功能齐全,但是我在自己的某个处理线程中调用它,您应该在处理循环或用于捕获帧的任何东西中调用它):

void MyCalibration::execute(IplImage* in, bool debug)
{
    const int CHESSBOARD_WIDTH = 8;
    const int CHESSBOARD_HEIGHT = 5;
    const int CHESSBOARD_INTERSECTION_COUNT = CHESSBOARD_WIDTH * CHESSBOARD_HEIGHT;

    //const bool DO_CALIBRATION = ((BoolProperty*)getProperty("DoCalibration"))->getValue();
    if(in->nChannels == 1)
        cvCopy(in,gray_image);
    else
        cvCvtColor(in,gray_image,CV_BGR2GRAY);

    int corner_count;
    CvPoint2D32f* corners = new CvPoint2D32f[CHESSBOARD_INTERSECTION_COUNT];
    int wasChessboardFound = cvFindChessboardCorners(gray_image, cvSize(CHESSBOARD_WIDTH, CHESSBOARD_HEIGHT), corners, &corner_count);

    if(wasChessboardFound) {
        // Refine the found corners
        cvFindCornerSubPix(gray_image, corners, corner_count, cvSize(5, 5), cvSize(-1, -1), cvTermCriteria(CV_TERMCRIT_ITER, 100, 0.1));

        // Add the corners to the array of calibration points
        calibrationPoints.push_back(corners);

        cvDrawChessboardCorners(in, cvSize(CHESSBOARD_WIDTH, CHESSBOARD_HEIGHT), corners, corner_count, wasChessboardFound);
    } 
}

Just in case you wondered about the class members, here is my class (IplImage was still around at the time I wrote it) :

以防万一你想知道班级成员,这是我的班级(在我写它的时候 IplImage 还在附近):

#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv/cv.h>

class MyCalibration
{
private:
    std::vector<CvPoint2D32f*> calibrationPoints;

    IplImage *gray_image;

public:
    MyCalibration(IplImage* in);
    void execute(IplImage* in, bool debug=false);
    ~MyCalibration(void);
};

And finally the constructor :

最后是构造函数:

MyCalibration::MyCalibration(IplImage* in)
{
    gray_image = cvCreateImage(cvSize(in->width,in->height),8,1);
}