Question

J'ai un ensemble d'images et je souhaite faire une collision croisée entre tous et afficher les résultats à l'aide des barres de track utilisant OPENCV 2.4.6 (colis hydro-ros). La partie correspondante est effectuée à l'aide d'un vecteur de vecteurs de vecteurs de CV :: dmatch-Objects:

image[0] --- image[3] -------- image[8] ------ ...
   |             |                 |
   |         cv::DMatch-vect   cv::DMatch-vect
   |
image[1] --- ...
   |
image[2] --- ...
   |
  ...
   |
image[N] --- ...

Parce que nous omettons faire correspondre une image avec elle-même (point de vue de le faire) et car une image de requête peut ne pas être assortie à tout le reste de chaque ensemble d'images de train assorties pour une image de requête peut avoir une taille différente du reste. Notez que la façon dont il est implémenté à droite, je correspond à deux fois une paire d'images deux fois, ce qui n'est bien sûr pas optimal (surtout que j'ai utilisé un correspondeur bruteforce avec une vérification croisée allumée, ce qui signifie essentiellement que je correspond à une paire d'images 4 fois! ) Mais pour le moment c'est ça. Afin d'éviter le dessin à la volée des paires d'images correspondantes, j'ai peuplé un vecteur de vecteurs de CV :: Mat-objets. Chaque CV :: Tapis représente l'image de requête actuelle et une image de train correspondante (je le peuplie à l'aide de CV :: Drawmatches ()):

image[0] --- cv::Mat[0,3] ---- cv::Mat[0,8] ---- ...
   |
image[1] --- ...
   |
image[2] --- ...
   |
  ...
   |
image[N] --- ...

note : dans l'exemple ci-dessus CV :: mat [0,3] signifie CV :: Tapis qui stocke le produit de CV :: Drawmatches () à l'aide de l'image [0] et de l'image [ 3].

Voici les paramètres de l'interface graphique:

  • Fenêtre principale: Ici, j'affiche ici l'image de requête en cours. Utilisation d'une barre de traquise - appelons-le pack_query - i Itérer à travers chaque image de mon ensemble.
  • Fenêtre secondaire: Ici, j'affiche ici la paire assortie (requête, train), où la combinaison entre le curseur de Track_Query et la position du curseur d'une autre barre de suivi dans cette fenêtre - appelons-le sur track_train - me permet de parcourir Toutes les images CV :: Match-Match pour l'image de requête en cours.

Le problème ici vient du fait que chaque requête peut avoir un nombre variable d'images de train assorties. Mon track_train devrait pouvoir s'adapter au nombre d'images de train assorties, c'est-à-dire le nombre d'éléments dans chaque CV :: mat-vecteur pour l'image de requête en cours. Malheureusement jusqu'à présent, je n'ai pas pu trouver un moyen de faire ça. La CV :: CreateTrackbar () nécessite un paramètre de compte, qui de ce que je vois définit la limite du curseur de la barre de chèque et ne peut pas être modifié ultérieurement. Corrige-moi si je me trompe depuis que c'est exactement ce qui me dérange. Une solution possible (moins élégante et impliquant diverses vérifications pour éviter les erros hors de portée) est de prendre la taille du plus grand ensemble d'images de train assorties et de l'utiliser comme limite pour mon track_train. Je voudrais éviter de le faire si possible. Une autre solution possible implique la création d'une barre de suivi par image de requête avec la plage de valeurs appropriée et échanger chacune dans mes fenêtres secondaires en fonction de l'image de requête sélectionnée. Pour l'instant, cela semble être le moyen le plus facile d'aller mais pose une grande surcharge de barres de chenquage sans parler de ce fait que je n'ai pas entendu parler de OpenCV vous permettant de masquer des contrôles de l'interface graphique. Voici deux exemples qui pourraient clarifier des choses un peu plus:

exemple 1: Dans la fenêtre principale, je sélectionne l'image 2 à l'aide de Track_Query. Pour cette image, j'ai réussi à faire correspondre 5 autres images de mon ensemble. Disons que ce sont les images 4, 10, 17, 18 et 20. La fenêtre secondaire se met automatiquement mise à jour et me montre la correspondance entre l'image 2 et l'image 4 (premier dans le sous-ensemble des images de train assorties). Track_train doit aller de 0 à 4. Déplacement du curseur dans les deux sens permet de passer à la mise à jour de l'image 4, 10, 17, 18 et 20 à chaque fois la fenêtre secondaire.

exemple 2: Dans la fenêtre principale, je sélectionne l'image 7 à l'aide de Track_Query. Pour cette image, j'ai réussi à faire correspondre 3 autres images de mon ensemble. Disons que ce sont des images 0, 1, 11 et 19. La fenêtre secondaire met à jour automatiquement et montre moi la correspondance entre l'image 2 et l'image 0 (premier dans le sous-ensemble des images de train assorties). Track_Train doit aller de 0 à 2. Déplacement du curseur dans les deux sens permettez-moi de passer par l'image 0, 1, 1 et 19 Mise à jour de chaque fois la fenêtre secondaire.

Si vous avez des questions, n'hésitez pas à demander et je vais y répondre aussi bien que je peux. Merci d'avance!

PS: Malheureusement, la manière dont le paquet ROS est-il au minimum de ce que OPENCV peut offrir. Pas d'intégration QT, pas d'OpenMP, non OpenGL, etc.

Était-ce utile?

La solution

Après plus de recherches, je suis à peu près sûr que cela n'est pas possible. C'est pourquoi j'ai mis en place la première proposition que j'ai donnée dans ma question - utilisez le vecteur de match avec le plus grand nombre de matchs pour déterminer une taille maximale pour la barre de capture, puis utilisez quelques vérifications pour éviter les exceptions à portée de gamme. Vous trouverez ci-dessous une description plus ou moins détaillée comment tout cela fonctionne. Étant donné que la procédure de correspondance de mon code implique des contrôles supplémentaires qui ne concernent pas le problème à la main, je vais la sauter ici. Notez que, dans un ensemble donné d'images, nous voulons faire correspondre, je vous reproche à une image en tant qu'hôte-image lorsque cette image (exemple: carte) est actuellement assortie à une image de scène (exemple: un ensemble de cartes) - Niveau supérieur de la Matchs-Vector (voir ci-dessous) et égal à l'index dans TRANSEDIMAGES (voir ci-dessous). Je trouve la notation train / requête à OpenCV un peu déroutant. Cette scène / objet notation est prise de http://docs.opencv.org /doc/tatudials/feats2D/feature_homography/freatu_homography.html . Vous pouvez modifier ou échanger la notation à votre goût, mais assurez-vous de le changer partout en conséquence, sinon vous risquez de vous retrouver avec des résultats étranges.

// stores all the images that we want to cross-match
std::vector<cv::Mat> processedImages;
// stores keypoints for each image in processedImages
std::vector<std::vector<cv::Keypoint> > keypoints;
// stores descriptors for each image in processedImages 
std::vector<cv::Mat> descriptors;

// fill processedImages here (read images from files, convert to grayscale, undistort, resize etc.), extract keypoints, compute descriptors
// ...

// I use brute force matching since I also used ORB, which has binary descriptors and HAMMING_NORM is the way to go
cv::BFmatcher matcher;
// matches contains the match-vectors for each image matched to all other images in our set
// top level index matches.at(X) is equal to the image index in processedImages
// middle level index matches.at(X).at(Y) gives the match-vector for the Xth image and some other Yth from the set that is successfully matched to X
std::vector<std::vector<std::vector<cv::DMatch> > > matches;
// contains images that store visually all matched pairs
std::vector<std::vector<cv::Mat> > matchesDraw;

// fill all the vectors above with data here, don't forget about matchesDraw
// stores the highest count of matches for all pairs - I used simple exclusion by simply comparing the size() of the current std::vector<cv::DMatch> vector with the previous value of this variable
long int sceneWithMaxMatches = 0;
// ...

// after all is ready do some additional checking here in order to make sure the data is usable in our GUI. A trackbar for example requires AT LEAST 2 for its range since a range (0;0) doesn't make any sense
if(sceneWithMaxMatches < 2)
  return -1;

// in this window show the image gallery (scene-images); the user can scroll through all image using a trackbar
cv::namedWindow("Images", CV_GUI_EXPANDED | CV_WINDOW_AUTOSIZE);
// just a dummy to store the state of the trackbar 
int imagesTrackbarState = 0;
// create the first trackbar that the user uses to scroll through the scene-images
// IMPORTANT: use processedImages.size() - 1 since indexing in vectors is the same as in arrays - it starts from 0 and not reducing it by 1 will throw an out-of-range exception
cv::createTrackbar("Images:", "Images", &imagesTrackbarState, processedImages.size() - 1, on_imagesTrackbarCallback, NULL);
// in this window we show the matched object-images relative to the selected image in the "Images" window
cv::namedWindow("Matches for current image", CV_WINDOW_AUTOSIZE);
// yet another dummy to store the state of the trackbar in this new window
int imageMatchesTrackbarState = 0;
// IMPORTANT: again since sceneWithMaxMatches stores the SIZE of a vector we need to reduce it by 1 in order to be able to use it for the indexing later on
cv::createTrackbar("Matches:", "Matches for current image", &imageMatchesTrackbarState, sceneWithMaxMatches - 1, on_imageMatchesTrackbarCallback, NULL);

while(true)
{
  char key = cv::waitKey(20);
  if(key == 27)
    break;

  // from here on the magic begins
  // show the image gallery; use the position of the "Images:" trackbar to call the image at that position
  cv::imshow("Images", processedImages.at(cv::getTrackbarPos("Images:", "Images")));

  // store the index of the current scene-image by calling the position of the trackbar in the "Images:" window
  int currentSceneIndex = cv::getTrackbarPos("Images:", "Images");
  // we have to make sure that the match of the currently selected scene-image actually has something in it
  if(matches.at(currentSceneIndex).size())
  {
    // store the index of the current object-image that we have matched to the current scene-image in the "Images:" window
    int currentObjectIndex = cv::getTrackbarPos("Matches:", "Matches for current image");
    cv::imshow(
            "Matches for current image",
            matchesDraw.at(currentSceneIndex).at(currentObjectIndex < matchesDraw.at(currentSceneIndex).size() ? // is the current object index within the range of the matches for the current object and current scene
            currentObjectIndex : // yes, return the correct index
            matchesDraw.at(currentSceneIndex).size() - 1));  // if outside the range show the last matched pair!
  }
}

// do something else
// ...

La partie délicate est la barre de chèque de la deuxième fenêtre responsable de l'accès aux images correspondantes à notre image actuellement sélectionnée dans la fenêtre "Images". Comme je l'ai expliqué ci-dessus, j'ai défini la barre de troisième barre "dans la fenêtre" correspondant à l'image actuelle "pour avoir une plage de 0 à (ScenewithMaxMatches-1). Cependant, toutes les images n'ont pas la même quantité de correspondances avec le reste de l'image de l'image (s'applique Tenfold si vous avez effectué un filtrage supplémentaire pour assurer des correspondances fiables, par exemple en exploitant les propriétés de l'homographie, Test de ratio, une vérification de distance min / max, etc. .). Parce que je n'ai pas pu trouver un moyen d'ajuster dynamiquement la plage de la barre de trousse, j'avais besoin d'une validation de l'index. Sinon, pour certaines des images et leurs matchs, l'application lancera une exception hors de portée. Cela est dû au fait simple que, pour certains matchs, nous essayons d'accéder à un vecteur de match avec un index supérieur à celui de la taille 1 parce que CV :: getrackbarpos () va jusqu'au (ScenewithMaxMatches - 1). Si la position de la barre de traquillage est hors de portée du vecteur actuellement sélectionné avec des correspondances, je définit simplement l'image MatchDraw dans "Matchs pour l'image actuelle" au dernier vecteur. Ici, j'exploite le fait que l'indexation ne peut pas aller au-dessous de zéro ainsi que la position de la barre de capture, il n'est donc pas nécessaire de vérifier cela, mais seulement ce qui vient après la position initiale 0. Si ce n'est pas votre cas, assurez-vous de vérifier le bas lié aussi et non seulement la partie supérieure.

J'espère que cela vous aidera!

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top