2017-07-05 6 views
0

J'ai créé un programme qui peut assembler plusieurs images et je cherche maintenant à améliorer l'efficacité de celui-ci. Selon la taille de l'image assemblée, elle est éventuellement trop grande et contient trop de points-clés pour que la machine ne dispose plus de mémoire allouable. Pour compenser cela mon objectif est de stocker tous les points clés et les descripteurs comme ils se trouvent pour que je ne ai pas besoin de les retrouver dans l'image maître cousu et seulement besoin de les trouver dans la nouvelle image étant cousue. J'ai eu ce processus fonctionnant en python mais n'ai pas eu la même chance en C++. Pour ce faire, je dois effectuer un perspectiveTransform() sur les points-clés et par conséquent les convertir de vector<keypoint> à vector<point2f> et de nouveau à vector<keypoint>. J'ai été capable de réaliser ceci et peux confirmer que cela fonctionne (choisir pour suivre). Je ne sais pas si le même processus doit être fait pour les descripteurs (actuellement je don mais soit son mal ou pas efficace). Problème: lorsque j'exécute cela, les keypoints et les descripteurs ne semblent pas fonctionner et je lance une erreur que j'ai créée étant: "Pas assez de correspondances trouvées", même si je sais qu'au moins les keypoints font leur chemin vers la fonction .OpenCV C++ créer ensemble réutilisable de descripteurs et points clés pour piquer plusieurs images

Voici le code pour les transforme et descripteurs points-clés. Le code calcule d'abord le warpPerspective à appliquer à l'image un car l'homographie ne déformera que la deuxième image. Le reste du codd traite des keypoints et des descripteurs.

tuple<Mat, vector<KeyPoint>, Mat> stitchMatches(Mat image1,Mat image2, Mat homography, vector<KeyPoint> kp1, vector<KeyPoint> kp2 , Mat desc1, Mat desc2){ 
    Mat result, destination, descriptors_updated; 
    vector<Point2f> fourPoint; 
    vector<KeyPoint> keypoints_updated; 

    //-Get the four corners of the first image (master) 
    fourPoint.push_back(Point2f (0,0)); 
    fourPoint.push_back(Point2f (image1.size().width,0)); 
    fourPoint.push_back(Point2f (0, image1.size().height)); 
    fourPoint.push_back(Point2f (image1.size().width, image1.size().height)); 
    //perspectiveTransform(Mat(fourPoint), destination, homography); 


    //- Get points used to determine Htr 
    double min_x, min_y, tam_x, tam_y; 
    float min_x1, min_x2, min_y1, min_y2, max_x1, max_x2, max_y1, max_y2; 
    min_x1 = min(fourPoint.at(0).x, fourPoint.at(1).x); 
    min_x2 = min(fourPoint.at(2).x, fourPoint.at(3).x); 
    min_y1 = min(fourPoint.at(0).y, fourPoint.at(1).y); 
    min_y2 = min(fourPoint.at(2).y, fourPoint.at(3).y); 
    max_x1 = max(fourPoint.at(0).x, fourPoint.at(1).x); 
    max_x2 = max(fourPoint.at(2).x, fourPoint.at(3).x); 
    max_y1 = max(fourPoint.at(0).y, fourPoint.at(1).y); 
    max_y2 = max(fourPoint.at(2).y, fourPoint.at(3).y); 
    min_x = min(min_x1, min_x2); 
    min_y = min(min_y1, min_y2); 
    tam_x = max(max_x1, max_x2); 
    tam_y = max(max_y1, max_y2); 

    //- Htr use to map image one to result in line with the alredy warped image 1 
    Mat Htr = Mat::eye(3,3,CV_64F); 
    if (min_x < 0){ 
     tam_x = image2.size().width - min_x; 
     Htr.at<double>(0,2)= -min_x; 
    } 
    if (min_y < 0){ 
     tam_y = image2.size().height - min_y; 
     Htr.at<double>(1,2)= -min_y; 
    } 

    result = Mat(Size(tam_x*2,tam_y*2), CV_8UC3,cv::Scalar(0,0,0)); 
    warpPerspective(image2, result, Htr, result.size(), INTER_LINEAR, BORDER_TRANSPARENT, 0); 
    warpPerspective(image1, result, (Htr*homography), result.size(), INTER_LINEAR, BORDER_TRANSPARENT,0); 



    //-- Variables to hold the keypoints at the respective stages 
    vector<Point2f> kp1Local,kp2Local; 
    vector<KeyPoint> kp1updated, kp2updated; 


    //Localize the keypoints to allow for perspective change 
    KeyPoint::convert(kp1, kp1Local); 
    KeyPoint::convert(kp2, kp2Local); 

    //perform persepctive transform on the keypoints of type vector<point2f> 
    perspectiveTransform(kp1Local, kp1Local, (Htr)); 
    perspectiveTransform(kp2Local, kp2Local, (Htr*homography)); 


    //convert keypoints back to type vector<keypoint> 
    for(size_t i = 0; i < kp1Local.size(); i++) { 
     kp1updated.push_back(KeyPoint(kp1Local[i], 1.f)); 
    } 
    for(size_t i = 0; i < kp2Local.size(); i++) { 
     kp2updated.push_back(KeyPoint(kp2Local[i], 1.f)); 
    } 

    //Add to master of list of keypoints to be passed along during next iteration of image 
    keypoints_updated.reserve(kp1updated.size() + kp2updated.size()); 
    keypoints_updated.insert(keypoints_updated.end(),kp1updated.begin(),kp1updated.end()); 
    keypoints_updated.insert(keypoints_updated.end(),kp2updated.begin(),kp2updated.end()); 

    //WarpPerspective of decriptors to match that of the images and cooresponding keypoints 
    Mat desc1New, desc2New; 
    warpPerspective(desc2, desc2New, Htr, result.size(), INTER_LINEAR, BORDER_TRANSPARENT, 0); 
    warpPerspective(desc1, desc1New, (Htr*homography), result.size(), INTER_LINEAR, BORDER_TRANSPARENT,0); 

    //create a new Mat including the descriports from desc1 and desc2 
    descriptors_updated.push_back(desc1New); 
    descriptors_updated.push_back(desc2New); 


    //------------TEST TO see if keypoints have moved 

    Mat img_keypoints; 
    drawKeypoints(result, keypoints_updated, img_keypoints, Scalar::all(-1), DrawMatchesFlags::DEFAULT); 

    imshow("Keypoints 1", img_keypoints); 
    waitKey(); 
    destroyAllWindows(); 



    return {result, keypoints_updated, descriptors_updated}; 
} 

