User Tools

Site Tools


cpp:ps

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
cpp:ps [2022/06/22 12:17] – [Résultat] francoiscpp:ps [2022/12/09 09:39] (current) charles
Line 1: Line 1:
 ====== Exemple Pattern Spectra ====== ====== Exemple Pattern Spectra ======
  
-===== Visualisation =====+Dans cet exemple, nous allons réaliser un programme qui produit des fichiers HDF5 (binaire structuré) contenant des tableaux à 2 dimensions de pattern spectra. 
 +Le programme prend 2 arguments : 
 +  * le nom du fichier contenant l'image en entrée qui construira un arbre MAX et des attributs 
 +  * le nom du fichier qui les données produites (principalement un pattern spectra)
  
 +Dans cet exemple nous proposons de réaliser un pattern spectra à 2 dimensions. Cela signifie que la contribution de chaque nœud sera cumulé en fonction
 +  * de la taille du nœud
 +  * et de sa caractéristique d'être compact ou non
  
-Dans cet exemple, nous allons réaliser un programme qui produit des fichiers HDF5 (binaire structuré) contenant des tableau à 2 dimension de pattern spectra.+===== Visualisation =====
  
 +Nous avons utilisé un script python pour visualiser le tableau à 2 dimensions.
 +Nous avons joué avec les paramètres pour disposer d'axes linéaires ou logarithmiques.
  
 ^ ^  linear  ^  log  ^ ^ ^  linear  ^  log  ^
Line 12: Line 20:
  
 ===== Code ===== ===== Code =====
 +
 +Il faut commencer par les déclarations d'usage. La première pour réaliser des traces lors de l'exécution (le calcul du périmètre et un peu lent). Les autres sont là pour rappel.
 <code c++> <code c++>
 #include <iostream> #include <iostream>
Line 29: Line 39:
 </code> </code>
  
 +Nous aurons besoin des quelques classes fondamentales : la structure d'arbre, le poids des nœuds et un ensembles d'autres attributs pour le pattern spectra.
 <code c++> <code c++>
 #include "ArrayTree/ArrayTreeBuilder.hpp" #include "ArrayTree/ArrayTreeBuilder.hpp"
Line 37: Line 48:
 </code> </code>
  
 +En fonction de ce qui a été déclaré, il peut être utile de simplifier les appels en omettant le contexte d'utilisation (par exemple en évitant de préfixer avec ''std::''). 
 <code c++> <code c++>
 using namespace std; using namespace std;
Line 44: Line 56:
 </code> </code>
  
 +Dans notre exemple, nous nous limiterons à des images 2D et la construction d'un arbre MAX.
 +Nous préfererons un histogramme logarithmique par défaut.
 +Nous choisissons un pattern spectra de 900 casses (30 bin x 30 bin).
 +La compression HDF5 a besoin de paramètres propres (taux de compression, taille de cache).
 <code c++> <code c++>
-inline unsigned int abs (unsigned int x) { return x;} 
- 
 typedef uint16_t DimBin; typedef uint16_t DimBin;
  
 static const int GeoDimT (2); static const int GeoDimT (2);
-static TreeType treeType = MAX; +static const TreeType treeType = MAX; 
-static DimBin linearCompactBin (false), linearAreaBin (false); +static const DimBin linearCompactBin (false), linearAreaBin (false); 
-static DimBin binCompactCount (30), binAreaCount (30); +static const DimBin binCompactCount (30), binAreaCount (30); 
-static unsigned int compressLevel (5); +static const unsigned int compressLevel (5); 
-static size_t cacheSize (1024*1024);+static const size_t cacheSize (1024*1024);
 </code> </code>
  
 +Nous déclarons la fonction ''patternSpectra'' qui réalisera le calcul et l'écriture du résultat. Elle sera donc dépendante de la nature des pixels lus InPixelT, de l'image en entrée et du nom de fichier à produire. 
 <code c++> <code c++>
 template<typename PixelT> void patternSpectra (const IImage<GeoDimT> &inputImage, const string &outputData); template<typename PixelT> void patternSpectra (const IImage<GeoDimT> &inputImage, const string &outputData);
 </code> </code>
 +
 +Nous définissons une fonction créant des intervalles (au nombre de ''binCount'') de valeurs logarithmiques entre un minimum et un maximum.
  
 <code c++> <code c++>
Line 74: Line 91:
 </code> </code>
  
 +Nous définissons une fonction créant des intervalles (au nombre de ''binCount'') de valeurs de même taille entre un minimum et un maximum.
 <code c++> <code c++>
 /** Create linear bin */ /** Create linear bin */
