/bboxgenerator/dt_box.cpp

https://github.com/metalbubble/CAM · C++ · 258 lines · 193 code · 34 blank · 31 comment · 24 complexity · ea87a3c4d8d6a12e723b4fde79ae6244 MD5 · raw file

  1. /*
  2. ----------------------------------------
  3. Given an heatmap, given out the bbox.
  4. 0. Get the DT-ed images
  5. 1. detect all contour in the bboxes
  6. 2. merge based on some rules.
  7. 3. output the bbox
  8. ----------------------------------------
  9. */
  10. #include <stdio.h>
  11. #include "dt.h"
  12. #include <vector>
  13. #include <algorithm>
  14. #include <opencv2/opencv.hpp>
  15. #include <assert.h>
  16. using namespace cv;
  17. using std::vector;
  18. #define SCALE_NUM 3
  19. struct Data
  20. {
  21. Data() : size(SCALE_NUM)
  22. {
  23. for (int i = 0; i < SCALE_NUM; ++i)
  24. {
  25. images[i] = NULL;
  26. }
  27. }
  28. ~Data()
  29. {
  30. for (int i = 0; i < SCALE_NUM; ++i)
  31. {
  32. if (images[i])
  33. {
  34. cvReleaseImage(&(images[i]));
  35. images[i] = NULL;
  36. }
  37. }
  38. }
  39. int size;
  40. IplImage *images[SCALE_NUM];
  41. };
  42. static int g_Ths[SCALE_NUM] = {30, 90, 150};
  43. static Data *
  44. fromDT(const IplImage *gray)
  45. {
  46. Data *data = new Data;
  47. for (int i = 0; i < data->size; ++i)
  48. {
  49. data->images[i] = cvCreateImage(cvGetSize(gray), 8, 1);
  50. cvThreshold(gray, data->images[i], g_Ths[i], 255, CV_THRESH_BINARY);
  51. dt_binary((unsigned char*)data->images[i]->imageData, data->images[i]->height, data->images[i]->width, data->images[i]->widthStep);
  52. cvThreshold(data->images[i], data->images[i], 10, 255, CV_THRESH_BINARY);
  53. }
  54. return data;
  55. }
  56. static int
  57. LIMIT(int v, int L, int R)
  58. {
  59. return v < L ? L : (v > R ? R : v);
  60. }
  61. static vector<CvRect>
  62. getBBox(struct Data *data)
  63. {
  64. vector<CvRect> bboxes;
  65. const int W = data->images[0]->width;
  66. const int H = data->images[0]->height;
  67. for (int i = 0; i < data->size; ++i)
  68. {
  69. cv::Mat a = cv::cvarrToMat(data->images[i]);
  70. vector< vector<cv::Point> >contours;
  71. vector<cv::Vec4i> hie;
  72. cv::findContours(a, contours, hie, CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE);
  73. for (int j = 0; j < contours.size(); ++j)
  74. {
  75. cv::Rect bb = cv::boundingRect( contours[j] );
  76. CvRect cr;
  77. cr.x = LIMIT(bb.x, 0, W-5);
  78. cr.y = LIMIT(bb.y, 0, H-5);
  79. cr.width = LIMIT(bb.width, 0, W - bb.x-5);
  80. cr.height = LIMIT(bb.height, 0, H-bb.y-5);
  81. //printf("%d, %d, %d, %d\n", W, H, cr.width, cr.height);
  82. bboxes.push_back(cr);
  83. }
  84. }
  85. return bboxes;
  86. }
  87. /*
  88. ----------------------------------------
  89. x_overlap = Math.max(0, Math.min(x12,x22) - Math.max(x11,x21));
  90. y_overlap = Math.max(0, Math.min(y12,y22) - Math.max(y11,y21));
  91. overlapArea = x_overlap * y_overlap;
  92. ----------------------------------------
  93. */
  94. static bool
  95. big_overlap(const CvRect &a, const CvRect &b)
  96. {
  97. int t = (double)std::max(a.width * a.height, b.width * b.height) * 0.5;
  98. int x11, y11, x12, y12, x21, y21, x22, y22;
  99. x11 = a.x;
  100. y11 = a.y;
  101. x12 = a.x + a.width;
  102. y12 = a.y + a.height;
  103. x21 = b.x;
  104. y21 = b.y;
  105. x22 = b.x + b.width;
  106. y22 = b.y + b.height;
  107. int x_overlap = std::max(0, std::min(x12,x22) - std::max(x11,x21));
  108. int y_overlap = std::max(0, std::min(y12,y22) - std::max(y11,y21));
  109. int overlapArea = x_overlap * y_overlap;
  110. return overlapArea > t;
  111. }
  112. /*
  113. ----------------------------------------
  114. 1. Overlap > max(area(A), area(B)) * 0.5
  115. 0. rank BB
  116. 1. from big to small:
  117. ----------------------------------------
  118. */
  119. static void
  120. mergeBBox(vector<CvRect> &bboxes)
  121. {
  122. for (int i = 0; i < bboxes.size(); ++i)
  123. {
  124. for (int j = i + 1; j < bboxes.size(); ++j)
  125. {
  126. if (big_overlap(bboxes[i], bboxes[j]))
  127. {
  128. // remove small one
  129. bboxes.erase(bboxes.begin() + j);
  130. }
  131. }
  132. }
  133. return ;
  134. }
  135. static bool
  136. my_cmp(const CvRect& a, const CvRect& b)
  137. {
  138. return a.width * a.height > b.width * b.height;
  139. }
  140. static void
  141. rankBBox(vector<CvRect> &bboxes)
  142. {
  143. std::sort(bboxes.begin(), bboxes.end(), my_cmp);
  144. }
  145. static void
  146. draw(const vector<CvRect> &rects, const char *iname)
  147. {
  148. IplImage *img = cvLoadImage(iname, 1);
  149. const CvScalar color = cvScalar(0,0,255,0);
  150. for (int i = 0; i < rects.size(); ++i)
  151. {
  152. CvRect r = rects[i];
  153. cvRectangle(img, cvPoint(r.x, r.y), cvPoint(r.x + r.width, r.y + r.height), color, 3, 8, 0);
  154. }
  155. cvNamedWindow("draw", 1);
  156. cvShowImage("draw", img);
  157. cvWaitKey(0);
  158. cvReleaseImage(&img);
  159. }
  160. static void
  161. output(const vector<CvRect> &rects, const char *filen)
  162. {
  163. FILE *fp = fopen(filen, "w");
  164. assert(fp != NULL);
  165. for (int i = 0; i < rects.size(); ++i)
  166. {
  167. fprintf(fp, "%d %d %d %d ", rects[i].x, rects[i].y, rects[i].width, rects[i].height);
  168. }
  169. fclose(fp);
  170. return ;
  171. }
  172. static void
  173. output(const vector<CvRect> &rects)
  174. {
  175. for (int i = 0; i < rects.size(); ++i)
  176. {
  177. printf("%d %d %d %d ", rects[i].x, rects[i].y, rects[i].width, rects[i].height);
  178. }
  179. printf("\n");
  180. }
  181. int
  182. main(int argc, char *argv[])
  183. {
  184. if (argc != 5 && argc != 6)
  185. {
  186. puts(">>>./program image.jpg th0 th1 th2\nor");
  187. puts(">>>./program image.jpg th0 th1 th2 output.txt");
  188. return -1;
  189. }
  190. IplImage *gray = cvLoadImage(argv[1], 0);
  191. if (!gray)
  192. {
  193. puts("Can not open image, dude!\n");
  194. }
  195. // set the thresholds
  196. {
  197. int t0, t1, t2;
  198. t0 = atoi(argv[2]);
  199. t1 = atoi(argv[3]);
  200. t2 = atoi(argv[4]);
  201. if (0 < t0 && t0 < t1 && t1 < t2 && t2 < 255)
  202. {
  203. g_Ths[0] = t0;
  204. g_Ths[1] = t1;
  205. g_Ths[2] = t2;
  206. }
  207. }
  208. Data *data = fromDT(gray);
  209. vector<CvRect> rects = getBBox(data);
  210. rankBBox(rects);
  211. mergeBBox(rects);
  212. //if (argc == 4)
  213. // draw(rects, argv[3]);
  214. if (argc == 6)
  215. output(rects, argv[5]);
  216. else
  217. output(rects);
  218. delete data;
  219. cvReleaseImage(&gray);
  220. return 0;
  221. }