2010-06-11 2 views
1

Я делаю простую программу калибровки на C++ с помощью OpenCV. Все идет хорошо, пока я не попытаюсь позвонить CVCalibrateCamera2. На данный момент, я получаю одну из нескольких ошибок:C++ OpenCV CVCalibrateCamera2 вызывает множество ошибок

Если количество изображений, которые я использую, равно 4 (что число точек втягивается из каждого изображения:

OpenCV Error: Sizes of input arguments do not match (Both matrices must have the same number of points) in unknown function, file ......\src\cv\cvfundam.cpp, line 870

Если количество изображений ниже 20:

OpenCV Error: Bad argument (The total number of matrix elements is not divisible by the new number of rows) in unknown function, file ......\src\cxcore\cxarray.cpp, line 2749

в противном случае, если количество изображения 20 или выше:

OpenCV Error: Unsupported format or combination of formats (Invalid matrix type) in unknown function, file ......\src\cxcore\cxarray.cpp, line 117

Я много раз проверял аргументы для CVCalibrateCamera2, и я уверен, что они имеют правильные размеры относительно друг друга. Кажется, что где-то программа пытается изменить матрицу на основе количества изображений, но я не могу понять, где и почему. Есть идеи? Я использую Eclipse Galileo, MINGW 5.1.6 и OpenCV 2.1.

+0

Можете ли вы разместить свой код, который вызывает cvCalibrateCamera2, и код, который генерирует точки объекта/точки изображения, которые ему переданы? Это может помочь сузить проблему. – WildCrustacean

ответ

0

Update:

Это код, который вызывает CVCalibrateCamera2():

void calibrate(CvMat * object_points, CvMat * image_points, CvMat * intrinsicsMatrix, CvMat * distortionVector){ 
    const int point_count = object_points->rows; 
    const int image_count = image_points->rows/point_count; 
    CvMat * const full_object_points = cvCreateMat(image_count * point_count, 3, CV_32FC1); 
    CvMat * const point_counts = cvCreateMat(image_count, 1, CV_32SC1); 
    for (int i = 0; i < image_count; i++){ 
     CV_MAT_ELEM(*point_counts, float, i, 0) = point_count; 
     for (int j = 0; j < point_count; j++){ 
      for (int k = 0; k < 3; k++){ 
       CV_MAT_ELEM(*full_object_points, float, i * point_count + j, k) = CV_MAT_ELEM(*object_points, float, j, k); 
      } 
     } 
} 
cvCalibrateCamera2(full_object_points, image_points, point_counts, cvSize(1, 1), intrinsicsMatrix, distortionVector, NULL, NULL, 0); 
} 

И это кусок, который собирает значения точек и передает их функции выше:

int main(){ 
    const float points [] [2] = {{0, 0}, {1, 0}, {2, 0}, {3, 0}}; 

    const int image_count = 5; 
    const int point_count = sizeof (points)/sizeof(points[1]); 

    CvMat * const object_points = cvCreateMat(point_count, 3, CV_32FC1); 
    for (int i = 0; i < point_count; i++){ 
     CV_MAT_ELEM(*object_points, float, i, 0) = points[i][0]; 
     CV_MAT_ELEM(*object_points, float, i, 1) = points[i][1]; 
     CV_MAT_ELEM(*object_points, float, i, 2) = 0; 
    } 

    CvMat * const image_points = cvCreateMat(image_count * point_count, 2, CV_32FC1); 
    collectPoints(setup, image_count, point_count, image_points); // See below about this 

    CvMat * const intrinsicsMatrix = cvCreateMat(3, 3, CV_32FC1); 

    CvMat * const distortionVector = cvCreateMat(5, 1, CV_32FC1); 

    calibrate(object_points, image_points, intrinsicsMatrix, distortionVector); 
} 

В приведенном выше коде collectPoints() - это функция, использующая стороннюю библиотеку (glitter's WiiYourself wiimote библиотека, если это имеет значение). Код ниже, но важно то, что возвращаемые точки имеют значения от -.5 до .5.

void collectPoints(wiimote_setup & setup, const int image_count, const int point_count, CvMat * const image_points){ 
    image_points->rows = image_count * point_count; 
    image_points->cols = 2; 

    bool A_pressed = false; 
    for (int i = 0; i < image_count; i++){ 
     while (true){ 
      setup.remote.RefreshState(); 
      if (setup.remote.Button.A()){ 
       if (!A_pressed){ 
        for (int j = 0; j < point_count; j++){ 
         wiimote_state::ir::dot & dot = setup.remote.IR.Dot[j]; 
         CV_MAT_ELEM(*image_points, float, i * point_count + j, 0) = .5 - dot.X; 
         CV_MAT_ELEM(*image_points, float, i * point_count + j, 1) = .5 - dot.Y; 
         cout << dot.X <<", " << dot.Y << "\n"; 
        } 
        cout << "\n"; 
        cout.flush(); 
        A_pressed = true; 
        break; 
       } 
      } else{ 
       A_pressed = false; 
      } 
     } 
    } 
} 
1

Я не уверен на 100% об этом, но я не думаю, что ваши объекты могут быть коллинеарными. В вашем коде у вас есть

const float points [] [2] = {{0, 0}, {1, 0}, {2, 0}, {3, 0}}; 

Эти точки находятся на одной линии (по оси x). Я думаю, что объектные точки должны определять плоскость для работы cvCalibrateCamera2. Это может объяснить ошибки, которые вы видите.

Насколько я знаю, процедуры калибровки OpenCV были разработаны в основном для использования с шаблоном шахматной доски (или некоторым другим планарным набором точек объекта), я не знаю, будут ли в вашей ситуации одинаковые алгоритмы.

Смежные вопросы