void ellipsetrack(avi_t *video, double *xc0, double *yc0, int Nc, int R, int Np, int Nf) { /* % ELLIPSETRACK tracks cells in the movie specified by 'video', at % locations 'xc0'/'yc0' with radii R using an ellipse with Np discrete % points, starting at frame number one and stopping at frame number 'Nf'. % % INPUTS: % video.......pointer to avi video object % xc0,yc0.....initial center location (Nc entries) % Nc..........number of cells % R...........initial radius % Np..........nbr of snaxels points per snake % Nf..........nbr of frames in which to track % % Matlab code written by: DREW GILLIAM (based on code by GANG DONG / % NILANJAN RAY) % Ported to C by: MICHAEL BOYER */ int i, j; // Compute angle parameter double *t = (double *) malloc(sizeof(double) * Np); double increment = (2.0 * PI) / (double) Np; for (i = 0; i < Np; i++) { t[i] = increment * (double) i ; } // Allocate space for a snake for each cell in each frame double **xc = alloc_2d_double(Nc, Nf + 1); double **yc = alloc_2d_double(Nc, Nf + 1); double ***r = alloc_3d_double(Nc, Np, Nf + 1); double ***x = alloc_3d_double(Nc, Np, Nf + 1); double ***y = alloc_3d_double(Nc, Np, Nf + 1); // Save the first snake for each cell for (i = 0; i < Nc; i++) { xc[i][0] = xc0[i]; yc[i][0] = yc0[i]; for (j = 0; j < Np; j++) { r[i][j][0] = (double) R; } } // Generate ellipse points for each cell for (i = 0; i < Nc; i++) { for (j = 0; j < Np; j++) { x[i][j][0] = xc[i][0] + (r[i][j][0] * cos(t[j])); y[i][j][0] = yc[i][0] + (r[i][j][0] * sin(t[j])); } } // Keep track of the total time spent on computing // the MGVF matrix and evolving the snakes long long MGVF_time = 0; long long snake_time = 0; // Process each frame int frame_num, cell_num; for (frame_num = 1; frame_num <= Nf; frame_num++) { printf("\rProcessing frame %d / %d", frame_num, Nf); fflush(stdout); // Get the current video frame and its dimensions MAT *I = get_frame(video, frame_num, 0, 1); int Ih = I->m; int Iw = I->n; // Set the current positions equal to the previous positions for (i = 0; i < Nc; i++) { xc[i][frame_num] = xc[i][frame_num - 1]; yc[i][frame_num] = yc[i][frame_num - 1]; for (j = 0; j < Np; j++) { r[i][j][frame_num] = r[i][j][frame_num - 1]; } } // Split the work among multiple threads, if OPEN is defined #ifdef OPEN #pragma omp parallel for num_threads(omp_num_threads) private(i, j) #endif // Track each cell for (cell_num = 0; cell_num < Nc; cell_num++) { // Make copies of the current cell's location double xci = xc[cell_num][frame_num]; double yci = yc[cell_num][frame_num]; double *ri = (double *) malloc(sizeof(double) * Np); for (j = 0; j < Np; j++) { ri[j] = r[cell_num][j][frame_num]; } // Add up the last ten y-values for this cell // (or fewer if there are not yet ten previous frames) double ycavg = 0.0; for (i = (frame_num > 10 ? frame_num - 10 : 0); i < frame_num; i++) { ycavg += yc[cell_num][i]; } // Compute the average of the last ten y-values // (this represents the expected y-location of the cell) ycavg = ycavg / (double) (frame_num > 10 ? 10 : frame_num); // Determine the range of the subimage surrounding the current position int u1 = max(xci - 4.0 * R + 0.5, 0 ); int u2 = min(xci + 4.0 * R + 0.5, Iw - 1); int v1 = max(yci - 2.0 * R + 1.5, 0 ); int v2 = min(yci + 2.0 * R + 1.5, Ih - 1); // Extract the subimage MAT *Isub = m_get(v2 - v1 + 1, u2 - u1 + 1); for (i = v1; i <= v2; i++) { for (j = u1; j <= u2; j++) { m_set_val(Isub, i - v1, j - u1, m_get_val(I, i, j)); } } // Compute the subimage gradient magnitude MAT *Ix = gradient_x(Isub); MAT *Iy = gradient_y(Isub); MAT *IE = m_get(Isub->m, Isub->n); for (i = 0; i < Isub->m; i++) { for (j = 0; j < Isub->n; j++) { double temp_x = m_get_val(Ix, i, j); double temp_y = m_get_val(Iy, i, j); m_set_val(IE, i, j, sqrt((temp_x * temp_x) + (temp_y * temp_y))); } } // Compute the motion gradient vector flow (MGVF) edgemaps long long MGVF_start_time = get_time(); MAT *IMGVF = MGVF(IE, 1, 1); MGVF_time += get_time() - MGVF_start_time; // Determine the position of the cell in the subimage xci = xci - (double) u1; yci = yci - (double) (v1 - 1); ycavg = ycavg - (double) (v1 - 1); // Evolve the snake long long snake_start_time = get_time(); ellipseevolve(IMGVF, &xci, &yci, ri, t, Np, (double) R, ycavg); snake_time += get_time() - snake_start_time; // Compute the cell's new position in the full image xci = xci + u1; yci = yci + (v1 - 1); // Store the new location of the cell and the snake xc[cell_num][frame_num] = xci; yc[cell_num][frame_num] = yci; for (j = 0; j < Np; j++) { r[cell_num][j][frame_num] = ri[j]; x[cell_num][j][frame_num] = xc[cell_num][frame_num] + (ri[j] * cos(t[j])); y[cell_num][j][frame_num] = yc[cell_num][frame_num] + (ri[j] * sin(t[j])); } // Output the updated center of each cell //printf("%d,%f,%f\n", cell_num, xci[cell_num], yci[cell_num]); // Free temporary memory m_free(IMGVF); free(ri); } // Output a new line to visually distinguish the output from different frames //printf("\n"); } // Free temporary memory free(t); free_2d_double(xc); free_2d_double(yc); free_3d_double(r); free_3d_double(x); free_3d_double(y); // Report average processing time per frame printf("\n\nTracking runtime (average per frame):\n"); printf("------------------------------------\n"); printf("MGVF computation: %.5f seconds\n", ((float) (MGVF_time)) / (float) (1000*1000*Nf)); printf(" Snake evolution: %.5f seconds\n", ((float) (snake_time)) / (float) (1000*1000*Nf)); }
void ellipsetrack(avi_t *video, double *xc0, double *yc0, int Nc, int R, int Np, int Nf) { /* % ELLIPSETRACK tracks cells in the movie specified by 'video', at % locations 'xc0'/'yc0' with radii R using an ellipse with Np discrete % points, starting at frame number one and stopping at frame number 'Nf'. % % INPUTS: % video.......pointer to avi video object % xc0,yc0.....initial center location (Nc entries) % Nc..........number of cells % R...........initial radius % Np..........number of snaxels points per snake % Nf..........number of frames in which to track % % Matlab code written by: DREW GILLIAM (based on code by GANG DONG / % NILANJAN RAY) % Ported to C by: MICHAEL BOYER */ // Compute angle parameter double *t = (double *) malloc(sizeof(double) * Np); double increment = (2.0 * PI) / (double) Np; int i, j; for (i = 0; i < Np; i++) { t[i] = increment * (double) i ; } // Allocate space for a snake for each cell in each frame double **xc = alloc_2d_double(Nc, Nf + 1); double **yc = alloc_2d_double(Nc, Nf + 1); double ***r = alloc_3d_double(Nc, Np, Nf + 1); double ***x = alloc_3d_double(Nc, Np, Nf + 1); double ***y = alloc_3d_double(Nc, Np, Nf + 1); // Save the first snake for each cell for (i = 0; i < Nc; i++) { xc[i][0] = xc0[i]; yc[i][0] = yc0[i]; for (j = 0; j < Np; j++) { r[i][j][0] = (double) R; } } // Generate ellipse points for each cell for (i = 0; i < Nc; i++) { for (j = 0; j < Np; j++) { x[i][j][0] = xc[i][0] + (r[i][j][0] * cos(t[j])); y[i][j][0] = yc[i][0] + (r[i][j][0] * sin(t[j])); } } // Allocate arrays so we can break up the per-cell for loop below double *xci = (double *) malloc(sizeof(double) * Nc); double *yci = (double *) malloc(sizeof(double) * Nc); double **ri = alloc_2d_double(Nc, Np); double *ycavg = (double *) malloc(sizeof(double) * Nc); int *u1 = (int *) malloc(sizeof(int) * Nc); int *u2 = (int *) malloc(sizeof(int) * Nc); int *v1 = (int *) malloc(sizeof(int) * Nc); int *v2 = (int *) malloc(sizeof(int) * Nc); MAT **Isub = (MAT **) malloc(sizeof(MAT *) * Nc); MAT **Ix = (MAT **) malloc(sizeof(MAT *) * Nc); MAT **Iy = (MAT **) malloc(sizeof(MAT *) * Nc); MAT **IE = (MAT **) malloc(sizeof(MAT *) * Nc); // Keep track of the total time spent on computing // the MGVF matrix and evolving the snakes long long MGVF_time = 0; long long snake_time = 0; // Process each frame sequentially int frame_num; for (frame_num = 1; frame_num <= Nf; frame_num++) { printf("\rProcessing frame %d / %d", frame_num, Nf); fflush(stdout); // Get the current video frame and its dimensions MAT *I = get_frame(video, frame_num, 0, 1); int Ih = I->m; int Iw = I->n; // Initialize the current positions to be equal to the previous positions for (i = 0; i < Nc; i++) { xc[i][frame_num] = xc[i][frame_num - 1]; yc[i][frame_num] = yc[i][frame_num - 1]; for (j = 0; j < Np; j++) { r[i][j][frame_num] = r[i][j][frame_num - 1]; } } // Sequentially extract the subimage near each cell int cell_num; for (cell_num = 0; cell_num < Nc; cell_num++) { // Make copies of the current cell's location xci[cell_num] = xc[cell_num][frame_num]; yci[cell_num] = yc[cell_num][frame_num]; for (j = 0; j < Np; j++) { ri[cell_num][j] = r[cell_num][j][frame_num]; } // Add up the last ten y values for this cell // (or fewer if there are not yet ten previous frames) ycavg[cell_num] = 0.0; for (i = (frame_num > 10 ? frame_num - 10 : 0); i < frame_num; i++) { ycavg[cell_num] += yc[cell_num][i]; } // Compute the average of the last ten values // (this represents the expected location of the cell) ycavg[cell_num] = ycavg[cell_num] / (double) (frame_num > 10 ? 10 : frame_num); // Determine the range of the subimage surrounding the current position u1[cell_num] = max(xci[cell_num] - 4.0 * R + 0.5, 0 ); u2[cell_num] = min(xci[cell_num] + 4.0 * R + 0.5, Iw - 1); v1[cell_num] = max(yci[cell_num] - 2.0 * R + 1.5, 0 ); v2[cell_num] = min(yci[cell_num] + 2.0 * R + 1.5, Ih - 1); // Extract the subimage Isub[cell_num] = m_get(v2[cell_num] - v1[cell_num] + 1, u2[cell_num] - u1[cell_num] + 1); for (i = v1[cell_num]; i <= v2[cell_num]; i++) { for (j = u1[cell_num]; j <= u2[cell_num]; j++) { m_set_val(Isub[cell_num], i - v1[cell_num], j - u1[cell_num], m_get_val(I, i, j)); } } // Compute the subimage gradient magnitude Ix[cell_num] = gradient_x(Isub[cell_num]); Iy[cell_num] = gradient_y(Isub[cell_num]); IE[cell_num] = m_get(Isub[cell_num]->m, Isub[cell_num]->n); for (i = 0; i < Isub[cell_num]->m; i++) { for (j = 0; j < Isub[cell_num]->n; j++) { double temp_x = m_get_val(Ix[cell_num], i, j); double temp_y = m_get_val(Iy[cell_num], i, j); m_set_val(IE[cell_num], i, j, sqrt((temp_x * temp_x) + (temp_y * temp_y))); } } } // Compute the motion gradient vector flow (MGVF) edgemaps for all cells concurrently long long MGVF_start_time = get_time(); MAT **IMGVF = MGVF(IE, 1, 1, Nc); MGVF_time += get_time() - MGVF_start_time; // Sequentially determine the new location of each cell for (cell_num = 0; cell_num < Nc; cell_num++) { // Determine the position of the cell in the subimage xci[cell_num] = xci[cell_num] - (double) u1[cell_num]; yci[cell_num] = yci[cell_num] - (double) (v1[cell_num] - 1); ycavg[cell_num] = ycavg[cell_num] - (double) (v1[cell_num] - 1); // Evolve the snake long long snake_start_time = get_time(); ellipseevolve(IMGVF[cell_num], &(xci[cell_num]), &(yci[cell_num]), ri[cell_num], t, Np, (double) R, ycavg[cell_num]); snake_time += get_time() - snake_start_time; // Compute the cell's new position in the full image xci[cell_num] = xci[cell_num] + u1[cell_num]; yci[cell_num] = yci[cell_num] + (v1[cell_num] - 1); // Store the new location of the cell and the snake xc[cell_num][frame_num] = xci[cell_num]; yc[cell_num][frame_num] = yci[cell_num]; for (j = 0; j < Np; j++) { r[cell_num][j][frame_num] = 0; r[cell_num][j][frame_num] = ri[cell_num][j]; x[cell_num][j][frame_num] = xc[cell_num][frame_num] + (ri[cell_num][j] * cos(t[j])); y[cell_num][j][frame_num] = yc[cell_num][frame_num] + (ri[cell_num][j] * sin(t[j])); } // Output the updated center of each cell // printf("\n%d,%f,%f", cell_num, xci[cell_num], yci[cell_num]); // Free temporary memory m_free(Isub[cell_num]); m_free(Ix[cell_num]); m_free(Iy[cell_num]); m_free(IE[cell_num]); m_free(IMGVF[cell_num]); } #ifdef OUTPUT if (frame_num == Nf) { FILE * pFile; pFile = fopen ("result.txt","w+"); for (cell_num = 0; cell_num < Nc; cell_num++) fprintf(pFile,"\n%d,%f,%f", cell_num, xci[cell_num], yci[cell_num]); fclose (pFile); } #endif free(IMGVF); // Output a new line to visually distinguish the output from different frames //printf("\n"); } // Free temporary memory free_2d_double(xc); free_2d_double(yc); free_3d_double(r); free_3d_double(x); free_3d_double(y); free(t); free(xci); free(yci); free_2d_double(ri); free(ycavg); free(u1); free(u2); free(v1); free(v2); free(Isub); free(Ix); free(Iy); free(IE); // Report average processing time per frame printf("\n\nTracking runtime (average per frame):\n"); printf("------------------------------------\n"); printf("MGVF computation: %.5f seconds\n", ((float) (MGVF_time)) / (float) (1000*1000*Nf)); printf(" Snake evolution: %.5f seconds\n", ((float) (snake_time)) / (float) (1000*1000*Nf)); printf("CAUTION: cpu_offset: %d time: %lf mseconds\n", cpu_offset, ((float) (MGVF_time)) / (float) (1000*1000*Nf)*1000); }