CamAdventure
 All Files Functions Macros
KirbyTrack.c
Go to the documentation of this file.
1 
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <cv.h>
15 #include <highgui.h>
16 
17 #include <SFML/Audio.hpp>
18 #include <SFML/Graphics.hpp>
19 #include <SFML/Window.hpp>
36 //#define CONFIG
37 #define SFML
38 
39 #define KIRBY
40 //#define ETOILE
41 
42 #define JEU 0.15
43 
44 //ATTENTION AFFICHAGE OPENCV INCOMPATIBLE AVEC AFFICHAGE SFML
45 //ATTENTION SFML SUPPORTE UN NOMBRE LIMITE DE SPRITE EN FCT DU PC
46 
47 /*Headers*/
57 void maj_angle(int vecX, int vecY, int rayon, double* angle); //Met à jour l'angle selon la distance CentreCamera - Cible
58 
68 int ajust_pos(int pos, int ref);
69 
77 void controle_moteur(double* angle);//Envoie les angles au moteur
78 
87 int limite_moteur(int val_pwm);//Verifie que les valeurs envoyees aux moteurs sont correctes
88 
103 void config(int* LowH, int* HighH, int* LowS, int* HighS, int* LowV, int* HighV); //Affiche le panneau de configuration de tracking avec les arguments comme valeur de base
104 
113 void affichage_config(IplImage* frame, IplImage* HSV, IplImage* Binaire); //Affiche le flux vidéos et ses différent traitements
114 
127 void Affichage_Tracking(IplImage* frame, int posX, int posY, int width, int height); //Dessine les informations de tracking sur frame
128 
137 void Position_moy(IplImage* Binaire, int* posX, int * posY); //Effectue le baricentre des pixels d'une image binaire pour obtenir la postion de l'objet
138 
154 void traitement(IplImage* frame, IplImage* HSV, IplImage* Binaire, int LowH, int HighH, int LowS, int HighS, int LowV, int HighV); //Effectue une binarisation de frame en fonction des bornes HSV
155 
162 int main(int argc, char* argv[])
163 {
164  //Initialisations
165  int height,width; //parameters of the image we are working on
166  int posX, posY; //Position objet
167  int boucle;
168 
169  double angle[2] = {100,100};
170 
171  int tracking; //0 = tracking OFF
172 , 1 = ON
173 
174 
175 #ifdef SFML
176  //Initialisation SFML
177 
178  sf::Texture txFlux;
179  sf::Sprite spFlux;
180  sf::Image imFlux;
181  sf::Event event;
182 
183  tracking = 0; //Pas de tracking de base en mode SFML
184 
185 #endif
186 
187  //Ouverture flux camera
188  CvCapture* capture = cvCaptureFromCAM( 0 );
189 
190  if( !capture ){
191  printf("ERROR: capture is NULL \n" );
192  exit(EXIT_FAILURE);
193  }
194 
195 
196  // grab an image from the capture
197  IplImage* frame = cvQueryFrame( capture );
198 
199  // get the image data
200  height = frame->height;
201  width = frame->width;
202 
203  // capture size -
204  CvSize size = cvSize(width,height);
205 
206 
207 #ifdef SFML
208  //Création de la fenetre principale
209  sf::RenderWindow window(sf::VideoMode(width+300, height), "KirbyTrack");
210 #endif
211 
212  // Initialize different images that are going to be used in the program
213  IplImage* hsv_frame = cvCreateImage(size, IPL_DEPTH_8U, 3); // image converted to HSV plane
214  IplImage* threshold = cvCreateImage(size, IPL_DEPTH_8U, 1);
215 
216 
217  //Controle couleur
218 #ifdef KIRBY
219  //Setup Kirby
220  int iLowH = 152;
221  int iHighH = 179;
222 
223  int iLowS = 48;
224  int iHighS = 255;
225 
226  int iLowV = 101;
227  int iHighV = 255;
228 #endif
229 #ifdef ETOILE
230  //Setup Etoile
231  int iLowH = 20;
232  int iHighH = 30;
233 
234  int iLowS = 100;
235  int iHighS = 255;
236 
237  int iLowV = 100;
238  int iHighV = 255;
239 #endif
240 
241 #ifdef CONFIG
242  //Affichage du panneau de config
243  config(&iLowH, &iHighH, &iLowS, &iHighS, &iLowV, &iHighV);
244 
245  boucle = 1;
246  tracking = 1; //Tracking de base en mode CONFIG
247 #endif
248 
249  while(boucle)
250  {
251 
252 #ifdef SFML
253  boucle = window.isOpen();
254 
255  // on inspecte tous les évènements de la fenêtre qui ont été émis depuis la précédente itération
256  while (window.pollEvent(event))
257  {
258  // évènement "fermeture demandée" : on ferme la fenêtre
259  if (event.type == sf::Event::Closed)
260  window.close();
261  }
262 #endif
263 
264  // Get one frame
265  frame = cvQueryFrame( capture );
266 
267  if( !frame ){
268  perror("ERROR: frame is null...");
269  break;
270  }
271 
272  //Binarisation du flux vidéo
273  traitement(frame, hsv_frame, threshold, iLowH, iHighH, iLowS, iHighS, iLowV, iHighV);
274 
275  // Calculate the moments to estimate the position of the ball
276  Position_moy(threshold, &posX, &posY);
277 
278  //Dessine les informations de tracking sur frame
279  Affichage_Tracking(frame, posX, posY, width, height);
280 
281 
282 #ifdef SFML
283 //Affichage SFML
284  /* Clear the screen */
285  window.clear(sf::Color::White);
286 
287 //Affichage de la frame
288 
289  //Le chargement pourrait etre plus optimisé en créant nous me l'image SFML en parcourant l'IplImage
290 
291  //Enregistrement de la frame openCV
292  cvSaveImage("Stock SFML/temp.jpg", frame);
293 
294  //Chargement de la frame en texture SFML
295  if (!txFlux.loadFromFile("Stock SFML/temp.jpg")){
296  printf("Erreur chargement image SFML\n" );
297  break;
298  }
299 
300  spFlux.setTexture(txFlux);
301  window.draw(spFlux);
302 
303 
304  sf::Vector2i PosMouse = sf::Mouse::getPosition(window);
305 //Detection du bouton tracking
306  if (sf::Mouse::isButtonPressed(sf::Mouse::Left)&&(PosMouse.x>640)&&(PosMouse.x<760)&&(PosMouse.y>0)&&(PosMouse.y<120)){
307  //printf("\n\n\n OK \n\n\n");
308  if (tracking){ tracking = 0;}
309  else tracking = 1;
310  cvWaitKey(100);
311  }
312  //printf("Pos Mouse : %d %d \n", PosMouse.x, PosMouse.y);
313 
314 //Dessin du bouton de tracking
315  sf::Texture txBut;
316  sf::Sprite button_tracking;
317 
318  if (!txBut.loadFromFile("Stock SFML/button.png")){
319  printf("Erreur chargement image SFML\n" );
320  break;
321  }
322 
323  button_tracking.setTexture(txBut);
324  button_tracking.setScale(0.5,0.5);
325  button_tracking.setPosition(sf::Vector2f(width+20, 20));
326 
327  if(tracking){ button_tracking.setColor(sf::Color::Green); }
328  else{ button_tracking.setColor(sf::Color::Red); }
329 
330  window.draw(button_tracking);
331 
332 //Ajout du texte
333  sf::Font font;
334  if (!font.loadFromFile("Stock SFML/arial.ttf")){
335  printf("Erreur chargement police SFML\n" );
336  break;
337  }
338 
339  sf::Text text;
340  // choix de la police à utiliser
341  text.setFont(font); // font est un sf::Font
342 
343  // choix de la chaîne de caractères à afficher
344  text.setString("Tracking Moteur");
345 
346  // choix de la taille des caractères
347  text.setCharacterSize(24); // exprimée en pixels, pas en points !
348 
349  //text.setFillColor(sf::Color::Black);
350  text.setColor(sf::Color::Black);
351 
352  text.setPosition(sf::Vector2f(width+100, 35));
353 
354  window.draw(text);
355 
356  /* Update the window */
357  window.display();
358 
359 #endif
360 //Envoie données moteurs
361  if(tracking){
362  //Mouvements moteurs
363  //printf("-PREMAJ_ANGLE...: %d %d\n",width,height);
364 
365  maj_angle(ajust_pos(posX-width/2,width), ajust_pos(posY-height/2,height), height*JEU, angle);
366  controle_moteur(angle);
367 
368  cvWaitKey(50);
369  }
370 
371 
372 #ifdef CONFIG
373  affichage_config(frame, hsv_frame, threshold); //Affichage du flux vidéo et de ses traitements
374 
375  if( (cvWaitKey(10) ) >= 0 ) break; //Arret capture
376 #endif
377 
378  }
379 
380  // Release the capture device housekeeping
381  cvReleaseCapture( &capture );
382 
383  cvReleaseImage(&threshold);
384  cvReleaseImage(&hsv_frame);
385  cvReleaseImage(&frame);
386 
387  return EXIT_SUCCESS;
388 }
389 
390 
391 void maj_angle(int vecX, int vecY, int rayon, double* angle){
392  //On ajustera coeff fonction du rayon. Si la cible est à une distance 5*r, il sera 5x plus rapide que s'il était à 1*r
393 
394  double coeffx, coeffy;
395  int l0, l1;
396 
397  //printf("-MAJ_ANGLE...Valeur maj_angle arguments : %d %d %d\n\tAnciens angles : %d %d\n\t",vecX,vecY,rayon,(int)angle[0],(int)angle[1]);
398 
399 
400  //Ajout d'un angle moteur pondéré par la distance
401  coeffx = -0.2*vecX/rayon;
402  coeffy = 0.2*vecY/rayon;
403  angle[0] += coeffx;
404  angle[1] += coeffy;
405 
406  //Majoration - minoration des angles moteurs
407  l0 = limite_moteur(angle[0]);
408  l1 = limite_moteur(angle[1]);
409  if (l0 != 0) angle[0] = l0;
410  if (l1 != 0) angle[1] = l1;
411 
412  //printf("Nouveaux angles : %lf %lf %d %d\n",angle[0],angle[1],(int)angle[0],(int)angle[0]);
413 }
414 
415 int ajust_pos(int pos, int ref){
416  if (pos > ref) return 0;
417  else return pos;
418 }
419 
420 int limite_moteur(int val_pwm){
421  int MAX_PWM = 130, MIN_PWM = 30;
422  if (val_pwm > MAX_PWM){
423  return MAX_PWM;
424  }
425  else if (val_pwm < MIN_PWM){
426  return MIN_PWM;
427  }
428  else{
429  return 0;
430  }
431 }
432 
433 void controle_moteur(double* angle){
434 
435  //Ouverture port serie
436  FILE* fichier = NULL;
437  fichier = fopen("/dev/ttyACM0","w");
438  if(fichier==NULL){
439  printf("Erreur ouverture fichier\n");
440  perror("fopen failed for /dev/ttyACM0" );
441  exit( EXIT_FAILURE );
442  }
443 
444  //Ecriture angles
445  fprintf(fichier,"%d\n",(int)angle[0]);
446  fprintf(fichier,"%d\n",(int)angle[1]);
447 
448  //Fermeture
449  fclose(fichier);
450  return;
451 }
452 
453 void traitement(IplImage* frame, IplImage* HSV, IplImage* Binaire, int LowH, int HighH, int LowS, int HighS, int LowV, int HighV){ //Effectue une binarisation de frame en fonction des bornes HSV
454 
455  // Covert color space to HSV as it is much easier to filter colors in the HSV color-space.
456  cvCvtColor(frame, HSV, CV_BGR2HSV);
457 
458  //Blur
459  cvSmooth( HSV, HSV, CV_GAUSSIAN, 15, 0,0,0); //suppression des parasites par flou gaussien
460 
461  //Binarisation
462 
463  CvScalar valinf={(double)LowH,(double)LowS,(double)LowV};
464  CvScalar valsup={(double)HighH,(double)HighS,(double)HighV};
465 
466  cvInRangeS(HSV, valinf,valsup, Binaire);
467 
468  //En cas d'erreur sur les trois ligne précédentes
469  //cvInRangeS(HSV, CvScalar(LowH,LowS,LowV),CvScalar(HighH,HighS,HighV), Binaire);
470 
471  //cvSmooth( Binaire, Binaire, CV_GAUSSIAN, 9, 9 ); //Legère suppression des parasites
472 }
473 
474 void Position_moy(IplImage* Binaire, int* posX, int * posY){ //Effectue le baricentre des pixels d'une image binaire pour obtenir la postion de l'objet
475 
476  CvMoments *moments = (CvMoments*)malloc(sizeof(CvMoments));
477 
478  cvMoments(Binaire, moments, 1);
479  // The actual moment values
480  double moment10 = cvGetSpatialMoment(moments, 1, 0);
481  double moment01 = cvGetSpatialMoment(moments, 0, 1);
482  double area = cvGetCentralMoment(moments, 0, 0);
483 
484  *posX = moment10/area;
485  *posY = moment01/area;
486 
487  free(moments);
488 }
489 
490 void config(int* LowH, int* HighH, int* LowS, int* HighS, int* LowV, int* HighV){ //Affiche le panneau de configuration de tracking avec les arguments comme valeur de base
491 
492  cvNamedWindow("Control", CV_WINDOW_AUTOSIZE); //create a window called "Control"
493 
494  //Create trackbars in "Control" window
495  cvCreateTrackbar("LowH", "Control", LowH, 179,NULL); //Hue (0 - 179)
496  cvCreateTrackbar("HighH", "Control", HighH, 179,NULL);
497 
498  cvCreateTrackbar("LowS", "Control", LowS, 255,NULL); //Saturation (0 - 255)
499  cvCreateTrackbar("HighS", "Control", HighS, 255,NULL);
500 
501  cvCreateTrackbar("LowV", "Control", LowV, 255,NULL); //Value (0 - 255)
502  cvCreateTrackbar("HighV", "Control", HighV, 255,NULL);
503 }
504 
505 void affichage_config(IplImage* frame, IplImage* HSV, IplImage* Binaire){ //Affiche le flux vidéos et ses différent traitements
506 
507  // Create a window in which the captured images will be presented
508  cvNamedWindow( "HSV", CV_WINDOW_AUTOSIZE );
509  cvNamedWindow( "Binaire", CV_WINDOW_AUTOSIZE );
510  cvNamedWindow( "Camera", CV_WINDOW_AUTOSIZE );
511 
512  cvShowImage( "HSV", HSV); // Original stream in the HSV color space
513  cvShowImage( "Binaire", Binaire); // The stream after color filtering
514  cvShowImage( "Camera", frame ); // Flux caméra avec tracking objet
515 }
516 
517 void Affichage_Tracking(IplImage* frame, int posX, int posY, int width, int height){ //Dessine les informations de tracking sur frame
518 
519  //Affichage zone suivie objet
520  cvCircle(frame, cvPoint(width/2,height/2), height*JEU, CV_RGB(0, 255, 0), 4, 8, 0 );
521 
522  if(posX<5&&posY<5){ //Si aucun objet spotted, pointeur rouge au centre
523  posX=width/2;
524  posY=height/2;
525  cvLine(frame, cvPoint(posX-20,posY), cvPoint(posX+20,posY), CV_RGB(255, 0, 0), 4, 8, 0 );
526  cvLine(frame, cvPoint(posX,posY-20), cvPoint(posX,posY+20), CV_RGB(255, 0, 0), 4, 8, 0 );
527  }
528  else{ //Objet spotted
529  //Affichage position de l'objet
530  cvLine(frame, cvPoint(posX-20,posY), cvPoint(posX+20,posY), CV_RGB(0, 0, 255), 4, 8, 0 );
531  cvLine(frame, cvPoint(posX,posY-20), cvPoint(posX,posY+20), CV_RGB(0, 0, 255), 4, 8, 0 );
532  }
533 }
void Position_moy(IplImage *Binaire, int *posX, int *posY)
Effectue le baricentre des pixels d'une image binaire pour obtenir la postion de l'objet.
Definition: KirbyTrack.c:474
void config(int *LowH, int *HighH, int *LowS, int *HighS, int *LowV, int *HighV)
Fonction d'affichage du panneau de configuration de la couleur à suivre.
Definition: KirbyTrack.c:490
#define JEU
Coefficient de tolérance pour le suivi d'objet.
Definition: KirbyTrack.c:42
int ajust_pos(int pos, int ref)
permet d'éviter des positions supérieures à ref considérées comme aberrantes.
Definition: KirbyTrack.c:415
void maj_angle(int vecX, int vecY, int rayon, double *angle)
Met à jour angle selon la distance entre le centre de la caméra et la cible, avec un tolérance circul...
Definition: KirbyTrack.c:391
int limite_moteur(int val_pwm)
Fonction qui vérifie que les valeurs envoyees aux moteurs sont correctes.
Definition: KirbyTrack.c:420
void Affichage_Tracking(IplImage *frame, int posX, int posY, int width, int height)
Fonction d'affichage des informations de suivi.
Definition: KirbyTrack.c:517
int main(int argc, char *argv[])
Entrée du programme.
Definition: KirbyTrack.c:162
void controle_moteur(double *angle)
Fonction d'envoie des angles aux moteurs.
Definition: KirbyTrack.c:433
void affichage_config(IplImage *frame, IplImage *HSV, IplImage *Binaire)
Fonction d'affichage du flux vidéo, du flux en HSV et de sa binarisation.
Definition: KirbyTrack.c:505
void traitement(IplImage *frame, IplImage *HSV, IplImage *Binaire, int LowH, int HighH, int LowS, int HighS, int LowV, int HighV)
Effectue une binarisation de frame en fonction des bornes HSV.
Definition: KirbyTrack.c:453