// segmLearn.cc - Classe Segmentation // robert - Programme du robot APBteam // Copyright (C) 2005 Olivier Gaillard /// @file segmLearn.cc Apprentissage du réseau de neurones #include "segmLearn.hh" #include /// Constructor SegmLearn SegmLearn::SegmLearn () : freq_ (0) { } /// Destructor SegmLearn SegmLearn::~SegmLearn () { delete [] freq_; } /// Genere des poids pour un noeud /// @param numNode numéro du noeud à changer void SegmLearn::weightsGen (const int numNode) { const int minWeight = 30; const int maxWeight = 220; // Parcours des 3 composantes for(int i=0; i<3; i++) { // Attribution aléatoire des poids node_[numNode*3+i] = (unsigned char) (255.0*rand()/(RAND_MAX+1.0)); if (node_[numNode*3+i] < minWeight) node_[numNode*3+i] = minWeight; else if (node_[numNode*3+i] > maxWeight) node_[numNode*3+i] = maxWeight; } } /// Construit un reseau de neurones /// @param nbOutput_ nombre de noeuds de la couche de sortie du NN /// @param loadFromFile (GENERATE ou LOADFROMFILE) indique si les poids sont charges d'un fichier ou generes aleatoirement void SegmLearn::buildNN (const int nbOutput, const bool loadFromFile) { nbOutput_ = nbOutput; // Initialisation des noeuds du NN delete [] node_; node_ = new unsigned char[nbOutput_*3]; delete [] index_; index_ = new int[nbOutput_]; // Permet de charger les poids du NN depuis un fichier ou en les initialisant aleatoirement if (loadFromFile) { // Verifie si le nombre de poids donne dans le fichier est suffisant if (oconfig_->nnNbNodeMax < nbOutput_) { std::cerr << "SegmLearn::buildNN : Nombre de nodes insuffisants dans le fichier poids" << std::endl; return; } // Charge les poids du NN et l'index des couleurs for (int i = 0; inode[i]; for (int i = 0; iindex[i]; } else { //initialition des noeuds aléatoirement srand((unsigned)time(0)); for(int i=0; itabData_; delete [] freq_; freq_ = new int[nbOutput_]; for(int i=0; innNil; i++) { // On choisit un pixel au hasard pixelNum = (unsigned long)(img->nbPixels_*(rand()/(RAND_MAX+1.0))); numOutputMax = findColorNN (tabData_ + pixelNum*3); // Mis a jour des poids for(int k=0; k<3; k++) { // Si on est en yuv ou hsi et que c'est la composante de lum_inosite, on ajoute un poids pour affecter son influence if (k == lumPos_) node_[numOutputMax*3+k] = (unsigned char)(oconfig_->nnSl*(node_[numOutputMax*3+k] + oconfig_->nnSl*tabData_[pixelNum*3+k])/(1+oconfig_->nnSl)); // Sinon calcul normal else node_[numOutputMax*3+k] = (unsigned char)((node_[numOutputMax*3+k] + oconfig_->nnSl*tabData_[pixelNum*3+k])/(1+oconfig_->nnSl)); // Recompense pour la sortie qui travaille freq_[numOutputMax]++; } // Verification des noeuds inutiles à partir de 300 iterations if ((i%300) == 299) { for (int k=0; k < nbOutput_; k++) { // Regeneration de nouveaux poids if (freq_[k] < oconfig_->nnLazyThreshold) weightsGen (k); // On remet le compteur a zero freq_[k] = 0; } } } } /// Renvoie le code de la couleur segmentee /// @param *x pointeur vers un tableau contenant une valeur RGB /// @param testOutputMax choix de l'utilisation d'un sueil maxi pour la sortie pour éviter qu'une couleur trop différente soit attribuer à une autre couleur unsigned char SegmLearn::findColorNN (const unsigned char *x, const bool testOutputMax) const { int numOutputMax=0; int output[nbOutput_]; int tmp; // Calcul des valeurs de sorties du NN pour ce pixel for(int j=0; jcolorMode == Image) && k==2)) output[j] += (int) oconfig_->nnInfluLum * tmp * tmp; // Sinon calcul normal else output[j] += tmp * tmp; } // On selectionne la sortie ayant la plus grande valeur comme couleur if (output[numOutputMax] > output[j]) numOutputMax = j; } // Test si la valeur de sortie est assez proche d'une couleur du rezo if ((testOutputMax) && (output[numOutputMax] > oconfig_->nnThresholdOutput)) numOutputMax = Segm::undefined; return numOutputMax; } /// Renvoie le code de la couleur segmentee /// @param *x pointeur vers un tableau contenant une valeur RGB /// @param testOutputMax choix de l'utilisation d'un sueil maxi pour la sortie pour éviter qu'une couleur trop différente soit attribuer à une autre couleur unsigned char SegmLearn::giveColor (const unsigned char *x, const bool testOutputMax, const bool nodeProcess, const bool lumFlag) { if (lumFlag && (lumPos_ >= 0)) addLum (x[lumPos_]); if (nodeProcess) return index_ [findColorNN (x, testOutputMax)]; else return findColorNN (x, testOutputMax); }