¿Qué es un valor de retorno" aceptable " de cv::calibrateCamera?


Antecedentes:

Actualmente estoy trabajando en un proyecto de stereo vision usando OpenCV. Estoy tratando de crear un mapa de disparidad a partir de un conjunto de dos imágenes rectificadas, pero no estoy obteniendo el resultado esperado. Al mirar las imágenes rectificadas, hay un notable desplazamiento vertical entre las imágenes, que no debería estar allí después de la rectificación. Actualmente estoy buscando cuál puede ser el error. Mi código se basa en la calibración estéreo y el código de correspondencia de el libro de OpenCV, y este ejemplo. Utilizo la interfaz C++ de OpenCV. Mi versión de OpenCV es 2.1, del repositorio Ubuntu 11.04.

Versión Corta de la pregunta:

Qué valor de retorno RMS es aceptable para la función:

double cv::calibrateCamera(...)

Actualmente calibra cada cámara usando un conjunto de ~20 pares de imágenes de tablero de ajedrez. Las cámaras son dos ojos PS3 idénticos (con una resolución de 640*480 píxeles) montados uno al lado del otro. cv::calibrateCamera devuelve un error RMS de entre 160 y 300 (He tenido resultados diferentes con diferentes conjuntos de imágenes). ¿Es este un valor aceptable para esta resolución de imagen o debería intentar obtener mejores imágenes de tablero de ajedrez?

Versión larga (detalles, ejemplos de código):

Para que funcione la visión estéreo; primero, quiero asegurarme de que la rutina de calibración de la cámara funcione correctamente. Utilizo una serie de imágenes de tablero de ajedrez para calibrar mi configuración estéreo, así:

// Find chessboard corners
cv::Mat left = ... //Load image
vector<cv::Point2f> points;

bool found = cv::findChessboardCorners(left, patternSize, points, CV_CALIB_CB_ADAPTIVE_THRESH | CV_CALIB_CB_NORMALIZE_IMAGE);
if(found)
  cv::cornerSubPix(left, points, cv::Size(11, 11), cv::Size(-1, -1), cv::TermCriteria(CV_TERMCRIT_EPS + CV_TERMCRIT_ITER, 30, 0.1));
imagePointsLeft.push_back(points);

Hago esto por un número de pares de imágenes y poner los puntos resultantes en imagePointsLeft y imagePointsRight. He ejecutado una verificación en un programa separado en las mismas imágenes donde confirmo visualmente que las imágenes izquierda y derecha registran correctamente todas las esquinas, en el mismo orden, utilizando cv::drawChessboardCorners. Para cada par de imágenes también relleno un conjunto de coordenadas de objeto de la siguiente manera:

vector<cv::Point3f> obj;
for(int i = 0; i < ny; i++)
  for(int j = 0; j < nx; j++)
    obj.push_back(cv::Point3f(i*squareSize,j*squareSize,0.0));
objectPoints.push_back(obj);

Luego intento calibrar las cámaras con estas imágenes:{[17]]}

double rms = cv::calibrateCamera(objectPoints, imagePointsLeft, m_imageSize, m_cameraMatrixLeft, m_distortionMatrixLeft, rvecsLeft, tvecsLeft);

Uso los intrínsecos de la cámara desde esta función cuando llamo a cv::stereoCalibrate usando la bandera CV_CALIB_FIX_INTRINSIC (esta forma de calibración estéreo se sugiere en la documentación, aquí).

Procedo a llamar cv::stereoRectify y cv::initUndistortRectifyMap, este último para ambas cámaras. Las imágenes rectificadas se producen con cv::remap utilizando la salida de initUndistortRectifyMap y una cámara livefeed. Ambas imágenes contienen solo píxeles válidos (sin áreas negras). Mi problema es que los píxeles de una fila dada no coinciden con la misma fila en la otra imagen (hay un ligero desplazamiento vertical). Esto hace que sea difícil obtener buenas resultados de algoritmos de correspondencia como StereoBM.

Author: Angie Quijano, 2011-05-13

1 answers

Hay un problema con la calibración de la cámara: cv::calibrateCamera() devuelve el error de reproyección del cuadrado medio raíz (RMS) [1] y debe estar entre 0.1 y 1.0 píxeles en una buena calibración. Para un punto de referencia, obtengo aproximadamente 0.25 px de error RMS usando mi cámara estéreo personalizada hecha de dos cámaras Playstation Eye sincronizadas por hardware que se ejecutan en la resolución de 640 x 480.

¿Está seguro de que las coordenadas de píxel devueltas por cv::findChessboardCorners() están en el mismo orden que las de obj? Si los ejes si se volteara, obtendría síntomas similares a los que está describiendo.

[1]: OpenCV calcula el error de reproyección proyectando puntos tridimensionales del tablero de ajedrez en la imagen utilizando el conjunto final de parámetros de calibración y comparando la posición de las esquinas. Un error RMS de 300 significa que, en promedio, cada uno de estos puntos proyectados está a 300 px de su posición real.

 24
Author: Michael Koval,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-04-04 17:32:21