Partage
  • Partager sur Facebook
  • Partager sur Twitter

Conversion vector en tableau

Sujet résolu
    25 octobre 2021 à 9:50:36

    Bonjour, j'ai un vector<Point> = [A,B ; C,D ; E,F; G,H] que j'aimerais convertir en array. J'ai donc créé un tab tel que int tab[4][4] . J'ai essayé de faire par une boucle for, puis la méthode copy(Point.begin(),Point.end(),tab) et avec memcpy, cela ne fonctionne pas. Auriez vous une solution ? Merci
    • Partager sur Facebook
    • Partager sur Twitter
      25 octobre 2021 à 10:11:50

      En c++ on évite d'utiliser les tableaux à la C comme int[4][4] mais on privilégiera les containeurs de la STL en faisant éventuellement des tableaux de struct plutôt que des tableaux à deux dimensions (qui sont juste des tableaux e tableaux)

      Pour une structure simple telle qu'un point (qu'il soit 2D ou 3D), avoir un std::vector<Point> me semble donc être une bonne chose. Si tu connais le nombre de point que tu auras à l'avance, std::array<Point,4> fait l'affaire 

      Sans info supplémentaire, difficile de dire si ta volonté de te ramener à un tableau int[4][4] est légitime ou farfelue. On est dans le cas d'un problèmeXY.

      Tu nous poses une question sur la solution Y que tu veux implémenter pour résoure ton problème X mais tu ne nous explique pas le problème X.

      Commence par nous expliquer ton problème de base avant de nous proposer ta tentative de solution et peut-être qu'on se rendra compte qu'il existe une bien meilleure solution que ce que tu essayes de faire avec du code C-style

      • Partager sur Facebook
      • Partager sur Twitter
        25 octobre 2021 à 10:12:46

        C'est des points dans la quatrième dimension ?

        #include <algorithm>
        #include <vector>
        #include <array>
        
        struct Point
        {
            int x;
            int y;
        };
        
        int main()
        {
            std::vector<Point> vp;
            std::array<Point, 4> ap;
            std::copy_n(vp.begin(), 4, ap.begin());
        
            return 0;
        }
        



        • Partager sur Facebook
        • Partager sur Twitter
          25 octobre 2021 à 10:29:09

          Je fais une détection de QR Code sur une image. Cette détection me donne un vector<Point> points.

          J'aimerais exploiter ces points il me semblait judicieux de les mettre dans un array après cette détection et donc de les copier.

          -
          Edité par Tuson 25 octobre 2021 à 10:31:20

          • Partager sur Facebook
          • Partager sur Twitter
            25 octobre 2021 à 10:53:13

            Qu'est ce qu'un tableau à la C te permettrait de faire qu'un std::vector ne te permet pas ?

            A priori rien, à moins d'interfacer son code C++ avec du code ou une interface C existante, on ne fait jamais ce que tu essayes de faire.

            Les containeurs de la bibliothèque standard te permettent de faire tout ce que les tableaux C permettent et même plus. Ils apportent aussi beaucoup plus de sécurité et t'empêchant (entre autre) d'accéder à des indices hors limite du tableau

            Avec le peu d'info à ma disposition je dirais que c'est une mauvaise idée de vouloir glisser du C dans ton code C++, ca ne t'apportera rien de plus à part des risques d'erreurs

            -
            Edité par ThibaultVnt 25 octobre 2021 à 10:57:08

            • Partager sur Facebook
            • Partager sur Twitter
              25 octobre 2021 à 11:00:19

              Si par exemple je veux récupérer la valeur en X je devrais écrire points[1][1] or cela ne fonctionne pas. Donc je me suis dis en mettant ces valeurs dans un array je pourrais mieux récupérer les valeurs.. Je me trompe peut être...

              -
              Edité par Tuson 25 octobre 2021 à 11:01:22

              • Partager sur Facebook
              • Partager sur Twitter
                25 octobre 2021 à 11:41:45

                Est ce que tu peux montrer ton code stp ?

                Parce que là je te répond en ne faisant que des suppositions sur ce que tu as et sur ce que tu essayes de faire

                Montre moi comment tu construits ton std::vector<Point> et montre moi les traitements que tu essayes de faire dessus stp 

                • Partager sur Facebook
                • Partager sur Twitter
                  25 octobre 2021 à 11:46:48

                  #include "code.hpp"
                  
                  
                  //using std::vector; 
                   
                  //using std::data;
                  
                  //using std::string; 
                  
                  std::ofstream logfile_detected("_logfile_detected.txt",std::ios::out);
                  
                  using namespace zbar;
                  using namespace cv;
                  using namespace std;
                  
                  typedef struct 
                  {
                  	string type; 
                  	string data; 
                  	vector <Point> location; 
                  }decodeObject;
                  
                  //char* char_array; 
                  
                  
                  void decode(Mat &img, vector<decodeObject>&decodeObjects, int &detected, char &chaine) 
                  {
                  	ImageScanner scanner;
                  	
                  	scanner.set_config(zbar::ZBAR_NONE, zbar::ZBAR_CFG_ENABLE, 1); 
                  	
                  	Mat imgGray; 
                  	cvtColor(img, imgGray, COLOR_BGR2GRAY); 
                  	
                  	zbar::Image image (img.cols, img.rows, "Y800", (uchar *)imgGray.data, img.cols * img.rows); 
                  	
                  	int n = scanner.scan(image); 
                  	
                  	for(Image::SymbolIterator symbol = image.symbol_begin(); symbol != image.symbol_end(); ++symbol)
                  	{
                  		decodeObject obj; 
                  		
                  		obj.type = symbol->get_type_name(); 
                  		obj.data = symbol-> get_data(); 
                  		
                  		int n = (obj.data).length(); 
                  		char char_array[n+1];
                  		
                  
                  		strcpy(char_array,(obj.data).c_str());
                  		//cout<<char_array<<endl;
                  		//std::cout<<"Type : " << obj.type << std::endl; 
                  		//std::cout<<"Data : " << obj.data << std::endl; 
                  		
                  		
                  		if (strcmp(char_array,&chaine)==0){
                  			detected = 1; 
                  		}	
                  
                  		
                  		for (int i =0; i < symbol->get_location_size(); i++)
                  		{
                  			obj.location.push_back(Point(symbol->get_location_x(i),symbol->get_location_y(i)));
                  		}
                  		
                  		decodeObjects.push_back(obj); 
                  		
                  	}
                  }
                  
                  void display(Mat &img, vector<decodeObject>&decodeObjects, Mat &img_copy) 
                  {
                  	
                  	img_copy = img.clone();
                  	
                  	for(int i =0; i<decodeObjects.size(); i++)
                  	{
                  		vector<Point> points = decodeObjects[i].location;
                  		vector<Point> hull; 
                  		
                  		if(points.size() > 4)
                  			convexHull(points, hull);
                  		else
                  			hull = points; 
                  			
                  		int n = hull.size(); 
                  		cout<<"hull = "<<hull<<endl;
                  		
                  		for(int j=0; j < n; j++)
                  		{
                  			line(img_copy,hull[j], hull[ (j+1) %n], cv::Scalar(255,0,0),3); 
                  			
                  		}
                  		imwrite("QR_code.jpg", img_copy);
                  		
                  		
                  		
                  
                  		
                  		
                  		
                  		
                  		
                  	}
                  	
                  }
                  
                  void scan(Mat& img,Mat& img_copy,int &detected,char &chaine)
                  {
                  	vector<decodeObject> decodeObjects; 
                  	decode(img, decodeObjects,detected,chaine); 
                  	display(img,decodeObjects,img_copy); 
                  }	
                  

                  Voila mon code. Je veux récupérer les valeurs de hull. Accéder à l'élément [0][0] par exemple.

                  • Partager sur Facebook
                  • Partager sur Twitter
                    25 octobre 2021 à 12:06:58

                    memcpy ça ne peux fonctionner qu'avec de simples structs qui sont "trivially copyable". D'une manière en général en C++, tu peux oublier cette technique. std::copy fera le nécessaire pour que les objets soient correctement copiés quels qu’ils soient.

                    Dans tous les cas, tu ne peux pas faire ce que tu veux, car cv::Point ne définit pas operator[], donc il faut manuellement aller chercher le "x" et le "y". Ou faire un wrapper. Aussi, la variable "hull" n'a pas forcément besoin de contenir de la mémoire quand elle fait juste référence à "points", dans ce cas, il est préférable de faire un std::move pour éviter de copier les points, mais ce n'est pas bon non plus.

                    • Partager sur Facebook
                    • Partager sur Twitter
                      25 octobre 2021 à 12:27:11

                      D'après la doc d'OpenCV (https://docs.opencv.org/4.5.3/db/d4e/classcv_1_1Point__.html)

                      Point est un typedef vers la classe Point2i qui est lui même un typdef vers le type cv::Point<int>. Si on regarde la doc de cette classe elle est composé de 2 champ publics x et y

                      Tu peux donc y accéder en lecture et écriture comme ceci : 

                      Point p{}; // création d'un point vide
                      p.x = 10;  // Affectation
                      p.y = 5;
                      
                      std::cout << p.x << " : " << p.y

                      Point ne connait pas l'opérateur [] c'est pour ça que tu ne peux pas faire de std::cout<<points[1][1]

                      std::cout << points[1].x << std::endl;
                      std::cout << points[1].y << std::endl;

                      Devrait marcher pour afficher les coordonnées x et y du 2ème point de ton std::vector


                      • Partager sur Facebook
                      • Partager sur Twitter
                        25 octobre 2021 à 13:12:46

                        JadeSalina a écrit:

                        mais ce n'est pas bon non plus.


                        Ce que je veux dire par là, c'est que la variable "hull" permet juste de choisir l'un ou l'autre des vector, de manière à ce que le code qui suit ne se pose pas la question de quel vector il manipule, c'est le même quelque soit le vector derrière.

                        Dans ce cas, la variable "hull" devrait plutôt être une référence sur l'un ou l'autre des vector. En supposant que "convexHull" retourne un nouveau vector contenant le résultat, on pourrait faire un truc comme ça :

                        vector<Point> points = decodeObjects[i].location;
                        const auto& hull = points.size() > 4 ? convexHull(points) : points;

                        Ou alors utiliser une lambda qui renvoie directement le résultat (utile si il y a + qu'une seule condition) :

                        vector<Point> points = decodeObjects[i].location;
                        const auto& hull = [&]() {
                            if (points.size() > 4)
                                return convexHull(points);
                            else
                                return points; 
                        }();

                        Ou encore, faire tout simplement une fonction qui effectue le traitement, et lui passer les bons paramètres en fonction de la situation :

                        void traitement(const std::vector<cv::Point>& hull, cv::Mat& img_copy)
                        {
                            int n = hull.size();
                            cout<<"hull = "<<hull<<endl;
                                
                            for(int j=0; j < n; j++)
                            {
                                line(img_copy,hull[j], hull[ (j+1) %n], cv::Scalar(255,0,0),3);
                            }
                            imwrite("QR_code.jpg", img_copy);
                        }
                        
                        void display(...)
                        {
                            img_copy = img.clone();
                            
                            for(int i=0; i<decodeObjects.size(); i++)
                            {
                                std::vector<cv::Point> points = decodeObjects[i].location;
                        
                                if(points.size() > 4)
                                    traitement(convexHull(points, hull), img_copy);
                                else
                                    traitement(points, img_copy);
                            }
                        }

                        A noter que tu peux modifier facilement la manière 2 et 3 pour garder ta fonction "convexHull" qui ne renvoie pas de nouveau vector (mais d'ailleurs pourquoi ne pas lui faire renvoyer un nouveau vector ?)

                        Et aussi, je pense que tu ne veux pas faire des "using namespace", même si c'est tentant à première vue de ne pas avoir à tout préfixer, ça reste bien d'être clair sur d'où vienne les éléments, surtout si on utilise beaucoup de librairies

                        • Partager sur Facebook
                        • Partager sur Twitter
                          25 octobre 2021 à 13:23:43

                          Merci pour toutes vos réponses. Mais je ne vois toujours pas comment je peux accéder à mes éléments. Ce n'est pas très clair dans ma tête 🤕
                          • Partager sur Facebook
                          • Partager sur Twitter
                            25 octobre 2021 à 13:31:52

                            hull est un vector de Point

                            Point est une classe qui contient deux attributes publics x et y

                            Donc tu fais hull[0] pour accéder au 1er Point de ton vector, tu fais hull[2] pour accéder au 3ème point de ton vector

                            si tu veux changer la valeur de x dans ton premier point tu fais hull[0].x = ....

                            Si tu veux utiliser (affichage, calcul, ect ...) la valeur de y de ton 2ème point tu fais par exemple 

                            int var = hull[1].y * 2

                            Ici je stock dans une nouvelle variable le double de la valeur y de ton 2ème point 

                            Tu as déjà fait le plus compliqué : récupérer un tableau de points

                            Pour utiliser ou accéder aux valeurs de tes éléments tu n'as rien de compliqué à faire, juste utiliser .x et .y sur des Points

                            • Partager sur Facebook
                            • Partager sur Twitter
                              25 octobre 2021 à 13:41:47

                              Oui j'ai compris. Ca fonctionne ! Mais, je suis embeter pour transférer mon "vector" de mon code.cpp à mon main... Comment je dois le déclarer dans ma fonction ? Car si je fais "vector<Point>hull"  forcement cela ne fonctionne pas..

                              -
                              Edité par Tuson 25 octobre 2021 à 13:59:00

                              • Partager sur Facebook
                              • Partager sur Twitter
                                25 octobre 2021 à 14:08:19

                                Un simple return ?

                                Ta fonction serait déclarée

                                vector<Point> display (...){
                                ... return hull; }

                                et donc également

                                vector<Point> scan (...) {...}

                                Et donc dans le main quelque chose comme

                                vector <Point> hull = scan (...);


                                Mais il y a peut-être mieux, je ne sais pas.

                                • Partager sur Facebook
                                • Partager sur Twitter

                                La gentillesse est le langage qu'un sourd peut entendre et qu'un aveugle peut voir.

                                Il n'y a qu'un seul monde et il est faux, cruel, contradictoire, séduisant et dépourvu de sens. Un monde ainsi constitué est le monde réel. Nous avons besoin de mensonges pour conquérir cette réalité, cette "vérité".

                                  25 octobre 2021 à 14:19:23

                                  code.cpp :

                                  ....
                                  ..

                                  void scan (Mat &img, .... vector<Point> &hull)

                                  code.hpp  :

                                  void scan (Mat &img, .... , std::vector<cv::Point> &hull)

                                  main : 

                                  #declation variable 
                                  typedef struct
                                  {
                                       std::vector <cv::Point> location
                                  } 
                                  
                                  vector <Point> hull_main; 
                                  
                                  
                                  # Algo # 
                                  ....
                                  ...
                                  ..
                                  
                                  scan(img,...., *hull_main); 
                                  



                                  Voici mon erreur :


                                  • Partager sur Facebook
                                  • Partager sur Twitter
                                    25 octobre 2021 à 16:00:30

                                    Il faut faire un petit peu attention à ce que tu écris et lire les messages d'erreurs ...

                                    On ne met pas d'espace entre vector et <>

                                    vector <Point> // pas bon
                                    std::vector<Point>  // bon

                                    Même chose dans

                                    typedef struct
                                    {
                                         std::vector <cv::Point> location
                                    }

                                    Mais ça non plus ça ne vas pas.

                                    Une struct c'est fait pour "créer un nouveau type" en regroupant plusieurs données. Par exemple :

                                    struct Point3D {
                                        int x = 0;
                                        int y = 0;
                                        int z = 0;
                                    }

                                    Ici je défini une structure qui contient 3 entiers et qui me permet de créer de variables de type Point3D. On peut dire que Point3D c'est "le nom" de ma structure.

                                    Quel est le nom de ta structure ? Quel est l'intéret de faire une stucture pour n'y ranger qu'un seul élément. Typedef c'est utilisé en C

                                    Soit t'es en C et tu fais quelque chose cette forme là :

                                    typedef struct {
                                        TYPE var1;
                                        TYPE var2;
                                        // d'autres variables de n'importe quel type
                                    } NOM_DE_La_STRUCTURE

                                    Soit t'es en C++ et tu fais directement

                                    struct NOM_DE_LA_STRUCTURE {
                                        TYPE var1;
                                        TYPE var2;
                                        // d'autres variables de n'importe quel type
                                    }


                                    Tu es sûr que tu as bien assimilé les bases du C++ ? Tu fais beaucoup de truc à la C dans un code C++ et tu n'as pas l'air au point sur la synthaxe de déclaration des structures ni sur leur utilisation

                                    OpenCV n'est pas non plus une lib très simple à utiliser si on a pas les bases solides. Peut-être devrait tu lever le pied et repasser un peu de temps à consolider ces bases sur un bon cours de C++

                                    • Partager sur Facebook
                                    • Partager sur Twitter
                                      25 octobre 2021 à 16:29:40

                                      ThibaultVnt a écrit:

                                      On ne met pas d'espace entre vector et <>

                                      Même si ce n'est pas beau, ce n'est pas une erreur.

                                      • Partager sur Facebook
                                      • Partager sur Twitter
                                        25 octobre 2021 à 16:58:00

                                        Oui d'accord je comprends ! Je me mélange encore les pinceaux entre le C et C++. Merci de votre aide à tous !
                                        • Partager sur Facebook
                                        • Partager sur Twitter
                                          25 octobre 2021 à 19:30:13

                                          Tuson a écrit:

                                          Oui d'accord je comprends ! Je me mélange encore les pinceaux entre le C et C++. Merci de votre aide à tous !


                                          Tu peux mettre en résolu le sujet alors... ^^
                                          • Partager sur Facebook
                                          • Partager sur Twitter

                                          La gentillesse est le langage qu'un sourd peut entendre et qu'un aveugle peut voir.

                                          Il n'y a qu'un seul monde et il est faux, cruel, contradictoire, séduisant et dépourvu de sens. Un monde ainsi constitué est le monde réel. Nous avons besoin de mensonges pour conquérir cette réalité, cette "vérité".

                                          Conversion vector en tableau

                                          × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                                          × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
                                          • Editeur
                                          • Markdown