Advertisement
Guest User

Untitled

a guest
May 6th, 2016
53
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 9.30 KB | None | 0 0
  1. #include "rocks.hpp"
  2. #include "camera_transforms.hpp"
  3. #include "camera_constants.hpp"
  4. #include <stdio.h>
  5. #include <algorithm>
  6.  
  7.  
  8. using namespace std;
  9. using namespace cv;
  10.  
  11. void drawRocks(Mat image, vector<Rock> &rocks, const Scalar &center_colour, const Scalar &circle_colour) {
  12. for (Rock rock : rocks) {
  13. Point2d center = realToPerspective(rock.center);
  14. double radius = rock.radius;
  15.  
  16. /* Circle center */
  17. circle(image, center, 3, center_colour, -1, 8, 0);
  18.  
  19. /* Circle radius */
  20. circle(image, center, radius, circle_colour, 3, 8, 0);
  21. }
  22. }
  23.  
  24.  
  25. /* Find rocks in a thresholded image */
  26. void findThresholdedRocks(Mat image, RockColour colour, vector<Rock> &rocks)
  27. {
  28. /* Find contours in the image, we'll use these to find rocks */
  29. vector< vector<Point> > contours;
  30. vector<Vec4i> hierarchy;
  31. findContours(image, contours, hierarchy, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE);
  32. if (hierarchy.size() == 0) {
  33. return;
  34. }
  35.  
  36. for (int idx = 0; idx >= 0; idx = hierarchy[idx][0]) {
  37. /* Check that contour appears to be rounded, hinting it's circular */
  38. if (contours[idx].size() < 10) {
  39. continue;
  40. }
  41.  
  42. /* Undistort our points */
  43. vector<Point2d> conts;
  44. Mat(contours[idx]).copyTo(conts);
  45.  
  46. vector<Point2d> undistorted;
  47. undistortPoints(conts, undistorted, CAMERA_MATRIX, DIST_COEFFS, Mat(), CAMERA_MATRIX);
  48.  
  49. /* Convert contour points into real space */
  50. vector<Point2d> real_points;
  51. for (Point2d screen_point : undistorted) {
  52. Point2d real = screenToReal(screen_point);
  53. real_points.push_back(real);
  54. }
  55.  
  56. /* Check that an ellipse covering the points is roughly circular */
  57. vector<Point2f> real_floats;
  58. Mat(real_points).copyTo(real_floats);
  59. RotatedRect rect = fitEllipse(real_floats);
  60. if (rect.size.height < rect.size.width / 1.2 || rect.size.height > rect.size.width * 1.2) {
  61. continue;
  62. }
  63.  
  64. Point2f center;
  65. float radius;
  66. minEnclosingCircle(real_floats, center, radius);
  67.  
  68. if (radius > ROCK_RADIUS_MIN && radius < ROCK_RADIUS_MAX) {
  69. Rock rock;
  70. rock.center = rect.center;
  71. rock.radius = radius / 5;
  72. rock.colour = colour;
  73.  
  74. rocks.push_back(rock);
  75. }
  76. }
  77. }
  78.  
  79.  
  80. void findRocks(Mat background, Mat image, vector<Rock> &red_rocks, vector<Rock> &yellow_rocks)
  81. {
  82. Mat subtracted;
  83. Mat hsv, hsv_background;
  84. cvtColor(image, hsv, CV_BGR2HSV);
  85. cvtColor(background, hsv_background, CV_BGR2HSV);
  86.  
  87. absdiff(hsv_background, hsv, subtracted);
  88.  
  89. Mat gray;
  90. cvtColor(subtracted, gray, CV_BGR2GRAY);
  91. GaussianBlur(gray, gray, Size(9, 9), 10, 10);
  92. GaussianBlur(hsv, hsv, Size(9, 9), 10, 10);
  93.  
  94. Mat red, yellow;
  95. inRange(hsv, RED_LOW_HSV, RED_HIGH_HSV, red);
  96. inRange(hsv, YELLOW_LOW_HSV, YELLOW_HIGH_HSV, yellow);
  97.  
  98. Mat thresholded;
  99. threshold(gray, thresholded, 20, 255, THRESH_BINARY);
  100.  
  101. findThresholdedRocks(yellow & thresholded, YELLOW_ROCK, yellow_rocks);
  102. findThresholdedRocks(red & thresholded, RED_ROCK, red_rocks);
  103.  
  104. /* Debug drawing */
  105. /*
  106. Mat undistorted;
  107. undistort(image, undistorted, CAMERA_MATRIX, DIST_COEFFS);
  108.  
  109. drawRocks(undistorted, red_rocks, Scalar(0,0,255), Scalar(0,0,255));
  110. drawRocks(undistorted, yellow_rocks, Scalar(0,200,200), Scalar(0,200,200));
  111.  
  112. imwrite("out-circles.jpg", undistorted);
  113.  
  114. */
  115.  
  116. subtracted.release();
  117. hsv.release();
  118. hsv_background.release();
  119. gray.release();
  120. red.release();
  121. yellow.release();
  122. thresholded.release();
  123. }
  124.  
  125.  
  126. static void rocksFromCircles(Mat image, RockColour colour, vector<Rock> &rocks)
  127. {
  128. vector<Vec3f> circles;
  129. HoughCircles(image, circles, CV_HOUGH_GRADIENT, 1, 15, 1, 32, 30, 40);
  130.  
  131. for (Vec3f circle : circles) {
  132. Rock rock;
  133. rock.center = perspectiveToReal(Point2d(circle[0], circle[1]));
  134. rock.radius = circle[2];
  135. rock.colour = RED_ROCK;
  136.  
  137. rocks.push_back(rock);
  138. }
  139. }
  140.  
  141.  
  142. void findRocksCircles(Mat background, Mat image, vector<Rock> &red_rocks, vector<Rock> &yellow_rocks, bool debug, String output_file)
  143. {
  144. Mat undistorted;
  145. undistort(image, undistorted, CAMERA_MATRIX, DIST_COEFFS, OPT_MATRIX);
  146. imwrite("border.jpg", undistorted);
  147.  
  148. Mat flat_perspective;
  149. warpPerspective(undistorted, flat_perspective, PERSPECTIVE_MATRIX, Size(PERSPECTIVE_SIZE.width/3 + 500, PERSPECTIVE_SIZE.height/3 + 200));
  150. undistorted.release();
  151.  
  152. Mat flat_hsv;
  153. cvtColor(flat_perspective, flat_hsv, CV_BGR2HSV);
  154.  
  155. Mat red, yellow;
  156. inRange(flat_hsv, CIRCLES_RED_LOW_HSV, CIRCLES_RED_HIGH_HSV, red);
  157. inRange(flat_hsv, CIRCLES_YELLOW_LOW_HSV, CIRCLES_YELLOW_HIGH_HSV, yellow);
  158.  
  159. vector<Mat> channels;
  160. split(flat_hsv, channels);
  161. flat_hsv.release();
  162.  
  163. Mat blurred, blurred_red, blurred_yellow;
  164. medianBlur(channels[1] & red, blurred_red, 11);
  165. medianBlur(channels[1] & yellow, blurred_yellow, 11);
  166. medianBlur(channels[1], blurred, 11);
  167.  
  168. red.release();
  169. yellow.release();
  170. for (Mat chan : channels) {
  171. chan.release();
  172. }
  173.  
  174. rocksFromCircles(blurred_red, RED_ROCK, red_rocks);
  175. rocksFromCircles(blurred_yellow, YELLOW_ROCK, yellow_rocks);
  176.  
  177. vector<Rock> possible_rocks;
  178. rocksFromCircles(blurred, YELLOW_ROCK, possible_rocks);
  179.  
  180. blurred_red.release();
  181. blurred_yellow.release();
  182. blurred.release();
  183.  
  184. drawRocks(flat_perspective, possible_rocks, Scalar(255,0,0), Scalar(255,0,0));
  185. drawRocks(flat_perspective, red_rocks, Scalar(0,0,255), Scalar(0,0,255));
  186. drawRocks(flat_perspective, yellow_rocks, Scalar(0,220,220), Scalar(0,220,220));
  187.  
  188. if (debug) {
  189. imwrite(output_file, flat_perspective);
  190. }
  191.  
  192. flat_perspective.release();
  193. }
  194.  
  195.  
  196. bool pointEq(Point2d p1, Point2d p2) {
  197. return p1 == p2;
  198. }
  199.  
  200. /* Must be unique */
  201. vector<Point2d> getProjectedCircle(size_t col, size_t row)
  202. {
  203. Point2d real_point = screenToReal(Point2d(col, row));
  204.  
  205. /* Get the projected circle points */
  206. vector<Point2d> points;
  207. for (Point2i circle_point : BASIC_CIRCLE) {
  208. Point2d pt = Point2d((double) circle_point.x, (double) circle_point.y);
  209. pt = real_point + (ROCK_RADIUS / BASIC_CIRCLE_RADIUS) * pt;
  210.  
  211. points.push_back(realToScreen(pt));
  212. }
  213.  
  214. unique(points.begin(), points.end(), pointEq);
  215. return points;
  216. }
  217.  
  218.  
  219. void addAccumulation(Mat &accumulation, size_t col, size_t row)
  220. {
  221. Rect accum_rect(Point(), accumulation.size());
  222. vector<Point2d> circle_points = getProjectedCircle(col, row);
  223.  
  224. for (Point2i point : circle_points) {
  225. if (accum_rect.contains(point)) {
  226. accumulation.at<uchar>(point.y, point.x) += 1;
  227. }
  228. }
  229. }
  230.  
  231.  
  232. Mat getSaturation(Mat& in){
  233. Mat out = Mat::zeros(in.size(), CV_8UC1);
  234.  
  235. for(int row = 0; row < in.rows; ++row) {
  236. uchar* p = in.ptr(row);
  237.  
  238. for(int col = 0; col < in.cols; ++col) {
  239. uchar s = max(p[0],max(p[1],p[2]))-min(p[0],min(p[1],p[2]));
  240. out.at<uchar>(row,col)=s;
  241. p += 3;
  242. }
  243. }
  244.  
  245. return out;
  246. }
  247.  
  248.  
  249. /* Find rocks with a custom circle detector */
  250. void findRocksCirclesFast(Mat background, Mat image, vector<Rock> &red_rocks, vector<Rock> &yellow_rocks)
  251. {
  252. /* Subtract the background */
  253. Mat subtracted;
  254. absdiff(background, image, subtracted);
  255.  
  256. /* Get saturation from the subtracted image */
  257. Mat saturation;
  258. saturation = getSaturation(subtracted);
  259. subtracted.release();
  260.  
  261. /* Blur the subtracted, saturated image */
  262. Mat blurred;
  263. blur(saturation, blurred, Size(7,7));
  264. saturation.release();
  265.  
  266. /* Perform edge detection on background subtracted image */
  267. Mat edges;
  268. Canny(blurred, edges, 1, 10);
  269. blurred.release();
  270.  
  271. /* Build up the accumulation matrix for our Hough transform */
  272. Mat accumulation = Mat::zeros(image.size(), CV_8UC1);
  273. for (size_t row = 0; row < edges.rows; ++row) {
  274. for (size_t col = 0; col < edges.cols; ++col) {
  275. if (255 == edges.at<uchar>(row, col)) {
  276. addAccumulation(accumulation, col, row);
  277. }
  278. }
  279. }
  280.  
  281. edges.release();
  282.  
  283. imwrite("accumulation.jpg", accumulation);
  284. /* Find local maxima in the accumulation matrix, this gives us
  285. screen space coordinates for the rocks.
  286. */
  287. // vector<Point2i> screen_centers = findLocalMaxima(accumulation);
  288.  
  289. accumulation.release();
  290. }
  291.  
  292.  
  293. vector<Point2i> BASIC_CIRCLE;
  294. void setupBasicCircle() {
  295. int back_width = BASIC_CIRCLE_RADIUS * 2;
  296.  
  297. int radius = BASIC_CIRCLE_RADIUS;
  298. Point2i center = Point2i(radius, radius);
  299. Mat back = Mat::zeros(back_width, back_width, CV_8UC1);
  300.  
  301. circle(back, center, radius, Scalar(255,255,255));
  302.  
  303. findNonZero(back, BASIC_CIRCLE);
  304.  
  305. for (size_t i = 0; i < BASIC_CIRCLE.size(); ++i) {
  306. BASIC_CIRCLE[i] -= Point2i((double) radius, (double) radius);
  307. }
  308. }
  309.  
  310.  
  311. double rockDist(Rock r1, Rock r2)
  312. {
  313. double dx = r1.center.x - r2.center.x;
  314. double dy = r1.center.y - r2.center.y;
  315.  
  316. return sqrt(dx * dx + dy * dy);
  317. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement