// segmNN.cc - Classe Segmentation // nono - Programme du robot Efrei Robotique I1-I2 2004 // Copyright (C) 2004 Olivier Gaillard /// @file segmNN.cc Segmente l'image et cree un tableau contenant des valeurs segmentees, creation du reseau de neurones et apprentissage #include "segmNN.h" #include #include #include #include #include using namespace std; /// Constructor SegmNN /// @param img classe img permettant d'acceder au donnees de l'image a traiter /// @param oconfig classe oconfig permettant d'acceder aux variables de oconfiguration SegmNN::SegmNN(Img *img) { // Sauvegarde les pointeurs SegmNN::img = img; oconfig = OConfig::GetInstance (); nbOutput = oconfig->nn_NbCouleurs; node = NULL; index = NULL; freq = NULL; tabSegm = NULL; } /// Destructor SegmNN SegmNN::~SegmNN() { delete [] node; delete [] index; delete [] freq; delete [] tabSegm; } /// Affiche les poids du reseau de neurones (neural network : NN) void SegmNN::ShowNodes() { // Affichage des poids du NN cout << "Poids:"; for(int i=0; inbNodeMax < nbOutput) { cerr << "SegmNN::BuildNN : Nombre de nodes insuffisants dans le fichier poids\n"; } else { // Charge les poids du NN et l'index des couleurs delete [] node; node = new unsigned char[nbOutput*3]; for (int i = 0; inode[i]; delete [] index; index = new int[nbOutput]; for (int i = 0; iindex[i]; freq = new unsigned int[nbOutput]; } return; } //initialition de random srand((unsigned)time(0)); // Initialisation des noeuds du NN delete [] node; node = new unsigned char[nbOutput*3]; delete [] index; index = new int[nbOutput]; delete [] freq; freq = new unsigned int[nbOutput]; for(int i=0; i 220) node[i*3+j] = 220; } } } /// Entraine un reseau de neurones void SegmNN::TrainNN() { unsigned long pixelNum; unsigned char *tabData; int output[nbOutput]; int numOutputMax=0; tabData = img->tabData; oconfig->colorMode = img->hsi*2 + img->yuv; oconfig->groupColor = 0; for(long i=0; inn_nil; i++) { // On choisit un pixel au hasard pixelNum = (unsigned long)(img->nbPixels*(rand()/(RAND_MAX+1.0))); // Calcul des valeurs de sorties pour ce pixel for(int j=0; jyuv && k==0) || (img->hsi && k==2)) output[j] += abs((int)(oconfig->nn_influ_lum*node[j*3+k]-tabData[pixelNum*3+k])*abs(node[j*3+k]-tabData[pixelNum*3+k])); else output[j] += abs(node[j*3+k]-tabData[pixelNum*3+k])*abs(node[j*3+k]-tabData[pixelNum*3+k]); } // On cherche la sortie ayant le plus haut niveau if (output[j] < output[numOutputMax]) numOutputMax = j; } // Mis a jour des poids for(int k=0; k<3; k++) { node[numOutputMax*3+k] = (unsigned char)((node[numOutputMax*3+k] + oconfig->nn_sl*tabData[pixelNum*3+k])/(1+oconfig->nn_sl)); // Recompense pour la sortie qui travaille freq[numOutputMax]++; // Verification des noeuds inutiles if ((i%300) == 299) { for (int k=0; k < nbOutput; k++) { if (freq[numOutputMax] < oconfig->nn_lazy_threshold) { // Regeneration de nouveaux poids for(int m=0; m<3; m++) { // Attribution aléatoire des poids node[numOutputMax*3+m] = (unsigned char) (255.0*rand()/(RAND_MAX+1.0)); if (node[numOutputMax*3+m] < 30) node[numOutputMax*3+m] = 30; else if (node[numOutputMax*3+m] > 220) node[numOutputMax*3+m] = 220; } } // 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 unsigned char SegmNN::FindColorNN(unsigned char *x, bool testUndefined) { int numOutputMax=0; int output[nbOutput]; int j,tmp; // Calcul des valeurs de sorties pour ce pixel // si on est en yuv if (img->yuv) { for(j=0; jnn_influ_lum*tmp*tmp)); tmp = node[j*3+1]-x[1]; output[j] += tmp*tmp; tmp = node[j*3+2]-x[2]; output[j] += tmp*tmp; // On selectionne la sortie ayant la plus grande valeur comme couleur if (output[numOutputMax] > output[j]) numOutputMax = j; } } // si on est en rgb else { for(j=0; j output[j]) numOutputMax = j; } } if ((testUndefined) && (output[numOutputMax] > oconfig->nn_threshold_output)) numOutputMax = UNDEFINED; // if (testUndefined) cout << output[numOutputMax] << endl; return numOutputMax; } /// Segmente l'image avec le reseau de neurones void SegmNN::Segm() { unsigned char* tabData = img->tabData; if (tabSegm) delete [] tabSegm; tabSegm = new unsigned char[img->nbPixels]; // Parcours de l'image pour la segmentation // On recupere l'index et non le numero de sortie du NN for (unsigned long i=0; inbPixels; i++) { tabSegm[i] = index[FindColorNN(tabData+i*3)]; } } /// Segmente l'image pour une seule couleur uniquement et permet donc d'isoler un ficher /// @param numColor numero de la couleur a isoler void SegmNN::Segm(int numColor) { unsigned char* tabData = img->tabData; if (tabSegm) delete [] tabSegm; tabSegm = new unsigned char[img->nbPixels]; // Parcours de l'image pour la segmentation for (unsigned long i=0; inbPixels; i++) { if (FindColorNN(tabData+i*3) == numColor) tabSegm[i] = 1; else tabSegm[i] = 0; } } /*void SegmNN::InitCache () { } */ /// Entraine plusieurs reseaux de neurones avec des parametres differents et crees les images associees void SegmNN::TestNN() { /* double sl[] = {0.01, 0.1, 1}; unsigned long nil[] = {100, 1000, 10000, 100000, 1000000}; int nc[] = {3,4,5,6,7,8}; char filename[30]; // Parcours de toutes les valeurs de nombres de couleurs for (int i_nc = 0; i_nc<6; i_nc++) { BuildNN(nc[i_nc], 0); // Parcours de toutes les valeurs de nombres d'itérations for (int i_nil = 0; i_nil<5; i_nil++) { oconfig->nn_nil = nil[i_nil]; // Parcours de toutes les valeurs de Step Learning for (int i_sl = 0; i_sl<4; i_sl++) { oconfig->nn_sl = sl[i_sl]; // Apprentissage du NN TrainNN(); // Segmentation Segm(); // Ecriture des résultats dans une image sprintf(filename, "NN/%i-%f-%luNN.jpg", nc[i_nc], sl[i_sl], nil[i_nil]); img->WriteSegm(filename, tabSegm); sprintf(filename, "NN/%i-%f-%luNN", nc[i_nc], sl[i_sl], nil[i_nil]); oconfig->node = node; oconfig->CreateNNFile(filename, oconfig->colorMode, nbOutput); } } } */ }