summaryrefslogtreecommitdiff
path: root/2004/i/nono/src/ovision/segmNN.cc
diff options
context:
space:
mode:
authorgaillaro2004-05-01 11:52:08 +0000
committergaillaro2004-05-01 11:52:08 +0000
commit109db2b0cce1b89c75e32f3705a1c5975391b3c5 (patch)
tree28da709aee1cbab296b99378e42a1e737403addf /2004/i/nono/src/ovision/segmNN.cc
parentf95f1fb2bc439178a9e7ca6102b57c02c791f3f0 (diff)
Ajout de ovision.
Diffstat (limited to '2004/i/nono/src/ovision/segmNN.cc')
-rw-r--r--2004/i/nono/src/ovision/segmNN.cc260
1 files changed, 260 insertions, 0 deletions
diff --git a/2004/i/nono/src/ovision/segmNN.cc b/2004/i/nono/src/ovision/segmNN.cc
new file mode 100644
index 0000000..d765f80
--- /dev/null
+++ b/2004/i/nono/src/ovision/segmNN.cc
@@ -0,0 +1,260 @@
+// 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 <iostream>
+#include <stdlib.h>
+#include <math.h>
+#include <time.h>
+using namespace std;
+
+/// Constructor SegmNN
+
+/// @param img classe img permettant d'acceder au donnees de l'image a traiter
+/// @param config classe config permettant d'acceder aux variables de configuration
+SegmNN::SegmNN(ImgFile *img, Config *config) {
+ // Sauvegarde les pointeurs
+ SegmNN::img = img;
+ SegmNN::config = config;
+ nbOutput = config->nn_NbCouleurs;
+
+ node = NULL;
+ index = NULL;
+ tabSegm = NULL;
+}
+
+/// Destructor SegmNN
+SegmNN::~SegmNN()
+{
+}
+
+
+/// Affiche les poids du reseau de neurones (neural network : NN)
+void SegmNN::ShowNodes() {
+
+ // Affichage des poids du NN
+ cout << "Poids:";
+ for(int i=0; i<nbOutput; i++)
+ printf("\t%u %u %u\n", node[i*3], node[i*3+1], node[i*3+2]);
+ cout << endl;
+}
+
+
+/// 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 SegmNN::BuildNN(int nbOutput, int loadFromFile) {
+
+ SegmNN::nbOutput = 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 (config->nbNodeMax < nbOutput) {
+ cerr << "SegmNN::BuildNN : Nombre de nodes insuffisants dans le fichier poids\n";
+ }
+ else {
+ // Charge les poids du NN et l'index des couleurs
+ node = config->node;
+ index = config->index;
+ }
+ return;
+ }
+
+ //initialition de random
+ srand((unsigned)time(0));
+
+ // Initialisation des noeuds du NN
+ if (node) delete [] node;
+ node = new unsigned char[nbOutput*3];
+ if (index) delete [] index;
+ index = new int[nbOutput];
+ if (freq) delete [] freq;
+ freq = new unsigned int[nbOutput];
+
+
+ for(int i=0; i<nbOutput; i++) {
+ index[i] = i;
+ freq[i] = 0;
+
+ for(int j=0; j<3; j++) {
+ // Attribution aléatoire des poids
+ node[i*3+j] = (unsigned char) (255.0*rand()/(RAND_MAX+1.0));
+ if (node[i*3+j] < 30) node[i*3+j] = 30;
+ else if (node[i*3+j] > 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;
+ config->colorMode = img->hsi*2 + img->yuv;
+ config->groupColor = 0;
+
+ for(long i=0; i<config->nn_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; j<nbOutput; j++) {
+ output[j] = 0;
+
+ for(int k=0; k<3; k++) {
+ if ((img->yuv && k==0) || (img->hsi && k==2))
+ output[j] += abs((int)(config->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] + config->nn_sl*tabData[pixelNum*3+k])/(1+config->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] < config->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) {
+
+ int numOutputMax=0;
+ int output[nbOutput];
+ int j;
+
+ // Calcul des valeurs de sorties pour ce pixel
+ for(j=0; j<nbOutput; j++) {
+ output[j] = 0;
+
+ for(int k=0; k<3; k++) {
+ if ((img->yuv && k==0) || (img->hsi && k==2))
+ output[j] += abs((int)(config->nn_influ_lum*node[j*3+k]-x[k])*abs(node[j*3+k]-x[k]));
+ else
+ output[j] += abs(node[j*3+k]-x[k])*abs(node[j*3+k]-x[k]);
+ }
+
+ // On selectionne la sortie ayant la plus grande valeur comme couleur
+ if (output[numOutputMax] > output[j]) {
+ numOutputMax = j;
+ }
+ }
+
+ 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; i<img->nbPixels; 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; i<img->nbPixels; i++) {
+ if (FindColorNN(tabData+i*3) == numColor) tabSegm[i] = 1;
+ else tabSegm[i] = 0;
+ }
+}
+
+
+/// 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++) {
+
+ config->nn_nil = nil[i_nil];
+
+ // Parcours de toutes les valeurs de Step Learning
+ for (int i_sl = 0; i_sl<4; i_sl++) {
+ config->nn_sl = sl[i_sl];
+
+ // Apprentissage du NN
+ TrainNN();
+
+ // Segmentation
+ Segm();
+
+ // Ecriture des résultats dans une image
+ sprintf(filename, "NN/%i-%lf-%luNN.jpg", nc[i_nc], sl[i_sl], nil[i_nil]);
+ img->WriteSegm(filename, tabSegm);
+ sprintf(filename, "NN/%i-%lf-%luNN", nc[i_nc], sl[i_sl], nil[i_nil]);
+ config->node = node;
+ config->CreateNNFile(filename, config->colorMode, nbOutput);
+ }
+ }
+ }
+}