2013-07-16 88 views
9

我想让OpenCV 2.4.5从我的摄像头识别棋盘图案。我不能得到那个工作,所以我决定尝试只使用一个“完美”的形象得到它的工作:findChessboardCorners校准失败

checkerboard with white border

,但它仍然是行不通的 - 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); 
    } 
} 

回答

14

通过试验和错误,我意识到patternsize应该是7x7,因为它计数内部角落。这个参数必须是确切的 - 8x8不会工作,但都不会低于7x7。

+3

棋盘必须是不对称的。我再说一遍,棋盘必须是不对称的。告诉我你如何可能校准,否则。 – CTZStef

+0

@laurenelizabeth你的回答让我更近了一步,但我似乎仍然有同样的问题。关于7x7而不是8x8的提示对我来说非常重要。但是,我仍然无法检测到拍摄棋盘的角落,甚至没有发现接近完美的照片。 –

+0

我们正在尝试使用不对称9x7棋盘,我们要求8x6(内部正方形)。它工作得非常快。没有问题检测。而且我们使用的是双摄像头,我们只考虑两台摄像头同时检测到的东西。 谢谢! – helios

2

棋盘的宽度和高度不能是相同的长度,即它需要是不对称的。这可能是你的问题的根源。 Here是一个关于使用OpenCV进行相机校准的非常好的教程。

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

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); 
    } 
} 

以防万一你想知道的类成员,这里是我的课(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); 
}; 

最后的构造:

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

那么,它使用7x7时,所以我不知道它需要不对称。尽管感谢教程链接! – laurenelizabeth

+1

您是否可以使用对称图案校准并重新映射相机?我不这么认为。因此,它没有工作。也许findChessboardCorners()工作,但这不是校准。 – CTZStef

+0

我只需要角落,而不是完整的校准例程。 – laurenelizabeth

8

而不是使用

Size patternsize(8,8); 

使用

Size patternsize(7,7);