Usando coincidencias del descriptor OpenCV con findFundamentalMat

Publiqué anteriormente con un problema relacionado con el mismo progtwig pero no recibí respuestas. Desde entonces he corregido el problema que estaba experimentando en ese momento, solo para enfrentar un problema nuevo.

Básicamente, estoy corrigiendo automáticamente los pares de imágenes estéreo para la rotación y la traducción utilizando un enfoque no calibrado. Utilizo algoritmos de detección de características como SURF para encontrar puntos en dos imágenes, un par de imágenes estéreo izquierda y derecha, y luego usar SURF nuevamente, coincido con los puntos entre las dos imágenes. Luego necesito usar estos puntos coincidentes para encontrar la matriz fundamental que puedo usar para corregir las imágenes.

Mi problema es este. Mis puntos coincidentes se almacenan en un solo vector de coincidencias de descriptores, que luego se filtran para valores atípicos. findFundamentalMat toma como entrada dos matrices separadas de puntos coincidentes. No sé cómo convertir de mi vector a mis dos matrices separadas.

cout << "< Matching descriptors..." << endl; vector filteredMatches; crossCheckMatching( descriptorMatcher, descriptors1, descriptors2, filteredMatches, 1 ); cout << filteredMatches.size() << " matches" << endl <" << endl; 

Se crea el vector.

 void crossCheckMatching( Ptr& descriptorMatcher, const Mat& descriptors1, const Mat& descriptors2, vector& filteredMatches12, int knn=1 ) { filteredMatches12.clear(); vector<vector > matches12, matches21; descriptorMatcher->knnMatch( descriptors1, descriptors2, matches12, knn ); descriptorMatcher->knnMatch( descriptors2, descriptors1, matches21, knn ); for( size_t m = 0; m < matches12.size(); m++ ) { bool findCrossCheck = false; for( size_t fk = 0; fk < matches12[m].size(); fk++ ) { DMatch forward = matches12[m][fk]; for( size_t bk = 0; bk < matches21[forward.trainIdx].size(); bk++ ) { DMatch backward = matches21[forward.trainIdx][bk]; if( backward.trainIdx == forward.queryIdx ) { filteredMatches12.push_back(forward); findCrossCheck = true; break; } } if( findCrossCheck ) break; } } } 

Las coincidencias se comprueban de forma cruzada y se almacenan dentro de filtrados.

 cout << "< Computing homography (RANSAC)..." << endl; vector points1; KeyPoint::convert(keypoints1, points1, queryIdxs); vector points2; KeyPoint::convert(keypoints2, points2, trainIdxs); H12 = findHomography( Mat(points1), Mat(points2), CV_RANSAC, ransacReprojThreshold ); cout <" << endl; 

La homografía se encuentra en función de un umbral que se establece en el tiempo de ejecución en el símbolo del sistema.

 //Mat drawImg; if( !H12.empty() ) // filter outliers { vector matchesMask( filteredMatches.size(), 0 ); vector points1; KeyPoint::convert(keypoints1, points1, queryIdxs); vector points2; KeyPoint::convert(keypoints2, points2, trainIdxs); Mat points1t; perspectiveTransform(Mat(points1), points1t, H12); for( size_t i1 = 0; i1 < points1.size(); i1++ ) { if( norm(points2[i1] - points1t.at((int)i1,0)) < 4 ) // inlier matchesMask[i1] = 1; } /* draw inliers drawMatches( leftImg, keypoints1, rightImg, keypoints2, filteredMatches, drawImg, CV_RGB(0, 255, 0), CV_RGB(0, 0, 255), matchesMask, 2 ); */ } 

Los partidos se filtran más para eliminar los valores atípicos.

…¿y entonces que? ¿Cómo divido lo que queda en dos Mat’s de puntos coincidentes para usar en findFundamentalMat?

EDITAR

