示例#1
0
/*  num_deriv_exterior() calculates the partial numerical derivative of image
    coordinates of a given 3D position, over each of the 6 exterior orientation
    parameters (3 position parameters, 3 rotation angles).

    Arguments:
    Calibration* cal_in  -      camera calibration object
    control_par *cpar -     control parameters

    double dpos, double dang - the step size for numerical differentiation,
        dpos for the metric variables, dang for the angle variables. Units
        are same as the units of the variables derived.
    vec3d pos - the current 3D position represented on the image.
    
    Return parameters:
    double x_ders[6], y_ders[6] respectively the derivatives of the x and y
        image coordinates as function of each of the orientation parameters.
 */
void num_deriv_exterior(Calibration* cal, control_par *cpar, double dpos, double dang, vec3d pos,
    double x_ders[6], double y_ders[6])
{
    int pd; 
    double step, xs, ys, xpd, ypd;
    double* vars[6];
    
    vars[0] = &(cal->ext_par.x0);
    vars[1] = &(cal->ext_par.y0);
    vars[2] = &(cal->ext_par.z0);
    vars[3] = &(cal->ext_par.omega);
    vars[4] = &(cal->ext_par.phi);
    vars[5] = &(cal->ext_par.kappa);
    
    /* Starting image position */
    rotation_matrix(&(cal->ext_par));
    img_coord (pos, cal, cpar->mm, &xs, &ys);
    
    for (pd = 0; pd < 6; pd++) {
        step = (pd > 2) ? dang : dpos;
        
        *(vars[pd]) += step;
        if (pd > 2) rotation_matrix(&(cal->ext_par));
        img_coord (pos, cal, cpar->mm, &xpd, &ypd);
        x_ders[pd] = (xpd - xs) / step;
        y_ders[pd] = (ypd - ys) / step;
        *(vars[pd]) -= step;
    }
    rotation_matrix(&(cal->ext_par));
}
示例#2
0
文件: ttools.c 项目: 3dptv/3dptv
void searchquader(double X, double Y, double Z, 
				  double xr[4], double xl[4], double yd[4], double yu[4])
{
	int    k, i;
	double x, y, xz, yz;
	coord_3d quader[8], point;

	/* project quader in image space to define search area */
	for (k=0; k<8; k++)
	{
		quader[k].pnr=k;
	}
	/* calculation of quader points */
	point.pnr=0; point.x=X; point.y=Y; point.z=Z;

	quader[0].x=X+tpar.dvxmin; quader[0].y=Y+tpar.dvymin; quader[0].z=Z+tpar.dvzmin; /* --- */
	quader[1].x=X+tpar.dvxmax; quader[1].y=Y+tpar.dvymin; quader[1].z=Z+tpar.dvzmin; /* +-- */
	quader[2].x=X+tpar.dvxmin; quader[2].y=Y+tpar.dvymax; quader[2].z=Z+tpar.dvzmin; /* -+- */
	quader[3].x=X+tpar.dvxmin; quader[3].y=Y+tpar.dvymin; quader[3].z=Z+tpar.dvzmax; /* --+ */ //changed by Beat and JuliAn Nov 2008
	quader[4].x=X+tpar.dvxmax; quader[4].y=Y+tpar.dvymax; quader[4].z=Z+tpar.dvzmin; /* ++- */
	quader[5].x=X+tpar.dvxmax; quader[5].y=Y+tpar.dvymin; quader[5].z=Z+tpar.dvzmax; /* +-+ */
	quader[6].x=X+tpar.dvxmin; quader[6].y=Y+tpar.dvymax; quader[6].z=Z+tpar.dvzmax; /* -++ */
	quader[7].x=X+tpar.dvxmax; quader[7].y=Y+tpar.dvymax; quader[7].z=Z+tpar.dvzmax; /* +++ */

	/* calculation of search area */
	for (i=0; i<n_img; i++)
	{
		xr[i]=0;
		xl[i]=imx;
		yd[i]=0;
		yu[i]=imy;
		img_coord (point.x, point.y, point.z, Ex[i], I[i], G[i], ap[i], mmp, &xz,&yz);
		metric_to_pixel (xz,yz, imx,imy, pix_x,pix_y, &xz,&yz, chfield);

		for (k=0; k<8; k++)
		{
			img_coord (quader[k].x, quader[k].y, quader[k].z, Ex[i], I[i], G[i], ap[i], mmp, &x,&y);
			metric_to_pixel (x,y, imx,imy, pix_x,pix_y, &x,&y, chfield);

			if (x <xl[i] ) xl[i]=x;
			if (y <yu[i] ) yu[i]=y;
			if (x >xr[i] ) xr[i]=x;
			if (y >yd[i] ) yd[i]=y;
		}
		if (xl[i] < 0 ) xl[i]=0;
		if (yu[i] < 0 ) yu[i]=0;
		if (xr[i] > imx) xr[i]=imx;
		if (yd[i] > imy) yd[i]=imy;

		xr[i]=xr[i]-xz;
		xl[i]=xz-xl[i];
		yd[i]=yd[i]-yz;
		yu[i]=yz-yu[i];
	}
	return;
}
示例#3
0
END_TEST

START_TEST(test_point_position)
{
    /* Generate target information based on a known point. In the simple case,
       calculated point must equal known point and average ray distance == 0.
       Then jigg the cameras symmetrically to get the same points again but 
       with an analytically derivable ray distance. */
    
    int cam, num_cams = 4;
    vec2d targs_plain[4], targs_jigged[4];
    
    Calibration *calib[4];
    char ori_tmpl[] = "cal/sym_cam%d.tif.ori";
    char ori_name[25];
    mm_np media_par = {1, 1., {1., 0., 0.}, {1., 0., 0.}, 1.};
    
    vec3d point = {17, 42, 0}; /* Something in the FOV, non-symmetric. */
    vec3d res, jigged;
    double jigg_amp = 0.5, skew_dist, jigged_correct;
    
    /* Target generation requires an existing calibration. */
    chdir("testing_fodder/");
    
    /* Four cameras on 4 quadrants. */
    for (cam = 0; cam < num_cams; cam++) {
        sprintf(ori_name, ori_tmpl, cam + 1);
        calib[cam] = read_calibration(ori_name, "cal/cam1.tif.addpar", NULL);
        
        img_coord(point, calib[cam], &media_par, 
            &(targs_plain[cam][0]), &(targs_plain[cam][1]));
        
        vec_copy(jigged, point);
        jigged[1] += ((cam % 2) ? jigg_amp : -jigg_amp);
        img_coord(jigged, calib[cam], &media_par, 
            &(targs_jigged[cam][0]), &(targs_jigged[cam][1]));
    }
    
    skew_dist = point_position(targs_plain, num_cams, &media_par, calib, res);
    fail_unless(skew_dist < 1e-10);
    vec_subt(point, res, res);
    fail_unless(vec_norm(res) < 1e-10);
    
    skew_dist = point_position(targs_jigged, num_cams, &media_par, calib, res);
    jigged_correct = 4*(2*jigg_amp)/6;
    /* two thirds, but because of details: each disagreeing pair (4 out of 6) 
       has a 2*jigg_amp error because the cameras are moved in opposite
       directions. */
    fail_unless(fabs(skew_dist - jigged_correct) < 0.05);
    vec_subt(point, res, res);
    fail_unless(vec_norm(res) < 0.01);
}
示例#4
0
END_TEST

START_TEST(test_convergence_measure)
{
    /* Generate target information based on known points. In the simple case,
       convergence will be spot-on. Then generate other targets based on a 
       per-camera jigging of 3D points and get convergence measure compatible 
       with the jig amplitude. */
    
    vec3d known[16], jigged;
    vec2d* targets[16];
    Calibration *calib[4];
    
    int num_cams = 4, num_pts = 16;
    int cam, cpt_vert, cpt_horz, cpt_ix;
    double jigg_amp = 0.5, jigged_skew_dist, jigged_correct;
    
    char ori_tmpl[] = "cal/sym_cam%d.tif.ori";
    char ori_name[25];
    
    /* Using a neutral medium, this isn't what's tested. */
    mm_np media_par = {1, 1., {1., 0., 0.}, {1., 0., 0.}, 1.};
    control_par *cpar;
    
    /* Target generation requires an existing calibration. */
    chdir("testing_fodder/");
    cpar = read_control_par("parameters/ptv.par");
    
    /* Four cameras on 4 quadrants looking down into a calibration target.
       Calibration taken from an actual experimental setup */
    for (cam = 0; cam < num_cams; cam++) {
        sprintf(ori_name, ori_tmpl, cam + 1);
        calib[cam] = read_calibration(ori_name, "cal/cam1.tif.addpar", NULL);
    }
    
    /* Reference points before jigging: */
    for (cpt_horz = 0; cpt_horz < 4; cpt_horz++) {
        for (cpt_vert = 0; cpt_vert < 4; cpt_vert++) {
            cpt_ix = cpt_horz*4 + cpt_vert;
            vec_set(known[cpt_ix], cpt_vert * 10, cpt_horz * 10, 0);
        }
    }
    
    /* Plain case: */
    for (cpt_ix = 0; cpt_ix < num_pts; cpt_ix++) {
        targets[cpt_ix] = (vec2d *) calloc(num_cams, sizeof(vec2d));
        
        for (cam = 0; cam < num_cams; cam++) {
            img_coord(known[cpt_ix], calib[cam], &media_par, 
                &(targets[cpt_ix][cam][0]), 
                &(targets[cpt_ix][cam][1]));
        }
    }
    fail_unless(fabs(weighted_dumbbell_precision(
        targets, 16, num_cams, &media_par, calib, 1, 0)) < 1e-10);
    /* With dumbbell length: */
    fail_unless(fabs(weighted_dumbbell_precision(
        targets, 16, num_cams, &media_par, calib, 10, 10)) < 1e-10);
    
    /* Jigged case (reusing target memory), moving the points and cameras 
       in parallel to create a known shift between parallel rays. */
    for (cam = 0; cam < num_cams; cam++) {
        calib[cam]->ext_par.y0 += ((cam % 2) ? jigg_amp : -jigg_amp);
        
        for (cpt_ix = 0; cpt_ix < num_pts; cpt_ix++) {
            vec_copy(jigged, known[cpt_ix]);
            jigged[1] += ((cam % 2) ? jigg_amp : -jigg_amp);
            
            img_coord(jigged, calib[cam], &media_par, 
                &(targets[cpt_ix][cam][0]), 
                &(targets[cpt_ix][cam][1]));
        }
    }
    jigged_skew_dist = weighted_dumbbell_precision(
        targets, 16, num_cams, &media_par, calib, 1, 0);
    jigged_correct = 16*4*(2*jigg_amp)/(16*6); 
    /* two thirds, but because of details: each disagreeing pair (4 out of 6) 
       has a 2*jigg_amp error because the cameras are moved in opposite
       directions. */
    fail_unless(fabs(jigged_skew_dist - jigged_correct) < 0.05 );
}
示例#5
0
文件: track.c 项目: yosefm/openptv
/* point_to_pixel is just a shortcut to two lines that repeat every so in track loop
 * img_coord (from 3d point to a 2d vector in metric units), followed by
 * metric_to_pixel (from 2d vector in metric units to the pixel position in the camera)
 * Arguments:
 * vec3d point in 3D space
 * Calibration *cal parameters
 * Control parameters (num cams, multimedia parameters, cpar->mm, etc.)
 * Returns (as a first argument):
 * vec2d with pixel positions (x,y) in the camera.
 */
