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));
}
Example #2
0
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);
}