From 8df6328c400012812394fe5957b6837636fc74fe Mon Sep 17 00:00:00 2001 From: gaillaro Date: Tue, 5 Apr 2005 18:30:06 +0000 Subject: interfaces pour l'apprentissage du RN et pour visionner les traitements d'images à partir de plusieurs sources (file, cam, serv) --- 2005/i/robert/src/ovision/ui/Makefile.defs | 19 + 2005/i/robert/src/ovision/ui/adjust.cc | 351 +++++++++ 2005/i/robert/src/ovision/ui/adjust.hh | 63 ++ 2005/i/robert/src/ovision/ui/comm.cc | 339 +++++++++ 2005/i/robert/src/ovision/ui/comm.hh | 60 ++ 2005/i/robert/src/ovision/ui/live.cc | 180 +++++ 2005/i/robert/src/ovision/ui/live.hh | 81 +++ 2005/i/robert/src/ovision/ui/mainui.cc | 51 ++ 2005/i/robert/src/ovision/ui/mainui.hh | 26 + 2005/i/robert/src/ovision/ui/testui.cc | 46 ++ 2005/i/robert/src/ovision/ui/testui.hh | 4 + 2005/i/robert/src/ovision/ui/ui.cc | 1057 ++++++++++++++++++++++++++++ 2005/i/robert/src/ovision/ui/ui.hh | 118 ++++ 13 files changed, 2395 insertions(+) create mode 100644 2005/i/robert/src/ovision/ui/Makefile.defs create mode 100644 2005/i/robert/src/ovision/ui/adjust.cc create mode 100644 2005/i/robert/src/ovision/ui/adjust.hh create mode 100644 2005/i/robert/src/ovision/ui/comm.cc create mode 100644 2005/i/robert/src/ovision/ui/comm.hh create mode 100644 2005/i/robert/src/ovision/ui/live.cc create mode 100644 2005/i/robert/src/ovision/ui/live.hh create mode 100644 2005/i/robert/src/ovision/ui/mainui.cc create mode 100644 2005/i/robert/src/ovision/ui/mainui.hh create mode 100644 2005/i/robert/src/ovision/ui/testui.cc create mode 100644 2005/i/robert/src/ovision/ui/testui.hh create mode 100644 2005/i/robert/src/ovision/ui/ui.cc create mode 100644 2005/i/robert/src/ovision/ui/ui.hh (limited to '2005/i') diff --git a/2005/i/robert/src/ovision/ui/Makefile.defs b/2005/i/robert/src/ovision/ui/Makefile.defs new file mode 100644 index 0000000..3bddbf3 --- /dev/null +++ b/2005/i/robert/src/ovision/ui/Makefile.defs @@ -0,0 +1,19 @@ +PROGRAMS += adjust ui +LIBS += adjust.a +LIBSGL= -L/usr/X11R6/lib -lGL -lGLU -lglut +LIBNCURSES=-lmenu -lncurses +CXXFLAGS = -Wall -g +LDFLAGS = -L/usr/pkg/lib + +adjust_OBJECTS = adjust.o comm.o img.o imgInterface.o image.o group.o segm.o segmLearn.o oconfig.o convertImg.o magnifier.o live.o $(data_OBJECTS) $(image_OBJECTS) $(video4linux_OBJECTS) $(utils_OBJECTS) +liveView_OBJECTS = liveView.o live.o img.o imgInterface.o image.o group.o segm.o segmLearn.o oconfig.o convertImg.o magnifier.o $(data_OBJECTS) $(image_OBJECTS) $(video4linux_OBJECTS) $(utils_OBJECTS) +ui_OBJECTS = ui.o mainui.o oconfig.o group.o segm.o + +ui: $(ui_OBJECTS:%.o=%.o) + $(CXX) $(LDFLAGS) $(LIBNCURSES) $^ -o $@ + +adjust: $(adjust_OBJECTS:%.o=%.o) + $(CXX) $(LDFLAGS) $(LIBSGL) $^ -o $@ + +liveView: $(liveView_OBJECTS:%.o=%.o) + $(CXX) $(LDFLAGS) $(LIBSGL) $^ -o $@ diff --git a/2005/i/robert/src/ovision/ui/adjust.cc b/2005/i/robert/src/ovision/ui/adjust.cc new file mode 100644 index 0000000..0dc35f2 --- /dev/null +++ b/2005/i/robert/src/ovision/ui/adjust.cc @@ -0,0 +1,351 @@ +#include // Header File For The GLUT Library +#include // Header File For The OpenGL32 Library +#include // Header File For The GLu32 Library +#include + +#include +#include +#include + +#include "adjust.hh" +#include "comm.hh" + +using namespace std; + +#define IMG_WIDTH 360 +#define IMG_HEIGHT 296 +#define WIDTH 1076 +#define HEIGHT 591 + +int window; +Comm *comm; + +int point[NB_POINTS_UI][2] = {{-1,-1},{-1,-1},{-1,-1},{-1,-1},{-1,-1}}; +int width=538; int height=395; + +int* getPpoint() +{ + return (int*)point; +} + + +/// Sortie du programme +void +leave (int numSignal) +{ + exit(0); +} + + +/// Sortie du programme anormal +void +tooLate(int numSignal) +{ + // Affichage d'un message d'erreur + cerr << "tooLate : Temps d'attente FIFO depasse\n"; + leave(-1); +} + + +/// Lecture du fifo et execution de la commande +void +executeUiCmds(int numSignal) +{ + // Reassignement du signal handler + signal(SIGUSR1, executeUiCmds); + + char buffer[50]; + + // On test si le fifo a ete initialiser + if (numSignal == SIGUSR2) + { + // Permet l'envoie du message d'initialisation + strcpy(buffer, "i\n"); + } + else + { + // Timer + signal(ALARM, tooLate); + alarm(5); + + // Lecture du FIFO + if (!read (comm->fifo, buffer, 50)) + { + cerr << "ReadUicmds : Error FIFO is empty" << endl; + return; + } + + alarm(0); + } + + // Parse de la commande recue + comm->executeUiCmds(buffer); + + // Envoyer un signal de réponse à UI + kill(comm->uiPid, SIGUSR1); +} + + +/// Chargement d'une texture a partir de donnees RGB +unsigned int +loadImage(int width, int height, unsigned char *data, unsigned int lastTex) +{ + GLuint tex; + + if (glIsTexture(lastTex)) glDeleteTextures(1, &lastTex); + + + // Mode de chargement des donnees + glPixelStorei (GL_UNPACK_ALIGNMENT, 1); + + // Creer une id pour stocker l'image + glGenTextures(1, &tex); + glBindTexture(GL_TEXTURE_2D, tex); + + // Stocke l'image + //glTexImage2D(GL_TEXTURE_2D, 0, 3, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data); + gluBuild2DMipmaps(GL_TEXTURE_2D, 3, width, height, GL_RGB, GL_UNSIGNED_BYTE, data); + + // Config des parametres + glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); + + // Retourne l'id de l'image + return tex; +} + + +/// Initialisation des fonctions OpenGL +void +initGL(int width, int height) +{ + // Initialisation du mode d'affichage + glClearColor(0.0f, 0.0f, 0.0f, 0.0f); + + // Mode de chargement des donnees + glPixelStorei (GL_UNPACK_ALIGNMENT, 1); + glShadeModel(GL_FLAT); + glEnable(GL_TEXTURE_2D); + + + // Remise a zero de la matrice de projection + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + + // Plan de projection en 2D + glOrtho(0.0, WIDTH, 0.0, HEIGHT, -1.0, 1.0); + glMatrixMode(GL_MODELVIEW); + + glPointSize(4.0f); +} + + + +/// Redimenssionement d'une fenetre +void +reSizeGLScene(int w, int h) +{ + // Evite div par 0 + if (height==0) h=1; + + height = h; + width = w; + + // Initialise le point de vue + glViewport(0, 0, w, h); + glMatrixMode(GL_PROJECTION); + + // Remise a zero et mode 2D + glLoadIdentity(); + glOrtho(0.0, WIDTH, 0.0, HEIGHT, -1.0, 1.0); + glMatrixMode(GL_MODELVIEW); + +} + + +/// Affiche une image +/// @param texId numero de la texture a afficher +void +drawImage(GLuint texId) +{ + int wMin, wMax; + int hMin, hMax; + + // Selection de l'image + glBindTexture(GL_TEXTURE_2D, comm->getTex ()[texId]); + + // Calcul des coordonnees de l'image + wMin = BORDER+(texId%3)*(352+BORDER); + wMax = 352+BORDER+(texId%3)*(352+BORDER); + hMin = HEIGHT-288-BORDER-(int)(texId/3)*(288+BORDER); + hMax = HEIGHT-BORDER-(int)(texId/3)*(288+BORDER); + + // Dessine un carre contenant l'image + glBegin(GL_QUADS); + glNormal3f( 0.0f, 0.0f, 1.0f); + glColor3f(1.0f,1.0f,1.0f); + glTexCoord2f(0.0f, 0.0f); glVertex3f(wMax, hMax, -1.0f); + glTexCoord2f(1.0f, 0.0f); glVertex3f(wMin, hMax, -1.0f); + glTexCoord2f(1.0f, 1.0f); glVertex3f(wMin, hMin, -1.0f); + glTexCoord2f(0.0f, 1.0f); glVertex3f(wMax, hMin, -1.0f); + glEnd(); +} + + +/// Dessine les images a l'ecran +void +drawGLScene() +{ + // Efface le buffer + glClear(GL_COLOR_BUFFER_BIT); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + + // Affiche toutes les images + for (int i=0; i= 0) +/* x = (int)((double)WIDTH/width * x); + y = height - y; + y = (int)((double)HEIGHT/height * y);*/ + glBegin(GL_POINTS); + glVertex3f( (float)((point[i][0] + BORDER) * (double)352 / IMG_WIDTH), + (float)((point[i][1] + BORDER) * (double)288 / IMG_HEIGHT), + -0.9f); + glVertex3f( (float)((point[i][0] + BORDER) * (double)352 / IMG_WIDTH), + (float)((point[i][1] + BORDER) * (double)288 / IMG_HEIGHT + 288 + BORDER), + -0.9f); + glEnd(); + + } + glEnable(GL_TEXTURE_2D); + + + glFlush(); + + // Affiche le buffer suivant + glutSwapBuffers(); +} + + +/// Interruptions du clavier +void +keyPressed(unsigned char key, int x, int y) +{ + // Touche Echap + if (key == 27) + { + glutDestroyWindow(window); + leave(0); + } + if (key == 'r') + comm->reloadConfig ("rc/vision.conf"); +} + +/// Gestion souris +void +mouseFunc(int button, int state, int x, int y) +{ + if (state == GLUT_UP) + { + // On calcul les coordonnees de l'image + x = (int)((double)WIDTH/width * x); + y = (int)((double)HEIGHT/height * y); + int imgX = -1; + int imgY = -1; + if ((x < 352+BORDER) && (y < BORDER+288) && (x > BORDER) && (y > BORDER)) + { + imgX = x * IMG_WIDTH / 352 - BORDER; + imgY = y * IMG_HEIGHT / 288 - BORDER; + + } + + if ((x < 352+BORDER) && (y < HEIGHT-BORDER) && (x > BORDER) && (y > 2*BORDER+288)) + { + imgX = x * IMG_WIDTH / 352 - BORDER; + imgY = y * IMG_HEIGHT / 288 - 3 * BORDER - 288; + } + + cout << "x " << imgX << " y " << imgY << endl; + int i=0; + + if (imgX >= 0) + { + imgY = IMG_HEIGHT - imgY; + + // Ajout de point + if (button == GLUT_LEFT_BUTTON) + { + while(i < NB_POINTS_UI) + { + if (point[i][0] < 0) + { + point[i][0] = imgX; + point[i][1] = imgY; + i=NB_POINTS_UI+3; + cout << "Point ajoute: " << imgX << ", " << imgY << endl; + } + i++; + } + if (i == NB_POINTS_UI+3) cout << "MouseFunc : 3 points sont deja selectionnes" << endl; + } + + // Suppression de point + else if (button == GLUT_RIGHT_BUTTON) + { + while(iinit (); + + //Initialisation des signal handlers + signal(SIGUSR1, executeUiCmds); + signal(SIGUSR2, executeUiCmds); + signal(SIGQUIT, leave); + + // Boucle principale + glutMainLoop(); + + return 1; +} diff --git a/2005/i/robert/src/ovision/ui/adjust.hh b/2005/i/robert/src/ovision/ui/adjust.hh new file mode 100644 index 0000000..9a248c8 --- /dev/null +++ b/2005/i/robert/src/ovision/ui/adjust.hh @@ -0,0 +1,63 @@ +// robert - programme du robot 2005 +// +// Copyright (C) 2005 Olivier Gaillard +// +// Robot APB Team/Efrei 2005. +// Web: http://assos.efrei.fr/robot/ +// Email: robot AT efrei DOT fr +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + +#ifndef adjust_h +#define adjust_h + +/// Constantes d'interruptions +#define QUIT 3 +#define USR1 10 +#define ALARM 14 + + +/// Proprietes de la fenetre +#define BORDER 5 +#define NBIMG 6 + +/// Constantes liees au chargement des commandes +#define NUMCOLORTOCHANGE 1 +#define COLORTOCHANGE 2 + +#define NBCOLORTOMERGE 1 +#define NUMCOLORTOMERGE 2 + +#define NUMCOLORTODEL 1 + +#define NBNNOUTPUT 1 + +#define NUMGROUP 1 + +#define NUMCOLORTOSHOW 1 + +#define FILENAME 1 + +#define NBCOLORNN 1 + +/// Affiche les images a l'ecran +void drawGLScene(); + +/// Chargement des textures a partir de donnees RGB +unsigned int loadImage(int width, int height, unsigned char *data, unsigned int lastTex); +int *getPpoint(); + +#endif // adjust_h diff --git a/2005/i/robert/src/ovision/ui/comm.cc b/2005/i/robert/src/ovision/ui/comm.cc new file mode 100644 index 0000000..906ad51 --- /dev/null +++ b/2005/i/robert/src/ovision/ui/comm.cc @@ -0,0 +1,339 @@ +// comm.cc - Classe Comm +// robert - Programme du robot APBteam +// Copyright (C) 2005 Olivier Gaillard + + +/// @file comm.cc Interprete les commandes envoyes par l'interface UI et les executent + +#include +#include +#include +#include +#include +#include + +#include "comm.hh" + +/// Constructeur +/// @param *filename nom de l'image a utiliser +Comm::Comm (const char *filename) + : yuvSwitch (0) +{ + // Copie du nom de l'image courante + strcpy(fname, filename); +} + +void +Comm::init () +{ + // Ecriture du PID dans un fichier + long pid = getpid(); + FILE *file = fopen("adjust.PID", "w+"); + if (!file) + { + std::cerr << "Comm::Comm Error during file opening" << std::endl; + return; + } + fprintf(file, "%li\n", pid); + fclose(file); + + live_ = new Live (NBIMG); + live_->init (fname); +} + +/// Destructeur +Comm::~Comm() +{ + close(fifo); +} + +/// Synchronisation des poids locaux et de ceux du programme ui +void +Comm::sendNodes () +{ + char buf[10]; + for (int i=0; i < live_->oconfig->nnNbColor*3; i++) + { + sprintf(buf, "%u\n", live_->segm->node_[i]); + write(fifo, buf, 10); + } +} + +/// Execute une commande venant de l'interface ui +/// @param *buffer ligne de commande a analyser +void +Comm::executeUiCmds (const char *buffer) +{ + std::cout << "Commande reçue : " << buffer; + std::stringstream ss; + ss << buffer; + char cmd; + ss >> cmd; + // Detection de la commande recue + switch (cmd) + { + case 'i': // ouverture du fifo + std::cout << "Initialisation du fifo\n"; + // Ouverture du fifo + fifo = open("uicmds", O_RDWR); + if (!fifo) { + std::cerr << "InitComm : Error during opening FIFO" << std::endl; + exit(1); + } + // On choppe le pid du prog ui situé dans le fichier uiPid.PID + FILE *file; + file = fopen("ui.PID", "r"); + if (!file) + { + std::cerr << "Comm::ExecuteUiCmds : PID file not found" << std::endl; + exit(1); + } + char buf[10]; + fgets(buf, 10, file); + uiPid = atol(buf); + fclose(file); + break; + + case 'c': // changement de couleur + int numColor; + ss >> numColor; + + // Changement des valeurs sur les poids du NN + int colorToChange; + for (int i=0; i<3; i++) + { + ss >> colorToChange; + live_->segm->node_[numColor*3+i] = colorToChange; + } + // On live_->segmente l'image puis on la stocke + live_->segmAndGroup (); + std::cout << "Couleur " << numColor << " changé aux valeurs " << (int)live_->segm->node_[numColor*3] << " " << (int)live_->segm->node_[numColor*3+1] << " " << (int)live_->segm->node_[numColor*3+2]; + break; + + case 'm': // mélanger couleurs + int nbColorToMerge, numIndexColor; + + // Si on recoit une commande de remise a zero de l'index_ + ss >> nbColorToMerge; + if (nbColorToMerge == -1) + { + for (int i=0; ioconfig->nnNbColor; i++) + live_->segm->index_[i] = i; + } + // Sinon on mix les couleurs + else + { + numIndexColor = live_->segm->index_[nbColorToMerge]; + + // On inscrit les changements dans l'index_ + int numColorToMerge; + for (int i=1; i> numColorToMerge; + live_->segm->index_[numColorToMerge] = numIndexColor; + } + } + // On live_->segmente l'image puis on la stocke + live_->segmAndGroup(); + std::cout << nbColorToMerge << " colors merged to " << numIndexColor << std::endl; + break; + + case 's': // isole une couleur + int numColorToShow; + ss >> numColorToShow; + // Cas ou toutes les couleurs doivent etre affiche + if (numColorToShow == -1) + live_->segmAndGroup (); + // Afficher seulement une couleur + else + live_->segmAndGroup (numColorToShow); + break; + + case 'd': // supprimer couleur + int numColorToDel; + ss >> numColorToDel; + // Decalage de toutes les couleurs pour supprimer une couleur + unsigned char *pCur; + pCur = &live_->oconfig->node[numColorToDel*3]; + for(int i=numColorToDel*3; ioconfig->nnNbColor*3; i++) + { + *(pCur) = *(pCur+3); + pCur++; + } + live_->oconfig->nnNbColor--; + // On refait le NN vu qu'il y a une couleur de moins + live_->segm->buildNN(live_->oconfig->nnNbColor, Segm::loadFromFile); + live_->segm->showNodes(); + // On live_->segmente l'image puis on la stocke + live_->segmAndGroup(); + break; + + case 'r': // Reload l'image + int nbNNOutput; + ss >> nbNNOutput; + // Reattribution du nombre de sorties d'origine + if (nbNNOutput != -1) live_->oconfig->nnNbColor = nbNNOutput; + // Recharge du fichier des poids + live_->oconfig->loadNNFile("rc/poids"); + // On refait le NN vu qu'il y a une couleur de moins + live_->segm->buildNN(live_->oconfig->nnNbColor, Segm::loadFromFile); + // On live_->segmente l'image puis on la stocke + live_->segmAndGroup(); + // Si l'image a ete sauve on change l'image pivot + if (nbNNOutput == -1) + live_->rootPics (); + break; + + case 'a': // Selectionne la couleur des objets à afficher + { + int obj; + ss >> obj; + std::cout << "Changement de l'objet affiché " << obj << std::endl; + live_->oconfig->uiGroupToDisplay = obj; + live_->segmAndGroup (); + live_->rootPics (); + } + break; + + case 'b': // Selectionne la couleur des objets + { + int col; + std::string obj; + ss >> obj >> col; + for (std::vector::iterator iter=live_->oconfig->groupColor.begin (); + iter != live_->oconfig->groupColor.end (); ++iter) + { + if (obj == iter->label) + { + iter->color = col; + break; + } + } + live_->segmAndGroup (); + live_->rootPics (); + } + break; + /* + case 'g': // Selection du live_->groupe + ss >> live_->oconfig->live_->groupColor; + */ + // On live_->segmente l'image puis on la stocke + live_->segmAndGroup(); + break; + + + case 'n': // Image suivante + std::cout << ss.str () << std::endl; + // Copie du nom de l'image courante + ss >> fname; + // Ouverture de l'image pilote et stockage + live_->img->loadRaw(fname, Image::rgb, 360, 296); + memcpy(live_->data[0], live_->img->tabData_, sizeof(char)*live_->img->nbPixels_*3); + live_->tex[0] = loadImage(live_->img->width_, live_->img->height_, live_->data[0], live_->tex[0]); + // Conversion en YUV et stockage + ConvertImg convert; + convert.RGBtoYUV (*live_->img); + // NN live_->oconfigure en RGB ou YUV ? + if (!live_->oconfig->inputColor == Image::rgb) live_->img->loadRaw(fname, Image::rgb, 360, 296); + live_->segmAndGroup(); + // Affichage de l'image pilote + live_->rootPics (); + break; + + + case 't': // Entraine le reseau + live_->segm->trainNN(live_->img); + // On live_->segmente l'image puis on la stocke + live_->segmAndGroup(); + // Synchronisation des poids avec ui + sendNodes(); + break; + + case 'p': // Regenere les poids du reseau + int nbColor; + ss >> nbColor; + // Assignation du nombre de couleurs a isoler par le reseau + live_->oconfig->nnNbColor = nbColor; + // Genere aleatoire les poids + live_->segm->buildNN(live_->oconfig->nnNbColor, Segm::generate); + // Apprentissage + live_->segm->trainNN(live_->img); + // On live_->segmente l'image puis on la stocke + live_->segmAndGroup(); + // Synchronisation des poids avec ui + sendNodes(); + break; + /* + case 'v': // Envoie les points pour le calcul de la distance + int *pPoint; + pPoint = getPpoint(); + + for (int i=0; ioconfig->tabPoint[i*4+0] = pPoint[i*2]; + // live_->oconfig->tabPoint[i*4+1] = pPoint[i*2+1]; + // live_->oconfig->tabPoint[i*4+2] = 0; + // live_->oconfig->tabPoint[i*4+3] = 0; + // } + + live_->oconfig->createDistFile("rc/dist", NB_POINTS_UI); + break; + *//* + case 'y': + yuvSwitch++; + + // Conversion en YUV et stockage + live_->img->loadRaw(filename, Image::yuv, 360, 296); + if (yuvSwitch%3 == 1) + { + ConvertImg convert; + convert.YUVtoRGB (live_->img->; + } + else if (yuvSwitch%3 == 2) + { + ConvertImg convert; + convert.RGBtoYUV (live_->img->; + } + delete[] live_->img->eft[1]; + live_->img->eft[1] = new unsigned char[live_->img->nbPixels_*3]; + memcpy(live_->img->eft[1], live_->img->tabData_, sizeof(char)*live_->img->nbPixels_*3); + live_->tex[3] = loadImage(live_->img->width_, live_->img->height_, live_->img->eft[1], live_->tex[3]); + live_->img->loadRaw(fname, Image::yuv, 360, 296); + break; + */ + case 'z': + live_->group->showZones(); + break; + /* + case 'f': + { + ///TODO + char buf[20]; + Zone *pCur = live_->group->zoneListBall; + write (fifo, "Groupes balles:\n", 20); + while(pCur) { + sprintf(buf, "%u %i %i %i %i\n", pCur->id, pCur->xmin, pCur->xmax, pCur->ymin, pCur->ymax); + write (fifo, buf, 20); + } + + pCur = live_->group->zoneListGoal; + write (fifo, "Groupes poteaux:\n", 20); + while(pCur) { + sprintf(buf, "%u %i %i %i %i\n", pCur->id, pCur->xmin, pCur->xmax, pCur->ymin, pCur->ymax); + write (fifo, buf, 20); + } + write (fifo, "end\n", 20); + } + break; + */ + } + drawGLScene(); +} + diff --git a/2005/i/robert/src/ovision/ui/comm.hh b/2005/i/robert/src/ovision/ui/comm.hh new file mode 100644 index 0000000..3d36cae --- /dev/null +++ b/2005/i/robert/src/ovision/ui/comm.hh @@ -0,0 +1,60 @@ +// robert - programme du robot 2005 +// +// Copyright (C) 2005 Olivier Gaillard +// +// Robot APB Team/Efrei 2005. +// Web: http://assos.efrei.fr/robot/ +// Email: robot AT efrei DOT fr +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +#ifndef comm_h +#define comm_h + +#include "live.hh" + +/// Interprete les commandes envoyes par l'interface UI et les executent +class Comm +{ + int yuvSwitch; + Live *live_; + /// nom de l'image courante + char fname[100]; + public: + /// Constructeur + Comm (const char *filename); + /// Destructeur + ~Comm (void); + /// classe de traitement de l'image pour affichage + /// PID du programme ui + long uiPid; + /// id utilisé pour l'ouverture du fifo + int fifo; + /// Initialisation + void init (); + /// Recharge le fichier de conf + void reloadConfig (const char *filename) {live_->reloadConfig (filename);} + /// Execute une commande venant de l'interface + void executeUiCmds (const char *buffer); + /// Accessors + unsigned* getTex () {return live_->tex;} + + private: + /// Synchronisation des poids locaux et de ceux du programme ui + void sendNodes(); +}; + + +#endif // comm_h diff --git a/2005/i/robert/src/ovision/ui/live.cc b/2005/i/robert/src/ovision/ui/live.cc new file mode 100644 index 0000000..21a7c3e --- /dev/null +++ b/2005/i/robert/src/ovision/ui/live.cc @@ -0,0 +1,180 @@ +// comm.cc - Classe Live +// robert - Programme du robot APBteam +// Copyright (C) 2005 Olivier Gaillard + + +/// @file live.cc Traitement de l'image dans le but d'être visualisé sur une interface + +#include +#include +#include +#include +#include +#include + +#include "live.hh" +#include "image/raw_reader.hh" +#include "data/data_input_file.hh" +#include "video4linux/video4linux.hh" + +/// Constructeur +/// @param *filename nom de l'image a utiliser +Live::Live (const unsigned nbImg, const ImageInput imgInput) + : group (0), imgInput_ (imgInput) +{ + if (nbImg < 6) nbImg_ = 6; + else nbImg_ = nbImg; +} + +void +Live::init (const char *filename) +{ + tex = new unsigned[nbImg_]; + data = new unsigned char*[nbImg_]; + // Creation de oconfig + oconfig = new OConfig (); + // Création de l'image + img = new ImgInterface; + // Ouverture de l'image pilote et stockage + Image::PixelFormat pf = Image::rgb; + switch (imgInput_) + { + case file: + { + // Copie du nom de l'image courante + strcpy (fname, filename); + std::string f (fname); + DataInputFile *dif = new DataInputFile (f); + DataInput *di = reinterpret_cast (dif); + reader_ = new RawReader (*di, 360, 296, pf); + } + break; + case cam: + { + Video4Linux *r; + r = new Video4Linux ("/dev/video", pf); + r->calibrate (); + reader_ = reinterpret_cast (r); + } + break; + case serv: + break; + } + img->load (*reader_); + // Allocation memoire pour les images + for (unsigned i=0; inbPixels_*3]; + memcpy(data[0], img->tabData_, sizeof(char) * img->nbPixels_ * 3); + tex[0] = loadImage(img->width_, img->height_, data[0], tex[0]); + // Initialisation de la segmentation + segm = new SegmLearn; + segm->buildNN (oconfig->nnNbColor, Segm::loadFromFile); + mag = new Magnifier (img, segm); + segmAndGroup (); + // Affichage de l'image pilote avec la couleur d'aquisition et en RGB + tex[1] = loadImage (img->width_, img->height_, data[0], tex[1]); + /*if (img->colorMode_ != Image::rgb) + { + ConvertImg conv; + conv.ConvertToRGB (*img); + tex[3] = loadImage (img->width_, img->height_, data[0], tex[4]); + img->loadRaw (fname, Image::rgb, 360, 296); + }*/ + rootPics (); +} + +/// Mis à jour de l'image +void +Live::updateImg (const char *filename) +{ + Image::PixelFormat pf = Image::rgb; + switch (imgInput_) + { + case file: + { + // Copie du nom de l'image courante + strcpy (fname, filename); + std::string f (filename); + DataInputFile *dif = new DataInputFile (f); + DataInput *di = reinterpret_cast (dif); + delete reader_; + reader_ = new RawReader (*di, 360, 296, pf); + } + break; + case cam: + case serv: + break; + } + img->load (*reader_); + memcpy(data[0], img->tabData_, sizeof(char) * img->nbPixels_ * 3); + tex[0] = loadImage(img->width_, img->height_, data[0], tex[0]); + segmAndGroup (); + rootPics (); +} + +/// Fixe une image ségmentée et une image de groupe dans la partie centrale +void +Live::rootPics () +{ + memcpy (data[1], data[2], sizeof (char)*img->nbPixels_*3); + memcpy (data[4], data[5], sizeof (char)*img->nbPixels_*3); + tex[1] = loadImage(img->width_, img->height_, data[1], tex[1]); + tex[4] = loadImage(img->width_, img->height_, data[4], tex[4]); + +} + +/// Destructeur +Live::~Live() +{ + // Liberation de la memoire + delete oconfig; + delete segm; + delete group; + delete [] data; +} + +/// Recharge le fichier de config +void +Live::reloadConfig (const char *filename) +{ + oconfig->load (filename); +} + + +/// Segmente et group les couleurs +void +Live::segmAndGroup(int numColorToShow) +{ + // Création des groupes + delete group; + group = new Group(img, segm); + std::vector list; + if (numColorToShow >= 0) + { + group->jumpPoints(numColorToShow); + list = group->getZoneList (); + } + else + { + group->jumpPoints(oconfig->groupColor); + mag->analyse (group->getZoneList ()); + list = mag->getItemList ((Group::ZoneType)oconfig->uiGroupToDisplay); + } + // Création de l'image des groupes + img->doGroupImg (list); + img->doImg (img->getTabSegm ()); + memcpy (data[5], img->getTabOut (), sizeof (char)*img->nbPixels_*3); + // Création de l'image segmentée + if (numColorToShow >= 0) + segm->segmImg (img, numColorToShow); + else + { + segm->segmImg (img); + img->addGroupToDisplay (img->getTabSegm (), list); + } + img->doImg (img->getTabSegm ()); + memcpy (data[2], img->getTabOut (), sizeof (char)*img->nbPixels_*3); + tex[2] = loadImage(img->width_, img->height_, data[2], tex[2]); + tex[5] = loadImage(img->width_, img->height_, data[5], tex[5]); +} + diff --git a/2005/i/robert/src/ovision/ui/live.hh b/2005/i/robert/src/ovision/ui/live.hh new file mode 100644 index 0000000..7c5301e --- /dev/null +++ b/2005/i/robert/src/ovision/ui/live.hh @@ -0,0 +1,81 @@ +// robert - programme du robot 2005 +// +// Copyright (C) 2005 Olivier Gaillard +// +// Robot APB Team/Efrei 2005. +// Web: http://assos.efrei.fr/robot/ +// Email: robot AT efrei DOT fr +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +#ifndef live_h +#define live_h + +#include "adjust.hh" +#include "ovision/see/convertImg.hh" +#include "ovision/see/imgInterface.hh" +#include "ovision/see/segmLearn.hh" +#include "ovision/see/oconfig.hh" +#include "ovision/see/group.hh" +#include "ovision/see/magnifier.hh" + +#define NB_POINTS_UI 6 + +/// Traitement de l'image dans le but d'être visualisé sur une interface +class Live +{ + unsigned nbImg_; + ImageReader *reader_; + public: + enum ImageInput {file, cam, serv}; + /// Constructeur + Live (const unsigned nbImg, const ImageInput imgInput = file); + /// Destructeur + ~Live (void); + + /// tableau des numeros de textures utilises par openGL + unsigned *tex; + /// tableau de donnees RGB stockant les images + unsigned char **data; + /// classe image + ImgInterface *img; + /// classe config + OConfig *oconfig; + /// classe segmentation + SegmLearn *segm; + /// classe group + Group *group; + /// classe magnifier + Magnifier *mag; + /// nom de l'image courante + char fname[100]; + + /// Initialisation + void init (const char *filename); + /// Recharge le fichier de config + void reloadConfig (const char *filename); + /// Segmentation et groupement des couleurs + void segmAndGroup(int numColorToShow = -1); + /// Fixe une image ségmentée et une image de groupe dans la partie centrale + void rootPics (); + /// Mis à jour de l'image + void updateImg (const char *filename); + + private: + ImageInput imgInput_; +}; + + +#endif // live_h diff --git a/2005/i/robert/src/ovision/ui/mainui.cc b/2005/i/robert/src/ovision/ui/mainui.cc new file mode 100644 index 0000000..39bd3c2 --- /dev/null +++ b/2005/i/robert/src/ovision/ui/mainui.cc @@ -0,0 +1,51 @@ +#include "ui.hh" + +#include + +#include +#include +#include + +using namespace std; + +UI *ui; +int ready; + +int +GetReady() +{ + return ready; +} + +void +SetReady(int i) +{ + ready = i; +} + + +// Lecture du fifo et execution de la commande +void +endSleep(int numSignal) +{ + // Reassignement du signal handler + signal(SIGUSR1, endSleep); + ready = 1; +} + + +int +main(int argc, char **argv) +{ + signal(SIGUSR1, endSleep); + + if (argc > 0) + { + ui = new UI (argv[1]); + } + else ui = new UI; + + ui->menu (); + + delete ui; +} diff --git a/2005/i/robert/src/ovision/ui/mainui.hh b/2005/i/robert/src/ovision/ui/mainui.hh new file mode 100644 index 0000000..ba855ae --- /dev/null +++ b/2005/i/robert/src/ovision/ui/mainui.hh @@ -0,0 +1,26 @@ +// robert - programme du robot 2005 +// +// Copyright (C) 2005 Olivier Gaillard +// +// Robot APB Team/Efrei 2005. +// Web: http://assos.efrei.fr/robot/ +// Email: robot AT efrei DOT fr +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + +int GetReady(); +void SetReady(int i); + diff --git a/2005/i/robert/src/ovision/ui/testui.cc b/2005/i/robert/src/ovision/ui/testui.cc new file mode 100644 index 0000000..2493256 --- /dev/null +++ b/2005/i/robert/src/ovision/ui/testui.cc @@ -0,0 +1,46 @@ +#include "ui.hh" + +#include + +#include +#include +#include + +using namespace std; + +UI *ui; +int ready; + +int +GetReady() +{ + return ready; +} + +void +SetReady(int i) +{ + ready = i; +} + + +// Lecture du fifo et execution de la commande +void +endSleep(int numSignal) +{ + // Reassignement du signal handler + signal(SIGUSR1, endSleep); + ready = 1; +} + + +int +main() +{ + signal(SIGUSR1, endSleep); + + ui = new UI; + ui->Menu(); + + delete ui; +} diff --git a/2005/i/robert/src/ovision/ui/testui.hh b/2005/i/robert/src/ovision/ui/testui.hh new file mode 100644 index 0000000..2d550cb --- /dev/null +++ b/2005/i/robert/src/ovision/ui/testui.hh @@ -0,0 +1,4 @@ + +int GetReady(); +void SetReady(int i); + diff --git a/2005/i/robert/src/ovision/ui/ui.cc b/2005/i/robert/src/ovision/ui/ui.cc new file mode 100644 index 0000000..525fca2 --- /dev/null +++ b/2005/i/robert/src/ovision/ui/ui.cc @@ -0,0 +1,1057 @@ +// ui.cc - Classe User Interface +// robert - Programme du robot APBteam +// Copyright (C) 2005 Olivier Gaillard + +/// @file ui.cc Interface ncurses permettant de piloter adjust + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ui.hh" +#include "mainui.hh" + +/// Nombre d'items du menu +#define NBITEMS 12 + + + +/// Items du menu principal +char *itemsName[NBITEMS][2] = {{"Move color", "Permet d'ajuster les niveaux d'une couleur"}, + {"Del color", "Enleve une couleur du reseau"}, + {"Merge colors", "Groupe plusieurs couleurs ensembles"}, + {"Object to display", "Selectionne l'object à afficher"}, + {"Change object color", "Selectionne l'index de la couleur d'un objet"}, + {"Show objets found", "Affiche les balles et poteaux trouvés"}, + {"Training", "Entraine le reseau de neurones"}, + {"New network", "Regenere de nouveaux poids pour le reseau"}, + {"Cancel changes", "Recharge le fichier de oconfig"}, + {"Save changes", "Sauvegarde les changements dans le fichier"}, + {"Quit", "Quitte le programme"}, + {NULL, NULL}}; + +/// Constructor +UI::UI(const char *filename) +{ + oconfig = new OConfig; + + // TODO verifier que le terminal est assez grand sinon écran noir + + + // Suppression de l'ancien fifo + system("rm -f uicmds"); + + // Creation du fifo + if (mknod("uicmds", S_IFIFO | 0666, 0) != 0) + { + std::cerr << "UI::UI : Error during fifo creation\n"; + return; + } + + // Ouverture du fifo + fifo = open("uicmds", O_RDWR); + if (fifo < 0) + { + std::cerr << "UI::UI : Error during fifo opening\n"; + return; + } + + // On choppe le pid du prog adjust situé dans le fichier adjust.PID + FILE *file; + file = fopen("adjust.PID", "r"); + if (!file) + { + std::cerr << "UI:UI : PID file not found" << std::endl; + exit(1); + } + char buf[10]; + fgets(buf, 10, file); + pid = atol(buf); + fclose(file); + + curImage = 0; + parseFileList(); + + oconfig->loadNNFile(); + savedNNColorNumber = oconfig->nnNbColor; + + // Ecriture du PID dans un fichier + long uiPid = getpid(); + file = fopen("ui.PID", "w+"); + if (!file) + { + std::cerr << "UI::UI : Error during file opening" << std::endl; + return; + } + fprintf(file, "%li\n", uiPid); + fclose(file); + + // Ouverture du fifo + kill(pid, SIGUSR2); + + // Init ncurses + initscr(); + start_color(); + keypad(stdscr, TRUE); + cbreak(); + noecho(); + curs_set(0); + + // Init couleurs + init_pair(1, COLOR_BLUE, COLOR_BLACK); + init_pair(2, COLOR_RED, COLOR_BLACK); + init_pair(3, COLOR_GREEN, COLOR_BLACK); + init_pair(4, COLOR_CYAN, COLOR_BLACK); + + if (filename) + { + sprintf(buf, "n %s\n", filename); + sendSignal(buf); + } +} + + +/// Destructeur +UI::~UI() +{ + // Libere memoire + unpost_menu(mainMenu); + free_menu(mainMenu); + for(int i = 0; i < NBITEMS; ++i) + free_item(item[i]); + endwin(); + + close(fifo); + + // Ferme adjust SIGQUIT + kill(pid, SIGQUIT); + + system("rm -f adjust.PID ui.PID"); + + if (fileList) delete fileList; +} + + +/// Synchronisation des poids locaux avec ceux du programme adjust +void +UI::updateNodes () +{ + char buf[10]; + + // On parcours toutes les couleurs + for (int i=0; i < oconfig->nnNbColor*3; i++) + { + // On lis le fifo et on le copie dans le tableau node + read(fifo, buf, 10); + oconfig->node[i] = atoi(buf); + } +} + + + +/// Cree la liste d'images a ouvrir +void +UI::parseFileList () +{ + // On enleve l'ancienne liste et on en cree une nouvelle + char buf[100]; + sprintf(buf, "rm -Rf imagelist ; ls %s | grep -e .jpg -e .JPG -e .png -e .PNG > imagelist", oconfig->imgPath); + system(buf); + + FILE *file; + file = fopen("imagelist", "r"); + if (!file) + { + std::cerr << "UI:ParseFileList : file not found" << std::endl; + std::cerr << "UI:ParseFileList : use 'ls pictures_dir > imagelist" << std::endl; + exit(1); + } + + lengthFileList = 0; + + while(fgets(buf, 30, file)) + lengthFileList++; + rewind(file); + + fileList = new char*[lengthFileList]; + int fileCount = 0; + char *p; + + while (fgets(buf, 30, file)) + { + fileList[fileCount] = new char[30]; + p = strtok(buf, "\t\n"); + if (p) + { + strcpy(fileList[fileCount], p); + fileCount++; + } + else lengthFileList--; + } +} + + +/// Envoie une donnee au prog adjust +/// @param *cmd commande a envoyer +void +UI::sendSignal (const char *cmd) +{ + // Ecrit dans le fifo + write(fifo, cmd, 50); + + // Envoie un signal USR1 au prog adjust + kill(pid, SIGUSR1); + + // Attente de la reponse de adjust + SetReady(0); + while (!GetReady()) + { + usleep(1); + } +} + +/// Affiche un msg dans la barre d'etat +/// @param *str message a afficher dans la barre d'etat +void +UI::printStatus (const char *str) +{ + // Creation de la fenetre + WINDOW *statusWindow = newwin(3, 60, 20, 5); + wattron(statusWindow, A_BOLD | COLOR_PAIR(4)); + + // Affichage du texte + wprintw(statusWindow, "%s\n", str); + wrefresh(statusWindow); + + // Liberation de la memoire + delwin(statusWindow); +} + + +/// menu de selection de couleur +/// @param type choix du texte des items +/// @param current item selectionne au depart +int +UI::chooseColor (const int type, const int current) +{ + // Choix de la couleur + char **colorName; + + // Nombre d'item a afficher + if (type == NB_COULEUR) + oconfig->nnNbColor = 10; + + // Creation des items + ITEM **colorItem = new ITEM*[oconfig->nnNbColor+2]; + colorName = new char*[oconfig->nnNbColor+1]; + for (int i=0; innNbColor; i++) + { + colorName[i] = new char[20]; + if (type == NUM_COULEUR) + sprintf(colorName[i], "Couleur %i", i); + else if (type == NB_COULEUR) + sprintf(colorName[i], "%i", i); + colorItem[i] = new_item(colorName[i] , NULL); + } + colorName[oconfig->nnNbColor] = new char[20]; + sprintf(colorName[oconfig->nnNbColor], "Annuler"); + colorItem[oconfig->nnNbColor] = new_item(colorName[oconfig->nnNbColor] , NULL); + colorItem[oconfig->nnNbColor+1] = NULL; + + // Creation de la fenetre + WINDOW *colorWindow = newwin(11, 15, 9, 35); + keypad(colorWindow, TRUE); + + // Creation du menu + MENU *colormenu = new_menu(colorItem); + set_menu_win(colormenu, colorWindow); + set_menu_mark(colormenu, " -> "); + post_menu(colormenu); + wrefresh(colorWindow); + + // Affichage d'info + printStatus("Utiliser ENTREE pour selectionner la couleur\n"); + + char buf[50]; + int car; + int col=0; + + if (type == NUM_COULEUR) + { + // Cree une image de la couleur selectionnee + sprintf(buf, "s %i\n", current); + sendSignal(buf); + } + + set_current_item(colormenu, colorItem[current]); + col = current; + + wrefresh(colorWindow); + + while((car = wgetch(colorWindow)) != 10) + { + switch (car) + { + case KEY_DOWN: // Touche BAS + // Deplacement dans le menu + if (col < (int)oconfig->nnNbColor) + { + menu_driver(colormenu, REQ_DOWN_ITEM); + col++; + } + break; + + case KEY_UP: // Touche HAUT + // Deplacement dans le menu + if (col > 0) + { + menu_driver(colormenu, REQ_UP_ITEM); + col--; + } + break; + } + + if ( (type == NUM_COULEUR) && (col < oconfig->nnNbColor)) + { + // Cree une image de la couleur selectionnee + sprintf(buf, "s %i\n", col); + sendSignal(buf); + } + + wrefresh(colorWindow); + } + + // Cas d'annulation + if (col == oconfig->nnNbColor) + { + col = -1; + + // On reaffiche l'image normale + sendSignal("r -1\n"); + } + + // Liberation memoire + for(int i=0; innNbColor; i++) + free_item(colorItem[i]); + free_menu(colormenu); + delwin(colorWindow); + colorWindow = newwin(11, 15, 9, 35); + wrefresh(colorWindow); + delwin(colorWindow); + delete [] colorName; + + // Retourne la valeur choisie par l'utilisateur + return col; +} + +/// menu de selection d'objet +int +UI::chooseObject (const int current) +{ + const int nbObjects = 5; + + // Creation des items + const char *objectName[15] = {"greenSkittle", "redSkittle", "border", "base", "gap", "undefined", "annuler"}; + ITEM **objectItem = new ITEM*[nbObjects+2]; + for (int i = 0; i < nbObjects+1; ++i) + objectItem[i] = new_item(objectName[i], NULL); + objectItem[nbObjects+1] = NULL; + + // Creation de la fenetre + WINDOW *objectWindow = newwin(7, 18, 10, 45); + keypad(objectWindow, TRUE); + + // Creation du menu + MENU *objectmenu = new_menu(objectItem); + set_menu_win(objectmenu, objectWindow); + set_menu_mark(objectmenu, " -> "); + post_menu(objectmenu); + wrefresh(objectWindow); + + // Affichage d'info + printStatus("Utiliser ENTREE pour selectionner l'objet\n"); + + int car; + int obj=0; + + set_current_item(objectmenu, objectItem[current]); + obj = current; + + wrefresh(objectWindow); + + while((car = wgetch(objectWindow)) != 10) + { + switch (car) + { + case KEY_DOWN: // Touche BAS + // Deplacement dans le menu + if (obj < nbObjects) + { + menu_driver(objectmenu, REQ_DOWN_ITEM); + obj++; + } + break; + + case KEY_UP: // Touche HAUT + // Deplacement dans le menu + if (obj > 0) + { + menu_driver(objectmenu, REQ_UP_ITEM); + obj--; + } + break; + } + +// if ( (type == NUM_COULEUR) && (obj < oconfig->nnNbColor)) +// { +// // Cree une image de la couleur selectionnee +// sprintf(buf, "s %i\n", obj); +// sendSignal(buf); +// } + + wrefresh(objectWindow); + } + + // Cas d'annulation + if (obj == nbObjects) + obj = -1; + + // Liberation memoire + for(int i=0; innNbColor+2]; + mergeName = new char*[oconfig->nnNbColor+1]; + for (int i=0; innNbColor; i++) + { + mergeName[i] = new char[20]; + sprintf(mergeName[i], "Couleur %i (%i)", i, oconfig->index[i]); + mergeItem[i] = new_item(mergeName[i] , NULL); + } + + // Ajout du choix unmerge a la fin du menu + mergeName[oconfig->nnNbColor] = new char[20]; + strcpy(mergeName[oconfig->nnNbColor], "Unmerge all"); + mergeItem[oconfig->nnNbColor] = new_item(mergeName[oconfig->nnNbColor], NULL); + mergeItem[oconfig->nnNbColor+1] = NULL; + + // Creation de la fenetre + WINDOW *mergeWindow = newwin(10, 20, 9, 35); + keypad(mergeWindow, TRUE); + + // Creation du menu + MENU *mergemenu = new_menu(mergeItem); + set_menu_win(mergemenu, mergeWindow); + set_menu_mark(mergemenu, " -> "); + menu_opts_off(mergemenu, O_ONEVALUE); + post_menu(mergemenu); + + wrefresh(mergeWindow); + + // Initialisation de variables + int c; + int end = 0; + int col = 0; + char buf[40]; + char cmd[50]; + char tmp[3]; + int nbColorToMerge = 0; + + // Cree une image de la couleur selectionnee + sendSignal("s 0\n"); + + // Affichage d'info + printStatus("ESPACE pour choisir les valeurs, ENTREE pour valider\n"); + + // Boucle du menu de selection des couleurs + int indexColor = -1; + while(!end) + { + c = wgetch(mergeWindow); + switch (c) + { + case ' ': // Touche ESPACE + // Selection d'un element + menu_driver(mergemenu, REQ_TOGGLE_ITEM); + break; + + case KEY_DOWN: // Touche BAS + // Deplacement dans le menu + if (col < oconfig->nnNbColor) + { + menu_driver(mergemenu, REQ_DOWN_ITEM); + col++; + } + break; + + case KEY_UP: // Touche HAUT + // Deplacement dans le menu + if (col > 0) + { + menu_driver(mergemenu, REQ_UP_ITEM); + col--; + } + break; + + case 10: // Touche ENTREE + // Validation des elements + items = menu_items(mergemenu); + + + // Si l'option unmerge est choisie + if ( item_index(current_item(mergemenu)) == item_count(mergemenu)-1) + { + // On remet a zero la table d'index + for (int i=0; innNbColor; i++) + oconfig->index[i] = i; + + // Fin de la boucle + end = 1; + nbColorToMerge++; + } + else + { + // Parcours des items du menu + for (int i=0; i< item_count(mergemenu)-1; i++) + // Si il on ete valide on les ajoute a la string + if (item_value(items[i]) == TRUE) + { + // Memorisation du premier index trouve pour + // le copier dans les autres couleurs choisies + if (indexColor == -1) indexColor = oconfig->index[i]; + sprintf(tmp, " %i", i); + strcat(buf, tmp); + nbColorToMerge++; + oconfig->index[i]= indexColor; + } + + // Flag de fin de boucle + end = 1; + } + break; + } + + if (col != oconfig->nnNbColor) + { + // Cree une image de la couleur selectionnee + sprintf(cmd, "s %i\n", col); + sendSignal(cmd); + } + } + + if (nbColorToMerge) + { + // Cas ou unmerge a ete selectionne + if (indexColor == -1) + { + // Envoie un signal + sprintf(cmd, "m %i\n", -1); + sendSignal(cmd); + + // Affichage d'info + sprintf(cmd, "Les index des couleurs ont ete remises a zero"); + printStatus(cmd); + } + else + { + // Finition de la chaine a envoye + strcat(buf, "\n"); + sprintf(cmd, "m %i", nbColorToMerge); + strcat(cmd, buf); + + // Envoie du signal + sendSignal(cmd); + + // Affichage d'info + sprintf(cmd, "Les couleurs melangees sont %s", buf+1); + printStatus(cmd); + } + } + else printStatus("Pas de couleur selectionnee\n"); + wrefresh(mergeWindow); + + + // Liberation memoire + for(int i=0; innNbColor; i++) + free_item(mergeItem[i]); + free_menu(mergemenu); + delwin(mergeWindow); + mergeWindow = newwin(10, 20, 9, 35); + wrefresh(mergeWindow); + delwin(mergeWindow); + delete [] mergeName; +} + + + +/// menu de suppression de couleur +void +UI::goDelColor() +{ + // menu de sélection de couleur + int numColor = chooseColor(NUM_COULEUR); + + // Annulation + if (numColor < 0) return; + + // Envoie du signal + char buf[50]; + sprintf(buf, "d %i\n", numColor); + sendSignal(buf); + + // On supprime la couleur en local + unsigned char *pCur; + pCur = &oconfig->node[numColor*3]; + for(int i=numColor*3; innNbColor*3; i++) + { + *(pCur) = *(pCur+3); + pCur++; + } + + oconfig->nnNbColor--; + + // Affichage d'info + sprintf(buf, "Couleur %i supprimee\n", numColor); + printStatus(buf); +} + + + +/// menu de selection du group a former +void +UI::goSelectGroup(const int type) +{ + // menu de selection de couleur +/* int tmp; + if (type == BALL) tmp = chooseColor(NUM_COULEUR, oconfig->groupColor); + else if (type == GOAL) tmp = chooseColor(NUM_COULEUR, oconfig->goalColor); + + + if (tmp != -1) + { + if (type == BALL) + { + + oconfig->groupColor = tmp; + + // Envoie d'un signal avec la valeur choisie + char buf[50]; + sprintf(buf, "g %i\n", tmp); + sendSignal(buf); + } + else if (type == GOAL) + { + oconfig->goalColor = tmp; + } + } + */ +} + + + +/// menu de suppression de couleur +void +UI::goChangeColor () +{ + unsigned char c[3]; + int ligne=0; + char cmd[50]; + + // menu de sélection de couleur + int col = chooseColor(NUM_COULEUR); + + // Annulation + if (col < 0) return; + + // Affectation des composantes actuelles + for (int i=0; i<3; i++) + c[i] = oconfig->node[col*3+i]; + + // Création de la fenetre + WINDOW *colorWindow = newwin(4, 60, 12, 25); + keypad(colorWindow, TRUE); + + // Initialisation de l'affichage + wprintw(colorWindow, "Couleur %i:\n", col); + wprintw(colorWindow, "<---------------------------------------------------->\n"); + wprintw(colorWindow, "<---------------------------------------------------->\n"); + wprintw(colorWindow, "<---------------------------------------------------->\n"); + + // Affichage du curseur sur les lignes + // ainsi que des valeurs des composantes de la couleur + wattron(colorWindow, A_BOLD | COLOR_PAIR(1)); + mvwprintw(colorWindow, 1, 56, "%3u", c[0]); + mvwprintw(colorWindow, 1, c[0]/5+1, "*"); + wattroff(colorWindow, A_BOLD | COLOR_PAIR(1)); + mvwprintw(colorWindow, 2, 56, "%3u", c[1]); + mvwprintw(colorWindow, 3, 56, "%3u", c[2]); + mvwprintw(colorWindow, 2, c[1]/5+1, "*"); + mvwprintw(colorWindow, 3, c[2]/5+1, "*"); + + wrefresh(colorWindow); + + // Boucle pour la selection des valeurs + int car; + while ((car = wgetch(colorWindow)) != 10) + { + switch(car) + { + case KEY_UP: // Touche HAUT + if (ligne != 0) + { + // Mise a jour affichage + mvwprintw(colorWindow, ligne+1, 56, "%3u", c[ligne]); + mvwprintw(colorWindow, ligne+1, c[ligne]/5+1, "*"); + ligne--; + } + break; + + case KEY_DOWN: // Touche BAS + if (ligne != 2) + { + // Mise a jour affichage + mvwprintw(colorWindow, ligne+1, 56, "%3u", c[ligne]); + mvwprintw(colorWindow, ligne+1, c[ligne]/5+1, "*"); + ligne++; + } + break; + + case KEY_LEFT: // Touche gauche + if (c[ligne] > 0) + { + // Mise a jour affichage + mvwprintw(colorWindow, ligne+1, c[ligne]/5+1, "-"); + c[ligne]--; + } + break; + + case KEY_RIGHT: // Touche droite + if (c[ligne] < 255) + { + // Mise a jour affichage + mvwprintw(colorWindow, ligne+1, c[ligne]/5+1, "-"); + c[ligne]++; + } + break; + + case KEY_NPAGE : // Touche gauche + if (c[ligne] > 9) + { + // Mise a jour affichage + mvwprintw(colorWindow, ligne+1, c[ligne]/5+1, "-"); + c[ligne]-=10; + } + break; + + case KEY_PPAGE: // Touche droite + if (c[ligne] < 246) + { + // Mise a jour affichage + mvwprintw(colorWindow, ligne+1, c[ligne]/5+1, "-"); + c[ligne]+=10; + } + break; + } + + // Mise a jour de l'affichage des valeurs + wattron(colorWindow, A_BOLD | COLOR_PAIR(1)); + mvwprintw(colorWindow, ligne+1, 56, "%3u", c[ligne]); + mvwprintw(colorWindow, ligne+1, c[ligne]/5+1, "*"); + wattroff(colorWindow, A_BOLD | COLOR_PAIR(1)); + + wrefresh(colorWindow); + + // Communication avec adjust + sprintf(cmd, "c %i %u %u %u\n", col, c[0], c[1], c[2]); + sendSignal(cmd); + + // Affichage d'info + sprintf(cmd, "Couleur %i change en %u %u %u\n", col, c[0], c[1], c[2]); + printStatus(cmd); + } + + // Affectation des nouvelles valeurs + for (int i=0; i<3; i++) + oconfig->node[col*3+i] = c[i]; + + // Communication avec adjust + sprintf(cmd, "c %i %u %u %u\n", col, c[0], c[1], c[2]); + sendSignal(cmd); + + // Suppression de la fenetre ecran et affichage + delwin(colorWindow); + colorWindow = newwin(4, 60, 12, 25); + wrefresh(colorWindow); + delwin(colorWindow); +} + +// Affiche les objets et poteaux trouvés +void +UI::showObjectsFound () +{ + // Creation de la fenetre + WINDOW *winInfo = newwin(15, 60, 5, 4); + + // Affichage du texte + + sendSignal ("f\n"); + + char buf[20] = "start"; + bool end = 1; + while ( end != 0 ) + { + read (fifo, buf, 20); + end = strcmp ("end\n", buf); + if (end != 0) wprintw (winInfo, "%s", buf); + } + + wrefresh(winInfo); + + // Liberation de la memoire + delwin(winInfo); +} + +void +UI::newNN (const int nbColor) +{ + char buf[20]; + if (nbColor != -1) + { + sprintf(buf, "p %i\n", nbColor); + sendSignal(buf); + + if (oconfig->node) delete [] oconfig->node; + oconfig->node = new unsigned char[nbColor*3]; + + oconfig->nnNbColor = nbColor; + + // Synchronisation des poids avec adjust + updateNodes (); + + printStatus("Nouveau reseau de neurones charge\n"); + } +} + +/// Affiche le menu principale +void +UI::menu () +{ + // Init items + item = new ITEM*[NBITEMS]; + for (int i=0; i "); + set_menu_win(mainMenu, mainWindow); + set_menu_sub(mainMenu, derwin(mainWindow, 13, 65, 3, 1)); + set_menu_format(mainMenu, NBITEMS, 1); + post_menu(mainMenu); + + // Actualisation de la fenetre + wrefresh(mainWindow); + + int c; + int select=0; + int end=0; + + // Affichage de l'aide de l'item + wattron(mainWindow,COLOR_PAIR(3)); + mvwprintw(mainWindow, 3+select, 25, itemsName[select][1]); + + char buf[50]; + + // Boucle du menu principal + while(!end) + { + c = wgetch(mainWindow); + switch(c) + { + case KEY_DOWN: // Touche flèche BAS + // On se déplace vers le bas + menu_driver(mainMenu, REQ_DOWN_ITEM); + if (select!=NBITEMS-2) + { + // Efface la ligne d'aide de l'item courant + mvwprintw(mainWindow,3+select, 25, "\t\t\t\t\t\t\t"); + select++; + } + break; + + case KEY_UP: // Touche flèche HAUT + // On se déplace vers le haut + menu_driver(mainMenu, REQ_UP_ITEM); + if (select!=0) + { + // Efface la ligne d'aide de l'item courant + mvwprintw(mainWindow,3+select, 25, "\t\t\t\t\t\t\t"); + select--; + } + break; + + case 10: // Touche ENTER + switch(select) + { + case NBITEMS-2: // Quitte le programme + end=1; + break; + + case 0: // Change les valeurs des poids du NN pour une couleur + goChangeColor(); + break; + + case 1: // Supprime une couleur + goDelColor(); + break; + + case 2: // Melange 2 couleurs + goMergeWindow(); + break; + + case 3: // Selectionne la couleur des objets à afficher + { + int obj; + obj = chooseObject(0); + if (obj >= 0) + { + sprintf(buf, "a %i\n", obj); + sendSignal(buf); + } + } + break; + + case 4: // Selectionne la couleur des objets + { + int obj, col; + obj = chooseObject(0); + if (obj >= 0) + { + col = chooseColor (NUM_COULEUR, 0); + if (col >= 0) + { + std::string name = Group::translateToColorName (obj); + sprintf(buf, "b %s %i\n", name.c_str (), col); + sendSignal(buf); + } + } + } + break; + + + case 5: // Affiche les objets trouvés + showObjectsFound (); + wrefresh (mainWindow); + break; + + case 6: // Entraine le NN + sprintf(buf, "t\n"); + sendSignal(buf); + + // Synchronisation des poids avec adjust + updateNodes (); + + printStatus ("Réseau de neurones entrainé\n"); + break; + + case 7: // Regeneration de poids + int nbColor; + nbColor = chooseColor (NB_COULEUR, oconfig->nnNbColor); + newNN (nbColor); + break; + + case 8:// Annuler les changements + // Reload du fichier de poids initial + oconfig->loadNNFile(); + + // Envoie du nombre de couleur initial du NN et reload de l'image + sprintf(buf, "r %i", savedNNColorNumber); + sendSignal(buf); + oconfig->nnNbColor = savedNNColorNumber; + + printStatus("Les changements ont été annulés\n"); + break; + + case 9: // Sauver les changements + // Sauvegarde des poids dans le fichier poids + oconfig->createNNFile("rc/poids", oconfig->nnNbColor); + + // Reload du NN et de l'image a partir des nouveaux poids + sprintf(buf, "r -1"); + sendSignal(buf); + + printStatus ("Les changements ont été sauvés\n"); + break; + } // END switch touche ENTER + + break; + + // Sortie du programme + case 27: // ECHAP + end=true; + break; + + // Changement d'image + case ' ': + // Image suivante + curImage++; + if (curImage >= lengthFileList) curImage = 0; + + // Envoie de la commande pour le chargement de la nouvelle image + sprintf (buf, "n %s%s\n", oconfig->imgPath, fileList[curImage]); + sendSignal (buf); + break; + + case 'g': + showObjectsFound (); + wgetch (mainWindow); + break; + + case 'n': + newNN (oconfig->nnNbColor); + break; + } + + // On affiche le texte d'aide de l'item correspondant + mvwprintw (mainWindow, 3+select, 25, itemsName[select][1]); + wrefresh (mainWindow); + } + + delwin (mainWindow); +} + + diff --git a/2005/i/robert/src/ovision/ui/ui.hh b/2005/i/robert/src/ovision/ui/ui.hh new file mode 100644 index 0000000..049ac6d --- /dev/null +++ b/2005/i/robert/src/ovision/ui/ui.hh @@ -0,0 +1,118 @@ +// robert - programme du robot 2005 +// +// Copyright (C) 2005 Olivier Gaillard +// +// Robot APB Team/Efrei 2005. +// Web: http://assos.efrei.fr/robot/ +// Email: robot AT efrei DOT fr +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +#ifndef UI_h +#define UI_h + +// Realisé a l'aide du "NCURSES Programming HOWTO" + + +#include +#include "ovision/see/oconfig.hh" +#include "ovision/see/group.hh" + + +#define NUM_COULEUR 1 +#define NB_COULEUR 2 + + +/// Interface ncurses permettant de piloter adjust +class UI { + + /// Variable utilisees pour ncurses + ITEM **item; + MENU *mainMenu; + WINDOW *mainWindow; + + /// Id du fifo + int fifo; + + /// PID du prog + long pid; + + /// Sauvegarde la valeur de sorties du NN + int savedNNColorNumber; + + /// liste des images + char **fileList; + + /// id de l'image actuel + int curImage; + + /// taille de la liste + int lengthFileList; + + OConfig *oconfig; + + + public: + /// Constructeurs. + UI (const char *filename = ""); + + /// Destructeur. + ~UI (void); + + /// Affiche le menu principale + void menu (); + + /// reponse du programme adjust + int uiReady; + + protected: + /// Cree la liste d'images a ouvrir + void parseFileList(); + + /// Menu de selection de couleur + int chooseColor (const int type, const int current = 0); + + /// Affiche un msg dans la barre d'etat + void printStatus (const char *str); + + /// Menu de suppression de couleur + void goDelColor (); + + /// menu de selection d'objet + int chooseObject (const int current); + + /// Menu de selection du group a former + void goSelectGroup (const int type); + + /// Menu de melange de couleurs + void goMergeWindow (); + + /// Menu de changements des composantes d'un poid du NN + void goChangeColor (); + + /// Synchronisation des poids locaux et de ceux du programme adjust + void updateNodes (); + + /// Envoie une donnee au prog adjust + void sendSignal (const char *buf); + + // Affiche les objets et poteaux trouvés + void showObjectsFound (); + + void newNN (const int nbColor); +}; + + +#endif // UI_h -- cgit v1.2.3