void point_to_pixel (vec2d v1, vec3d point, Calibration *cal, control_par *cpar){
    img_coord(point, cal, cpar->mm, &v1[0], &v1[1]);
    metric_to_pixel(&v1[0], &v1[1], v1[0], v1[1], cpar);
}
示例#6
0
/*     track backwards */
void trackback_c ()
{
    char  buf[256];
    int i, j, h, k, step, invol=0;
    int zaehler1, philf[4][MAX_CANDS];
    int count1=0, count2=0, zusatz=0;
    int quali=0;
    double x2[4], y2[4], angle, acc, lmax, dl;
    double xr[4], xl[4], yd[4], yu[4];
    vec3d diff_pos, X[7]; /* 7 reference points used in the algorithm, TODO: check if can reuse some */
    double xn[4], yn[4];
    double rr, Ymin=0, Ymax=0;
    double npart=0, nlinks=0;
    foundpix *w, p16[4*MAX_CANDS];

    sequence_par *seq_par;
    track_par *tpar;
    volume_par *vpar;
    control_par *cpar;
    framebuf *fb;
    
    /* Shortcuts to inside current frame */
    P *curr_path_inf, *ref_path_inf;
    corres *ref_corres;
    target **ref_targets;
    int _ix; /* For use in any of the complex index expressions below */
    int _frame_parts; /* number of particles in a frame */
    
    display = 1; 
    /* read data */
    seq_par = read_sequence_par("parameters/sequence.par", 4);
    tpar = read_track_par("parameters/track.par");
    vpar = read_volume_par("parameters/criteria.par");
    cpar = read_control_par("parameters/ptv.par");

    fb = (framebuf *) malloc(sizeof(framebuf));
    fb_init(fb, 4, cpar->num_cams, MAX_TARGETS, 
        "res/rt_is", "res/ptv_is", "res/added", seq_par->img_base_name);

    /* Prime the buffer with first frames */
    for (step = seq_par->last; step > seq_par->last - 4; step--) {
        fb_read_frame_at_end(fb, step, 1);
        fb_next(fb);
    }
    fb_prev(fb);
    
    lmax = norm((tpar->dvxmin - tpar->dvxmax), (tpar->dvymin - tpar->dvymax),
	    (tpar->dvzmin - tpar->dvzmax));
    volumedimension (glob_cal, &(vpar->X_lay[1]), &(vpar->X_lay[0]), &Ymax,
        &Ymin, &(vpar->Zmax_lay[1]), &(vpar->Zmin_lay[0]), cpar);

    /* sequence loop */
    for (step = seq_par->last - 1; step > seq_par->first; step--) {
        sprintf (buf, "Time step: %d, seqnr: %d, Particle info:",
            step - seq_par->first, step);
        
        for (h = 0; h < fb->buf[1]->num_parts; h++) {
            curr_path_inf = &(fb->buf[1]->path_info[h]);
            
            /* We try to find link only if the forward search failed to. */ 
            if ((curr_path_inf->next < 0) || (curr_path_inf->prev != -1)) continue;

            for (j = 0; j < 7; j++) vec_init(X[j]);
            curr_path_inf->inlist = 0;
            reset_foundpix_array(p16, 16, fb->num_cams);
            
            /* 3D-position of current particle */
            vec_copy(X[1], curr_path_inf->x);
            
            /* use information from previous to locate new search position
            and to calculate values for search area */
            ref_path_inf = &(fb->buf[0]->path_info[curr_path_inf->next]);
	        vec_copy(X[0], ref_path_inf->x);
            search_volume_center_moving(ref_path_inf->x, curr_path_inf->x, X[2]);

            for (j=0; j < fb->num_cams; j++) {   
                img_coord (j, X[2][0], X[2][1], X[2][2], Ex[j],I[j], G[j], ap[j],
                    *(cpar->mm), &xn[j], &yn[j]);
                metric_to_pixel(&xn[j], &yn[j], xn[j], yn[j], cpar);
            }

            /* calculate searchquader and reprojection in image space */
            searchquader(X[2][0], X[2][1], X[2][2], xr, xl, yd, yu, tpar, cpar);

            for (j = 0; j < fb->num_cams; j++) {
                zaehler1 = candsearch_in_pix (
                    fb->buf[2]->targets[j], fb->buf[2]->num_targets[j], xn[j], yn[j],
                    xl[j], xr[j], yu[j], yd[j], philf[j], cpar);

                for(k=0; k<4; k++) {
                    if( zaehler1>0) {
                        if (philf[j][k] == -999){
                            p16[j*4+k].ftnr=-1;
                        } else {
                            p16[j*4+k].ftnr=fb->buf[3]->targets[j][philf[j][k]].tnr;
                            p16[j*4+k].whichcam[j]=1;
                        }
                    }
                }
            }
            /* search in pix for candidates in next time step */
            //for (j = 0; j < fb->num_cams; j++) { 
            //    register_closest_neighbs(fb->buf[2]->targets[j],
            //        fb->buf[2]->num_targets[j], j, xn[j], yn[j],
            //        xl[j], xr[j], yu[j], yd[j], &p16[j*MAX_CANDS]);
            //}

            /* fill and sort candidate struct */
            sortwhatfound(p16, &zaehler1, fb->num_cams);
            w = (foundpix *) calloc (zaehler1, sizeof (foundpix));

            /*end of candidate struct */
            if (zaehler1 > 0) count2++;
            copy_foundpix_array(w, p16, zaehler1, fb->num_cams);

            for (i = 0; i < zaehler1; i++) {
                ref_path_inf = &(fb->buf[2]->path_info[w[i].ftnr]);
                vec_copy(X[3], ref_path_inf->x);

                vec_subt(X[1], X[3], diff_pos);
                if (pos3d_in_bounds(diff_pos, tpar)) {
                    angle_acc(X[1], X[2], X[3], &angle, &acc);

                    /* *********************check link *****************************/
                    if ((acc < tpar->dacc && angle < tpar->dangle) || \
                        (acc < tpar->dacc/10))
                    {
                        dl = (vec_diff_norm(X[1], X[3]) + 
                            vec_diff_norm(X[0], X[1]) )/2;
                        quali=w[i].freq;
                        rr = (dl/lmax + acc/tpar->dacc + angle/tpar->dangle)/quali;
                        register_link_candidate(curr_path_inf, rr, w[i].ftnr);
                    }
                }
            }

            free(w);
            /******************/
            quali=0;

            /* reset img coord because num_cams < 4 */
            for (j=0;j<4;j++) { x2[j]=-1e10; y2[j]=-1e10;}

            /* if old wasn't found try to create new particle position from rest */
            if (tpar->add) {
                if ( curr_path_inf->inlist == 0) {
                    for (j = 0; j < fb->num_cams; j++) {
                        /* use fix distance to define xl, xr, yu, yd instead of searchquader */
                        xl[j]= xr[j]= yu[j]= yd[j] = 3.0;

                        zaehler1 = candsearch_in_pixrest (fb->buf[2]->targets[j], 
                            fb->buf[2]->num_targets[j], xn[j], yn[j],
                            xl[j], xr[j], yu[j], yd[j], philf[j], cpar);
                        if(zaehler1 > 0) {
                            _ix = philf[j][0];
                            x2[j] = fb->buf[2]->targets[j][_ix].x;
                            y2[j] = fb->buf[2]->targets[j][_ix].y;
                        }
                    }

                    for (j = 0; j < fb->num_cams; j++) {
                        if (x2[j] !=-1e10 && y2[j] != -1e10) {
                            pixel_to_metric(&x2[j], &y2[j], x2[j],y2[j], cpar); 
                            quali++;
                        }
                    }

                    if (quali>=2) {
                        vec_copy(X[3], X[2]);
                        invol=0;

                        det_lsq_3d (glob_cal, *(cpar->mm),
                            x2[0], y2[0], x2[1], y2[1], x2[2], y2[2], x2[3], y2[3],
                            &(X[3][0]), &(X[3][1]), &(X[3][2]), fb->num_cams);

                        /* volume check */
                        if ( vpar->X_lay[0] < X[3][0] && X[3][0] < vpar->X_lay[1] &&
                            Ymin < X[3][1] && X[3][1] < Ymax &&
                            vpar->Zmin_lay[0] < X[3][2] && X[3][2] < vpar->Zmax_lay[1]) 
                                {invol = 1;}

                        vec_subt(X[1], X[3], diff_pos);
                        if (invol == 1 && pos3d_in_bounds(diff_pos, tpar)) { 
                            angle_acc(X[1], X[2], X[3], &angle, &acc);

                            if ( (acc<tpar->dacc && angle<tpar->dangle) || \
                                (acc<tpar->dacc/10) ) 
                            {
                                dl = (vec_diff_norm(X[1], X[3]) + 
                                    vec_diff_norm(X[0], X[1]) )/2;
                                rr =(dl/lmax+acc/tpar->dacc + angle/tpar->dangle)/(quali);

                                ref_path_inf = &(fb->buf[2]->path_info[
                                    fb->buf[2]->num_parts]);
                                vec_copy(ref_path_inf->x, X[3]);
                                reset_links(ref_path_inf);

                                _frame_parts = fb->buf[2]->num_parts;
                                register_link_candidate(curr_path_inf, rr,
                                    _frame_parts);
                                
                                ref_corres = &(fb->buf[2]->correspond[_frame_parts]);
                                ref_targets = fb->buf[2]->targets;

                                for (j = 0;j < fb->num_cams; j++) {
                                    ref_corres->p[j]=-1;
                                    
                                    if(philf[j][0]!=-999) {
                                        _ix = philf[j][0];
                                        ref_targets[j][_ix].tnr = _frame_parts;
                                        ref_corres->p[j] = _ix;
                                        ref_corres->nr = _frame_parts;
                                    }
                                }
                                fb->buf[2]->num_parts++;
                            }
                        }
                        invol=0;
                    }
                }
            } /* end of if old wasn't found try to create new particle position from rest */
        } /* end of h-loop */

        for (h = 0; h < fb->buf[1]->num_parts; h++) {
            curr_path_inf = &(fb->buf[1]->path_info[h]);
        
            if(curr_path_inf->inlist > 0 ) {
                sort(curr_path_inf->inlist, (float *)curr_path_inf->decis,
                    curr_path_inf->linkdecis);
            }
        }

        /* create links with decision check */
        count1=0; zusatz=0;
        for (h = 0; h < fb->buf[1]->num_parts; h++) {
            curr_path_inf = &(fb->buf[1]->path_info[h]);
            
            if (curr_path_inf->inlist > 0 ) {
                /* if old/new and unused prev == -1 and next == -2 link is created */
                ref_path_inf = &(fb->buf[2]->path_info[curr_path_inf->linkdecis[0]]);
                
                if ( ref_path_inf->prev == PREV_NONE && \
                    ref_path_inf->next == NEXT_NONE )
                {
                    curr_path_inf->finaldecis = curr_path_inf->decis[0];
                    curr_path_inf->prev = curr_path_inf->linkdecis[0];
                    fb->buf[2]->path_info[curr_path_inf->prev].next = h;
                    zusatz++;
                }

                /* old which link to prev has to be checked */
                if ((ref_path_inf->prev != PREV_NONE) && \
                    (ref_path_inf->next == NEXT_NONE) )
                {
                    vec_copy(X[0], fb->buf[0]->path_info[curr_path_inf->next].x);
                    vec_copy(X[1], curr_path_inf->x);
                    vec_copy(X[3], ref_path_inf->x);
                    vec_copy(X[4], fb->buf[3]->path_info[ref_path_inf->prev].x);
                    for (j = 0; j < 3; j++) 
                        X[5][j] = 0.5*(5.0*X[3][j] - 4.0*X[1][j] + X[0][j]);

                    angle_acc(X[3], X[4], X[5], &angle, &acc);
                    
                    if ( (acc<tpar->dacc && angle<tpar->dangle) ||  (acc<tpar->dacc/10) ) {
                        curr_path_inf->finaldecis = curr_path_inf->decis[0];
                        curr_path_inf->prev = curr_path_inf->linkdecis[0];
                        fb->buf[2]->path_info[curr_path_inf->prev].next = h;
                        zusatz++;
                    }
                }
            }

            if (curr_path_inf->prev != -1 ) count1++;
        } /* end of creation of links with decision check */

        sprintf (buf, "step: %d, curr: %d, next: %d, links: %d, lost: %d, add: %d",
            step, fb->buf[1]->num_parts, fb->buf[2]->num_parts, count1,
            fb->buf[1]->num_parts - count1, zusatz);

        /* for the average of particles and links */
        npart = npart + fb->buf[1]->num_parts;
        nlinks = nlinks + count1;

        fb_next(fb);
        fb_write_frame_from_start(fb, step);
        if(step > seq_par->first + 2) { fb_read_frame_at_end(fb, step - 3, 1); }
    } /* end of sequence loop */

    /* average of all steps */
    npart /= (seq_par->last - seq_par->first - 1);
    nlinks /= (seq_par->last - seq_par->first - 1);

    printf ("Average over sequence, particles: %5.1f, links: %5.1f, lost: %5.1f\n",
    npart, nlinks, npart-nlinks);

    fb_next(fb);
    fb_write_frame_from_start(fb, step);
    
    fb_free(fb);
    free(fb);
    free(tpar);

    /* reset of display flag */
    display = 1;
}
示例#7
0
void trackcorr_c_loop (tracking_run *run_info, int step, int display)
{
   /* sequence loop */
    char  val[256], buf[256];
    int j, h, k, mm, kk, invol=0;
    int zaehler1, zaehler2, philf[4][MAX_CANDS];
    int count1=0, count2=0, count3=0, zusatz=0;
    int intx0, intx1, inty0, inty1;
    int intx2, inty2;
    int quali=0;
    vec3d diff_pos, X[7]; /* 7 reference points used in the algorithm, TODO: check if can reuse some */
    double x1[4], y1[4], x2[4], y2[4], angle, acc, angle0, acc0,  dl;
    double xr[4], xl[4], yd[4], yu[4], angle1, acc1;
    double xp[4], yp[4], xc[4], yc[4], xn[4], yn[4];
    double rr;
    int flag_m_tr=0;
    
    /* Shortcuts to inside current frame */
    P *curr_path_inf, *ref_path_inf;
    corres *curr_corres, *ref_corres;
    target **curr_targets, **ref_targets;
    int _ix; /* For use in any of the complex index expressions below */
    int _frame_parts; /* number of particles in a frame */

    /* Shortcuts into the tracking_run struct */
    framebuf *fb;
    track_par *tpar;
    volume_par *vpar;
    control_par *cpar;
    
    /* Remaining globals:
    all those in trackcorr_c_init.
    calibration globals.
    */
    
    foundpix *w, *wn, p16[4*MAX_CANDS];
    sprintf (buf, "Time step: %d, seqnr: %d, Particle info:",
        step - run_info->seq_par->first, step);
    count1=0; zusatz=0;
    
    fb = run_info->fb;
    tpar = run_info->tpar;
    vpar = run_info->vpar;
    cpar = run_info->cpar;
    curr_targets = fb->buf[1]->targets;
    
    /* try to track correspondences from previous 0 - corp, variable h */
    for (h = 0; h < fb->buf[1]->num_parts; h++) {
        for (j = 0; j < 7; j++) vec_init(X[j]);
        
        curr_path_inf = &(fb->buf[1]->path_info[h]);
        curr_corres = &(fb->buf[1]->correspond[h]);
        
	    curr_path_inf->inlist = 0;
        reset_foundpix_array(p16, 16, fb->num_cams);
        
	    /* 3D-position */
	    vec_copy(X[1], curr_path_inf->x);

	    /* use information from previous to locate new search position
	       and to calculate values for search area */
	    if (curr_path_inf->prev >= 0) {
            ref_path_inf = &(fb->buf[0]->path_info[curr_path_inf->prev]);
	        vec_copy(X[0], ref_path_inf->x);
            search_volume_center_moving(ref_path_inf->x, curr_path_inf->x, X[2]);
            
	        for (j = 0; j < fb->num_cams; j++) {
                img_coord (j, X[2][0], X[2][1], X[2][2], Ex[j],I[j], G[j], ap[j],
                    *(cpar->mm), &xn[j], &yn[j]);
		        metric_to_pixel(&x1[j], &y1[j], xn[j], yn[j], cpar);
	        }
	    } else {  
            vec_copy(X[2], X[1]);
	        for (j=0; j < fb->num_cams; j++) {
	            if (curr_corres->p[j] == -1) {
                    img_coord (j, X[2][0], X[2][1], X[2][2], Ex[j],I[j], G[j],
                        ap[j], *(cpar->mm), &xn[j], &yn[j]);
                    metric_to_pixel(&x1[j], &y1[j], xn[j], yn[j], cpar);
	            } else {
                    _ix = curr_corres->p[j];
                    x1[j] = curr_targets[j][_ix].x;
                    y1[j] = curr_targets[j][_ix].y;
                }
            }
	    } 
        
	    /* calculate searchquader and reprojection in image space */
	    searchquader(X[2][0], X[2][1], X[2][2], xr, xl, yd, yu, tpar, cpar);

	    /* search in pix for candidates in next time step */
	    for (j = 0; j < fb->num_cams; j++) {
            register_closest_neighbs(fb->buf[2]->targets[j],
                fb->buf[2]->num_targets[j], j, x1[j], y1[j],
                xl[j], xr[j], yu[j], yd[j], &p16[j*MAX_CANDS], cpar);
	    }
        
	    /* fill and sort candidate struct */
	    sortwhatfound(p16, &zaehler1, fb->num_cams);
	    w = (foundpix *) calloc (zaehler1, sizeof (foundpix));
        
	    if (zaehler1 > 0) count2++;
        copy_foundpix_array(w, p16, zaehler1, fb->num_cams);
	    /*end of candidate struct */

	    /* check for what was found */
	    for (mm=0; mm<zaehler1;mm++) { /* zaehler1-loop */
	        /* search for found corr of current the corr in next
		    with predicted location */

            reset_foundpix_array(p16, 16, fb->num_cams);

	        /* found 3D-position */
            ref_path_inf = &(fb->buf[2]->path_info[w[mm].ftnr]);
            vec_copy(X[3], ref_path_inf->x);

	        if (curr_path_inf->prev >= 0) {
                for (j = 0; j < 3; j++) 
                    X[5][j] = 0.5*(5.0*X[3][j] - 4.0*X[1][j] + X[0][j]);
	        } else {
                search_volume_center_moving(X[1], X[3], X[5]);
            }
            searchquader(X[5][0], X[5][1], X[5][2], xr, xl, yd, yu, tpar, cpar);

	        for (j = 0; j < fb->num_cams; j++) {
                img_coord (j, X[5][0], X[5][1], X[5][2], Ex[j],I[j], G[j], ap[j],
                    *(cpar->mm), &xn[j], &yn[j]);
		        metric_to_pixel(&x2[j], &y2[j], xn[j], yn[j], cpar);
	        }

	        /* search for candidates in next time step */
	        for (j=0; j < fb->num_cams; j++) {
	            zaehler2 = candsearch_in_pix (fb->buf[3]->targets[j], 
                    fb->buf[3]->num_targets[j], x1[j], y1[j],
					xl[j], xr[j], yu[j], yd[j], philf[j], cpar);

		        for(k = 0; k < 4; k++) {
				    if (philf[j][k] == -999) {
                        p16[j*4+k].ftnr=-1;
				    } else {
				        if (fb->buf[3]->targets[j][philf[j][k]].tnr != -1) {
                            _ix = philf[j][k];
                            p16[j*4+k].ftnr = fb->buf[3]->targets[j][_ix].tnr;
                            p16[j*4+k].whichcam[j] = 1;
					    }
				    }
		        }
		    }
	        /* end of search in pix */

	        /* fill and sort candidate struct */
	        sortwhatfound(p16, &zaehler2, fb->num_cams);
	        wn = (foundpix *) calloc (zaehler2, sizeof (foundpix));
	        if (zaehler2 > 0) count3++;
            copy_foundpix_array(wn, p16, zaehler2, fb->num_cams);

	        /*end of candidate struct */
	        /* ************************************************ */
	        for (kk=0; kk < zaehler2; kk++)  { /* zaehler2-loop */
                ref_path_inf = &(fb->buf[3]->path_info[wn[kk].ftnr]);
                vec_copy(X[4], ref_path_inf->x);

                vec_subt(X[4], X[3], diff_pos);
                if ( pos3d_in_bounds(diff_pos, tpar)) { 
                    angle_acc(X[3], X[4], X[5], &angle1, &acc1);

                    if (curr_path_inf->prev >= 0) {
                        angle_acc(X[1], X[2], X[3], &angle0, &acc0);
		            } else {
                        acc0=acc1; angle0=angle1;
                    }

                    acc=(acc0+acc1)/2; angle=(angle0+angle1)/2;
                    quali=wn[kk].freq+w[mm].freq;

                    if ((acc < tpar->dacc && angle < tpar->dangle) || \
                        (acc < tpar->dacc/10)) 
                    {
                        dl = (vec_diff_norm(X[1], X[3]) + 
                            vec_diff_norm(X[4], X[3]) )/2;
                        rr = (dl/run_info->lmax + acc/tpar->dacc + angle/tpar->dangle)/(quali);
                        register_link_candidate(curr_path_inf, rr, w[mm].ftnr);
                    }
		        }
	        }   /* end of zaehler2-loop */

	        /* creating new particle position */
	        /* *************************************************************** */
	        for (j = 0;j < fb->num_cams; j++) {
                img_coord (j, X[5][0], X[5][1], X[5][2], Ex[j],I[j], G[j], ap[j],
                    *(cpar->mm), &xn[j], &yn[j]);
		        metric_to_pixel(&xn[j], &yn[j], xn[j], yn[j], cpar);
	        }

	        /* reset img coord because of num_cams < 4 */
	        for (j=0;j < fb->num_cams; j++) { x2[j]=-1e10; y2[j]=-1e10; }

	        /* search for unused candidates in next time step */
	        for (j = 0;j < fb->num_cams; j++) {
		        /* use fix distance to define xl, xr, yu, yd instead of searchquader */
		        xl[j]= xr[j]= yu[j]= yd[j] = 3.0;

	            zaehler2 = candsearch_in_pixrest (fb->buf[3]->targets[j], 
                    fb->buf[3]->num_targets[j], xn[j], yn[j],
					xl[j], xr[j], yu[j], yd[j], philf[j], cpar);
		        if(zaehler2>0 ) {
                    _ix = philf[j][0];
		            x2[j] = fb->buf[3]->targets[j][_ix].x;
                    y2[j] = fb->buf[3]->targets[j][_ix].y;
		        }
		    }
	        quali=0;

	        for (j = 0; j < fb->num_cams; j++) {
		        if (x2[j] != -1e10 && y2[j] != -1e10) {
		        pixel_to_metric(&x2[j],&y2[j], x2[j],y2[j], cpar); 
                quali++;
		        }
		    }

	        if ( quali >= 2) {
                vec_copy(X[4], X[5]);
		        invol=0; 

		        det_lsq_3d (glob_cal, *(cpar->mm), x2[0], y2[0], x2[1], y2[1], 
                    x2[2], y2[2], x2[3], y2[3],
                    &(X[4][0]), &(X[4][1]), &(X[4][2]), fb->num_cams);

		        /* volume check */
                if ( vpar->X_lay[0] < X[4][0] && X[4][0] < vpar->X_lay[1] &&
		            run_info->ymin < X[4][1] && X[4][1] < run_info->ymax &&
		            vpar->Zmin_lay[0] < X[4][2] && X[4][2] < vpar->Zmax_lay[1]) {invol=1;}

                vec_subt(X[3], X[4], diff_pos);
                if ( invol == 1 && pos3d_in_bounds(diff_pos, tpar) ) { 
                    angle_acc(X[3], X[4], X[5], &angle, &acc);

                    if ((acc < tpar->dacc && angle < tpar->dangle) || \
                        (acc < tpar->dacc/10)) 
                    {
                        dl=(vec_diff_norm(X[1], X[3]) + 
                            vec_diff_norm(X[4], X[3]) )/2;
                        rr = (dl/run_info->lmax + acc/tpar->dacc + angle/tpar->dangle) /
                            (quali+w[mm].freq);
                        register_link_candidate(curr_path_inf, rr, w[mm].ftnr);

                        if (tpar->add) {
                            ref_path_inf = &(fb->buf[3]->path_info[
                                fb->buf[3]->num_parts]);
                            vec_copy(ref_path_inf->x, X[4]);
                            reset_links(ref_path_inf);

                            _frame_parts = fb->buf[3]->num_parts;
                            ref_corres = &(fb->buf[3]->correspond[_frame_parts]);
                            ref_targets = fb->buf[3]->targets;
			                for (j = 0; j < fb->num_cams; j++) {
				                ref_corres->p[j]=-1;
                                
				                if(philf[j][0]!=-999) {
                                    _ix = philf[j][0];
                                    ref_targets[j][_ix].tnr = _frame_parts;
                                    ref_corres->p[j] = _ix;
                                    ref_corres->nr = _frame_parts;
				                }
			                }
			                fb->buf[3]->num_parts++;
                            zusatz++; 
                        }
                    }
                }
		        invol=0;
	        }
	        quali=0;

	        /* end of creating new particle position */
	        /* *************************************************************** */
            
	        /* try to link if kk is not found/good enough and prev exist */
	        if ( curr_path_inf->inlist == 0 && curr_path_inf->prev >= 0 ) {
                vec_subt(X[3], X[1], diff_pos);
                
                if (pos3d_in_bounds(diff_pos, tpar)) {
                    angle_acc(X[1], X[2], X[3], &angle, &acc);

                    if ( (acc < tpar->dacc && angle < tpar->dangle) || \
                        (acc < tpar->dacc/10) )
                    {
                        quali = w[mm].freq;
                        dl = (vec_diff_norm(X[1], X[3]) + 
                            vec_diff_norm(X[0], X[1]) )/2;
                        rr = (dl/run_info->lmax + acc/tpar->dacc + angle/tpar->dangle)/(quali);
                        register_link_candidate(curr_path_inf, rr, w[mm].ftnr);
			        }
		        }
	        }

	        free(wn);
        } /* end of zaehler1-loop */
        
	    /* begin of inlist still zero */
	    if (tpar->add) {
	        if ( curr_path_inf->inlist == 0 && curr_path_inf->prev >= 0 ) {
                for (j = 0; j < fb->num_cams; j++) {
                    img_coord (j, X[2][0], X[2][1], X[2][2], Ex[j],I[j], G[j],
                        ap[j], *(cpar->mm), &xn[j], &yn[j]);
		            metric_to_pixel(&xn[j], &yn[j], xn[j], yn[j], cpar);
		            x2[j]=-1e10;
                    y2[j]=-1e10;
                } 

    		    /* search for unused candidates in next time step */
		        for (j = 0; j < fb->num_cams; j++) {
		            /*use fix distance to define xl, xr, yu, yd instead of searchquader */
		            xl[j]= xr[j]= yu[j]= yd[j] = 3.0;
	                zaehler2 = candsearch_in_pixrest (fb->buf[2]->targets[j], 
                        fb->buf[2]->num_targets[j], xn[j], yn[j],
					    xl[j], xr[j], yu[j], yd[j], philf[j], cpar);
		            if(zaehler2 > 0) {
                        _ix = philf[j][0];
	    	            x2[j] = fb->buf[2]->targets[j][_ix].x;
                        y2[j] = fb->buf[2]->targets[j][_ix].y;
		            }
		        }
		        quali=0;

		        for (j = 0; j < fb->num_cams; j++) {
		            if (x2[j] !=-1e10 && y2[j] != -1e10) {
		                pixel_to_metric(&x2[j], &y2[j], x2[j], y2[j], cpar);
                        quali++;
		            }
		        }

		        if (quali>=2) {
                    vec_copy(X[3], X[2]);
		            invol=0; 
    
	    	        det_lsq_3d (glob_cal, *(cpar->mm),
                        x2[0], y2[0], x2[1], y2[1], x2[2], y2[2], x2[3], y2[3],
                        &(X[3][0]), &(X[3][1]), &(X[3][2]), fb->num_cams);

		            /* in volume check */
		            if ( vpar->X_lay[0] < X[3][0] && X[3][0] < vpar->X_lay[1] &&
                        run_info->ymin < X[3][1] && X[3][1] < run_info->ymax &&
                        vpar->Zmin_lay[0] < X[3][2] && 
                        X[3][2] < vpar->Zmax_lay[1]) {invol = 1;}

                    vec_subt(X[2], X[3], diff_pos);
                    if ( invol == 1 && pos3d_in_bounds(diff_pos, tpar) ) { 
                        angle_acc(X[1], X[2], X[3], &angle, &acc);

                        if ( (acc < tpar->dacc && angle < tpar->dangle) || \
                            (acc < tpar->dacc/10) ) 
                        {
                            dl = (vec_diff_norm(X[1], X[3]) + 
                                vec_diff_norm(X[0], X[1]) )/2;
                            rr = (dl/run_info->lmax + acc/tpar->dacc + angle/tpar->dangle)/(quali);
                            
                            ref_path_inf = &(fb->buf[2]->path_info[
                                fb->buf[2]->num_parts]);
                            vec_copy(ref_path_inf->x, X[3]);
                            reset_links(ref_path_inf);

                            _frame_parts = fb->buf[2]->num_parts;
                            register_link_candidate(curr_path_inf, rr, _frame_parts);
                            
                            ref_corres = &(fb->buf[2]->correspond[_frame_parts]);
                            ref_targets = fb->buf[2]->targets;
			                for (j = 0;j < fb->num_cams; j++) {
                                ref_corres->p[j]=-1;
                                
                                if(philf[j][0]!=-999) {
                                    _ix = philf[j][0];
                                    ref_targets[j][_ix].tnr = _frame_parts;
                                    ref_corres->p[j] = _ix;
                                    ref_corres->nr = _frame_parts;
                                }
                            }
                            fb->buf[2]->num_parts++;
                            zusatz++;
                        }
                    }
		            invol=0;
		        } // if quali >= 2
            }
        }
	    /* end of inlist still zero */
	    /***********************************/

	    free(w);
	} /* end of h-loop */
    
    /* sort decis and give preliminary "finaldecis"  */
    for (h = 0; h < fb->buf[1]->num_parts; h++) {
        curr_path_inf = &(fb->buf[1]->path_info[h]);
        
	    if(curr_path_inf->inlist > 0 ) {
	        sort(curr_path_inf->inlist, (float *) curr_path_inf->decis,
                curr_path_inf->linkdecis);
      	    curr_path_inf->finaldecis = curr_path_inf->decis[0];
	        curr_path_inf->next = curr_path_inf->linkdecis[0];
	    }
	}

    /* create links with decision check */
    for (h = 0;h < fb->buf[1]->num_parts; h++) {
        curr_path_inf = &(fb->buf[1]->path_info[h]);

	    if(curr_path_inf->inlist > 0 ) {
            ref_path_inf = &(fb->buf[2]->path_info[curr_path_inf->next]);
            
	        if (ref_path_inf->prev == -1) {	
	            /* best choice wasn't used yet, so link is created */
                ref_path_inf->prev = h; 
            } else {
	            /* best choice was already used by mega[2][mega[1][h].next].prev */
	            /* check which is the better choice */
	            if ( fb->buf[1]->path_info[ref_path_inf->prev].finaldecis > \
                    curr_path_inf->finaldecis) 
                {
		            /* remove link with prev */
		            fb->buf[1]->path_info[ref_path_inf->prev].next = NEXT_NONE;
                    ref_path_inf->prev = h; 
		        } else {
		            curr_path_inf->next = NEXT_NONE;
	            }
	        }
        }
        if (curr_path_inf->next != -2 ) count1++;
    } 
    /* end of creation of links with decision check */
    /* ******** Draw links now ******** */
    m1_tr = 0;
    
    if (display) {
        for (h = 0; h < fb->buf[1]->num_parts; h++) {
            curr_path_inf = &(fb->buf[1]->path_info[h]);
            curr_corres = &(fb->buf[1]->correspond[h]);
            ref_corres = &(fb->buf[2]->correspond[curr_path_inf->next]);
            
            if (curr_path_inf->next != -2 ) {
                strcpy(buf,"");
                sprintf(buf ,"green");
	
                for (j = 0; j < fb->num_cams; j++) {
                    if (curr_corres->p[j] > 0 && ref_corres->p[j] > 0) {
                        flag_m_tr=1;  
                        xp[j] = curr_targets[j][curr_corres->p[j]].x;
               		    yp[j] = curr_targets[j][curr_corres->p[j]].y;
               		    xc[j] = fb->buf[2]->targets[j][ref_corres->p[j]].x;
               		    yc[j] = fb->buf[2]->targets[j][ref_corres->p[j]].y;
               		    predict (xp[j], yp[j], xc[j], yc[j], &xn[j], &yn[j]);
                        
               		    if ( ( fabs(xp[j]-zoom_x[j]) < cpar->imx/(2*zoom_f[j]))
                            && (fabs(yp[j]-zoom_y[j]) < cpar->imy/(2*zoom_f[j])))
                        {
	                        strcpy(val,"");
                           	sprintf(val ,"orange");

                        	intx0 = (int)(cpar->imx/2 + zoom_f[j]*(xp[j] - zoom_x[j]));
	                        inty0 = (int)(cpar->imy/2 + zoom_f[j]*(yp[j] - zoom_y[j]));
                            intx1 = (int)(cpar->imx/2 + zoom_f[j]*(xc[j] - zoom_x[j]));
	                        inty1 = (int)(cpar->imy/2 + zoom_f[j]*(yc[j] - zoom_y[j]));
	                        intx2 = (int)(cpar->imx/2 + zoom_f[j]*(xn[j] - zoom_x[j]));
	                        inty2 = (int)(cpar->imy/2 + zoom_f[j]*(yn[j] - zoom_y[j]));

	                        intx0_tr[j][m1_tr]=intx0;
	                        inty0_tr[j][m1_tr]=inty0;
	                        intx1_tr[j][m1_tr]=intx1;
	                        inty1_tr[j][m1_tr]=inty1;
	                        intx2_tr[j][m1_tr]=intx2;
	                        inty2_tr[j][m1_tr]=inty2;
	                        pnr1_tr[j][m1_tr]=-1;
	                        pnr2_tr[j][m1_tr]=-1;
	                        pnr3_tr[j][m1_tr]=-1;
		
	                        if (curr_path_inf->finaldecis > 0.2) {
	            	            pnr1_tr[j][m1_tr] = h;
		                        pnr2_tr[j][m1_tr] = curr_path_inf->next;
		                        pnr3_tr[j][m1_tr] = curr_path_inf->finaldecis;
		                    }
                        }
                    }

                    if (flag_m_tr==0)  {
                        intx0_tr[j][m1_tr]=0;
    	                inty0_tr[j][m1_tr]=0;
	                    intx1_tr[j][m1_tr]=0;
	                    inty1_tr[j][m1_tr]=0;
	                    intx2_tr[j][m1_tr]=0;
	                    inty2_tr[j][m1_tr]=0;
	                    pnr1_tr[j][m1_tr]=-1;
	                    pnr2_tr[j][m1_tr]=-1;
	                    pnr3_tr[j][m1_tr]=-1; 
                    }
                    flag_m_tr=0;
                }
                m1_tr++;
            }
        }
    }
    /* ******** End of Draw links now ******** */
    sprintf (buf, "step: %d, curr: %d, next: %d, links: %d, lost: %d, add: %d",
        step, fb->buf[1]->num_parts, fb->buf[2]->num_parts, count1, 
        fb->buf[1]->num_parts - count1, zusatz);

    /* for the average of particles and links */
    npart = npart + fb->buf[1]->num_parts;
    nlinks = nlinks + count1;

    fb_next(fb);
    fb_write_frame_from_start(fb, step);
    if(step < run_info->seq_par->last - 2) {
        fb_read_frame_at_end(fb, step + 3, 0); 
    }
} /* end of sequence loop */
示例#8
0
int flow_demo_c (ClientData clientData, Tcl_Interp* interp, int argc, const char** argv)
{
  int i, i_seq, nr, j,pft_version=3,num_points,dumy;
  char	        name[128];
  unsigned char	*imgf;
  Tk_PhotoHandle img_handle;
  Tk_PhotoImageBlock img_block;

  nr = atoi(argv[1]);

  fpp = fopen_r ("parameters/sequence.par");
  for (i=0; i<4; i++)
    fscanf (fpp, "%s\n", seq_name[i]);     /* name of sequence */
  fscanf (fpp,"%d\n", &seq_first);
  fscanf (fpp,"%d\n", &seq_last);
  fclose (fpp);


  /* allocate memory */
  imgf = (unsigned char *) calloc (imgsize, 1);

  fpp = fopen ("parameters/pft_version.par", "r");
  if (fpp){
      fscanf (fpp, "%d\n", &pft_version);
	  pft_version=pft_version+3;
      fclose (fpp);
  }
  else{
	  fpp = fopen ("parameters/pft_version.par", "w");
      fprintf(fpp,"%d\n", 0);
	  fclose(fpp);
  }

  /* load and display images */
  for (i_seq=seq_first; i_seq<=seq_last; i_seq++){
      compose_name_plus_nr (seq_name[nr], "", i_seq, name);
      fp1 = fopen_r (name);	if (! fp1)	return TCL_OK;
      sprintf (buf, "display camera %d, image %d", nr+1, i_seq);
      Tcl_SetVar(interp, "tbuf", buf, TCL_GLOBAL_ONLY);
      Tcl_Eval(interp, ".text delete 2");
      Tcl_Eval(interp, ".text insert 2 $tbuf");

      read_image (interp, name, imgf);
      fclose (fp1);

      img_handle = Tk_FindPhoto( interp, "temp");
      Tk_PhotoGetImage (img_handle, &img_block);

      sprintf(buf, "newimage %d", nr+1);
      Tcl_Eval(interp, buf);

      
	  if(pft_version==4){
         sprintf (filename, "%s%s", name,"_targets");
	      /* read targets of camera nr*/
	     nt4[3][nr]=0;

	     fp1= fopen (filename, "r");
	     if (! fp1) printf("Can't open ascii file: %s\n", filename);

         fscanf (fp1, "%d\n", &nt4[3][nr]);
         for (j=0; j<nt4[3][nr]; j++){
	          fscanf (fp1, "%4d %lf %lf %d %d %d %d %d\n",
		      &pix[nr][j].pnr, &pix[nr][j].x,
		      &pix[nr][j].y, &pix[nr][j].n ,
		      &pix[nr][j].nx ,&pix[nr][j].ny,
		      &pix[nr][j].sumg, &pix[nr][j].tnr);
	     }
         fclose (fp1);
         num[nr] = nt4[3][nr];
		 if (display){
	         for (j=0; j<num[nr]; j++){
	             drawcross (interp, (int) pix[nr][j].x, (int) pix[nr][j].y,cr_sz, nr, "blue");
	         }
			 printf ("drawing %d 2d ", num[nr]);
		 }

         sprintf (filename, "res/rt_is.%d", i_seq);
		 fp1= fopen (filename, "r");
  if (fp1){
         fscanf (fp1, "%d\n", &num_points);
         for (j=0; j<num_points; j++){
	         if (n_img==4){
		        fscanf(fp1, "%d %lf %lf %lf %d %d %d %d\n",
	            &dumy, &fix[j].x, &fix[j].y, &fix[j].z,
	            &geo[0][j].pnr, &geo[1][j].pnr, &geo[2][j].pnr, &geo[3][j].pnr);
		     }
		     if (n_img==3){
		        fscanf(fp1, "%d %lf %lf %lf %d %d %d %d\n",
	            &dumy, &fix[j].x, &fix[j].y, &fix[j].z,
	            &geo[0][j].pnr, &geo[1][j].pnr, &geo[2][j].pnr);
		     }
		     if (n_img==2){ // Alex's patch. 24.09.09. Working on Wesleyan data of 2 cameras only
		        fscanf(fp1, "%d %lf %lf %lf %d %d %d %d\n",
	            &dumy, &fix[j].x, &fix[j].y, &fix[j].z,
	            &geo[0][j].pnr, &geo[1][j].pnr);
	         }
		 }
         fclose (fp1);
		 if (display){
	         for (j=0; j<num_points; j++){
				 img_coord (fix[j].x,fix[j].y,fix[j].z, Ex[nr], I[nr], G[nr], ap[nr], mmp, &pix[nr][j].x,&pix[nr][j].y);
				 metric_to_pixel (pix[nr][j].x,pix[nr][j].y, imx,imy, pix_x,pix_y, &pix[nr][j].x,&pix[nr][j].y, chfield);
				 //if(geo[nr][j].pnr>-1){
	             //    drawcross (interp, (int) pix[nr][geo[nr][j].pnr].x, (int) pix[nr][geo[nr][j].pnr].y,cr_sz, nr, "yellow");
				 //}
				 drawcross (interp, (int) pix[nr][j].x, (int) pix[nr][j].y,cr_sz, nr, "red");
		     }
			 printf ("and %d corresponding 3d positions for frame %d\n", num_points,i_seq);
		 }
  }	
	  }
      Tcl_Eval(interp, "update idletasks");
    }
    printf ("done\n\n");

  free (imgf);
  return TCL_OK;
}
示例#9
0
int trajectories_c(ClientData clientData, Tcl_Interp* interp, int argc, const char** argv) 
/* draws crosses for detected points in a displayed image */
{
  int   k, intx1, inty1, intx2, inty2;
  int i, anz1, anz2, m, j;
  FILE *fp1;
  char val[256];
  vector *line1, *line2;
  double color;
  coord_2d p1[4], p2[4];

  cr_sz = atoi(Tcl_GetVar2(interp, "mp", "pcrossize",  TCL_GLOBAL_ONLY));

  fpp = fopen_r ("parameters/sequence.par");

  /* name of sequence */
  fscanf (fpp,"%d\n", &seq_first);
  fscanf (fpp,"%d\n", &seq_last);
  fclose (fpp);
  
  sprintf (buf, "Show trajectories "); puts (buf);
  Tcl_SetVar(interp, "tbuf", buf, TCL_GLOBAL_ONLY);
  Tcl_Eval(interp, ".text delete 2");
  Tcl_Eval(interp, ".text insert 2 $tbuf");


  for (i=seq_first; i<seq_last;i++)
    {
      if (i < 10)             sprintf (val, "res/ptv_is.%1d", i);
      else if (i < 100)       sprintf (val, "res/ptv_is.%2d",  i);
      else       sprintf (val, "res/ptv_is.%3d",  i);
 
      fp1 = fopen (val, "r");
      
      color = ((double)(i-seq_first))/((double)(seq_last-2-seq_first));
      fscanf (fp1,"%d\n", &anz1);
      
      line1 = (vector *) malloc (anz1 * sizeof (vector));
      for (j=0;j<anz1;j++) {
	fscanf (fp1, "%d\n", &line1[j].p);
	fscanf (fp1, "%d\n", &line1[j].n);
	fscanf (fp1, "%lf\n", &line1[j].x1);
	fscanf (fp1, "%lf\n", &line1[j].y1);
	fscanf (fp1, "%lf\n", &line1[j].z1);
      }

      strcpy(val, "");     
      fclose (fp1);

      /* read next time step */     
      if (i+1 < 10)             sprintf (val, "res/ptv_is.%1d", i+1);
      else if (i+1 < 100)       sprintf (val, "res/ptv_is.%2d",  i+1);
      else       sprintf (val, "res/ptv_is.%3d",  i+1);
      
      fp1 = fopen (val, "r");      
      fscanf (fp1,"%d\n", &anz2);
      line2 = (vector *) calloc (anz2, sizeof (vector));
      
      for (j=0;j<anz2;j++) {
	fscanf (fp1, "%d\n", &line2[j].p);
	fscanf (fp1, "%d\n", &line2[j].n);
	fscanf (fp1, "%lf\n", &line2[j].x1);
	fscanf (fp1, "%lf\n", &line2[j].y1);
	fscanf (fp1, "%lf\n", &line2[j].z1);
      }
      fclose (fp1);
      
      for(j=0;j<anz1;j++) { 	
	m = line1[j].n;

	if (m >= 0)  {	  
	  for (k=0; k<n_img; k++)
	    {
	      img_coord (line1[j].x1, line1[j].y1, line1[j].z1, Ex[k],I[k], G[k], ap[k], mmp, &p1[k].x, &p1[k].y);
	      metric_to_pixel (p1[k].x, p1[k].y, imx,imy, pix_x,pix_y, &p1[k].x, &p1[k].y, chfield);
	      
	      img_coord (line2[m].x1, line2[m].y1, line2[m].z1, Ex[k],I[k], G[k], ap[k], mmp, &p2[k].x, &p2[k].y);
	      metric_to_pixel (p2[k].x, p2[k].y, imx,imy, pix_x,pix_y, &p2[k].x, &p2[k].y, chfield); 
	      
	      if ( fabs( p2[k].x-zoom_x[k]) < imx/(2*zoom_f[k])
		   && ( fabs(p2[k].y-zoom_y[k]) < imy/(2*zoom_f[k])) )
		{	
		  intx1 = (int)(imx/2+zoom_f[k]*(p1[k].x-zoom_x[k]));
		  inty1 = (int)(imy/2+zoom_f[k]*(p1[k].y-zoom_y[k]));
		  intx2 = (int)(imx/2+zoom_f[k]*(p2[k].x-zoom_x[k]));
		  inty2 = (int)(imy/2+zoom_f[k]*(p2[k].y-zoom_y[k]));

		  drawcross ( interp, intx1, inty1, cr_sz+1, k, "blue");	 
		  drawcross ( interp, intx2, inty2, cr_sz+1, k, "red");
		  drawvector (interp, intx1, inty1, intx2, inty2, 2, k, "green");
		}	
	    }
	}
	}
	  Tcl_Eval(interp, "update idletasks");	      


      strcpy(val, "");
      free(line1); free(line2);
    }  /* end of sequence loop */
  
  sprintf(val, "...done");
  Tcl_SetVar(interp, "tbuf", val, TCL_GLOBAL_ONLY);
  Tcl_Eval(interp, ".text delete 3");
  Tcl_Eval(interp, ".text insert 3 $tbuf"); 
  
  return TCL_OK;
}
示例#10
0
int raw_orient (Calibration* cal, control_par *cpar, int nfix, vec3d fix[], target pix[])
{
    double  X[10][6], y[10], XPX[6][6], XPy[6], beta[6];
    int     i, j, n, itnum, stopflag;
    double  dm = 0.0001,  drad = 0.0001;
    double 	xp, yp, xc, yc;
    vec3d   pos;

    /* init X, y (set to zero) */
    for (i = 0; i < 10; i++) {
      for (j = 0; j < 6; j++)
        X[i][j] = 0;
      y[i] = 0;
    }

    cal->added_par.k1 = 0;
    cal->added_par.k2 = 0;
    cal->added_par.k3 = 0;
    cal->added_par.p1 = 0;
    cal->added_par.p2 = 0;
    cal->added_par.scx = 1;
    cal->added_par.she = 0;

    /* main loop, program runs through it, until none of the beta values
     comes over a threshold and no more points are thrown out
     because of their residuals */

    itnum = 0;
    stopflag = 0;

    while ((stopflag == 0) && (itnum < 20)) {
        ++itnum;

        for (i = 0, n = 0; i < nfix; i++) {
            /* we do not check the order - trust the user to click the points
               in the correct order of appearance in man_ori and in the calibration
               parameters GUI
            */
            pixel_to_metric (&xc, &yc, pix[i].x, pix[i].y, cpar);
            /* no corrections as additional parameters are neglected
                correct_brown_affin (xc, yc, cal->added_par, &xc, &yc);
            */
    
            /* every calibration dot is projected to the mm position, xp, yp */
            vec_set(pos, fix[i][0], fix[i][1], fix[i][2]);
            rotation_matrix(&(cal->ext_par));
            img_coord (pos, cal, cpar->mm, &xp, &yp);
    
            /* numeric derivatives of internal camera coefficients */
            num_deriv_exterior(cal, cpar, dm, drad, pos, X[n], X[n + 1]);
    
            y[n]   = xc - xp;
            y[n+1] = yc - yp;
    
            n += 2;
        }

        /* Gauss Markoff Model */
    
        ata ((double *) X, (double *) XPX, n, 6, 6);
        matinv ((double *) XPX, 6, 6);
        atl ((double *) XPy, (double *) X, y, n, 6, 6);
        matmul ((double *) beta, (double *) XPX, (double *) XPy, 6,6,1,6,6);
    
        stopflag = 1;
        for (i = 0; i < 6; i++) {
          if (fabs (beta[i]) > 0.1 )
            stopflag = 0;
        }
    
        cal->ext_par.x0 += beta[0];
        cal->ext_par.y0 += beta[1];
        cal->ext_par.z0 += beta[2];
        cal->ext_par.omega += beta[3];
        cal->ext_par.phi += beta[4];
        cal->ext_par.kappa += beta[5];
    
    }

    if (stopflag) {
        rotation_matrix(&(cal->ext_par));
    }
    return stopflag;
}
示例#11
0
/*  orient() calculates orientation of the camera, updating its calibration 
    structure using the definitions and algorithms well described in [1].
    
    Arguments:
    Calibration* cal_in - camera calibration object
    control_par *cpar - control parameters
    int nfix - number of 3D known points
    vec3d fix[]	- each of nfix items is one 3D position of known point on
        the calibration object.
    target pix[] - image coordinates corresponding to each point in ``fix``.
        can be obtained from the set of detected 2D points using 
        sortgrid(). The points which are associated with fix[] have real 
        pointer (.pnr attribute), others have -999.
    orient_par flags - structure of all the flags of the parameters to be 
        (un)changed, read from orient.par parameter file using 
        read_orient_par(), defaults are zeros except for x_scale which is
        by default 1.
    
    Output:
    Calibration *cal_in - if the orientation routine converged, this structure
    is updated, otherwise, returned untouched. The routine works on a copy of
    the calibration structure, cal.
    double sigmabeta[] - array of deviations for each of the interior and 
        exterior parameters and glass interface vector (19 in total).

    Returns:
    On success, a pointer to an array of residuals. For each observation point
    i = 0..n-1, residual 2*i is the Gauss-Markof residual for the x coordinate
    and residual 2*i + 1 is for the y. Then come 10 cells with the delta 
    between initial guess and final solution for internal and distortion 
    parameters, which are also part of the G-M model and described in it.
    On failure returns NULL.
*/
double* orient (Calibration* cal_in, control_par *cpar, int nfix, vec3d fix[],
            target pix[], orient_par *flags, double sigmabeta[20]) 
{
    int  	i,j,n, itnum, stopflag, n_obs=0, maxsize;

    double  ident[IDT], XPX[NPAR][NPAR], XPy[NPAR], beta[NPAR], omega=0;
    double xp, yp, xpd, ypd, xc, yc, r, qq, p, sumP;

    int numbers;

    double al,be,ga,nGl,e1_x,e1_y,e1_z,e2_x,e2_y,e2_z,safety_x,safety_y,safety_z;
    double *P, *y, *yh, *Xbeta, *resi;
    vec3d glass_dir, tmp_vec, e1, e2;

    Calibration *cal;

    /* small perturbation for translation/rotation in meters and in radians */
    double  dm = 0.00001,  drad = 0.0000001;

    cal = malloc (sizeof (Calibration));
    memcpy(cal, cal_in, sizeof (Calibration));

    maxsize = nfix*2 + IDT;
    
    P = (double *) calloc(maxsize, sizeof(double));
    y = (double *) calloc(maxsize, sizeof(double));
    yh = (double *) calloc(maxsize, sizeof(double));
    Xbeta = (double *) calloc(maxsize, sizeof(double));
    resi = (double *) calloc(maxsize, sizeof(double));

    double (*X)[NPAR] = malloc(sizeof (*X) * maxsize);
    double (*Xh)[NPAR] = malloc(sizeof (*Xh) * maxsize);

    for(i = 0; i < maxsize; i++) {
        for(j = 0; j < NPAR; j++) {
    	      X[i][j] = 0.0;
    	      Xh[i][j] = 0.0;
        }
        y[i] = 0;
        P[i] = 1;
    }
    
    for(i = 0; i < NPAR; i++)
        sigmabeta[j] = 0.0;

    if(flags->interfflag){
        numbers = 18;
    } else{
        numbers = 16;
    }

    vec_set(glass_dir, 
        cal->glass_par.vec_x, cal->glass_par.vec_y, cal->glass_par.vec_z);
    nGl = vec_norm(glass_dir);

    e1_x = 2*cal->glass_par.vec_z - 3*cal->glass_par.vec_x;
    e1_y = 3*cal->glass_par.vec_x - 1*cal->glass_par.vec_z;
    e1_z = 1*cal->glass_par.vec_y - 2*cal->glass_par.vec_y;
    vec_set(tmp_vec, e1_x, e1_y, e1_z);
    unit_vector(tmp_vec, e1);

    e2_x = e1_y*cal->glass_par.vec_z - e1_z*cal->glass_par.vec_x;
    e2_y = e1_z*cal->glass_par.vec_x - e1_x*cal->glass_par.vec_z;
    e2_z = e1_x*cal->glass_par.vec_y - e1_y*cal->glass_par.vec_y;
    vec_set(tmp_vec, e2_x, e2_y, e2_z);
    unit_vector(tmp_vec, e2);

    al = 0;
    be = 0;
    ga = 0;

    /* init identities */
    ident[0] = cal->int_par.cc;
    ident[1] = cal->int_par.xh;
    ident[2] = cal->int_par.yh;
    ident[3] = cal->added_par.k1;
    ident[4] = cal->added_par.k2;
    ident[5] = cal->added_par.k3;
    ident[6] = cal->added_par.p1;
    ident[7] = cal->added_par.p2;
    ident[8] = cal->added_par.scx;
    ident[9] = cal->added_par.she;

    safety_x = cal->glass_par.vec_x;
    safety_y = cal->glass_par.vec_y;
    safety_z = cal->glass_par.vec_z;
    
    /* main loop, program runs through it, until none of the beta values
      comes over a threshold and no more points are thrown out
      because of their residuals */

    itnum = 0;  
    stopflag = 0;
    while ((stopflag == 0) && (itnum < NUM_ITER)) {
      itnum++;

      for (i = 0, n = 0; i < nfix; i++) {
        /* check for correct correspondence
        note that we do not use anymore pointer in fix, the points are read by
        the order of appearance and if we want to use every other point
        we use 'i', just check it is not -999 */
        if(pix[i].pnr != i) continue;
        
        switch (flags->useflag) {
            case 1: if ((i % 2) == 0)  continue;  break;
            case 2: if ((i % 2) != 0)  continue;  break;
            case 3: if ((i % 3) == 0)  continue;  break;
        }

        /* get metric flat-image coordinates of the detected point */
        pixel_to_metric (&xc, &yc, pix[i].x, pix[i].y, cpar);
        correct_brown_affin (xc, yc, cal->added_par, &xc, &yc);

        /* Projected 2D position on sensor of corresponding known point */
        rotation_matrix(&(cal->ext_par));
        img_coord (fix[i], cal, cpar->mm, &xp, &yp);

        /* derivatives of distortion parameters */

        r = sqrt (xp*xp + yp*yp);

        X[n][7] = cal->added_par.scx;
        X[n+1][7] = sin(cal->added_par.she);

        X[n][8] = 0;
        X[n+1][8] = 1;

        X[n][9] = cal->added_par.scx * xp * r*r;
        X[n+1][9] = yp * r*r;

        X[n][10] = cal->added_par.scx * xp * pow(r,4.0);
        X[n+1][10] = yp * pow(r,4.0);

        X[n][11] = cal->added_par.scx * xp * pow(r,6.0);
        X[n+1][11] = yp * pow(r,6.0);

        X[n][12] = cal->added_par.scx * (2*xp*xp + r*r);
        X[n+1][12] = 2 * xp * yp;

        X[n][13] = 2 * cal->added_par.scx * xp * yp;
        X[n+1][13] = 2*yp*yp + r*r;

        qq =  cal->added_par.k1*r*r; qq += cal->added_par.k2*pow(r,4.0);
        qq += cal->added_par.k3*pow(r,6.0);
        qq += 1;
        X[n][14] = xp * qq + cal->added_par.p1 * (r*r + 2*xp*xp) + \
                                                            2*cal->added_par.p2*xp*yp;
        X[n+1][14] = 0;

        X[n][15] = -cos(cal->added_par.she) * yp;
        X[n+1][15] = -sin(cal->added_par.she) * yp;

        /* numeric derivatives of projection coordinates over external 
           parameters, 3D position and the angles */
        
        num_deriv_exterior(cal, cpar, dm, drad, fix[i], X[n], X[n + 1]);

        /* Num. deriv. of projection coords over sensor distance from PP */
        cal->int_par.cc += dm;
        rotation_matrix(&(cal->ext_par));
        img_coord (fix[i], cal, cpar->mm, &xpd, &ypd);
        X[n][6]   = (xpd - xp) / dm;
        X[n+1][6] = (ypd - yp) / dm;
        cal->int_par.cc -= dm;

        /* ditto, over water-glass-air interface position vector */
        al += dm;
        cal->glass_par.vec_x += e1[0]*nGl*al;
        cal->glass_par.vec_y += e1[1]*nGl*al;
        cal->glass_par.vec_z += e1[2]*nGl*al;

        img_coord (fix[i], cal, cpar->mm, &xpd, &ypd);
        X[n][16]      = (xpd - xp) / dm;
        X[n+1][16] = (ypd - yp) / dm;

        al -= dm;
        cal->glass_par.vec_x = safety_x;
        cal->glass_par.vec_y = safety_y;
        cal->glass_par.vec_z = safety_z;

        be += dm;
        cal->glass_par.vec_x += e2[0]*nGl*be;
        cal->glass_par.vec_y += e2[1]*nGl*be;
        cal->glass_par.vec_z += e2[2]*nGl*be;

        img_coord (fix[i], cal, cpar->mm, &xpd, &ypd);
        X[n][17]      = (xpd - xp) / dm;
        X[n+1][17] = (ypd - yp) / dm;

        be -= dm;
        cal->glass_par.vec_x = safety_x;
        cal->glass_par.vec_y = safety_y;
        cal->glass_par.vec_z = safety_z;

        ga += dm;
        cal->glass_par.vec_x += cal->glass_par.vec_x*nGl*ga;
        cal->glass_par.vec_y += cal->glass_par.vec_y*nGl*ga;
        cal->glass_par.vec_z += cal->glass_par.vec_z*nGl*ga;

        img_coord (fix[i], cal, cpar->mm, &xpd, &ypd);
        X[n][18]      = (xpd - xp) / dm;
        X[n+1][18] = (ypd - yp) / dm;

        ga -= dm;
        cal->glass_par.vec_x = safety_x;
        cal->glass_par.vec_y = safety_y;
        cal->glass_par.vec_z = safety_z;

        y[n]   = xc - xp;
        y[n+1] = yc - yp;

        n += 2;
      }
      
      n_obs = n;
      
      /* identities */
      for (i = 0; i < IDT; i++)
        X[n_obs + i][6 + i] = 1;
        
      y[n_obs+0] = ident[0] - cal->int_par.cc;
      y[n_obs+1] = ident[1] - cal->int_par.xh;
      y[n_obs+2] = ident[2] - cal->int_par.yh;
      y[n_obs+3] = ident[3] - cal->added_par.k1;
      y[n_obs+4] = ident[4] - cal->added_par.k2;
      y[n_obs+5] = ident[5] - cal->added_par.k3;
      y[n_obs+6] = ident[6] - cal->added_par.p1;
      y[n_obs+7] = ident[7] - cal->added_par.p2;
      y[n_obs+8] = ident[8] - cal->added_par.scx;
      y[n_obs+9] = ident[9] - cal->added_par.she;

      /* weights */
      for (i = 0; i < n_obs; i++)
          P[i] = 1;

      P[n_obs+0] = ( ! flags->ccflag) ?  POS_INF : 1;
      P[n_obs+1] = ( ! flags->xhflag) ?  POS_INF : 1;
      P[n_obs+2] = ( ! flags->yhflag) ?  POS_INF : 1;
      P[n_obs+3] = ( ! flags->k1flag) ?  POS_INF : 1;
      P[n_obs+4] = ( ! flags->k2flag) ?  POS_INF : 1;
      P[n_obs+5] = ( ! flags->k3flag) ?  POS_INF : 1;
      P[n_obs+6] = ( ! flags->p1flag) ?  POS_INF : 1;
      P[n_obs+7] = ( ! flags->p2flag) ?  POS_INF : 1;
      P[n_obs+8] = ( ! flags->scxflag) ?  POS_INF : 1;
      P[n_obs+9] = ( ! flags->sheflag) ?  POS_INF : 1;

      n_obs += IDT;
      sumP = 0;
      for (i = 0; i < n_obs; i++) {       	/* homogenize */
          p = sqrt (P[i]);
          for (j = 0; j < NPAR; j++)
              Xh[i][j] = p * X[i][j];
            
          yh[i] = p * y[i];
          sumP += P[i];
      }
        
      /* Gauss Markoff Model it is the least square adjustment 
         of the redundant information contained both in the spatial 
         intersection and the resection, see [1], eq. 23 */
      ata ((double *) Xh, (double *) XPX, n_obs, numbers, NPAR );
      matinv ((double *) XPX, numbers, NPAR);
      atl ((double *) XPy, (double *) Xh, yh, n_obs, numbers, NPAR);
      matmul ((double *) beta, (double *) XPX, (double *) XPy, 
          numbers, numbers,1, NPAR, NPAR);

      stopflag = 1;
      for (i = 0; i < numbers; i++) {
          if (fabs (beta[i]) > CONVERGENCE)  stopflag = 0;
      }

      if ( ! flags->ccflag) beta[6] = 0.0;
      if ( ! flags->xhflag) beta[7] = 0.0;
      if ( ! flags->yhflag) beta[8] = 0.0;
      if ( ! flags->k1flag) beta[9] = 0.0;
      if ( ! flags->k2flag) beta[10] = 0.0;
      if ( ! flags->k3flag) beta[11] = 0.0;
      if ( ! flags->p1flag) beta[12] = 0.0;
      if ( ! flags->p2flag) beta[13] = 0.0;
      if ( ! flags->scxflag)beta[14] = 0.0;
      if ( ! flags->sheflag) beta[15] = 0.0;

      cal->ext_par.x0 += beta[0];
      cal->ext_par.y0 += beta[1];
      cal->ext_par.z0 += beta[2];
      cal->ext_par.omega += beta[3];
      cal->ext_par.phi += beta[4];
      cal->ext_par.kappa += beta[5];
      cal->int_par.cc += beta[6];
      cal->int_par.xh += beta[7];
      cal->int_par.yh += beta[8];
      cal->added_par.k1 += beta[9];
      cal->added_par.k2 += beta[10];
      cal->added_par.k3 += beta[11];
      cal->added_par.p1 += beta[12];
      cal->added_par.p2 += beta[13];
      cal->added_par.scx += beta[14];
      cal->added_par.she += beta[15];

      if (flags->interfflag) {
          cal->glass_par.vec_x += e1[0]*nGl*beta[16];
          cal->glass_par.vec_y += e1[1]*nGl*beta[16];
          cal->glass_par.vec_z += e1[2]*nGl*beta[16];
          cal->glass_par.vec_x += e2[0]*nGl*beta[17];
          cal->glass_par.vec_y += e2[1]*nGl*beta[17];
          cal->glass_par.vec_z += e2[2]*nGl*beta[17];
      }
    }

    /* compute residuals etc. */
    matmul ( (double *) Xbeta, (double *) X, (double *) beta, n_obs, 
        numbers, 1, n_obs, NPAR);
    omega = 0;
    for (i = 0; i < n_obs; i++) {
        resi[i] = Xbeta[i] - y[i];
        omega += resi[i] * P[i] * resi[i];
    }
    sigmabeta[NPAR] = sqrt (omega / (n_obs - numbers));

    for (i = 0; i < numbers; i++) { 
        sigmabeta[i] = sigmabeta[NPAR] * sqrt(XPX[i][i]);
    }

    free(X);
    free(P);
    free(y);
    free(Xbeta);
    free(Xh);

    if (stopflag){
        rotation_matrix(&(cal->ext_par));
        memcpy(cal_in, cal, sizeof (Calibration));
        return resi;
    }
    else {
        free(resi);
        return NULL;
    }
}