Я новичок в OpenCV
и в настоящее время я работаю над проектом, требующим точного сопоставления пикселей с сантиметрами / миллиметрами / любой единицей реального мира.
Я выполнил стерео калибровку в OpenCV
затем стерео ректификация. И, таким образом, я получил как внутренние, так и внешние параметры.
Во время выполнения стереокалибровки я не указал точный квадратный размер (25 на 25 мм) скороговорки на шахматной доске. Я только ввел количество горизонтальных и вертикальных внутренних углов, а также количество досок. Так будет ли это иметь эффект при перепроектировании в 3D? Если да, то как мне включить размер квадрата в функцию StereoCalibrate.
Во-вторых, значения fx
а также fy
из матрицы камеры получены 513,86, а из данных EXIF - 3,7 мм. Итак, какова точная связь между обоими?
В-третьих, я использовал reprojectImageTo3D
и получил трехмерные мировые координаты. Каковы точные единицы этих координат (см / мм / дюймы / и т. Д.)?
По сути, я хочу получить точное отображение от пикселя до реальных единиц измерения, и после большого количества чтения и поиска я не смог этого сделать. Пожалуйста, помогите мне с этим вопросом.
Я согласен с другими ответами на первые два вопроса. Но просто, чтобы уточнить и уточнить подробнее,
1)
Посмотрите на параметр squareSize в блоке кода ниже.
Здесь вы даете размер квадрата. Что он делает, так это вычисляет положение каждого угла на шахматной доске и помещает его в вектор точек, называемый objectPoints. Это возможно, потому что у шахматной доски есть регулярный образец.
Вектор objectPoints становится первым параметром вашей функции StereoCalibrate.
Также помните, что в любых единицах измерения, которые вы указываете для squareSize, результаты калибровки (кроме, конечно, fx и fy) будут в тех же единицах.
for( j = 0; j < boardSize.height; j++ ){
for( k = 0; k < boardSize.width; k++ ){
objectPoints.push_back(Point3f(j*squareSize, k*squareSize, 0));
}
}
2)
FX и FY, что вы получите, будет в пикселях. Чтобы получить фокусное расстояние в мм, нужно умножить его на коэффициент масштабирования.
Соотношение между fx, fy и вашим фактическим фокусным расстоянием в мм определяется размером датчика вашей камеры. Вы должны быть в состоянии найти этот параметр в спецификации камеры.
Коэффициент масштабирования, который я упомянул выше, будет количеством пикселей на мм для датчика вашей камеры.
3)
3D-координаты мира, которые вы получаете, это именно то, что вы упомянули. Координаты. Ссылка с некоторой точки в вашей системе. Они Икс, Y а также координаты z из точек объекта. Координаты не имеют единиц!
Пока я могу ответить на два первых вопроса:
1: Первый параметр в резюме :: stereoCalibrate является вектором точек объекта, вы можете заполнить его, используя следующую функцию:
void CalcBoardCornerPositions(cv::Size boardSize, double squareSize, std::vector<cv::Point3f>& corners) {
corners.clear();
for( int i = 0; i < boardSize.height; ++i )
for( int j = 0; j < boardSize.width; ++j )
corners.push_back(cv::Point3f(float( j*squareSize ), float( i*squareSize ), 0));
}
И затем используйте это:
std::vector<std::vector<cv::Point3f> > objectPoints(1);
CalcBoardCornerPositions(boardSize, squareSize, objectPoints[0]);
cv::stereoCalibrate(objectPoints, imagePointsA, imagePointsB, _cameraMatrixA, /// etc
2: Матрица камеры fx и fy на самом деле имеют фокусное расстояние умноженная по плотности пикселей в направлении x и y соответственно. Это означает
fx = f * cx
FY = F * Cy
где cx = imageSize.width / sensorSize.width и cy = imageSize.height / sensorSize.height.
Обычно cx == cy в современных камерах. Размер датчика вашей камеры вы можете найти в руководстве по эксплуатации камеры.
StereoCalibrate
это фактический размер вашего калибровочного шаблона, который вам нужно создать самостоятельно. Например, если у вас есть сетка для шахматной доски 6×5 с квадратами 3 мм, вам нужно создать матрицу, которая будет содержать положение каждого из углов, выраженное в системе отсчета на шахматной доске, например. [(0,0,0)(0,3,0)(0,6,0)...]
и так далее.fx
а также fy
по этому.