Ошибка калибровки стерео в OpenCV - (-3: внутренняя ошибка) CALIB_CHECK_COND - плохо подготовленная матрица для входного массива 1 в функции 'CalibrateExtrinsics' - PullRequest
0 голосов
/ 03 апреля 2020

opencv версия 3.4.9

Я использую этот код для калибровки. Моя стереоскопическая камера c состоит из двух камер GoPro Session (с настройками - 1080p 30 кадров в секунду, средний угол), установленных на алюминиевой плоскости на расстоянии 90 см друг от друга, а также использует беспроводной пульт дистанционного управления для синхронизации камер c. Я снял 2-минутное видео, охватывающее каждого ангела обеих камер, я использовал свой экран телевизора в качестве платы (мне нужно было, чтобы он был большим, потому что камеры слишком далеко друг от друга), и я разбил видео на кадры, а также Я удалил все кадры, где алгоритм не смог найти шахматную доску (если одна из камер не может найти шаблон, точный кадр был удален с обеих камер). При тестировании искажения с использованием этого шахматного рисунка 9x6 я заметил, что каждая картинка выглядит ужасно после искажения

enter image description here

вот оригинал. Я перепробовал все, со светом, с печатной платой на бумаге и приклеенной к плоской доске, каждый раз, когда неискаженное изображение выглядит так

enter image description here

и многие другие иногда это выглядит хуже, чем это, и также стоит упомянуть, что я изменяю размеры изображений с 1920x1080 до 640x360 перед тем, как удалить их.

Основная проблема заключается в том, что я получаю эту ошибку каждый раз, когда запускаю этот код из github

cv2.error: OpenCV(3.4.9) /io/opencv/modules/calib3d/src/fisheye.cpp:1421: error: (-3:Internal error) CALIB_CHECK_COND - Ill-conditioned matrix for input array 1 in function 'CalibrateExtrinsics'

и я понятия не имею, что делать. Я думаю, что плохая проблема искажения вызывает эту ошибку, или я ошибаюсь ?? Пожалуйста, скажите мне, что делать.

1 Ответ

2 голосов
/ 09 апреля 2020

Таким образом, здесь возникает ошибка: https://github.com/opencv/opencv/blob/master/modules/calib3d/src/fisheye.cpp#L1421 при оценке вектора единичных значений w вывод из разложения сингулярных значений (SVD). В частности, отношение первого сингулярного значения и последнего сингулярного значения (svd.w.at<double>(0) / svd.w.at<double>((int)svd.w.total() - 1)) превышает пороговое значение (в данном случае 1e6, основанное на переменной thresh_cond).

Похоже, Вы можете настроить, будет ли это условие (check_cond) оцениваться, используя CALIB_CHECK_COND (https://github.com/opencv/opencv/blob/master/modules/calib3d/src/fisheye.cpp#L740), что может быть предоставлено в функции stereoCalibrate: https://docs.opencv.org/3.4/db/d58/group__calib3d__fisheye.html#gadbb3a6ca6429528ef302c784df47949b. Функция stereoCalibrate вызывается в этой строке в используемом вами скрипте; вам просто нужно изменить cv2.CALIB_FIX_INTRINSIC на cv2.fisheye.CALIB_CHECK_COND.

Надеюсь, это поможет или, по крайней мере, даст вам некоторые результаты!

Обновление

После изменения флага с cv2.CALIB_FIX_INTRINSIC до cv2.fisheye.CALIB_CHECK_COND возникает новая ошибка из-за ошибочного утверждения: (-215:Assertion failed) abs_max < threshold in function 'stereoCalibrate'. Это утверждение происходит здесь: https://github.com/opencv/opencv/blob/master/modules/calib3d/src/fisheye.cpp#L1023. Быстрый поиск в Google дает два вопроса из форума вопросов OpenCV:

Оба из них заключают одно и то же: в наборах изображений, которые они использовали, были некоторые плохие стереопары, которые нужно было удалить. Кроме того, в строке из исходного кода есть один комментарий над утверждением при вычислении abs_max: //check goodness of stereopair (https://github.com/opencv/opencv/blob/master/modules/calib3d/src/fisheye.cpp#L1013).

Один из ответов в на форумах OpenCV, появившихся недавно (март 2020 г.), были некоторые логики c для проверки наличия плохих стереопар: https://answers.opencv.org/question/213931/assertion-failed-abs_max-threshold-in-function-stereocalibrate/?answer=227486#post -id-227486

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

    diff = cornersL - cornersR
    lengths = np.linalg.norm(diff[:, :, 1], axis=-1)
    sum = np.sum(lengths, axis=0)
    if (sum > 2000.0):
        print(f"THIS STEREO PAIR IS BROKEN!!! Diff is: {sum}")
        cornersR = np.flipud(cornersR)

В качестве альтернативы, вы можете просто continue, если это условие выполнено, и вообще пропустить эти пары (хотя я не уверен если это было бы идеально). Вы также можете распечатать / сохранить имена изображений (leftName) и (rightName), чтобы их можно было проверить - хотя в этот момент я бы рекомендовал просто добавить точку останова, где происходит проверка, и перейти к оценивать в реальном времени.

...