No Description
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

image.cpp 7.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260
  1. /*
  2. * Copyright (C) 2018 dimercur
  3. *
  4. * This program is free software: you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License as published by
  6. * the Free Software Foundation, either version 3 of the License, or
  7. * (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  16. */
  17. /**
  18. * \file image.cpp
  19. * \author L.Senaneuch
  20. * \version 1.0
  21. * \date 06/06/2017
  22. * \brief Fonctions de traitement d'image utilisable pour la détection du robot.
  23. *
  24. * \details Ce fichier utilise la libraire openCV2 pour faciliter le traitement d'image dans le projet Destijl.
  25. * Il permet de faciliter la détection de l'arène et la détection du robot.
  26. * /!\ Attention Bien que celui-ci soit un .cpp la structure du code n'est pas sous forme d'objet.
  27. */
  28. #include "image.h"
  29. #include <iostream>
  30. using namespace cv;
  31. #ifndef __STUB__
  32. #ifdef __FOR_PC__
  33. VideoCapture cap;
  34. #else
  35. using namespace raspicam;
  36. #endif /* __FOR_PC__ */
  37. #else
  38. Image stubImg;
  39. #endif
  40. using namespace std;
  41. float calculAngle(Position * positionRobot);
  42. int cropArena(Image *imgInput, Image *imgOutput, Arene *AreneInput);
  43. float euclideanDist(Point& p, Point& q);
  44. void draw_arena(Image *imgInput, Image *imgOutput, Arene *monArene)
  45. {
  46. if(imgInput!=imgOutput)
  47. *imgOutput=imgInput->clone();
  48. rectangle(*imgOutput,monArene->tl(),monArene->br(),Scalar(0,0,125),2,8,0);
  49. }
  50. int open_camera(Camera *camera)
  51. {
  52. #ifndef __STUB__
  53. #ifdef __FOR_PC__
  54. // open the default camera, use something different from 0 otherwise;
  55. // Check VideoCapture documentation.
  56. printf("Opening Camera...\n");
  57. if(!cap.open(0))
  58. return -1;
  59. return 0;
  60. #else // for raspberry
  61. camera->set(CV_CAP_PROP_FORMAT, CV_8UC3);
  62. camera->set(CV_CAP_PROP_FRAME_WIDTH,WIDTH);
  63. camera->set(CV_CAP_PROP_FRAME_HEIGHT,HEIGHT);
  64. printf("Opening Camera...\n");
  65. if (!(camera->open())) {
  66. perror("Can't open Camera\n") ;
  67. return -1;
  68. }
  69. else
  70. {
  71. printf("Camera warmup 2sec\n");
  72. sleep(2);
  73. printf("Start capture\n");
  74. return 0;
  75. }
  76. #endif /* __FOR_PC__ */
  77. #else
  78. return 0;
  79. #endif
  80. }
  81. void get_image(Camera *camera, Image * monImage, const char * fichier) // getImg(Camera, Image img);
  82. {
  83. #ifndef __STUB__
  84. #ifdef __FOR_PC__
  85. if (monImage != NULL)
  86. {
  87. cap>>*monImage;
  88. }
  89. #else // for raspberry
  90. camera->grab();
  91. camera->retrieve(*monImage);
  92. cvtColor(*monImage,*monImage,CV_BGR2RGB);
  93. #endif /* __FOR_PC__ */
  94. #else
  95. stubImg = imread(fichier, CV_LOAD_IMAGE_COLOR);
  96. stubImg.copyTo(*monImage);
  97. #endif
  98. }
  99. void close_camera(Camera *camera) // closeCam(Camera) : camera Entrer
  100. {
  101. #ifndef __STUB__
  102. #ifdef __FOR_PC__
  103. cap.release();
  104. #else // for raspberry
  105. camera->release();
  106. #endif /* __FOR_PC__ */
  107. #else
  108. #endif
  109. }
  110. int detect_arena(Image *monImage, Arene *rectangle) // Image en entrée // rectangle en sortie
  111. {
  112. vector<vector<Point> > contours;
  113. vector<Point> approx;
  114. vector<Vec4i> hierarchy;
  115. Image imageTrt;
  116. cvtColor(*monImage,imageTrt,CV_RGB2GRAY); // conversion en niveau de gris
  117. threshold(imageTrt,imageTrt,128,255,CV_THRESH_BINARY); // Threshold les éléments les plus clair
  118. Canny(imageTrt, imageTrt, 100,200,3); // detection d'angle
  119. findContours(imageTrt, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point(0, 0));
  120. for(unsigned int i = 0; i < contours.size();i++)
  121. {
  122. approxPolyDP(Image(contours[i]), approx, arcLength(Image(contours[i]), true)*0.1, true);
  123. if(approx.size()==4 && fabs(cv::contourArea(contours[i])) > 100000)
  124. {
  125. *rectangle = boundingRect(Image(contours[i]));
  126. return 0;
  127. }
  128. }
  129. return -1;
  130. }
  131. int cropArena(Image *imgInput, Image *imgOutput, Arene *areneInput) // image // rectangle // image2
  132. {
  133. Image img;
  134. img=imgInput->clone();
  135. *imgOutput = img(*areneInput);
  136. return 0;
  137. }
  138. float euclideanDist(Point& p, Point& q) {
  139. Point diff = p - q;
  140. return cv::sqrt(diff.x*diff.x + diff.y*diff.y);
  141. }
  142. void compress_image(Image *imgInput, Jpg *imageCompress) // image entrée // imageEncodé en sortie
  143. {
  144. imencode(".jpg",*imgInput,*imageCompress);
  145. }
  146. int detect_position(Image *imgInput, Position *posTriangle, Arene * monArene) // entree : image / sortie tab pos
  147. {
  148. vector<vector<Point> > contours;
  149. vector<Point> approx;
  150. vector<Vec4i> hierarchy;
  151. Image imgTraitment;
  152. if(monArene==NULL)
  153. imgTraitment=imgInput->clone();
  154. else
  155. cropArena(imgInput,&imgTraitment, monArene);
  156. cvtColor(imgTraitment,imgTraitment,CV_RGB2GRAY);
  157. threshold(imgTraitment,imgTraitment,128,255,CV_THRESH_BINARY);
  158. findContours(imgTraitment, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point(0, 0));
  159. int nbrTriangle = 0;
  160. for(unsigned int i = 0;i < contours.size();i++)
  161. {
  162. approxPolyDP(Mat(contours[i]), approx, arcLength(Mat(contours[i]), true)*0.17, true);
  163. if(approx.size() == 3 && fabs(contourArea(contours[i])) > 200 && fabs(contourArea(contours[i])) < 700)
  164. {
  165. Point a,b,c;
  166. Point center;
  167. a = approx[0];
  168. b = approx[1];
  169. c = approx[2];
  170. if(monArene !=NULL) // ajout de l'offset de l'arène
  171. {
  172. a.x += monArene->x;
  173. a.y += monArene->y;
  174. b.x += monArene->x;
  175. b.y += monArene->y;
  176. c.x += monArene->x;
  177. c.y += monArene->y;
  178. }
  179. center.x = (a.x + b.x + c.x)/3;
  180. center.y = (a.y + b.y + c.y)/3;
  181. posTriangle[nbrTriangle].center=center;
  182. if(euclideanDist(center,b) > euclideanDist(center,a) && euclideanDist(center,b) > euclideanDist(center,c) )
  183. {
  184. posTriangle[nbrTriangle].direction=b;
  185. //line(img,center,b,Scalar(0,125,0),2,8,0);
  186. }
  187. else if(euclideanDist(center,a) > euclideanDist(center,c))
  188. {
  189. posTriangle[nbrTriangle].direction=a;
  190. //line(img,center,a,Scalar(0,125,0),2,8,0);
  191. }
  192. else
  193. {
  194. posTriangle[nbrTriangle].direction=c;
  195. //line(img,center,c,Scalar(0,125,0),2,8,0);
  196. }
  197. posTriangle[nbrTriangle].angle=calculAngle(&posTriangle[nbrTriangle]);
  198. nbrTriangle++;
  199. }
  200. }
  201. return nbrTriangle;
  202. }
  203. void draw_position(Image *imgInput, Image *imgOutput, Position *positionRobot) // img E/S pos : E
  204. {
  205. if(imgInput!=imgOutput)
  206. {
  207. *imgOutput=imgInput->clone();
  208. }
  209. line(*imgOutput,positionRobot->center,positionRobot->direction,Scalar(0,125,0),2,8,0);
  210. }
  211. float calculAngle(Position * positionRobot) // position en entree
  212. {
  213. float a = positionRobot->direction.x - positionRobot->center.x;
  214. float b = positionRobot->direction.y - positionRobot->center.y ;
  215. float angle = atan2(b,a);
  216. return angle * 180.f/M_PI;
  217. }