Line 86: Line 104:
 </code> </code>
  
 +Le point d'entrée du programme commencera par analyser les arguments :
 +
 +  * argv[0] : nom du programme
 +  * argv[1] : nom du fichier contenant l'image en entrée
 +  * argv[2] : nom du fichier contenant les données produites
 <code c++> <code c++>
 int int
Line 98: Line 121:
 </code> </code>
  
 +En fonction des pixels de l'image nous invoquerons la fonction ''patternSpectra'' avec le bon type. 
 <code c++> <code c++>
   switch (inputImage.getDataType ()) {   switch (inputImage.getDataType ()) {
Line 123: Line 147:
 </code> </code>
  
 +Voici la fonction principale du programme. 
 +Elle commence par lire les pixels.
 <code c++> <code c++>
 template<typename PixelT> template<typename PixelT>
Line 132: Line 158:
   Raster<PixelT, GeoDimT> raster;   Raster<PixelT, GeoDimT> raster;
   // image size (width x height)   // image size (width x height)
-  Size<GeoDimT> size (inputImage.getSize ());+  const Size<GeoDimT> size (inputImage.getSize ());
   // read first band (0) in 2D mode from origine [0,0] to end [width, height].   // read first band (0) in 2D mode from origine [0,0] to end [width, height].
   inputImage.readBand (raster, 0, NullPoint2D, size);   inputImage.readBand (raster, 0, NullPoint2D, size);
 </code> </code>
  
 +Nous déclarons l'objet arbre qui contiendra le chaînage des feuilles vers la racine. 
 <code c++> <code c++>
   cout << "Build tree" << endl;   cout << "Build tree" << endl;
   // no border (i.e. all pixels are take in account)   // no border (i.e. all pixels are take in account)
-  Border<GeoDimT> border (size, false);+  const Border<GeoDimT> border (size, false);
   // neighbors take in account (default connectivity C4)   // neighbors take in account (default connectivity C4)
-  GraphWalker<GeoDimT> graphWalker (border);+  const GraphWalker<GeoDimT> graphWalker (border);
   // tree builder base on raster, connectivity and type of tree   // tree builder base on raster, connectivity and type of tree
   ArrayTreeBuilder<PixelT, PixelT, GeoDimT> atb (raster, graphWalker, treeType);   ArrayTreeBuilder<PixelT, PixelT, GeoDimT> atb (raster, graphWalker, treeType);
Line 153: Line 180:
 </code> </code>
  
 +Nous déclenchons la construction de l'arbre.
 +  * ATB contient les éléments de l'images (matrice de pixels, connectivité, type d'arbre)
 +  * tree coquille vide qui va contenir l'arbre
 +  * weightAttributes est le premier tableau d'attributs associés aux nœuds (niveaux de gris)
 <code c++> <code c++>
   atb.buildTree (tree, weightAttributes);   atb.buildTree (tree, weightAttributes);
 </code> </code>
  
 +Nous créons autant de tableau d'attributs associés aux nœuds que nécessaire (taille en pixels, périmètre, propriété d'être compact).
 <code c++> <code c++>
   // create area attribute   // create area attribute
   cout << "Build Area Attributes" << endl;   cout << "Build Area Attributes" << endl;
-  AreaAttributes<GeoDimT> areaAttributes (tree);+  const AreaAttributes<GeoDimT> areaAttributes (tree);
   cout << "Build Perimeter Attributes" << endl;   cout << "Build Perimeter Attributes" << endl;
-  PerimeterAttributes<GeoDimT> perimeterAttributes (tree, graphWalker);+  const PerimeterAttributes<GeoDimT> perimeterAttributes (tree, graphWalker);
   cout << "Build Compactness Attributes" << endl;   cout << "Build Compactness Attributes" << endl;
-  CompactnessAttributes<GeoDimT> compactnessAttributes (tree, areaAttributes, perimeterAttributes);+  const CompactnessAttributes<GeoDimT> compactnessAttributes (tree, areaAttributes, perimeterAttributes);
 </code> </code>
  
 +Nous construisons des intervalles de valeurs (abscisses et ordonnées).
 <code c++> <code c++>
   cout << "Build PS" << endl;   cout << "Build PS" << endl;
-  static DimImg MaxArea (size.getPixelsCount ()); +  const DimImg MaxArea (size.getPixelsCount ()); 
-  vector<double> compactScale = linearCompactBin ?+  const vector<double> compactScale = linearCompactBin ?
     linearSpace (0., 1., binCompactCount) :     linearSpace (0., 1., binCompactCount) :
     logSpace (1./MaxArea, 1., binCompactCount);     logSpace (1./MaxArea, 1., binCompactCount);
