C ++ OpenCV CVCalibrateCamera2 вызывает несколько ошибок - PullRequest
1 голос
/ 12 июня 2010

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

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

Ошибка OpenCV: размеры входных аргументов не совпадают (обе матрицы должны иметь одинаковое количество точек) в неизвестной функции, файл ...... \ src \ cv \ cvfundam.cpp, строка 870

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

Ошибка OpenCV: неверный аргумент (общее количество элементов матрицы не делится на новое количество строк) в неизвестной функции, файле...... \ src \ cxcore \ cxarray.cpp, строка 2749

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

Ошибка OpenCV: не поддерживаетсяформат или комбинация форматов (недопустимый тип матрицы) в неизвестной функции, файл ...... \ src \ cxcore \ cxarray.cpp, строка 117

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

Ответы [ 2 ]

1 голос
/ 15 июня 2010

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

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

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

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

0 голосов
/ 13 июня 2010

Обновление:

Это код, который вызывает 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 () - это функция, использующая стороннюю библиотеку (библиотеку WiiYourself wiimote gl.tter, если это имеет значение). Код приведен ниже, но важно то, что возвращаемые точки имеют значения в диапазоне от -.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;
            }
        }
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...