detect_main.c 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290
  1. #include "find_ellipse.h"
  2. #include "track_ellipse.h"
  3. // Global variables used by OpenCL functions
  4. cl_context context;
  5. cl_command_queue command_queue;
  6. cl_device_id device;
  7. // Helper function to print usage
  8. void usage(char *argv0) {
  9. char *help =
  10. "\nUsage: %s [switches] \n\n"
  11. " -i :input file \n"
  12. " -f :frames to process \n"
  13. " -p platform_id :OCL platform to use [default=0]\n"
  14. " -d device_id :OCL device to use [default=0]\n"
  15. " -g use_gpu :1 for GPU 0 for CPU [default=0]\n";
  16. fprintf(stderr, help, argv0);
  17. exit(-1);
  18. }
  19. int main(int argc, char ** argv) {
  20. // Let the user specify the number of frames to process
  21. int num_frames = 0;
  22. // Open video file
  23. char *video_file_name = 0;
  24. // Arguments parsing for platform, device and type
  25. // Variables to store information on platform and device to use_gpu
  26. int platform_id = 0;
  27. int device_id = 0;
  28. int use_gpu = 0;
  29. /* obtain command line arguments and change appropriate options */
  30. int opt;
  31. extern char *optarg;
  32. while ((opt=getopt(argc,argv,"i:f:p:d:g:"))!= EOF) {
  33. switch (opt) {
  34. case 'p': platform_id = atoi(optarg);
  35. break;
  36. case 'd': device_id = atoi(optarg);
  37. break;
  38. case 'g': use_gpu = atoi(optarg);
  39. break;
  40. case 'i': video_file_name = optarg;
  41. break;
  42. case 'f': num_frames = atoi(optarg);
  43. break;
  44. case '?': usage(argv[0]);
  45. break;
  46. default: usage(argv[0]);
  47. break;
  48. }
  49. }
  50. // Choose the best GPU in case there are multiple available
  51. choose_GPU(platform_id, device_id, use_gpu);
  52. // Keep track of the start time of the program
  53. long long program_start_time = get_time();
  54. avi_t *cell_file = AVI_open_input_file(video_file_name, 1);
  55. if (cell_file == NULL) {
  56. AVI_print_error("Error with AVI_open_input_file");
  57. exit(EXIT_FAILURE);
  58. }
  59. // Transfer precomputed constants to the GPU
  60. compute_constants();
  61. int i, j, *crow, *ccol, pair_counter = 0, x_result_len = 0, Iter = 20, ns = 4, k_count = 0, n;
  62. MAT *cellx, *celly, *A;
  63. double *GICOV_spots, *t, *G, *x_result, *y_result, *V, *QAX_CENTERS, *QAY_CENTERS;
  64. double threshold = 1.8, radius = 10.0, delta = 3.0, dt = 0.01, b = 5.0;
  65. // Extract a cropped version of the first frame from the video file
  66. MAT *image_chopped = get_frame(cell_file, 0, 1, 0);
  67. printf("Detecting cells in frame 0\n");
  68. // Get gradient matrices in x and y directions
  69. MAT *grad_x = gradient_x(image_chopped);
  70. MAT *grad_y = gradient_y(image_chopped);
  71. m_free(image_chopped);
  72. // Get GICOV matrices corresponding to image gradients
  73. long long GICOV_start_time = get_time();
  74. MAT *gicov = GICOV(grad_x, grad_y);
  75. long long GICOV_end_time = get_time();
  76. // Dilate the GICOV matrices
  77. long long dilate_start_time = get_time();
  78. MAT *img_dilated = dilate(gicov);
  79. long long dilate_end_time = get_time();
  80. // Find possible matches for cell centers based on GICOV and record the rows/columns in which they are found
  81. pair_counter = 0;
  82. crow = (int *) malloc(gicov->m * gicov->n * sizeof(int));
  83. ccol = (int *) malloc(gicov->m * gicov->n * sizeof(int));
  84. for(i = 0; i < gicov->m; i++) {
  85. for(j = 0; j < gicov->n; j++) {
  86. if(!double_eq(m_get_val(gicov,i,j), 0.0) && double_eq(m_get_val(img_dilated,i,j), m_get_val(gicov,i,j)))
  87. {
  88. crow[pair_counter]=i;
  89. ccol[pair_counter]=j;
  90. pair_counter++;
  91. }
  92. }
  93. }
  94. GICOV_spots = (double *) malloc(sizeof(double) * pair_counter);
  95. for(i = 0; i < pair_counter; i++)
  96. GICOV_spots[i] = sqrt(m_get_val(gicov, crow[i], ccol[i]));
  97. G = (double *) calloc(pair_counter, sizeof(double));
  98. x_result = (double *) calloc(pair_counter, sizeof(double));
  99. y_result = (double *) calloc(pair_counter, sizeof(double));
  100. x_result_len = 0;
  101. for (i = 0; i < pair_counter; i++) {
  102. if ((crow[i] > 29) && (crow[i] < BOTTOM - TOP + 39)) {
  103. x_result[x_result_len] = ccol[i];
  104. y_result[x_result_len] = crow[i] - 40;
  105. G[x_result_len] = GICOV_spots[i];
  106. x_result_len++;
  107. }
  108. }
  109. // Make an array t which holds each "time step" for the possible cells
  110. t = (double *) malloc(sizeof(double) * 36);
  111. for (i = 0; i < 36; i++) {
  112. t[i] = (double)i * 2.0 * PI / 36.0;
  113. }
  114. // Store cell boundaries (as simple circles) for all cells
  115. cellx = m_get(x_result_len, 36);
  116. celly = m_get(x_result_len, 36);
  117. for(i = 0; i < x_result_len; i++) {
  118. for(j = 0; j < 36; j++) {
  119. m_set_val(cellx, i, j, x_result[i] + radius * cos(t[j]));
  120. m_set_val(celly, i, j, y_result[i] + radius * sin(t[j]));
  121. }
  122. }
  123. A = TMatrix(9,4);
  124. V = (double *) malloc(sizeof(double) * pair_counter);
  125. QAX_CENTERS = (double * )malloc(sizeof(double) * pair_counter);
  126. QAY_CENTERS = (double *) malloc(sizeof(double) * pair_counter);
  127. memset(V, 0, sizeof(double) * pair_counter);
  128. memset(QAX_CENTERS, 0, sizeof(double) * pair_counter);
  129. memset(QAY_CENTERS, 0, sizeof(double) * pair_counter);
  130. // For all possible results, find the ones that are feasibly leukocytes and store their centers
  131. k_count = 0;
  132. for (n = 0; n < x_result_len; n++) {
  133. if ((G[n] < -1 * threshold) || G[n] > threshold) {
  134. MAT * x, *y;
  135. VEC * x_row, * y_row;
  136. x = m_get(1, 36);
  137. y = m_get(1, 36);
  138. x_row = v_get(36);
  139. y_row = v_get(36);
  140. // Get current values of possible cells from cellx/celly matrices
  141. x_row = get_row(cellx, n, x_row);
  142. y_row = get_row(celly, n, y_row);
  143. uniformseg(x_row, y_row, x, y);
  144. // Make sure that the possible leukocytes are not too close to the edge of the frame
  145. if ((m_min(x) > b) && (m_min(y) > b) && (m_max(x) < cell_file->width - b) && (m_max(y) < cell_file->height - b)) {
  146. MAT * Cx, * Cy, *Cy_temp, * Ix1, * Iy1;
  147. VEC *Xs, *Ys, *W, *Nx, *Ny, *X, *Y;
  148. Cx = m_get(1, 36);
  149. Cy = m_get(1, 36);
  150. Cx = mmtr_mlt(A, x, Cx);
  151. Cy = mmtr_mlt(A, y, Cy);
  152. Cy_temp = m_get(Cy->m, Cy->n);
  153. for (i = 0; i < 9; i++)
  154. m_set_val(Cy, i, 0, m_get_val(Cy, i, 0) + 40.0);
  155. // Iteratively refine the snake/spline
  156. for (i = 0; i < Iter; i++) {
  157. int typeofcell;
  158. if(G[n] > 0.0) typeofcell = 0;
  159. else typeofcell = 1;
  160. splineenergyform01(Cx, Cy, grad_x, grad_y, ns, delta, 2.0 * dt, typeofcell);
  161. }
  162. X = getsampling(Cx, ns);
  163. for (i = 0; i < Cy->m; i++)
  164. m_set_val(Cy_temp, i, 0, m_get_val(Cy, i, 0) - 40.0);
  165. Y = getsampling(Cy_temp, ns);
  166. Ix1 = linear_interp2(grad_x, X, Y);
  167. Iy1 = linear_interp2(grad_x, X, Y);
  168. Xs = getfdriv(Cx, ns);
  169. Ys = getfdriv(Cy, ns);
  170. Nx = v_get(Ys->dim);
  171. for (i = 0; i < Ys->dim; i++)
  172. v_set_val(Nx, i, v_get_val(Ys, i) / sqrt(v_get_val(Xs, i)*v_get_val(Xs, i) + v_get_val(Ys, i)*v_get_val(Ys, i)));
  173. Ny = v_get(Xs->dim);
  174. for (i = 0; i < Xs->dim; i++)
  175. v_set_val(Ny, i, -1.0 * v_get_val(Xs, i) / sqrt(v_get_val(Xs, i)*v_get_val(Xs, i) + v_get_val(Ys, i)*v_get_val(Ys, i)));
  176. W = v_get(Nx->dim);
  177. for (i = 0; i < Nx->dim; i++)
  178. v_set_val(W, i, m_get_val(Ix1, 0, i) * v_get_val(Nx, i) + m_get_val(Iy1, 0, i) * v_get_val(Ny, i));
  179. V[n] = mean(W) / std_dev(W);
  180. // Find the cell centers by computing the means of X and Y values for all snaxels of the spline contour
  181. QAX_CENTERS[k_count] = mean(X);
  182. QAY_CENTERS[k_count] = mean(Y) + TOP;
  183. k_count++;
  184. // Free memory
  185. v_free(W);
  186. v_free(Ny);
  187. v_free(Nx);
  188. v_free(Ys);
  189. v_free(Xs);
  190. m_free(Iy1);
  191. m_free(Ix1);
  192. v_free(Y);
  193. v_free(X);
  194. m_free(Cy_temp);
  195. m_free(Cy);
  196. m_free(Cx);
  197. }
  198. // Free memory
  199. v_free(y_row);
  200. v_free(x_row);
  201. m_free(y);
  202. m_free(x);
  203. }
  204. }
  205. // Free memory
  206. free(V);
  207. free(ccol);
  208. free(crow);
  209. free(GICOV_spots);
  210. free(t);
  211. free(G);
  212. free(x_result);
  213. free(y_result);
  214. m_free(A);
  215. m_free(celly);
  216. m_free(cellx);
  217. m_free(img_dilated);
  218. m_free(gicov);
  219. m_free(grad_y);
  220. m_free(grad_x);
  221. // Report the total number of cells detected
  222. printf("Cells detected: %d\n\n", k_count);
  223. // Report the breakdown of the detection runtime
  224. printf("Detection runtime\n");
  225. printf("-----------------\n");
  226. printf("GICOV computation: %.5f seconds\n", ((float) (GICOV_end_time - GICOV_start_time)) / (1000*1000));
  227. printf(" GICOV dilation: %.5f seconds\n", ((float) (dilate_end_time - dilate_start_time)) / (1000*1000));
  228. printf(" Total: %.5f seconds\n", ((float) (get_time() - program_start_time)) / (1000*1000));
  229. // Now that the cells have been detected in the first frame,
  230. // track the ellipses through subsequent frames
  231. if (num_frames > 1) printf("\nTracking cells across %d frames\n", num_frames);
  232. else printf("\nTracking cells across 1 frame\n");
  233. long long tracking_start_time = get_time();
  234. int num_snaxels = 20;
  235. ellipsetrack(cell_file, QAX_CENTERS, QAY_CENTERS, k_count, radius, num_snaxels, num_frames);
  236. printf(" Total: %.5f seconds\n", ((float) (get_time() - tracking_start_time)) / (float) (1000*1000*num_frames));
  237. // Report total program execution time
  238. printf("\nTotal application run time: %.5f seconds\n", ((float) (get_time() - program_start_time)) / (1000*1000));
  239. return 0;
  240. }