Beispiel #1
0
	int sobel_argb32_3x3_partial(vbx_uword_t *sobel_out, vbx_uword_t *argb_in, const short image_width,
	                             const short image_height, const short image_pitch, const short renorm)
	{
		VBX::Prefetcher<vbx_uword_t> input(1,image_width,argb_in,argb_in+image_height*image_pitch,image_pitch);
		VBX::Vector<vbx_uword_t> output(image_width);
		VBX::Vector<vbx_uhalf_t>* luma[3];
		luma[0]=new VBX::Vector<vbx_uhalf_t>(image_width);
		luma[1]=new VBX::Vector<vbx_uhalf_t>(image_width);
		luma[2]=new VBX::Vector<vbx_uhalf_t>(image_width);
		VBX::Vector<vbx_uhalf_t> gradient_x(image_width);
		VBX::Vector<vbx_uhalf_t> gradient_y(image_width);
		VBX::Vector<vbx_uhalf_t>* sobel_rows[3];

		sobel_rows[0]=new VBX::Vector<vbx_uhalf_t>(image_width);
		sobel_rows[1]=new VBX::Vector<vbx_uhalf_t>(image_width);
		sobel_rows[2]=new VBX::Vector<vbx_uhalf_t>(image_width);
		input.fetch();
		int rowmod3=0;
		for(int row=0;row<image_height;row++){
			input.fetch();

			VBX::Vector<vbx_uhalf_t>& sobel_top= *sobel_rows[rowmod3];
			VBX::Vector<vbx_uhalf_t>& sobel_bot= *sobel_rows[mod3(rowmod3+2)];
			VBX::Vector<vbx_uhalf_t>& luma_top= *luma[rowmod3];
			VBX::Vector<vbx_uhalf_t>& luma_mid= *luma[mod3(rowmod3+1)];
			VBX::Vector<vbx_uhalf_t>& luma_bot= *luma[mod3(rowmod3+2)];
			rowmod3=mod3(rowmod3+1);
			argb_to_luma8(luma_bot,input[0]);
			sobel_row( sobel_bot ,luma_bot);
			if(row<2){
				continue;
			}

			gradient_y=absdiff(sobel_top,sobel_bot);
			gradient_x=luma_top +luma_bot + luma_mid*2;
			gradient_x[1 upto image_width-1]=absdiff(gradient_x[0 upto image_width-2],gradient_x[2 upto image_width]);

			output=((gradient_x + gradient_y) >> renorm);

			output.cond_move(output>0xFF,0xFF);

			output*=0x010101;

			//write to output buffer, skipping first and last elements
			output[1 upto (image_width -1)].dma_write(sobel_out+(row-1)*image_pitch +1);

		}
		output=0;
		output.dma_write(sobel_out);
		output.dma_write(sobel_out+ (image_height-1)*image_pitch);
		delete luma[0];
		delete luma[1];
		delete luma[2];
		delete sobel_rows[0];
		delete sobel_rows[1];
		delete sobel_rows[2];

		return 0;
	}
Beispiel #2
0
	int sobel_luma8_3x3(vbx_uword_t *output,
	                    unsigned char *input,
	                    const short image_width,
	                    const short image_height,
	                    const short image_pitch,
	                    const short renorm)
	{
		VBX::Prefetcher<vbx_ubyte_t> luma_in(3,image_width,input,input+image_height*image_pitch,image_pitch);
		VBX::Vector<vbx_uhalf_t> *sobel[3];
		sobel[0]=new VBX::Vector<vbx_uhalf_t>(image_width-2);
		sobel[1]=new VBX::Vector<vbx_uhalf_t>(image_width-2);
		sobel[2]=new VBX::Vector<vbx_uhalf_t>(image_width-2);
		VBX::Vector<vbx_uhalf_t> gradient_x(image_width-2);
		VBX::Vector<vbx_uhalf_t> gradient_y(image_width-2);
		VBX::Vector<vbx_uword_t> row_out(image_width);
		VBX::Vector<vbx_uhalf_t> tmp(image_width);
		if(!tmp.data){
			printf("Out of scratchpad memory\n");
			return -1;
		}
		luma_in.fetch();
		luma_in.fetch();

		sobel_row(*sobel[0],luma_in[0]);
		luma_in.fetch();
		sobel_row(*sobel[1],luma_in[1]);
		//set first row black
		row_out=0;
		row_out.dma_write(output);
		for(int row=0,s_t=0,s_b=2;row<image_height-(3-1);row++,s_t++,s_b++){
			luma_in.fetch();
			//use reference to refer to vectors without copying
			VBX::Vector<vbx_ubyte_t>& luma_top=luma_in[0];
			VBX::Vector<vbx_ubyte_t>& luma_mid=luma_in[1];
			VBX::Vector<vbx_ubyte_t>& luma_bot=luma_in[2];
			if(s_t>=3)s_t=0;//mod 3
			if(s_b>=3)s_b=0;//mod 3
			VBX::Vector<vbx_uhalf_t>& sobel_top=*sobel[s_t];
			VBX::Vector<vbx_uhalf_t>& sobel_bot=*sobel[s_b];

			sobel_row(sobel_bot,luma_bot);

			gradient_y=absdiff(sobel_top,sobel_bot);
			tmp=luma_top+luma_bot+(luma_mid<<1);
			gradient_x=absdiff(tmp,tmp[2 upto image_width]);
			//sum the gradients, normalize and saturate at 255
			row_out[1 upto image_width-1]=(gradient_x+gradient_y)>>renorm;
			row_out.cond_move(row_out>255,255);
			//copy lowest byte into the 2nd and 3rd;
			row_out*=0x10101;
			row_out.dma_write(output+(row+1)*image_pitch);
		}
		//set last row black
		row_out=0;
		row_out.dma_write(output+(image_height-1)*image_width);
		return 0;
	}