-  vector<double> areaScale = linearAreaBin ?+  const vector<double> areaScale = linearAreaBin ?
     linearSpace (1., MaxArea, binAreaCount) :     linearSpace (1., MaxArea, binAreaCount) :
     logSpace (1, MaxArea, binAreaCount);     logSpace (1, MaxArea, binAreaCount);
 </code> </code>
  
 +Nous calculons le pattern spectra en parcourant tous les nœuds.
 <code c++> <code c++>
   vector<double> psTab (binAreaCount * binCompactCount, 0.);   vector<double> psTab (binAreaCount * binCompactCount, 0.);
Line 186: Line 220:
  
   for (DimParent compId = 0; compId < rootId; ++compId) {   for (DimParent compId = 0; compId < rootId; ++compId) {
-    DimBin areaBinId = lower_bound (areaScale.begin (), areaScale.end (), double (areaValues[compId])) - areaScale.begin (); +    const DimBin areaBinId = lower_bound (areaScale.begin (), areaScale.end (), double (areaValues[compId])) - areaScale.begin (); 
-    DimBin compactBinId = lower_bound (compactScale.begin (), compactScale.end (), double (compactValues[compId])) - compactScale.begin (); +    const DimBin compactBinId = lower_bound (compactScale.begin (), compactScale.end (), double (compactValues[compId])) - compactScale.begin (); 
-    double diff = abs (double (weightValues[compId])- +    const double diff = abs (double (weightValues[compId]) - 
-        double (weightValues[tree.getCompParent (compId)])); +      double (weightValues[tree.getCompParent (compId)])); 
-    double volume = diff * areaValues[compId];+    const double volume = diff * areaValues[compId];
  
-    size_t id (compactBinId + areaBinId * binCompactCount);+    const size_t id (compactBinId + areaBinId * binCompactCount);
     psTab [id] += volume;     psTab [id] += volume;
   }   }
 </code> </code>
  
 +Nous construisons, pour l'exemple, une représentation réduite du pattern spectra (de nombreuses cases sont vides).
 <code c++> <code c++>
   vector<DimBin> reduceBinIdx;   vector<DimBin> reduceBinIdx;
Line 208: Line 243:
 </code> </code>
  
 +Nous sauvons les valeurs dans un fichier HDF5.
 <code c++> <code c++>
   cout << "Write HDF5" << endl;   cout << "Write HDF5" << endl;
Line 227: Line 263:
 ===== Résultat ===== ===== Résultat =====
  
-Visualisation de la structure du fichier +La commande ''h5ls'' permet de visualiser la structure du fichier 
-  * PS :  +  * PS : Tableau à 2 dimension contenant le Pattern Spectra (''30*30 = 900'') 
-  * XLabel, XTick : +  * XLabel, XTick : Nom de l'axe des abscisses et des intervalles choisis 
-  * YLabel, Ytick : +  * YLabel, Ytick : Nom de l'axe des abscisses et des intervalles choisis 
-  * patchPSBinIdx, patchPSBinVal :+  * patchPSBinIdx, patchPSBinVal : représentation réduite du tableau (seuls les cases avec une valeur sont enregistré avec leur index).
 <code bash> <code bash>
 $ h5ls arles.kor  $ h5ls arles.kor 
Line 243: Line 279:
 </code> </code>
  
-Visualisation des données du fichier+La commande ''h5dump'' permet d'afficher les valeurs contenues dans le fichier.
 <code bash> <code bash>
 $ h5dump arles.kor  $ h5dump arles.kor 
 HDF5 "arles.kor" { HDF5 "arles.kor" {
 GROUP "/" { GROUP "/" {
 +</code>
 +
 +Le Pattern Spectra est constitué de 30 x 30 cases.
 +<code bash>
    DATASET "PS" {    DATASET "PS" {
       DATATYPE  H5T_IEEE_F64LE       DATATYPE  H5T_IEEE_F64LE
Line 259: Line 299:
 </code> </code>
  
-Abscisse+Voici les information permettant de reconstituer l'axe des abscisses.
 <code bash> <code bash>
    DATASET "XLabel" {    DATASET "XLabel" {
Line 284: Line 324:
 </code> </code>
  
-Ordonnée+Voici les information permettant de reconstituer l'axe des ordonnées.
 <code bash> <code bash>
    DATASET "YLabel" {    DATASET "YLabel" {
Line 308: Line 348:
    }    }
 </code> </code>
-Données réduites+ 
 +Pour l'exemple voici une autre représentation (réduite) du Parttern Spectra.
 <code bash> <code bash>
  
cpp/ps.1655900274.txt.gz · Last modified: 2022/06/22 12:17 by francois