// group.cc - Classe Group // nono - Programme du robot Efrei Robotique I1-I2 2004 // Copyright (C) 2004 Olivier Gaillard /// @file group.cc Cree une liste chainee de zones correspondant aux balles #include "group.h" #include #include #include #include using namespace std; #define BALL 1 #define GOAL 2 /// Constructeur /// @param *img classe image /// @param *segm classe segmNN Group::Group(Img *img, SegmNN *segm) { // Sauvegarde des pointeurs Group::img = img; Group::segm = segm; width = img->width; height = img->height; tabOut = NULL; zoneListBall = NULL; zoneListGoal = NULL; } /// Destructeur Group::~Group() { } /// Supprime la liste des groupes void Group::FreeGroups () { ZONE *pCur = zoneListBall; ZONE *pPrev; while (pCur) { pPrev = pCur; pCur = pCur->next; free(pPrev); } pCur = zoneListGoal; while (pCur) { pPrev = pCur; pCur = pCur->next; free(pPrev); } zoneListBall = NULL; zoneListGoal = NULL; } /// Construit la table des distances void Group::DoDeltaTable () { } /// Retourne le delta utilisé pour la dissociation de 2 balles proches int Group::GetDelta (int y) { // return 50; return (int)(20 + y*0.1); } /// Cherche l'objet complet a partir d'un pixel donne /// @param numColor numero de la couleur a chercher /// @param x,y coordonnees de depart pour la recherche void Group::Plague(int type, unsigned char numColor, int x, int y) { int xmax = x; int xmin = x; int ymax = y; int ymin = y; // TODO ajouter une inertie ? // Parcours de l'objet trouve de haut en bas while ((xmax < img->width-1)&& (segm->FindColorNN(img->tabData + ((++xmax)+y* img->width)*3) == numColor)) {} while ((xmin > 0) && (segm->FindColorNN(img->tabData + ((--xmin)+y* img->width)*3) == numColor)) {} while ((ymax < img->height-1) && (segm->FindColorNN(img->tabData + (x+(++ymax)* img->width)*3) == numColor)) {} while ((ymin > 0) && (segm->FindColorNN(img->tabData + (x+(--ymin)* img->width)*3) == numColor)) {} /*while ((xmax < img->width-1)&& (tabSegm[(++xmax)+y* img->width] == numColor)) {} while ((xmin > 0) && (tabSegm[(--xmin)+y* img->width] == numColor)) {} while ((ymax < img->height-1) && (tabSegm[x+(++ymax)* img->width] == numColor)) {} while ((ymin > 0) && (tabSegm[x+(--ymin)* img->width] == numColor)) {} */ // Verification la validite des entrees /* if ((xmin < 0) || (xmin > img->width)) xmin = 0; if ((xmax > img->img->width) || (xmax < 0)) xmax = img->width; if ((ymin < 0) || (ymin > height)) ymin = 0; if ((ymax > img->height) || (ymax < 0)) ymax = img->height; */ // Calcul du centre de l'image int centerx, centery; centerx = (xmax+xmin)/2; centery = (ymax+ymin)/2; ZONE *pCur; if (type == BALL) { pCur = zoneListBall; } else if (type == GOAL) { // if (!((pCur->ymin <= 0) && (pCur->ymax >= img->width))) // return; pCur = zoneListGoal; } ZONE *pLast=NULL; int imgY; while (pCur) { imgY = (pCur->centery + centery) / 2; // si on a deja ce groupe on actualise les donnees du groupe if ((numColor == pCur->idColor) && (abs(pCur->centerx - centerx) <= GetDelta(imgY)) && (abs(pCur->centery - centery) <= GetDelta(imgY))) { if (xmin < pCur->xmin) pCur->xmin = xmin; if (xmax > pCur->xmax) pCur->xmax = xmax; if (ymin < pCur->ymin) pCur->ymin = ymin; if (ymax > pCur->ymax) pCur->ymax = ymax; pCur->centerx = (pCur->xmax+pCur->xmin)/2; pCur->centery = (pCur->ymax+pCur->ymin)/2; return; } pLast = pCur; pCur = pCur->next; } // Si il n'est pas presente on l'ajoute if (!pCur) { if (!pLast) { if (type == BALL) { zoneListBall = new ZONE; pLast = zoneListBall; } else if (type == GOAL) { zoneListGoal = new ZONE; pLast = zoneListGoal; } } else { pLast->next = new ZONE; pLast = pLast->next; } pLast->xmin = xmin; pLast->xmax = xmax; pLast->ymin = ymin; pLast->ymax = ymax; pLast->centerx = centerx; pLast->centery = centery; pLast->idColor = numColor; // test si la balle est vu partiellement ou completement if ((pLast->xmin <= 0) || (pLast->ymin <= 0) || (pLast->xmax >= img->width) || (pLast->ymax >= img->height)) pLast->partial = 1; else pLast->partial = 0; pLast->next = NULL; } } /// Affiche les zones trouvees void Group::ShowZones() { ZONE *pCur = zoneListBall; cout << "Groupes balles:" << endl; while(pCur) { printf("%u %i %i %i %i\n", pCur->idColor, pCur->xmin, pCur->xmax, pCur->ymin, pCur->ymax); pCur = pCur->next; } pCur = zoneListGoal; cout << "Groupes poteaux:" << endl; while(pCur) { printf("%u %i %i %i %i\n", pCur->idColor, pCur->xmin, pCur->xmax, pCur->ymin, pCur->ymax); pCur = pCur->next; } } /// Selectionne les points a tester dans l'image /// @param numColor numero de la couleur a trouver void Group::JumpPoints(unsigned char numColorBall, unsigned char numColorGoal) { FreeGroups (); // Initialisation de la couleur a chercher numColorBall = segm->index[numColorBall]; if (numColorGoal != 255) numColorGoal = segm->index[numColorGoal]; int curColor; // Parcours d'une partie des pixels de l'image for (int x=0; xwidth; x+=10) { for (int y=0; yheight; y+=10) { // if (tabSegm[y*img->width+x] == numColor) curColor = segm->FindColorNN(img->tabData + ((y*img->width+x) * 3)); if (curColor == numColorBall) Plague(BALL, numColorBall, x, y); else if (curColor == numColorGoal) Plague(GOAL, numColorGoal, x, y); } } } /// Creation du tableau de RGB pour faire une image void Group::TabOut() { ZONE *pCur = zoneListBall; // On verifie que des groupes ont ete trouve if (!pCur) { cerr << "Group::TabOut : No group defined" << endl; if (tabOut) delete [] tabOut; return; } // Allocation de la memoire if (tabOut) delete [] tabOut; tabOut = new unsigned char[img->nbPixels]; // On initialise le tableau pour une image noire for (unsigned int i=0; inbPixels; i++) tabOut[i] = 0; // Parcours de la liste des zones trouvees while (pCur) { // Remplissage de la zone avec une couleur for(int i=pCur->xmin; ixmax; i++) for (int j=pCur->ymin; jymax; j++) tabOut[j* img->width+i] = pCur->idColor+1; pCur = pCur->next; } }