Beispiel #3
0
// Per OpenVX
// Implements the Sobel Image Filter k.
// This k produces two output planes (one can be omitted) in the x and y plane.
// The Sobel Operators Gx,Gy are defined as:
//
//          -1  0  1            -1 -2 -1
//     Gx = -2  0  2       Gy =  0  0  0
//           1  0  1             1  2  1
//
// https://www.khronos.org/registry/vx/specs/1.0/html/da/d4b/group__group__vision__function__sobel3x3.html
//
std::pair<Halide::Func, Halide::Func> sobel_3x3(Halide::Func input, bool grayscale) {
    Halide::Func kx("kx"), ky("ky");
    Halide::Func gradient_x("gradient_x"), gradient_y("gradient_y");
    Halide::RDom r(-1,3,-1,3);
    Halide::Var x,y,c;

    kx(x,y) = 0;
    kx(-1,-1) = -1;
    kx(0,-1) = 0;
    kx(1,-1) = 1;
    kx(-1, 0) = -2;
    kx(0, 0) = 0;
    kx(1, 0) = 2;
    kx(-1, 1) = -1;
    kx(0, 1) = 0;
    kx(1, 1) = 1;
    if (grayscale)
        gradient_x(x,y) = sum(input(x+r.x, y+r.y) * kx(r.x, r.y));
    else
        gradient_x(x,y,c) = sum(input(x+r.x, y+r.y, c) * kx(r.x, r.y));

    ky(x,y) = 0;
    ky(-1,-1) = -1;
    ky(0,-1) = -2;
    ky(1,-1) = -1;
    ky(-1, 0) =  0;
    ky(0, 0) =  0;
    ky(1, 0) =  0;
    ky(-1, 1) =  1;
    ky(0, 1) =  2;
    ky(1, 1) =  1;
    if (grayscale)
        gradient_y(x,y) = sum(input(x+r.x, y+r.y) * ky(r.x, r.y));
    else
        gradient_y(x,y,c) = sum(input(x+r.x, y+r.y, c) * ky(r.x, r.y));

    std::pair<Halide::Func, Halide::Func> ret = std::make_pair(gradient_x, gradient_y);
    return ret;
}
Beispiel #4
0
// Main
int main(int argc, char ** argv) {

	// Choose the best GPU in case there are multiple available
	choose_GPU();

	// Keep track of the start time of the program
	long long program_start_time = get_time();
	
	if (argc !=3){
	fprintf(stderr, "usage: %s <input file> <number of frames to process>", argv[0]);
	exit(1);
	}
	
	// Let the user specify the number of frames to process
	int num_frames = atoi(argv[2]);
	
	// Open video file
	char *video_file_name = argv[1];
	
	avi_t *cell_file = AVI_open_input_file(video_file_name, 1);
	if (cell_file == NULL)	{
		AVI_print_error("Error with AVI_open_input_file");
		return -1;
	}
	
	int i, j, *crow, *ccol, pair_counter = 0, x_result_len = 0, Iter = 20, ns = 4, k_count = 0, n;
	MAT *cellx, *celly, *A;
	double *GICOV_spots, *t, *G, *x_result, *y_result, *V, *QAX_CENTERS, *QAY_CENTERS;
	double threshold = 1.8, radius = 10.0, delta = 3.0, dt = 0.01, b = 5.0;
	
	// Extract a cropped version of the first frame from the video file
	MAT *image_chopped = get_frame(cell_file, 0, 1, 0);
	printf("Detecting cells in frame 0\n");
	
	// Get gradient matrices in x and y directions
	MAT *grad_x = gradient_x(image_chopped);
	MAT *grad_y = gradient_y(image_chopped);
	
	// Allocate for gicov_mem and strel
	gicov_mem = (float*) malloc(sizeof(float) * grad_x->m * grad_y->n);
	strel = (float*) malloc(sizeof(float) * strel_m * strel_n);

	m_free(image_chopped);

	int grad_m = grad_x->m;
	int grad_n = grad_y->n;
	
#pragma acc data create(sin_angle,cos_angle,theta,tX,tY) \
	create(gicov_mem[0:grad_x->m*grad_y->n])
{
	// Precomputed constants on GPU
	compute_constants();

	// Get GICOV matrices corresponding to image gradients
	long long GICOV_start_time = get_time();
	MAT *gicov = GICOV(grad_x, grad_y);
	long long GICOV_end_time = get_time();

	// Dilate the GICOV matrices
	long long dilate_start_time = get_time();
	MAT *img_dilated = dilate(gicov);
	long long dilate_end_time = get_time();
} /* end acc data */
	
	// Find possible matches for cell centers based on GICOV and record the rows/columns in which they are found
	pair_counter = 0;
	crow = (int *) malloc(gicov->m * gicov->n * sizeof(int));
	ccol = (int *) malloc(gicov->m * gicov->n * sizeof(int));
	for(i = 0; i < gicov->m; i++) {
		for(j = 0; j < gicov->n; j++) {
			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)))
			{
				crow[pair_counter]=i;
				ccol[pair_counter]=j;
				pair_counter++;
			}
		}
	}

	GICOV_spots = (double *) malloc(sizeof(double) * pair_counter);
	for(i = 0; i < pair_counter; i++)
		GICOV_spots[i] = sqrt(m_get_val(gicov, crow[i], ccol[i]));
	
	G = (double *) calloc(pair_counter, sizeof(double));
	x_result = (double *) calloc(pair_counter, sizeof(double));
	y_result = (double *) calloc(pair_counter, sizeof(double));
	
	x_result_len = 0;
	for (i = 0; i < pair_counter; i++) {
		if ((crow[i] > 29) && (crow[i] < BOTTOM - TOP + 39)) {
			x_result[x_result_len] = ccol[i];
			y_result[x_result_len] = crow[i] - 40;
			G[x_result_len] = GICOV_spots[i];
			x_result_len++;
		}
	}
	
	// Make an array t which holds each "time step" for the possible cells
	t = (double *) malloc(sizeof(double) * 36);
	for (i = 0; i < 36; i++) {
		t[i] = (double)i * 2.0 * PI / 36.0;
	}
	
	// Store cell boundaries (as simple circles) for all cells
	cellx = m_get(x_result_len, 36);
	celly = m_get(x_result_len, 36);
	for(i = 0; i < x_result_len; i++) {
		for(j = 0; j < 36; j++) {
			m_set_val(cellx, i, j, x_result[i] + radius * cos(t[j]));
			m_set_val(celly, i, j, y_result[i] + radius * sin(t[j]));
		}
	}
	
	A = TMatrix(9,4);
	V = (double *) malloc(sizeof(double) * pair_counter);
	QAX_CENTERS = (double * )malloc(sizeof(double) * pair_counter);
	QAY_CENTERS = (double *) malloc(sizeof(double) * pair_counter);
	memset(V, 0, sizeof(double) * pair_counter);
	memset(QAX_CENTERS, 0, sizeof(double) * pair_counter);
	memset(QAY_CENTERS, 0, sizeof(double) * pair_counter);

	// For all possible results, find the ones that are feasibly leukocytes and store their centers
	k_count = 0;
	for (n = 0; n < x_result_len; n++) {
		if ((G[n] < -1 * threshold) || G[n] > threshold) {
			MAT * x, *y;
			VEC * x_row, * y_row;
			x = m_get(1, 36);
			y = m_get(1, 36);

			x_row = v_get(36);
			y_row = v_get(36);

			// Get current values of possible cells from cellx/celly matrices
			x_row = get_row(cellx, n, x_row);
			y_row = get_row(celly, n, y_row);
			uniformseg(x_row, y_row, x, y);

			// Make sure that the possible leukocytes are not too close to the edge of the frame
			if ((m_min(x) > b) && (m_min(y) > b) && (m_max(x) < cell_file->width - b) && (m_max(y) < cell_file->height - b)) {
				MAT * Cx, * Cy, *Cy_temp, * Ix1, * Iy1;
				VEC  *Xs, *Ys, *W, *Nx, *Ny, *X, *Y;
				Cx = m_get(1, 36);
				Cy = m_get(1, 36);
				Cx = mmtr_mlt(A, x, Cx);
				Cy = mmtr_mlt(A, y, Cy);
				
				Cy_temp = m_get(Cy->m, Cy->n);
				
				for (i = 0; i < 9; i++)
					m_set_val(Cy, i, 0, m_get_val(Cy, i, 0) + 40.0);
					
				// Iteratively refine the snake/spline
				for (i = 0; i < Iter; i++) {
					int typeofcell;
					
					if(G[n] > 0.0) typeofcell = 0;
					else typeofcell = 1;
					
					splineenergyform01(Cx, Cy, grad_x, grad_y, ns, delta, 2.0 * dt, typeofcell);
				}
				
				X = getsampling(Cx, ns);
				for (i = 0; i < Cy->m; i++)
					m_set_val(Cy_temp, i, 0, m_get_val(Cy, i, 0) - 40.0);
				Y = getsampling(Cy_temp, ns);
				
				Ix1 = linear_interp2(grad_x, X, Y);
				Iy1 = linear_interp2(grad_x, X, Y);
				Xs = getfdriv(Cx, ns);
				Ys = getfdriv(Cy, ns);
				
				Nx = v_get(Ys->dim);
				for (i = 0; i < Ys->dim; i++)
					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)));
					
				Ny = v_get(Xs->dim);
				for (i = 0; i < Xs->dim; i++)
					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)));
					
				W = v_get(Nx->dim);
				for (i = 0; i < Nx->dim; i++)
					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));
					
				V[n] = mean(W) / std_dev(W);
				
				// Find the cell centers by computing the means of X and Y values for all snaxels of the spline contour
				QAX_CENTERS[k_count] = mean(X);
				QAY_CENTERS[k_count] = mean(Y) + TOP;
				
				k_count++;
				
				// Free memory
				v_free(W);
				v_free(Ny);
				v_free(Nx);
				v_free(Ys);
				v_free(Xs);
				m_free(Iy1);
				m_free(Ix1);
				v_free(Y);
				v_free(X);
				m_free(Cy_temp);
				m_free(Cy);
				m_free(Cx);				
			}

			// Free memory
			v_free(y_row);
			v_free(x_row);
			m_free(y);
			m_free(x);
		}
	}
	
	// Free memory
	free(gicov_mem);
	free(strel);
	free(V);
	free(ccol);
	free(crow);
	free(GICOV_spots);
	free(t);
	free(G);
	free(x_result);
	free(y_result);
	m_free(A);
	m_free(celly);
	m_free(cellx);
	m_free(img_dilated);
	m_free(gicov);
	m_free(grad_y);
	m_free(grad_x);
	
	// Report the total number of cells detected
	printf("Cells detected: %d\n\n", k_count);
	
	// Report the breakdown of the detection runtime
	printf("Detection runtime\n");
	printf("-----------------\n");
	printf("GICOV computation: %.5f seconds\n", ((float) (GICOV_end_time - GICOV_start_time)) / (1000*1000));
	printf("   GICOV dilation: %.5f seconds\n", ((float) (dilate_end_time - dilate_start_time)) / (1000*1000));
	printf("            Total: %.5f seconds\n", ((float) (get_time() - program_start_time)) / (1000*1000));
	
	// Now that the cells have been detected in the first frame,
	//  track the ellipses through subsequent frames
	if (num_frames > 1) printf("\nTracking cells across %d frames\n", num_frames);
	else                printf("\nTracking cells across 1 frame\n");
	long long tracking_start_time = get_time();
	int num_snaxels = 20;
	ellipsetrack(cell_file, QAX_CENTERS, QAY_CENTERS, k_count, radius, num_snaxels, num_frames);
	printf("           Total: %.5f seconds\n", ((float) (get_time() - tracking_start_time)) / (float) (1000*1000*num_frames));	
	
	// Report total program execution time
    printf("\nTotal application run time: %.5f seconds\n", ((float) (get_time() - program_start_time)) / (1000*1000));

	return 0;
}
void ellipseevolve(MAT *f, double *xc0, double *yc0, double *r0, double *t, int Np, double Er, double Ey) {
    /*
    % ELLIPSEEVOLVE evolves a parametric snake according
    %  to some energy constraints.
    %
    % INPUTS:
    %   f............potential surface
    %   xc0,yc0......initial center position
    %   r0,t.........initial radii & angle vectors (with Np elements each)
    %   Np...........number of snaxel points per snake
    %   Er...........expected radius
    %   Ey...........expected y position
    %
    % OUTPUTS
    %   xc0,yc0.......final center position
    %   r0...........final radii
    %
    % Matlab code written by: DREW GILLIAM (based on work by GANG DONG /
    %                                                        NILANJAN RAY)
    % Ported to C by: MICHAEL BOYER
    */


    // Constants
    double deltax = 0.2;
    double deltay = 0.2;
    double deltar = 0.2;
    double converge = 0.1;
    double lambdaedge = 1;
    double lambdasize = 0.2;
    double lambdapath = 0.05;
    int iterations = 1000;      // maximum number of iterations

    int i, j;

    // Initialize variables
    double xc = *xc0;
    double yc = *yc0;
    double *r = (double *) malloc(sizeof(double) * Np);
    for (i = 0; i < Np; i++) r[i] = r0[i];

    // Compute the x- and y-gradients of the MGVF matrix
    MAT *fx = gradient_x(f);
    MAT *fy = gradient_y(f);

    // Normalize the gradients
    int fh = f->m, fw = f->n;
    for (i = 0; i < fh; i++) {
        for (j = 0; j < fw; j++) {
            double temp_x = m_get_val(fx, i, j);
            double temp_y = m_get_val(fy, i, j);
            double fmag = sqrt((temp_x * temp_x) + (temp_y * temp_y));
            m_set_val(fx, i, j, temp_x / fmag);
            m_set_val(fy, i, j, temp_y / fmag);
        }
    }

    double *r_old = (double *) malloc(sizeof(double) * Np);
    VEC *x = v_get(Np);
    VEC *y = v_get(Np);


    // Evolve the snake
    int iter = 0;
    double snakediff = 1.0;
    while (iter < iterations && snakediff > converge) {

        // Save the values from the previous iteration
        double xc_old = xc, yc_old = yc;
        for (i = 0; i < Np; i++) {
            r_old[i] = r[i];
        }

        // Compute the locations of the snaxels
        for (i = 0; i < Np; i++) {
            v_set_val(x, i, xc + r[i] * cos(t[i]));
            v_set_val(y, i, yc + r[i] * sin(t[i]));
        }

        // See if any of the points in the snake are off the edge of the image
        double min_x = v_get_val(x, 0), max_x = v_get_val(x, 0);
        double min_y = v_get_val(y, 0), max_y = v_get_val(y, 0);
        for (i = 1; i < Np; i++) {
            double x_i = v_get_val(x, i);
            if (x_i < min_x) min_x = x_i;
            else if (x_i > max_x) max_x = x_i;
            double y_i = v_get_val(y, i);
            if (y_i < min_y) min_y = y_i;
            else if (y_i > max_y) max_y = y_i;
        }
        if (min_x < 0.0 || max_x > (double) fw - 1.0 || min_y < 0 || max_y > (double) fh - 1.0) break;


        // Compute the length of the snake
        double L = 0.0;
        for (i = 0; i < Np - 1; i++) {
            double diff_x = v_get_val(x, i + 1) - v_get_val(x, i);
            double diff_y = v_get_val(y, i + 1) - v_get_val(y, i);
            L += sqrt((diff_x * diff_x) + (diff_y * diff_y));
        }
        double diff_x = v_get_val(x, 0) - v_get_val(x, Np - 1);
        double diff_y = v_get_val(y, 0) - v_get_val(y, Np - 1);
        L += sqrt((diff_x * diff_x) + (diff_y * diff_y));

        // Compute the potential surface at each snaxel
        MAT *vf  = linear_interp2(f,  x, y);
        MAT *vfx = linear_interp2(fx, x, y);
        MAT *vfy = linear_interp2(fy, x, y);

        // Compute the average potential surface around the snake
        double vfmean  = sum_m(vf ) / L;
        double vfxmean = sum_m(vfx) / L;
        double vfymean = sum_m(vfy) / L;

        // Compute the radial potential surface
        int m = vf->m, n = vf->n;
        MAT *vfr = m_get(m, n);
        for (i = 0; i < n; i++) {
            double vf_val  = m_get_val(vf,  0, i);
            double vfx_val = m_get_val(vfx, 0, i);
            double vfy_val = m_get_val(vfy, 0, i);
            double x_val = v_get_val(x, i);
            double y_val = v_get_val(y, i);
            double new_val = (vf_val + vfx_val * (x_val - xc) + vfy_val * (y_val - yc) - vfmean) / L;
            m_set_val(vfr, 0, i, new_val);
        }

        // Update the snake center and snaxels
        xc =  xc + (deltax * lambdaedge * vfxmean);
        yc = (yc + (deltay * lambdaedge * vfymean) + (deltay * lambdapath * Ey)) / (1.0 + deltay * lambdapath);
        double r_diff = 0.0;
        for (i = 0; i < Np; i++) {
            r[i] = (r[i] + (deltar * lambdaedge * m_get_val(vfr, 0, i)) + (deltar * lambdasize * Er)) /
                   (1.0 + deltar * lambdasize);
            r_diff += fabs(r[i] - r_old[i]);
        }

        // Test for convergence
        snakediff = fabs(xc - xc_old) + fabs(yc - yc_old) + r_diff;

        // Free temporary matrices
        m_free(vf);
        m_free(vfx);
        m_free(vfy);
        m_free(vfr);

        iter++;
    }

    // Set the return values
    *xc0 = xc;
    *yc0 = yc;
    for (i = 0; i < Np; i++)
        r0[i] = r[i];

    // Free memory
    free(r);
    free(r_old);
    v_free( x);
    v_free( y);
    m_free(fx);
    m_free(fy);
}
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));
}
Beispiel #7
0
template <typename PointInT, typename PointOutT> void
pcl::IntegralImageNormalEstimation<PointInT, PointOutT>::computePointNormalMirror (
    const int pos_x, const int pos_y, const unsigned point_index, PointOutT &normal)
{
  float bad_point = std::numeric_limits<float>::quiet_NaN ();

  const int width = input_->width;
  const int height = input_->height;

  // ==============================================================
  if (normal_estimation_method_ == COVARIANCE_MATRIX) 
  {
    if (!init_covariance_matrix_)
      initCovarianceMatrixMethod ();

    const int start_x = pos_x - rect_width_2_;
    const int start_y = pos_y - rect_height_2_;
    const int end_x = start_x + rect_width_;
    const int end_y = start_y + rect_height_;

    unsigned count = 0;
    sumArea<unsigned>(start_x, start_y, end_x, end_y, width, height, boost::bind(&IntegralImage2D<float, 3>::getFiniteElementsCountSE, &integral_image_XYZ_, _1, _2, _3, _4), count);
    
    // no valid points within the rectangular reagion?
    if (count == 0)
    {
      normal.normal_x = normal.normal_y = normal.normal_z = normal.curvature = bad_point;
      return;
    }

    EIGEN_ALIGN16 Eigen::Matrix3f covariance_matrix;
    Eigen::Vector3f center;
    typename IntegralImage2D<float, 3>::SecondOrderType so_elements;
    typename IntegralImage2D<float, 3>::ElementType tmp_center;
    typename IntegralImage2D<float, 3>::SecondOrderType tmp_so_elements;

    center[0] = 0;
    center[1] = 0;
    center[2] = 0;
    tmp_center[0] = 0;
    tmp_center[1] = 0;
    tmp_center[2] = 0;
    so_elements[0] = 0;
    so_elements[1] = 0;
    so_elements[2] = 0;
    so_elements[3] = 0;
    so_elements[4] = 0;
    so_elements[5] = 0;

    sumArea<typename IntegralImage2D<float, 3>::ElementType>(start_x, start_y, end_x, end_y, width, height, boost::bind(&IntegralImage2D<float, 3>::getFirstOrderSumSE, &integral_image_XYZ_, _1, _2, _3, _4), tmp_center);
    sumArea<typename IntegralImage2D<float, 3>::SecondOrderType>(start_x, start_y, end_x, end_y, width, height, boost::bind(&IntegralImage2D<float, 3>::getSecondOrderSumSE, &integral_image_XYZ_, _1, _2, _3, _4), so_elements);

    center[0] = float (tmp_center[0]);
    center[1] = float (tmp_center[1]);
    center[2] = float (tmp_center[2]);

    covariance_matrix.coeffRef (0) = static_cast<float> (so_elements [0]);
    covariance_matrix.coeffRef (1) = covariance_matrix.coeffRef (3) = static_cast<float> (so_elements [1]);
    covariance_matrix.coeffRef (2) = covariance_matrix.coeffRef (6) = static_cast<float> (so_elements [2]);
    covariance_matrix.coeffRef (4) = static_cast<float> (so_elements [3]);
    covariance_matrix.coeffRef (5) = covariance_matrix.coeffRef (7) = static_cast<float> (so_elements [4]);
    covariance_matrix.coeffRef (8) = static_cast<float> (so_elements [5]);
    covariance_matrix -= (center * center.transpose ()) / static_cast<float> (count);
    float eigen_value;
    Eigen::Vector3f eigen_vector;
    pcl::eigen33 (covariance_matrix, eigen_value, eigen_vector);
    flipNormalTowardsViewpoint (input_->points[point_index], vpx_, vpy_, vpz_, eigen_vector[0], eigen_vector[1], eigen_vector[2]);
    normal.getNormalVector3fMap () = eigen_vector;

    // Compute the curvature surface change
    if (eigen_value > 0.0)
      normal.curvature = fabsf (eigen_value / (covariance_matrix.coeff (0) + covariance_matrix.coeff (4) + covariance_matrix.coeff (8)));
    else
      normal.curvature = 0;

    return;
  }
  // =======================================================
  else if (normal_estimation_method_ == AVERAGE_3D_GRADIENT) 
  {
    if (!init_average_3d_gradient_)
      initAverage3DGradientMethod ();

    const int start_x = pos_x - rect_width_2_;
    const int start_y = pos_y - rect_height_2_;
    const int end_x = start_x + rect_width_;
    const int end_y = start_y + rect_height_;

    unsigned count_x = 0;
    unsigned count_y = 0;

    sumArea<unsigned>(start_x, start_y, end_x, end_y, width, height, boost::bind(&IntegralImage2D<float, 3>::getFiniteElementsCountSE, &integral_image_DX_, _1, _2, _3, _4), count_x);
    sumArea<unsigned>(start_x, start_y, end_x, end_y, width, height, boost::bind(&IntegralImage2D<float, 3>::getFiniteElementsCountSE, &integral_image_DY_, _1, _2, _3, _4), count_y);


    if (count_x == 0 || count_y == 0)
    {
      normal.normal_x = normal.normal_y = normal.normal_z = normal.curvature = bad_point;
      return;
    }
    Eigen::Vector3d gradient_x (0, 0, 0);
    Eigen::Vector3d gradient_y (0, 0, 0);

    sumArea<typename IntegralImage2D<float, 3>::ElementType>(start_x, start_y, end_x, end_y, width, height, boost::bind(&IntegralImage2D<float, 3>::getFirstOrderSumSE, &integral_image_DX_, _1, _2, _3, _4), gradient_x);
    sumArea<typename IntegralImage2D<float, 3>::ElementType>(start_x, start_y, end_x, end_y, width, height, boost::bind(&IntegralImage2D<float, 3>::getFirstOrderSumSE, &integral_image_DY_, _1, _2, _3, _4), gradient_y);


    Eigen::Vector3d normal_vector = gradient_y.cross (gradient_x);
    double normal_length = normal_vector.squaredNorm ();
    if (normal_length == 0.0f)
    {
      normal.getNormalVector3fMap ().setConstant (bad_point);
      normal.curvature = bad_point;
      return;
    }

    normal_vector /= sqrt (normal_length);

    float nx = static_cast<float> (normal_vector [0]);
    float ny = static_cast<float> (normal_vector [1]);
    float nz = static_cast<float> (normal_vector [2]);

    flipNormalTowardsViewpoint (input_->points[point_index], vpx_, vpy_, vpz_, nx, ny, nz);

    normal.normal_x = nx;
    normal.normal_y = ny;
    normal.normal_z = nz;
    normal.curvature = bad_point;
    return;
  }
  // ======================================================
  else if (normal_estimation_method_ == AVERAGE_DEPTH_CHANGE) 
  {
    if (!init_depth_change_)
      initAverageDepthChangeMethod ();

    int point_index_L_x = pos_x - rect_width_4_ - 1;
    int point_index_L_y = pos_y;
    int point_index_R_x = pos_x + rect_width_4_ + 1;
    int point_index_R_y = pos_y;
    int point_index_U_x = pos_x - 1;
    int point_index_U_y = pos_y - rect_height_4_;
    int point_index_D_x = pos_x + 1;
    int point_index_D_y = pos_y + rect_height_4_;

    if (point_index_L_x < 0)
      point_index_L_x = -point_index_L_x;
    if (point_index_U_x < 0)
      point_index_U_x = -point_index_U_x;
    if (point_index_U_y < 0)
      point_index_U_y = -point_index_U_y;

    if (point_index_R_x >= width)
      point_index_R_x = width-(point_index_R_x-(width-1));
    if (point_index_D_x >= width)
      point_index_D_x = width-(point_index_D_x-(width-1));
    if (point_index_D_y >= height)
      point_index_D_y = height-(point_index_D_y-(height-1));

    const int start_x_L = pos_x - rect_width_2_;
    const int start_y_L = pos_y - rect_height_4_;
    const int end_x_L = start_x_L + rect_width_2_;
    const int end_y_L = start_y_L + rect_height_2_;

    const int start_x_R = pos_x + 1;
    const int start_y_R = pos_y - rect_height_4_;
    const int end_x_R = start_x_R + rect_width_2_;
    const int end_y_R = start_y_R + rect_height_2_;

    const int start_x_U = pos_x - rect_width_4_;
    const int start_y_U = pos_y - rect_height_2_;
    const int end_x_U = start_x_U + rect_width_2_;
    const int end_y_U = start_y_U + rect_height_2_;

    const int start_x_D = pos_x - rect_width_4_;
    const int start_y_D = pos_y + 1;
    const int end_x_D = start_x_D + rect_width_2_;
    const int end_y_D = start_y_D + rect_height_2_;

    unsigned count_L_z = 0;
    unsigned count_R_z = 0;
    unsigned count_U_z = 0;
    unsigned count_D_z = 0;

    sumArea<unsigned>(start_x_L, start_y_L, end_x_L, end_y_L, width, height, boost::bind(&IntegralImage2D<float, 1>::getFiniteElementsCountSE, &integral_image_depth_, _1, _2, _3, _4), count_L_z);
    sumArea<unsigned>(start_x_R, start_y_R, end_x_R, end_y_R, width, height, boost::bind(&IntegralImage2D<float, 1>::getFiniteElementsCountSE, &integral_image_depth_, _1, _2, _3, _4), count_R_z);
    sumArea<unsigned>(start_x_U, start_y_U, end_x_U, end_y_U, width, height, boost::bind(&IntegralImage2D<float, 1>::getFiniteElementsCountSE, &integral_image_depth_, _1, _2, _3, _4), count_U_z);
    sumArea<unsigned>(start_x_D, start_y_D, end_x_D, end_y_D, width, height, boost::bind(&IntegralImage2D<float, 1>::getFiniteElementsCountSE, &integral_image_depth_, _1, _2, _3, _4), count_D_z);

    if (count_L_z == 0 || count_R_z == 0 || count_U_z == 0 || count_D_z == 0)
    {
      normal.normal_x = normal.normal_y = normal.normal_z = normal.curvature = bad_point;
      return;
    }

    float mean_L_z = 0;
    float mean_R_z = 0;
    float mean_U_z = 0;
    float mean_D_z = 0;

    sumArea<float>(start_x_L, start_y_L, end_x_L, end_y_L, width, height, boost::bind(&IntegralImage2D<float, 1>::getFirstOrderSumSE, &integral_image_depth_, _1, _2, _3, _4), mean_L_z);
    sumArea<float>(start_x_R, start_y_R, end_x_R, end_y_R, width, height, boost::bind(&IntegralImage2D<float, 1>::getFirstOrderSumSE, &integral_image_depth_, _1, _2, _3, _4), mean_R_z);
    sumArea<float>(start_x_U, start_y_U, end_x_U, end_y_U, width, height, boost::bind(&IntegralImage2D<float, 1>::getFirstOrderSumSE, &integral_image_depth_, _1, _2, _3, _4), mean_U_z);
    sumArea<float>(start_x_D, start_y_D, end_x_D, end_y_D, width, height, boost::bind(&IntegralImage2D<float, 1>::getFirstOrderSumSE, &integral_image_depth_, _1, _2, _3, _4), mean_D_z);

    mean_L_z /= float (count_L_z);
    mean_R_z /= float (count_R_z);
    mean_U_z /= float (count_U_z);
    mean_D_z /= float (count_D_z);


    PointInT pointL = input_->points[point_index_L_y*width + point_index_L_x];
    PointInT pointR = input_->points[point_index_R_y*width + point_index_R_x];
    PointInT pointU = input_->points[point_index_U_y*width + point_index_U_x];
    PointInT pointD = input_->points[point_index_D_y*width + point_index_D_x];

    const float mean_x_z = mean_R_z - mean_L_z;
    const float mean_y_z = mean_D_z - mean_U_z;

    const float mean_x_x = pointR.x - pointL.x;
    const float mean_x_y = pointR.y - pointL.y;
    const float mean_y_x = pointD.x - pointU.x;
    const float mean_y_y = pointD.y - pointU.y;

    float normal_x = mean_x_y * mean_y_z - mean_x_z * mean_y_y;
    float normal_y = mean_x_z * mean_y_x - mean_x_x * mean_y_z;
    float normal_z = mean_x_x * mean_y_y - mean_x_y * mean_y_x;

    const float normal_length = (normal_x * normal_x + normal_y * normal_y + normal_z * normal_z);

    if (normal_length == 0.0f)
    {
      normal.getNormalVector3fMap ().setConstant (bad_point);
      normal.curvature = bad_point;
      return;
    }

    flipNormalTowardsViewpoint (input_->points[point_index], vpx_, vpy_, vpz_, normal_x, normal_y, normal_z);
    
    const float scale = 1.0f / sqrtf (normal_length);

    normal.normal_x = normal_x * scale;
    normal.normal_y = normal_y * scale;
    normal.normal_z = normal_z * scale;
    normal.curvature = bad_point;

    return;
  }
  // ========================================================
  else if (normal_estimation_method_ == SIMPLE_3D_GRADIENT) 
  {
    PCL_THROW_EXCEPTION (PCLException, "BORDER_POLICY_MIRROR not supported for normal estimation method SIMPLE_3D_GRADIENT");
  }

  normal.getNormalVector3fMap ().setConstant (bad_point);
  normal.curvature = bad_point;
  return;
}
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);
}
Beispiel #9
-1
ImageRAII canny( IplImage * image, std::pair< int, int > thresh, double sigma )
{
	const char * WINDOW_NAME = "Basic Canny Edge Detector";

	ImageRAII grayscale( cvCreateImage( cvGetSize( image ), image->depth, 1 ) );
	ImageRAII destination( cvCreateImage( cvGetSize( image ), image->depth, grayscale.image->nChannels ) );
	ImageRAII gaussian( cvCreateImage( cvGetSize( image ), image->depth, grayscale.image->nChannels ) );
	ImageRAII gradient_x( cvCreateImage( cvGetSize( image ), image->depth, grayscale.image->nChannels ) );
	ImageRAII gradient_y( cvCreateImage( cvGetSize( image ), image->depth, grayscale.image->nChannels ) );
	ImageRAII gradient( cvCreateImage( cvGetSize( image ), image->depth, grayscale.image->nChannels ) );
	ImageRAII orientation( cvCreateImage( cvGetSize( image ), image->depth, grayscale.image->nChannels ) );

	// convert image to grayscale
	cvCvtColor( image, grayscale.image, CV_BGR2GRAY );

	// gaussian smoothing
	cvSmooth( grayscale.image, gaussian.image, CV_GAUSSIAN, GAUSSIAN_X, GAUSSIAN_Y, sigma );
	// find edge strength
	cvSobel( gaussian.image, gradient_x.image, 1, 0, 3 );
	cvSobel( gaussian.image, gradient_y.image, 0, 1, 3 );
	// find edge orientation
	CvSize image_size = cvGetSize( gaussian.image );

	for( int i = 0; i < image_size.width; i++ )
	{
		for( int j = 0; j < image_size.height; j++ )
		{
			double x = cvGet2D( gradient_x.image, j, i ).val[0];
			double y = cvGet2D( gradient_y.image, j, i ).val[0];
			float angle;

			if( x == 0 )
			{
				if( y == 0 )
					angle = 0;
				else
					angle = 90;
			}
			else
				angle = cvFastArctan( y, x );

			CvScalar g;
			CvScalar a;
		   	g.val[0] = cvSqrt( pow( x, 2 ) + pow( y, 2 ) );
			a.val[0] = find_angle( angle );

			cvSet2D( destination.image, j, i, g );
			cvSet2D( orientation.image, j, i, a );
		}
	}

	ImageRAII suppressed_image = nonMaxSup( destination.image, orientation.image );
	ImageRAII hysteresis_image = hysteresis( suppressed_image.image, orientation.image, thresh );

	cvNamedWindow( WINDOW_NAME );
	cvShowImage( WINDOW_NAME, destination.image );
	cvMoveWindow( WINDOW_NAME, image_size.width, 0 );

	return hysteresis_image;
}