// skittle.cc - Classe Skittle // robert - Programme du robot APBteam // Copyright (C) 2005 Olivier Gaillard /// @file skittle.cc Reconnaissance des objets quilles #include #include "skittle.hh" #include "hotelling.hh" /// Constructeur Skittle::Skittle (Img *img, Segm *segm) : segm_ (segm), img_ (img), pcX_ (0), pcY_ (0) { oconfig_ = OConfig::getInstance (); } /// Destructeur Skittle::~Skittle (void) { } /// Recherche de la composante principale void Skittle::pca (const Zone &zone) { // Agrandissement de la zone de recherche const int grow = oconfig_->skittleGrow; int ymin = minWithBorder (zone.ymin - grow, 0); int ymax = maxWithBorder (zone.ymax + grow, img_->height_); int xmin = minWithBorder (zone.xmin - grow, 0); int xmax = maxWithBorder (zone.xmax + grow, img_->width_); /// Initialisation du saut de point int jump = oconfig_->jumpPointDist/oconfig_->skittleDivJump; if (!jump) jump = 1; // Parcours d'une partie des pixels de l'image int tmpY; std::vector l; for (int y = ymin; y < ymax; y += jump) { tmpY = y*img_->width_; for (int x = xmin; x < xmax; x += jump) if (segm_->giveColor (img_->tabData_ + ((tmpY + x) * 3), true, true) == zone.color) { Hpoint h (x, y); l.push_back (h); } } // Calcul de la composante principale Hotelling hote (l); hote.eigenVectors (); hote.getPC (pcX_, pcY_); } /// Utilisé pour la recherche de la courbure, cherche le point le plus haut int Skittle::climb (const int startX, int startY, const int color) { while (segm_->giveColor (img_->tabData_ + ((startY*img_->width_ + startX) * 3), true, true) == color) --startY; return startY; } /// Vérifie qu'un catadiopre est à proximité Skittle::Pos Skittle::whereIsReflectBand (const Zone &zone, const std::vector &listReflectBand) { const double minAreaRatio = 0.1; const double maxAreaRatio = 0.4; // Test les variables de composantes principales + liste transmise if (pcX_ || !pcY_ || listReflectBand.size ()) return error; // Analyse de la taille if (zone.area < minAreaRatio || zone.area > maxAreaRatio) // valeur réelle 0.2 // Parcours la liste des catadiopres for (std::vector::const_iterator iter = listReflectBand.begin (); iter != listReflectBand.end (); ++iter) { // Test la distance cartésienne if (dist (iter->centerx, iter->centery, zone.centerx, zone.centery)) // Test la distance orthogonale if (orthoDist (iter->centerx - zone.centerx, iter->centery - zone.centery, pcX_, pcY_)) { if (iter->centerx > zone.centerx) return up; else return down; } } return farAway; } /// Recherche de du côté de la courbure Skittle::Pos Skittle::bend (const Zone &zone) { /// Border const int border = oconfig_->skittleBorder; /// Initialisation du saut de point int jump = oconfig_->jumpPointDist/oconfig_->skittleDivJump; if (!jump) jump = 1; /// Initialisation du point de départ const int startY = minWithBorder ((int)(zone.ymin + (zone.ymax - zone.ymin) * 0.25), 0); /// Point supérieur de la quille int upperPoint; /// Recherche du premier et du dernier point int firstPoint = climb (maxWithBorder (zone.xmin + border, img_->width_), startY, zone.color); int lastPoint = climb (minWithBorder (zone.xmax - border, 0), startY, zone.color); int limitPoint = firstPoint > lastPoint ? firstPoint : lastPoint; std::cout << " " << firstPoint << " " << lastPoint << " " << limitPoint << std::endl; int above = 0; int below = 0; std::cout << " "; /// Parcours des autres points for (int i = zone.xmin + border + jump; i < zone.xmax - border - jump; i+=jump) { upperPoint = climb (i, startY, zone.color); std::cout << upperPoint << " "; if (upperPoint > limitPoint) ++below; else ++above; } std::cout << std::endl; const int score = (int)((zone.xmax - zone.xmin - 2*border) / jump * oconfig_->skittleScoreBendRatio) - 2; Pos bending = error; if (above > score) bending = up; else if (below > score) bending = down; return bending; } /// Analyse la zone bool Skittle::analyse (const Zone &zone, const std::vector &listReflectBand) { // group est partiel ? // if (zone.partial) // quille verticale sur l'image ? if ((zone.ymax - zone.ymin)/(double)(zone.xmax - zone.xmin) > oconfig_->skittleVerticalRatio) { std::cout << "vertical !!!" << std::endl; // debout ou couché ? bend_ = bend (zone); whereIsReflectBand (zone, listReflectBand); } else // calcul de l'orientation pca (zone); return true; } /// Affiche les infos sur la quille void Skittle::show () const { std::cout << " position : " << (bend_ == up ? "up" : (bend_ == down ? "down" : "error")) << "\n"; std::cout << " orientation : " << pcX_ << ", " << pcY_ << "\n"; std::cout << " catadiopre: " << (reflectBand_ == up ? "up" : (reflectBand_ == down ? "down" : (reflectBand_ == farAway ? "farAway" : "error"))) << std::endl; }