Ahora he usado mi máscara para hacer un vector finalMatches como tal (esto reemplaza el procedimiento de filtrado final anterior):

 Mat drawImg; if( !H12.empty() ) // filter outliers { size_t i1; vector matchesMask( filteredMatches.size(), 0 ); vector points1; KeyPoint::convert(keypoints1, points1, queryIdxs); vector points2; KeyPoint::convert(keypoints2, points2, trainIdxs); Mat points1t; perspectiveTransform(Mat(points1), points1t, H12); for( i1 = 0; i1 < points1.size(); i1++ ) { if( norm(points2[i1] - points1t.at((int)i1,0)) < 4 ) // inlier matchesMask[i1] = 1; } for( i1 = 0; i1 < filteredMatches.size(); i1++ ) { if ( matchesMask[i1] == 1 ) finalMatches.push_back(filteredMatches[i1]); } namedWindow("matches", 1); // draw inliers drawMatches( leftImg, keypoints1, rightImg, keypoints2, filteredMatches, drawImg, CV_RGB(0, 255, 0), CV_RGB(0, 0, 255), matchesMask, 2 ); imshow("matches", drawImg); } 

Sin embargo, todavía no sé cómo dividir mi vector final de Matches DMatch en matrices Mat, que necesito incluir en findFundamentalMat, por favor, ayuda !!!

EDITAR

Solución de trabajo (tipo de)

 Mat drawImg; vector finalPoints1; vector finalPoints2; if( !H12.empty() ) // filter outliers { size_t i, idx; vector matchesMask( filteredMatches.size(), 0 ); vector points1; KeyPoint::convert(keypoints1, points1, queryIdxs); vector points2; KeyPoint::convert(keypoints2, points2, trainIdxs); Mat points1t; perspectiveTransform(Mat(points1), points1t, H12); for( i = 0; i < points1.size(); i++ ) { if( norm(points2[i] - points1t.at((int)i,0)) < 4 ) // inlier matchesMask[i] = 1; } for ( idx = 0; idx < filteredMatches.size(); idx++) { if ( matchesMask[idx] == 1 ) { finalPoints1.push_back(keypoints1[filteredMatches[idx].queryIdx].pt); finalPoints2.push_back(keypoints2[filteredMatches[idx].trainIdx].pt); } } namedWindow("matches", 0); // draw inliers drawMatches( leftImg, keypoints1, rightImg, keypoints2, filteredMatches, drawImg, CV_RGB(0, 255, 0), CV_RGB(0, 0, 255), matchesMask, 2 ); imshow("matches", drawImg); } 

Y luego introduzco finalPoints1 y finalPoints2 en findFundamentalMat como Mat’s. Ahora mi único problema es que mi salida no es remota como se esperaba, todas las imágenes están arruinadas: – /

La matriz de coincidencia son compensaciones en las matrices de descriptores. Como cada descriptor tiene un punto clave correspondiente, puede simplemente iterar y construir dos matrices de puntos clave a partir de los índices. Estos puntos clave pueden luego introducirse en findFundamentalMat.

Editar:

Creo que su error está en la generación de las FinalMatches donde está perdiendo información. El vector filterMatches está sobrecargado. Los índices en los que matchMask is 1 muestra los índices en los puntos clave1, mientras que los índices almacenados en finalMatches son los índices en los puntos clave2. Al presionar hacia abajo en FinalMatches, en efecto estás perdiendo el primer conjunto de índices.

Intenta lo siguiente:

Tenga un bucle que cuente cuántas coincidencias reales hay:

 int num_matches = 0; for( int idx = 0; idx < matchesMask.size(); idx++ ) { if ( matchesMask[idx] == 1 ) num_matches++; } 

Ahora declare CvMats de tamaño correcto:

 matched_points1 = cvCreateMat(2,numPoints,CV_32F); matched_points2 = cvCreateMat(2,numPoints,CV_32F); 

Ahora itere sobre los Matches filtrados e inserte: (la syntax exacta puede diferir, se entiende la idea)

 offset = 0; for (int idx = 0; idx < matchesMask.size(); idx++) { if ( matchesMask[idx] == 1 ) { matched_points1[2*offset] = keypoints1[idx].pt.x; matched_points1[2*offset+1] = keypoints1[idx].pt.y; matched_points2[2*offset] = keypoints2[filteredMatches[idx]].pt.x; matched_points2[2*offset+1] = keypoints2[filteredMatches[idx]].pt.y; offset++; } }