Le code suivant est mon programme d'assemblage principal qui effectue l'assemblage réel.

tuple<Mat,vector<KeyPoint>,Mat> stitch(Mat img1,Mat img2 ,vector<KeyPoint> keypoints, Mat descriptors, String featureDetection,String featureExtractor,String keypointsMatcher,String showMatches){ 

    Mat desc, desc1, desc2, homography, result, croppedResult,descriptors_updated; 
    std::vector<KeyPoint> keypoints_updated, kp1, kp2; 
    std::vector<DMatch> matches; 
    //-Base Case[2] 
    if (keypoints.empty()){ 

     //-Detect Keypoints and their descriptors 
     tie(kp1,desc1) = KeyPointDescriptor(img1, featureDetection,featureExtractor); 
     tie(kp2,desc2) = KeyPointDescriptor(img2, featureDetection,featureExtractor); 

     //Find matches and calculated homography based on keypoints and descriptors 
     std::tie(matches,homography) = matchFeatures(kp1, desc1,kp2, desc2, keypointsMatcher); 
     //draw matches if requested 
     if(showMatches == "true"){ 
      drawMatchedImages(img1, kp1, img2, kp2, matches); 
     } 
     //stitch the images and update the keypoint and descriptors 
     std::tie(result,keypoints_updated,descriptors_updated) = stitchMatches(img1, img2, homography,kp1,kp2,desc1,desc2); 
     //crop function using created cropping function 
     croppedResult = crop(result); 
     return {croppedResult,keypoints_updated,descriptors_updated}; 

    } 

    //base case[3:n] 
    else{ 

     //Get keypoints and descriptors of new image and add to respective lists 
     tie(kp2,desc2) = KeyPointDescriptor(img2, featureDetection,featureExtractor); 

     //find matches and determine homography 
     std::tie(matches,homography) = matchFeatures(keypoints_updated,descriptors_updated,kp2,desc2, keypointsMatcher); 
     //draw matches if requested 
     if(showMatches == "true") 
      drawMatchedImages(img1, keypoints, img2, kp2, matches); 

     //stitch the images and update the keypoint and descriptors 
     tie(result,keypoints_updated,descriptors_updated) = stitchMatches(img1, img2, homography,keypoints,kp2,descriptors,desc2); 
     //crop function using created cropping function 
     croppedResult = crop(result); 
     return {croppedResult,keypoints_updated,descriptors_updated}; 
     } 
} 

Enfin, voici l'image des points-clés qui sont transformés sur l'image cousue. Toute aide est tellement appréciée!

enter image description here

Répondre

1

Après passer au peigne fin le Je vient de se trouver que j'utilisais la mauvaise variable à un moment donné! :)