2013-07-16 22 views
9

Ich versuche OpenCV 2.4.5 zu bekommen, um ein Schachbrettmuster von meiner Webcam zu erkennen. Ich konnte es nicht, dass die Arbeit bekommen, so habe ich beschlossen, zu versuchen, es zu bekommen arbeiten nur mit einem „perfekten“ Bild:findChessboardCorners schlägt fehl für die Kalibrierung Bild

checkerboard with white border

aber es wird immer noch nicht funktioniert - patternFound jedes Mal false zurückgibt. Hat jemand eine Idee, was ich falsch mache?

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

Antwort

14

Durch Versuch und Irrtum erkannte ich, dass Mustergröße 7x7 sein sollte, da es interne Ecken zählt. Dieser Parameter muss genau sein - 8x8 wird nicht funktionieren, aber auch nicht weniger als 7x7.

+3

das Schachbrett muss assymetric sein. Ich wiederhole, das Schachbrett muss assymetrisch sein. Sag mir, wie du sonst noch kalibrieren kannst. – CTZStef

+0

@laurenelizabeth Deine Antwort brachte mich einen Schritt näher, aber ich habe anscheinend immer noch das gleiche Problem. Der Tipp von 7x7 statt 8x8 war mir sehr wichtig. Allerdings kann ich die Ecken fotografierter Schachbretter immer noch nicht erkennen, auch nicht auf nahezu perfekten Fotos. –

+0

Wir versuchen mit asymmetrischen 9x7 Schachbrett, und wir fragen nach 8x6 (innere Quadrate). Es hat einfach sehr schnell funktioniert. Keine Probleme beim Erkennen. Und wir verwenden eine Doppelkamera, bei der wir nur dann in Betracht ziehen, wenn beide Kameras das Ding gleichzeitig erkennen. DANKE !!! – helios

2

Breite und Höhe des Schachbretts können nicht gleich lang sein, d. H. Es muss asymmetrisch sein. Dies könnte die Ursache Ihres Problems sein. Here ist ein sehr gutes Tutorial über Kamerakalibrierung mit OpenCV.

Unten ist der Code, den ich für meine Kalibrierung verwende (getestet und voll funktionsfähig, ABER ich nenne es in meinem eigenen Verarbeitungs-Thread, Sie sollten es in Ihrer Verarbeitungsschleife oder was auch immer Sie verwenden, um Ihre Frames zu fangen) :

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

Nur für den Fall gefragt, über die die Teilnehmer meiner Klasse, hier ist (IplImage noch um zu der Zeit war ich es geschrieben habe):

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

Und schließlich der Baumeister:

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

Nun, es funktionierte, als ich 7x7 benutzte, also bin ich nicht sicher, dass es asymmetrisch sein muss. Danke für den Tutorial-Link! – laurenelizabeth

+1

Konnten Sie Ihre Kamera mit einem symmetrischen Muster kalibrieren und neu zuordnen? Ich denke nicht. Daher hat es nicht funktioniert. Vielleicht hat findChessboardCorners() funktioniert, aber das ist keine Kalibrierung. – CTZStef

+0

Ich brauchte nur die Ecken, nicht die kompletten Kalibrierungsroutinen. – laurenelizabeth

8

Statt

Size patternsize(8,8); 

Verwendung mit

Size patternsize(7,7);