Beispiel #1
0
/* Estimate relative pose from a given set of point matches */
int EstimatePose5Point(const std::vector<Keypoint> &k1, 
                       const std::vector<Keypoint> &k2, 
                       std::vector<KeypointMatch> matches, 
                       int num_trials, double threshold, 
                       double *K1, double *K2, 
                       double *R, double *t)
{
    int num_pts = (int) matches.size();

    v2_t *k1_pts = new v2_t[num_pts];
    v2_t *k2_pts = new v2_t[num_pts];

    for (int i = 0; i < num_pts; i++) {
	int idx1 = matches[i].m_idx1;
	int idx2 = matches[i].m_idx2;

	k1_pts[i] = v2_new(k1[idx1].m_x, k1[idx1].m_y);
	k2_pts[i] = v2_new(k2[idx2].m_x, k2[idx2].m_y);
    }

    int num_inliers = compute_pose_ransac(num_pts, k1_pts, k2_pts, 
                                          K1, K2, threshold, num_trials, R, t);

    delete [] k1_pts;
    delete [] k2_pts;

    return num_inliers;
}
Beispiel #2
0
/* Compute the mean of a set of vectors */
v2_t v2_mean(int n, v2_t *v) {
    int i;
    v2_t mean = v2_new(0.0, 0.0);
    
    for (i = 0; i < n; i++) {
	mean = v2_add(mean, v[i]);
    }

    return v2_scale(1.0 / n, mean);
}
Beispiel #3
0
/* Compute the centroid of an array of 2D vectors */
v2_t v2_compute_centroid(v2_t *pts, int num_pts) {
    int i;
    v2_t centroid = v2_new(0.0, 0.0);

    for (i = 0; i < num_pts; i++) {
	Vx(centroid) += Vx(pts[i]);
	Vy(centroid) += Vy(pts[i]);
    }

    return v2_scale(1.0 / ((double) num_pts), centroid);
}
Beispiel #4
0
std::vector<v2_t> GetPointProjections(const CameraInfo &cam, 
                                      const std::vector<PointData> &points,
                                      const std::vector<int> &indices,
                                      bool inside_only, 
                                      int &num_inside)
{
    int num_points = (int) indices.size();
    std::vector<v2_t> projs;
    BoundingBox bbox = cam.GetBoundingBox();

    num_inside = 0;

    for (int i = 0; i < num_points; i++) {
	int pidx = indices[i];
	const PointData &p = points[pidx];
	
	double proj[2];

#if 1
	bool in_front = cam.Project(p.m_pos, proj);

	if (!in_front)
	    continue;

	bool inside = bbox.Contains(proj[0], proj[1]);
#else
	bool inside = cam.Project(p.m_pos, proj);
#endif

	if (inside)
	    num_inside++;

	if (inside_only && inside) 
	    projs.push_back(v2_new(proj[0], proj[1]));
	else if (!inside_only)
	    projs.push_back(v2_new(proj[0], proj[1]));
    }

    return projs;
}
Beispiel #5
0
iv2_t iv2_compute_centroid(iv2_t *pts, int num_pts) {
    int i;
    v2_t centroid = v2_new(0.0, 0.0);
    iv2_t i_centroid;

    for (i = 0; i < num_pts; i++) {
	Vx(centroid) += (double) Vx(pts[i]);
	Vy(centroid) += (double) Vy(pts[i]);
    }

#define ROUND(x) (((x) < 0.0) ? (int) ((x) - 0.5) : (int) ((x) + 0.5))
    centroid = v2_scale(1.0 / ((double) num_pts), centroid);
    i_centroid = iv2_new((int16_t) ROUND(Vx(centroid)), 
			 (int16_t) ROUND(Vy(centroid)));
    
    return i_centroid;
}
Beispiel #6
0
/* Add new points to the bundle adjustment */
int 
BundlerApp::BundleAdjustAddAllNewPoints(int num_points, int num_cameras,
                                        int *added_order,
                                        camera_params_t *cameras,
                                        v3_t *points, v3_t *colors,
                                        double reference_baseline,
                                        std::vector<ImageKeyVector> &pt_views,
                                        double max_reprojection_error,
                                        int min_views)
{
    std::vector<int> track_idxs;
    std::vector<ImageKeyVector> new_tracks;

    int num_tracks_total = (int) m_track_data.size();
    int *tracks_seen = new int[num_tracks_total];
    for (int i = 0; i < num_tracks_total; i++) {
	tracks_seen[i] = -1;
    }

    /* Gather up the projections of all the new tracks */
    for (int i = 0; i < num_cameras; i++) {
	int image_idx1 = added_order[i];

	int num_keys = GetNumKeys(image_idx1);
	
	for (int j = 0; j < num_keys; j++) {
	    Keypoint &key = GetKey(image_idx1, j);

	    if (key.m_track == -1)
		continue;  /* Key belongs to no track */

	    if (key.m_extra != -1)
		continue;  /* Key is outlier or has already been added */

	    int track_idx = key.m_track;
	    
	    /* Check if this track is already associated with a point */
	    if (m_track_data[track_idx].m_extra != -1)
		continue;

	    /* Check if we've seen this track */
	    int seen = tracks_seen[track_idx];

	    if (seen == -1) {
		/* We haven't yet seen this track, create a new track */
		tracks_seen[track_idx] = (int) new_tracks.size();

		ImageKeyVector track;
		track.push_back(ImageKey(i, j));
		new_tracks.push_back(track);
		track_idxs.push_back(track_idx);
	    } else {
		new_tracks[seen].push_back(ImageKey(i, j));
	    }
	}
    }
    
    delete [] tracks_seen;

    /* Now for each (sub) track, triangulate to see if the track is
     * consistent */
    int pt_count = num_points;

    int num_ill_conditioned = 0;
    int num_high_reprojection = 0;
    int num_cheirality_failed = 0;
    int num_added = 0;

    int num_tracks = (int) new_tracks.size();
    for (int i = 0; i < num_tracks; i++) {
	int num_views = (int) new_tracks[i].size();
	
	if (num_views < min_views) continue;  /* Not enough views */

#if 0
	printf("Triangulating track ");
	PrintTrack(new_tracks[i]);
	printf("\n");
#endif

	/* Check if at least two cameras fix the position of the point */
	bool conditioned = false;
	bool good_distance = false;
	double max_angle = 0.0;
	for (int j = 0; j < num_views; j++) {
	    for (int k = j+1; k < num_views; k++) {
		int camera_idx1 = new_tracks[i][j].first;
		int image_idx1 = added_order[camera_idx1];
		int key_idx1 = new_tracks[i][j].second;

		int camera_idx2 = new_tracks[i][k].first;
		int image_idx2 = added_order[camera_idx2];
		int key_idx2 = new_tracks[i][k].second;

		Keypoint &key1 = GetKey(image_idx1, key_idx1);
		Keypoint &key2 = GetKey(image_idx2, key_idx2);

		v2_t p = v2_new(key1.m_x, key1.m_y);
		v2_t q = v2_new(key2.m_x, key2.m_y);

                if (m_optimize_for_fisheye) {
                    double p_x = Vx(p), p_y = Vy(p);
                    double q_x = Vx(q), q_y = Vy(q);
                    
                    m_image_data[image_idx1].
                        UndistortPoint(p_x, p_y, Vx(p), Vy(p));
                    m_image_data[image_idx2].
                        UndistortPoint(q_x, q_y, Vx(q), Vy(q));
                }

		double angle = ComputeRayAngle(p, q, 
					       cameras[camera_idx1], 
					       cameras[camera_idx2]);

		if (angle > max_angle)
		    max_angle = angle;

		/* Check that the angle between the rays is large
		 * enough */
		if (RAD2DEG(angle) >= m_ray_angle_threshold) {
		    conditioned = true;
		}

#if 0
		double dist_jk = 
		    GetCameraDistance(cameras + j, cameras + k, 
				      m_explicit_camera_centers);

		if (dist_jk > m_min_camera_distance_ratio * reference_baseline)
		    good_distance = true;
#else
                good_distance = true;
#endif
	    }
	}
	
	if (!conditioned || !good_distance) {
	    num_ill_conditioned++;

#if 0
	    printf(">> Track is ill-conditioned [max_angle = %0.3f]\n", 
		   RAD2DEG(max_angle));
	    fflush(stdout);
#endif
	    continue;
	}
	
	double error;
	v3_t pt;

        if (!m_panorama_mode) {
            pt = TriangulateNViews(new_tracks[i], added_order, cameras, 
                                   error, true);
        } else {
            pt = GeneratePointAtInfinity(new_tracks[i], added_order, cameras, 
                                         error, true);
        }
       
		// Changed by Wan, Yi
	if (::isnan(error) || error > max_reprojection_error) {
	    num_high_reprojection++;
#if 0
	    printf(">> Reprojection error [%0.3f] is too large\n", error);
	    fflush(stdout);
#endif
	    continue;	    
	}

	bool all_in_front = true;
	for (int j = 0; j < num_views; j++) {
	    int camera_idx = new_tracks[i][j].first;
	    bool in_front = CheckCheirality(pt, cameras[camera_idx]);
	 
	    if (!in_front) {
		all_in_front = false;
		break;
	    }
	}

	if (!all_in_front) {
	    num_cheirality_failed++;

#if 0
	    printf(">> Cheirality check failed\n");
	    fflush(stdout);
#endif
	    continue;
	}
	
	/* All tests succeeded, so let's add the point */
#if 0
	printf("Triangulating track ");
	PrintTrack(new_tracks[i]);
	printf("\n");
	printf(">> All tests succeeded [%0.3f, %0.3f] for point [%d]\n", 
	       RAD2DEG(max_angle), error, pt_count);
#endif

	fflush(stdout);

	points[pt_count] = pt;

	int camera_idx = new_tracks[i][0].first;
	int image_idx = added_order[camera_idx];
	int key_idx = new_tracks[i][0].second;

	unsigned char r = GetKey(image_idx, key_idx).m_r;
	unsigned char g = GetKey(image_idx, key_idx).m_g;
	unsigned char b = GetKey(image_idx, key_idx).m_b;
	colors[pt_count] = v3_new((double) r, (double) g, (double) b);
    
	pt_views.push_back(new_tracks[i]);

	/* Set the point index on the keys */
	for (int j = 0; j < num_views; j++) {
	    int camera_idx = new_tracks[i][j].first;
	    int image_idx = added_order[camera_idx];
	    int key_idx = new_tracks[i][j].second;
	    GetKey(image_idx, key_idx).m_extra = pt_count;
	}

	int track_idx = track_idxs[i];
	m_track_data[track_idx].m_extra = pt_count;
	
	pt_count++;
        num_added++;
    }

    printf("[AddAllNewPoints] Added %d new points\n", num_added);
    printf("[AddAllNewPoints] Ill-conditioned tracks: %d\n", 
           num_ill_conditioned);
    printf("[AddAllNewPoints] Bad reprojections: %d\n", num_high_reprojection);
    printf("[AddAllNewPoints] Failed cheirality checks: %d\n", 
           num_cheirality_failed);

    return pt_count;
}
Beispiel #7
0
v2* v2_copy(v2* v) {
  v2* ret = v2_new(0,0);
  memcpy(ret->v, v->v, 2 * sizeof(float));

  return ret;
}
bool BundlerApp::EstimateRelativePose(int i1, int i2, 
                                      camera_params_t &camera1, 
                                      camera_params_t &camera2)
{
    MatchIndex list_idx;

    if (i1 < i2)
        list_idx = GetMatchIndex(i1, i2);
    else
        list_idx = GetMatchIndex(i2, i1);

    std::vector<KeypointMatch> &matches = m_matches.GetMatchList(list_idx);
    int num_matches = (int) matches.size();

    double f1 = m_image_data[i1].m_init_focal;
    double f2 = m_image_data[i2].m_init_focal;

    double E[9], F[9];
    std::vector<int> inliers;

    if (!m_optimize_for_fisheye) {
        inliers = 
            EstimateEMatrix(m_image_data[i1].m_keys, m_image_data[i2].m_keys, 
                            matches,
                            4 * m_fmatrix_rounds, // 8 * m_fmatrix_rounds,
                            m_fmatrix_threshold * m_fmatrix_threshold, 
                            f1, f2, E, F);
    } else {
        /* FIXME */
        inliers = 
            EstimateEMatrix(m_image_data[i1].m_keys, m_image_data[i2].m_keys, 
                            matches,
                            4 * m_fmatrix_rounds, // 8 * m_fmatrix_rounds,
                            m_fmatrix_threshold * m_fmatrix_threshold, 
                            f1, f2, E, F);        
    }

    if ((int) inliers.size() == 0)
        return false;

    int num_inliers = (int) inliers.size();
    printf("  Found %d / %d inliers (%0.3f%%)\n", num_inliers, num_matches,
           100.0 * num_inliers / num_matches);


    /* Estimate a homography with the inliers */
    std::vector<KeypointMatch> match_inliers;
    for (int i = 0; i < num_inliers; i++) {
        match_inliers.push_back(matches[inliers[i]]);
    }

    int num_match_inliers = (int) match_inliers.size();

    double H[9];
    std::vector<int> Hinliers = 
        EstimateTransform(m_image_data[i1].m_keys, m_image_data[i2].m_keys,
                          match_inliers, MotionHomography,
                          128 /*m_homography_rounds*/, 
                          6.0 /*m_homography_threshold*/, H);

    printf("  Found %d / %d homography inliers (%0.3f%%)\n",
           (int) Hinliers.size(), num_inliers, 
           100.0 * Hinliers.size() / num_inliers);

    bool initialized = false;
    if ((int) Hinliers.size() > 0) {
        matrix_print(3, 3, H);
        printf("\n");
    
        if ((double) Hinliers.size() / num_inliers >= 0.75 /*0.85*/) {
            KeypointMatch &match0 = matches[Hinliers[0]];
            v2_t p10 = v2_new(m_image_data[i1].m_keys[match0.m_idx1].m_x,
                              m_image_data[i1].m_keys[match0.m_idx1].m_y);
            v2_t p20 = v2_new(m_image_data[i2].m_keys[match0.m_idx2].m_x,
                              m_image_data[i2].m_keys[match0.m_idx2].m_y);

            double R1[9], t1[3], R2[9], t2[3];
            bool success = 
                DecomposeHomography(H, f1, f2, R1, t1, R2, t2, p10, p20);
        
            if (success) {
                printf("[BundleTwoFrame] Using homography "
                       "for initialization\n");

                /* Decide which solution to use */
                double F1h[9], F2h[9];
                ComputeFundamentalMatrix(f1, f2, R1, t1, F1h);
                ComputeFundamentalMatrix(f1, f2, R2, t2, F2h);
                
                double F1hT[9], F2hT[9];
                matrix_transpose(3, 3, F1h, F1hT);
                matrix_transpose(3, 3, F2h, F2hT);

                int num_inliers1 = 0, num_inliers2 = 0;

                for (int i = 0; i < num_match_inliers; i++) {
                    const KeypointMatch &match = match_inliers[i];
                    const Keypoint &k1 = m_image_data[i1].m_keys[match.m_idx1];
                    const Keypoint &k2 = m_image_data[i2].m_keys[match.m_idx2];

                    v3_t rt = v3_new(k1.m_x, k1.m_y, 1.0);
                    v3_t lft = v3_new(k2.m_x, k2.m_y, 1.0);
                    double r1a = fmatrix_compute_residual(F1h, lft, rt);
                    double r1b = fmatrix_compute_residual(F1hT, rt, lft);

                    double r2a = fmatrix_compute_residual(F2h, lft, rt);
                    double r2b = fmatrix_compute_residual(F2hT, rt, lft);

                    if (r1a < m_fmatrix_threshold && r1b < m_fmatrix_threshold)
                        num_inliers1++;

                    if (r2a < m_fmatrix_threshold && r2b < m_fmatrix_threshold)
                        num_inliers2++;
                }

                initialized = true;

                double *R, *t;
                printf("  H1: %d inliers, H2: %d inliers\n", 
                       num_inliers1, num_inliers2);
                if (num_inliers1 > num_inliers2) {
                    R = R1;
                    t = t1;
                } else {
                    R = R2;
                    t = t2;
                }

                memcpy(camera2.R, R, sizeof(double) * 9);
                matrix_transpose_product(3, 3, 3, 1, R, t, camera2.t);
                matrix_scale(3, 1, camera2.t, -1.0, camera2.t);
            }
        }
    }

    if (!initialized) {
        KeypointMatch &match = matches[inliers[0]];
        v2_t p1 = v2_new(m_image_data[i1].m_keys[match.m_idx1].m_x / f1,
                         m_image_data[i1].m_keys[match.m_idx1].m_y / f1);
        v2_t p2 = v2_new(m_image_data[i2].m_keys[match.m_idx2].m_x / f2,
                         m_image_data[i2].m_keys[match.m_idx2].m_y / f2);
    
        double R[9], t[3];
        int success = find_extrinsics_essential(E, p1, p2, R, t);
    
        if (!success) {
            return false;
        }

        memcpy(camera2.R, R, sizeof(double) * 9);

        matrix_transpose_product(3, 3, 3, 1, R, t, camera2.t);
        matrix_scale(3, 1, camera2.t, -1.0, camera2.t);
    }

    return true;
}
Beispiel #9
0
/* Compute the pair-wise minimum / maximum of two vectors */
v2_t v2_minimum(v2_t u, v2_t v) {
    return v2_new(MIN(Vx(u), Vx(v)),
		  MIN(Vy(u), Vy(v)));
}
Beispiel #10
0
v2_t v2_scale(double s, v2_t v) {
    return v2_new(s * Vx(v), s * Vy(v));
}
Beispiel #11
0
/* Add new points to the bundle adjustment */
int BundlerApp::BundleAdjustAddNewPoints(int camera_idx, 
                                         int num_points, int num_cameras,
                                         int *added_order,
                                         camera_params_t *cameras,
                                         v3_t *points, v3_t *colors,
                                         double reference_baseline,
                                         std::vector<ImageKeyVector> &pt_views)
{
    int pt_count = num_points;

    int image_idx = added_order[camera_idx];

    /* Recompute the locations of the new points given the initial
     * pose estimate */
    for (int i = 0; i < num_cameras; i++) {
	int other = added_order[i];

	if (other == image_idx)
	    continue;

	int first = MIN(image_idx, other);
	int second = MAX(image_idx, other);

	MatchIndex idx = GetMatchIndex(first, second);

        SetMatchesFromTracks(first, second);

	printf("  Matches[%d,%d] = %d\n", image_idx, other,
               (int) m_matches.GetNumMatches(idx));
	       // (int) m_match_lists[idx].size());

	double disti = GetCameraDistance(cameras + i, cameras + camera_idx);

	printf("  dist0, disti = %0.3e, %0.3e\n", reference_baseline, disti);

	if (disti < m_min_camera_distance_ratio * reference_baseline) {
	    printf("  Distance too low (possible panorama?)\n");
            // m_match_lists[idx].clear();
            m_matches.ClearMatch(idx);
	    continue;
	}

        std::vector<KeypointMatch> &list = m_matches.GetMatchList(idx);
	for (int j = 0; j < (int) list.size(); j++) {
	    int idx1 = list[j].m_idx1;
	    int idx2 = list[j].m_idx2;

	    int this_idx, other_idx;
	    if (image_idx == first) {
		this_idx = idx1;
		other_idx = idx2;
	    } else {
		other_idx = idx1;
		this_idx = idx2;
	    }
		
	    if (GetKey(other,other_idx).m_extra == -2) {
		/* The other key was already marked as an outlier */
		continue;
	    } else if (GetKey(image_idx,this_idx).m_extra == -2) {
		/* This key was already marked as an outlier */
		continue;
	    }

	    if (GetKey(other,other_idx).m_extra == -1 &&
		GetKey(image_idx,this_idx).m_extra >= 0) {  

		/**** Connecting an existing point *** */


		/* Connect up the other point to this one */
		int pt_idx = GetKey(image_idx,this_idx).m_extra;

		/* Check reprojection error */	    
		v2_t pr = sfm_project_final(cameras + i, points[pt_idx], 
					    true, m_estimate_distortion);

		double dx = GetKey(other,other_idx).m_x - Vx(pr);
		double dy = GetKey(other,other_idx).m_y - Vy(pr);
		    
		double proj_error = sqrt(dx * dx + dy * dy);

		if (proj_error >= 32.0) {
		    printf("  Would have connected existing match "
			   "%d ==> %d [%d] (cam: %d), \n"
			   "    but reprojection error (%0.3f) "
			   "is too high.\n", 
			   this_idx, other_idx, pt_idx, other, proj_error);
		} else {
		    printf("  Connecting existing match "
			   "%d ==> %d [%d] (cam: %d) [%0.3f]\n",
			   this_idx, other_idx, pt_idx, other, proj_error);
		    
		    GetKey(other,other_idx).m_extra = pt_idx;
		    pt_views[pt_idx].push_back(ImageKey(i, other_idx));
		}
	    } else if (GetKey(other,other_idx).m_extra == -1) {

		if (GetKey(image_idx,this_idx).m_extra != -1) {
		    printf("Error!  Key (%d,%d) shouldn't be seen yet!\n",
			   image_idx, this_idx);
		    printf("Point index is %d\n", 
			   GetKey(image_idx,this_idx).m_extra);
		}

		/* This is a new point */
		GetKey(other,other_idx).m_extra = pt_count;
		GetKey(image_idx,this_idx).m_extra = pt_count;

		/* Set up the 3D point */
		v2_t p = v2_new(GetKey(other,other_idx).m_x,
				GetKey(other,other_idx).m_y);
		    
		v2_t q = v2_new(GetKey(image_idx,this_idx).m_x,
				GetKey(image_idx,this_idx).m_y);

                if (m_optimize_for_fisheye) {
                    double p_x = Vx(p), p_y = Vy(p);
                    double q_x = Vx(q), q_y = Vy(q);
                    
                    m_image_data[other].
                        UndistortPoint(p_x, p_y, Vx(p), Vy(p));
                    m_image_data[image_idx].
                        UndistortPoint(q_x, q_y, Vx(q), Vy(q));
                }

		double proj_error = 0.0;
		bool in_front = false;
		double angle = 0.0;

		points[pt_count] = 
		    Triangulate(p, q, cameras[i], cameras[camera_idx], 
				proj_error, in_front, angle, true);


		/* Check that the angle between the rays is large
		 * enough */
		if (RAD2DEG(angle) < m_ray_angle_threshold) {
		    printf(" Ray angle %d => %d is too small (%0.3f)\n", 
			   this_idx, other_idx, RAD2DEG(angle));

		    /* Remove point */
		    GetKey(other,other_idx).m_extra = -1;
		    GetKey(image_idx,this_idx).m_extra = -1;

		    continue;
		}

		/* Check the reprojection error */
		if (proj_error >= ADD_REPROJECTION_ERROR) {
		    printf("  Projection error for %d => %d is %0.3e, "
			   "removing\n",
			   this_idx, other_idx, proj_error);

		    /* Remove point */
		    GetKey(other,other_idx).m_extra = -2;
		    GetKey(image_idx,this_idx).m_extra = -2;

		    continue;
		}

		/* Check cheirality */
		if (!in_front) {
		    printf("  Cheirality violated!\n");

		    /* Remove point */
		    GetKey(other,other_idx).m_extra = -2;
		    GetKey(image_idx,this_idx).m_extra = -2;

		    continue;
		}

		printf("  Adding match %d ==> %d [%d] (cam: %d ==> %d) "
		       "[%0.3f, %0.3f]\n", 
		       other_idx, this_idx, pt_count, image_idx, other, 
		       RAD2DEG(angle), proj_error);

		/* Finally, add the point */
		unsigned char r = GetKey(other,other_idx).m_r;
		unsigned char g = GetKey(other,other_idx).m_g;
		unsigned char b = GetKey(other,other_idx).m_b;

		colors[pt_count] = v3_new((double) r, 
					  (double) g,
					  (double) b);
    
		ImageKeyVector views;
		views.push_back(ImageKey(i, other_idx));
		views.push_back(ImageKey(camera_idx, this_idx));
		pt_views.push_back(views);

		pt_count++;

	    } else if (GetKey(other,other_idx).m_extra >= 0 && 
		       GetKey(image_idx,this_idx).m_extra == -1) {

		/* We didn't connect this point originally --
		 * check if it's now a good idea to add it in */

		/* Connect up the other point to this one */
		int pt_idx = GetKey(other,other_idx).m_extra;

		/* Check reprojection error */
		v2_t pr = sfm_project_final(cameras + camera_idx, 
					    points[pt_idx],
					    true, m_estimate_distortion);

		double dx = GetKey(image_idx,this_idx).m_x - Vx(pr);
		double dy = GetKey(image_idx,this_idx).m_y - Vy(pr);
		    
		double proj_error = sqrt(dx * dx + dy * dy);

		if (proj_error <= INIT_REPROJECTION_ERROR) {
		    printf("  Reconnecting point [%d] (%d) (error: %0.3f)\n", 
			   pt_idx, this_idx, proj_error);
		    GetKey(image_idx,this_idx).m_extra = pt_idx;
		    pt_views[pt_idx].push_back(ImageKey(camera_idx,this_idx));
		} else {
		    /* Throw out this point as an outlier */
		    GetKey(image_idx,this_idx).m_extra = -2;
		}
	    }
	}

        // m_match_lists[idx].clear();
        m_matches.ClearMatch(idx);
    }

    return pt_count;
}
Beispiel #12
0
v2_t v2_maximum(v2_t u, v2_t v) {   
    return v2_new(MAX(Vx(u), Vx(v)),
		  MAX(Vy(u), Vy(v)));
}
Beispiel #13
0
/* Create a new image by applying transformation T to img and 
 * resampling.  Resize the image so that the whole thing fits when
 * transformed. */
img_t *img_resample_bbox(img_t *img, trans2D_t *T) {
    int w = img->w, h = img->h;
    int x, y;
    trans2D_t *Tinv = transform_invert(T);
    int w_new, h_new, i;
    // double x_min = DBL_MAX, x_max = -DBL_MAX, y_min = DBL_MAX, y_max = -DBL_MAX;
    v2_t min = v2_new(DBL_MAX, DBL_MAX);
    v2_t max = v2_new(-DBL_MAX, -DBL_MAX);
    v2_t origin;
    img_t *Timg;

    /* Find the new dimensions of the window */
    v2_t crs[4]; /* Four corners of the original image */

    crs[0] = v2_new(0, 0);
    crs[1] = v2_new(0, h - 1);
    crs[2] = v2_new(w - 1, 0);
    crs[3] = v2_new(w - 1, h - 1);

    for (i = 0; i < 4; i++) {
	crs[i] = v2_add(crs[i], img->origin);
	crs[i] = transform_vector(T, crs[i]);
	min = v2_minimum(min, crs[i]);
	max = v2_maximum(max, crs[i]);
    }

    Vx(min) = floor(Vx(min));
    Vy(min) = floor(Vy(min));

    w_new = iround(floor(Vx(max) - Vx(min) + 1));
    h_new = iround(floor(Vy(max) - Vy(min) + 1));
    origin = min;

    Timg = img_new(w_new, h_new);
    Timg->origin = origin;

    for (y = 0; y < h_new; y++) {
        for (x = 0; x < w_new; x++) {
            double Tp[2];
	    fcolor_t c;

            /* Invert the point (x, y) - trans */
            transform_point(Tinv, x + Vx(origin), y + Vy(origin), &Tp[0], &Tp[1]);
            
#if 1
            /* Check if the result is in range */
            if (Tp[0] < Vx(img->origin) || Tp[1] < Vy(img->origin) || 
		Tp[0] > Vx(img->origin) + w - 1 || Tp[1] > Vy(img->origin) + h - 1) {

		/* pass */

	    } else {
		/* Check if the result is valid */
		int x_f = (int) (Tp[0] - Vx(img->origin));
		int x_c = x_f + 1;
		int y_f = (int) (Tp[1] - Vy(img->origin));
		int y_c = y_f + 1;

		if (img_pixel_is_valid(img, x_f, y_f) ||
		    img_pixel_is_valid(img, x_c, y_f) ||
		    img_pixel_is_valid(img, x_f, y_c) ||
		    img_pixel_is_valid(img, x_c, y_c)) {

		    /* Apply bilinear interpolation */
		    c = pixel_lerp(img, Tp[0] - Vx(img->origin), Tp[1] - Vy(img->origin));
		    img_set_pixel(Timg, x, y, iround(c.r), iround(c.g), iround(c.b));
		} else {
		    // img_nullify_pixel(Timg, x, y);
		}
		
            }
#else
	    if (Tp[0] < 0.0) Tp[0] = 0.0;
	    else if (Tp[0] > w - 1) Tp[0] = w - 1;
	    if (Tp[1] < 0.0) Tp[1] = 0.0;
	    else if (Tp[1] > h - 1) Tp[1] = h - 1;

	    c = pixel_lerp(img, Tp[0], Tp[1]);
	    img_set_pixel(Timg, x, y, c.r, c.g, c.b);
#endif
        }
    }

    /* Add the old origin to the image */
    // Timg->origin = v2_add(origin, img->origin);
    transform_free(Tinv);

    return Timg;
}
Beispiel #14
0
/* Fit a plane to the points at the given indices */
std::vector<int> FitPlaneToPoints(const std::vector<PointData> &points,
                                  const std::vector<int> &indices,
                                  double *plane, 
                                  int ransac_rounds,
                                  double ransac_threshold,
                                  bool par_to_up, bool perp_to_up,
                                  double *up)
{
    if (par_to_up && perp_to_up) {
	printf("[FitPlaneToPoints] Error: cannot be both "
	       "parallel and perpendicular to the up vector!\n");
	perp_to_up = false;
    }

    std::vector<int> inliers;
    if (!par_to_up) {
        /* Marshall the points */
        int num_points = (int) indices.size();
        v3_t *pts = new v3_t[num_points];
        for (int i = 0; i < num_points; i++) {
            int pt_idx = indices[i];
            const PointData &pt = points[pt_idx];
            pts[i] = v3_new(pt.m_pos[0], pt.m_pos[1], pt.m_pos[2]);
        }

        /* Fit the plane */
        int num_inliers = 0;
        double error = fit_3D_plane_ortreg_ransac(num_points, pts, 
                                                  ransac_rounds, 
                                                  ransac_threshold,
                                                  &num_inliers, plane);

        printf("error = %0.3f\n", error);

        /* Gather the inliers */
        for (int i = 0; i < num_points; i++) {
            double dist = plane_point_distance(plane, pts[i]);
            if (dist < ransac_threshold) {
                inliers.push_back(indices[i]);
            }
        }

        if (perp_to_up) {
            /* Compute the mean of the inliers */
            int num_inliers = (int) inliers.size();
            v3_t *pts_inlier = new v3_t[num_inliers];

            for (int i = 0; i < num_inliers; i++) {
                int pt_idx = inliers[i];
                const PointData &pt = points[pt_idx];
                pts_inlier[i] = v3_new(pt.m_pos[0], pt.m_pos[1], pt.m_pos[2]);
            }
            
            v3_t mean = v3_mean(num_inliers, pts_inlier);

            double dot;
            matrix_product(1, 3, 3, 1, up, mean.p, &dot);

            plane[0] = up[0];
            plane[1] = up[1];
            plane[2] = up[2];
            plane[3] = -dot;

            delete [] pts_inlier;
        }

        delete [] pts;
    } else {
        assert(fabs(up[1] - 1.0) < 1.0e-5);

        /* Marshall the points */
        int num_points = (int) indices.size(); // points.size();
        v2_t *pts = new v2_t[num_points];
        for (int i = 0; i < num_points; i++) {
            int pt_idx = indices[i];
            const PointData &pt = points[pt_idx];

            pts[i] = v2_new(pt.m_pos[0], pt.m_pos[2]);
        }

        /* Fit the plane */
        double line[3];
        int num_inliers = 0;
        double error = fit_2D_line_ortreg_ransac(num_points, pts, 
                                                 ransac_rounds, 
                                                 ransac_threshold,
                                                 &num_inliers, line);

        plane[0] = line[0];
        plane[1] = 0.0;
        plane[2] = line[1];
        plane[3] = line[2];

        printf("error = %0.3f\n", error);
        printf("num_inliers = %d\n", num_inliers);

        /* Gather the inliers */
        for (int i = 0; i < num_points; i++) {
            int pt_idx = indices[i];
            const PointData &p = points[pt_idx];
            v3_t pt = v3_new(p.m_pos[0], p.m_pos[1], p.m_pos[2]);
            double dist = plane_point_distance(plane, pt);

            if (dist < ransac_threshold) {
                inliers.push_back(indices[i]);
            }
        }
    }

    return inliers;
}
Beispiel #15
0
/* Triangulate two points */
v3_t Triangulate(v2_t p, v2_t q, 
                 camera_params_t c1, camera_params_t c2, 
                 double &proj_error, bool &in_front, double &angle,
                 bool explicit_camera_centers)
{
    double K1[9], K2[9];
    double K1inv[9], K2inv[9];

    GetIntrinsics(c1, K1);
    GetIntrinsics(c2, K2);
    
    matrix_invert(3, K1, K1inv);
    matrix_invert(3, K2, K2inv);

    /* Set up the 3D point */
    // EDIT!!!
    double proj1[3] = { Vx(p), Vy(p), -1.0 };
    double proj2[3] = { Vx(q), Vy(q), -1.0 };

    double proj1_norm[3], proj2_norm[3];

    matrix_product(3, 3, 3, 1, K1inv, proj1, proj1_norm);
    matrix_product(3, 3, 3, 1, K2inv, proj2, proj2_norm);

    v2_t p_norm = v2_new(proj1_norm[0] / proj1_norm[2],
			 proj1_norm[1] / proj1_norm[2]);
    
    v2_t q_norm = v2_new(proj2_norm[0] / proj2_norm[2],
			 proj2_norm[1] / proj2_norm[2]);

    /* Undo radial distortion */
    p_norm = UndistortNormalizedPoint(p_norm, c1);
    q_norm = UndistortNormalizedPoint(q_norm, c2);

    /* Compute the angle between the rays */
    angle = ComputeRayAngle(p, q, c1, c2);

    /* Triangulate the point */
    v3_t pt;
    if (!explicit_camera_centers) {
	pt = triangulate(p_norm, q_norm, c1.R, c1.t, c2.R, c2.t, &proj_error);
    } else {
	double t1[3];
	double t2[3];
			
	/* Put the translation in standard form */
	matrix_product(3, 3, 3, 1, c1.R, c1.t, t1);
	matrix_scale(3, 1, t1, -1.0, t1);
	matrix_product(3, 3, 3, 1, c2.R, c2.t, t2);
	matrix_scale(3, 1, t2, -1.0, t2);
			
	pt = triangulate(p_norm, q_norm, c1.R, t1, c2.R, t2, &proj_error);
    }

    proj_error = (c1.f + c2.f) * 0.5 * sqrt(proj_error * 0.5);

    /* Check cheirality */
    bool cc1 = CheckCheirality(pt, c1);
    bool cc2 = CheckCheirality(pt, c2);

    in_front = (cc1 && cc2);

    return pt;
}
Beispiel #16
0
/* Triangulate a subtrack */
v3_t BundlerApp::TriangulateNViews(const ImageKeyVector &views, 
                                   int *added_order, 
                                   camera_params_t *cameras,
                                   double &error, 
                                   bool explicit_camera_centers)
{
    int num_views = (int) views.size();

    v2_t *pv = new v2_t[num_views];
    double *Rs = new double[9 * num_views];
    double *ts = new double[3 * num_views];
	
    for (int i = 0; i < num_views; i++) {
	camera_params_t *cam = NULL;

	int camera_idx = views[i].first;
	int image_idx = added_order[camera_idx];
	int key_idx = views[i].second;
	Keypoint &key = GetKey(image_idx, key_idx);

	double p3[3] = { key.m_x, key.m_y, 1.0 };

        if (m_optimize_for_fisheye) {
            /* Undistort the point */
            double x = p3[0], y = p3[1];
            m_image_data[image_idx].UndistortPoint(x, y, p3[0], p3[1]);
        }

	double K[9], Kinv[9];
	GetIntrinsics(cameras[camera_idx], K);
	matrix_invert(3, K, Kinv);

	double p_n[3];
	matrix_product(3, 3, 3, 1, Kinv, p3, p_n);

        // EDIT!!!
	pv[i] = v2_new(-p_n[0], -p_n[1]);
        pv[i] = UndistortNormalizedPoint(pv[i], cameras[camera_idx]);

	cam = cameras + camera_idx;

	memcpy(Rs + 9 * i, cam->R, 9 * sizeof(double));
	if (!explicit_camera_centers) {
	    memcpy(ts + 3 * i, cam->t, 3 * sizeof(double));
	} else {
	    matrix_product(3, 3, 3, 1, cam->R, cam->t, ts + 3 * i);
	    matrix_scale(3, 1, ts + 3 * i, -1.0, ts + 3 * i);
	}
    }
    
    v3_t pt = triangulate_n(num_views, pv, Rs, ts, &error);

    error = 0.0;
    for (int i = 0; i < num_views; i++) {
	int camera_idx = views[i].first;
	int image_idx = added_order[camera_idx];
	int key_idx = views[i].second;
	Keypoint &key = GetKey(image_idx, key_idx);

	v2_t pr = sfm_project_final(cameras + camera_idx, pt, 
				    explicit_camera_centers ? 1 : 0,
                                    m_estimate_distortion ? 1 : 0);
        
        if (m_optimize_for_fisheye) {
            double x = Vx(pr), y = Vy(pr);
            m_image_data[image_idx].DistortPoint(x, y, Vx(pr), Vy(pr));
        }        

	double dx = Vx(pr) - key.m_x;
	double dy = Vy(pr) - key.m_y;

	error += dx * dx + dy * dy;
    }

    error = sqrt(error / num_views);

    delete [] pv;
    delete [] Rs;
    delete [] ts;

    return pt;
}
Beispiel #17
0
v2_t v2_add(v2_t u, v2_t v) {
    return v2_new(Vx(u) + Vx(v),
		  Vy(u) + Vy(v));
}
Beispiel #18
0
v2_t v2_sub(v2_t u, v2_t v) {
    return v2_new(Vx(u) - Vx(v),
		  Vy(u) - Vy(v));
}
/* Quickly compute pose of all cameras */
void BundlerApp::BundleAdjustFast() 
{
    clock_t start = clock();

    /* Compute initial image information */
    ComputeGeometricConstraints();//读取constrains.txt里面的信息,构造track信息

#if 0
    /* Read keypoints */
    printf("[BundleAdjust] Reading key colors...\n");
    ReadKeyColors();
#endif

    /* Set track pointers to -1 */
    for (int i = 0; i < (int) m_track_data.size(); i++) 
	{
		m_track_data[i].m_extra = -1;
    }

    /* For now, assume all images form one connected component */
    int num_images = GetNumImages();
    int *added_order = new int[num_images];
    int *added_order_inv = new int[num_images];


    /* **** Run bundle adjustment! **** */

    camera_params_t *cameras = new camera_params_t[num_images];
    int max_pts = (int) m_track_data.size(); // 1243742; /* HACK! */
    v3_t *points = new v3_t[max_pts];
    v3_t *colors = new v3_t[max_pts];
    std::vector<ImageKeyVector> pt_views;


    /* Initialize the bundle adjustment */
    int num_init_cams = 0;
    InitializeBundleAdjust(num_init_cams, added_order, added_order_inv,
			   cameras, points, colors, pt_views, 
			   m_use_constraints);

    int i_best = -1, j_best = -1, max_matches = 0;
    double max_score = 0.0;
    int curr_num_cameras, curr_num_pts;
    int pt_count;

    if (num_init_cams == 0) 
	{
		BundlePickInitialPair(i_best, j_best, true);

		added_order[0] = i_best;
		added_order[1] = j_best;

		printf("[BundleAdjust] Adjusting cameras "
			   "%d and %d (score = %0.3f)\n", 
			   i_best, j_best, max_score);

		/* **** Set up the initial cameras **** */
		double init_focal_length_0 = 0.0, init_focal_length_1 = 0.0;
		pt_count = curr_num_pts = 
	    SetupInitialCameraPair(i_best, j_best, 
				   init_focal_length_0, init_focal_length_1,
				   cameras, points, colors, pt_views);

        DumpOutputFile(m_output_directory, "bundle.init.out",
                       num_images, 2, curr_num_pts,
                       added_order, cameras, points, colors, pt_views);

		/* Run sfm for the first time */
		double error0;
		error0 = RunSFM(curr_num_pts, 2, 0, false,
				cameras, points, added_order, colors, pt_views);

		printf("  focal lengths: %0.3f, %0.3f\n", cameras[0].f, cameras[1].f);
#if 1
		if (m_fix_necker) {
			/* Swap the cameras and flip the depths to deal with Necker
			 * reversal */

			camera_params_t cameras_old[2];
			v3_t *points_old;

			points_old = new v3_t [curr_num_pts];

			memcpy(points_old, points, sizeof(v3_t) * curr_num_pts);
			memcpy(cameras_old, cameras, sizeof(camera_params_t) * 2);

			camera_params_t tmp = cameras[0];
			memcpy(cameras[0].R, cameras[1].R, sizeof(double) * 9);
			memcpy(cameras[0].t, cameras[1].t, sizeof(double) * 3);
			cameras[0].f = init_focal_length_0;
			cameras[0].k[0] = cameras[0].k[1] = 0.0;

			memcpy(cameras[1].R, tmp.R, sizeof(double) * 9);
			memcpy(cameras[1].t, tmp.t, sizeof(double) * 3);
			cameras[1].f = init_focal_length_1;
			cameras[1].k[0] = cameras[1].k[1] = 0.0;
	
			double K1inv[9] = 
			{ 1.0 / cameras[0].f, 0.0, 0.0,
			  0.0, 1.0 / cameras[0].f, 0.0,
			  0.0, 0.0, 1.0 };

			double K2inv[9] = 
			{ 1.0 / cameras[1].f, 0.0, 0.0,
			  0.0, 1.0 / cameras[1].f, 0.0,
			  0.0, 0.0, 1.0 };

			for (int i = 0; i < curr_num_pts; i++) {
				int k1 = pt_views[i][0].second;
				int k2 = pt_views[i][1].second;

				double proj1[3] = { GetKey(added_order[0],k1).m_x,
							GetKey(added_order[0],k1).m_y,
							-1.0 };
		
				double proj2[3] = { GetKey(added_order[1],k2).m_x,
							GetKey(added_order[1],k2).m_y,
							-1.0 };

				double proj1_norm[3], proj2_norm[3];
		
				matrix_product(3, 3, 3, 1, K1inv, proj1, proj1_norm);
				matrix_product(3, 3, 3, 1, K2inv, proj2, proj2_norm);

				v2_t p = v2_new(proj1_norm[0] / proj1_norm[2],
						proj1_norm[1] / proj1_norm[2]);
	    
				v2_t q = v2_new(proj2_norm[0] / proj2_norm[2],
						proj2_norm[1] / proj2_norm[2]);

				double proj_error;
		
				double t1[3];
				double t2[3];
			
				/* Put the translation in standard form */
				matrix_product(3, 3, 3, 1, cameras[0].R, cameras[0].t, t1);
				matrix_scale(3, 1, t1, -1.0, t1);
				matrix_product(3, 3, 3, 1, cameras[1].R, cameras[1].t, t2);
				matrix_scale(3, 1, t2, -1.0, t2);
		
				points[i] = triangulate(p, q, 
										cameras[0].R, t1, cameras[1].R, t2,
										&proj_error);
			}

			double error1;
			error1 = RunSFM(curr_num_pts, 2, 0, false,
					cameras, points, added_order, colors, pt_views);
		}
#endif
		DumpPointsToPly(m_output_directory, "points001.ply", 
                        curr_num_pts, 2, points, colors, cameras);

		if (m_bundle_output_base != NULL) {
			char buf[256];
			sprintf(buf, "%s%03d.out", m_bundle_output_base, 1);
			DumpOutputFile(m_output_directory, buf, num_images, 2, curr_num_pts,
				   added_order, cameras, points, colors, pt_views);
		}

		curr_num_cameras = 2;
    } 
	else {
		curr_num_cameras = num_init_cams;
		pt_count = curr_num_pts = (int) m_point_data.size();
    }
    
    int round = 0;
    while (curr_num_cameras < num_images) {
		int parent_idx;
		int max_cam = 
            FindCameraWithMostMatches(curr_num_cameras, curr_num_pts, 
                                      added_order, parent_idx, 
                                      max_matches, pt_views);

		printf("[BundleAdjust] max_matches = %d\n", max_matches);

		if (max_matches < m_min_max_matches)
	    break; /* No more connections */

		/* Find all images with 75% of the matches of the maximum 
         * (unless overruled by m_num_points_add_camera) */
		std::vector<ImagePair> image_set;

        if (false && max_matches < 48) { /* disabling this */
            image_set.push_back(ImagePair(max_cam, parent_idx));
        } else {
            int nMatches = iround(0.75 * max_matches);

            if (m_num_matches_add_camera > 0) {
                /* Alternate threshold based on user parameter */
                nMatches = std::min(nMatches, m_num_matches_add_camera);
            }

			image_set = 
                FindCamerasWithNMatches(nMatches,
                                        curr_num_cameras, curr_num_pts, 
                                        added_order, pt_views);
        }
        
		int num_added_images = (int) image_set.size();

		printf("[BundleAdjustFast] Registering %d images\n",
			   num_added_images);

		for (int i = 0; i < num_added_images; i++)
			printf("[BundleAdjustFast] Adjusting camera %d\n",
			   image_set[i].first);

	/* Now, throw the new cameras into the mix */
    int image_count = 0;
	for (int i = 0; i < num_added_images; i++) {
	    int next_idx = image_set[i].first;
	    int parent_idx = image_set[i].second;

	    added_order[curr_num_cameras + image_count] = next_idx;

	    printf("[BundleAdjust[%d]] Adjusting camera %d "
		   "(parent = %d)\n", 
		   round, next_idx, 
                   (parent_idx == -1 ? -1 : added_order[parent_idx]));

	    /* **** Set up the new camera **** */
        bool success = false;
        camera_params_t camera_new = 
		BundleInitializeImage(m_image_data[next_idx], 
				    next_idx, 
                    curr_num_cameras + image_count,
				    curr_num_cameras, curr_num_pts,
				    added_order, points, 
				    NULL, cameras, 
				    pt_views, &success);

        if (success) {
            cameras[curr_num_cameras+image_count] = camera_new;
            image_count++;
        } else {
            printf("[BundleAdjust] Couldn't initialize image %d\n",
                    next_idx);
            m_image_data[next_idx].m_ignore_in_bundle = true;
        }
	}
	

	/* Compute the distance between the first pair of cameras */
    double dist0 = 0.0;
	printf("[BundleAdjust] Adding new matches\n");

	pt_count = curr_num_pts;
	
	curr_num_cameras += image_count;

        if (!m_skip_add_points) {
            pt_count = 
                BundleAdjustAddAllNewPoints(pt_count, curr_num_cameras,
                                            added_order, cameras, 
                                            points, colors,
                                            dist0, pt_views);
        }
        
	curr_num_pts = pt_count;

	printf("[BundleAdjust] Number of points = %d\n", pt_count);
	fflush(stdout);

        if (!m_skip_full_bundle) {
            /* Run sfm again to update parameters */
            RunSFM(curr_num_pts, curr_num_cameras, 0, false,
                   cameras, points, added_order, colors, pt_views);

            /* Remove bad points and cameras */
            RemoveBadPointsAndCameras(curr_num_pts, curr_num_cameras + 1, 
                                      added_order, cameras, points, colors, 
                                      pt_views);

            printf("  focal lengths:\n");
	
            for (int i = 0; i < curr_num_cameras; i++) {
                if(m_image_data[added_order[i]].m_has_init_focal) {
                    printf("   [%03d] %0.3f (%0.3f) %s %d; %0.3e %0.3e\n", 
                           i, cameras[i].f, 
                           m_image_data[added_order[i]].m_init_focal,
                           m_image_data[added_order[i]].m_name,
                           added_order[i], cameras[i].k[0], cameras[i].k[1]);
                } else {
                    printf("   [%03d] %0.3f %s %d; %0.3e %0.3e\n", 
                           i, cameras[i].f, 
                           m_image_data[added_order[i]].m_name,
                           added_order[i], cameras[i].k[0], cameras[i].k[1]);
                }
                // printf("   [%03d] %0.3f\n", i, cameras[i].f);
            }

            fflush(stdout);
        }

	/* Dump output for this round */
	char buf[256];
	sprintf(buf, "points%03d.ply", curr_num_cameras);

	DumpPointsToPly(m_output_directory, buf, 
                        curr_num_pts, curr_num_cameras, 
                        points, colors, cameras);

	if (m_bundle_output_base != NULL) {
	    sprintf(buf, "%s%03d.out", m_bundle_output_base, 
                    curr_num_cameras);
	    DumpOutputFile(m_output_directory, buf, 
                           num_images, curr_num_cameras, curr_num_pts,
			   added_order, cameras, points, colors, pt_views);
	}

	round++;
    }//while

    clock_t end = clock();

    printf("[BundleAdjust] Bundle adjustment took %0.3fs\n",
	   (end - start) / ((double) CLOCKS_PER_SEC));

    if (m_estimate_ignored) {
        EstimateIgnoredCameras(curr_num_cameras,
                               cameras, added_order,
                               curr_num_pts, points, colors, pt_views);
    }

    /* Dump output */
    if (m_bundle_output_file != NULL) {
	DumpOutputFile(m_output_directory, m_bundle_output_file, 
		       num_images, curr_num_cameras, curr_num_pts,
		       added_order, cameras, points, colors, pt_views);
    }

    /* Save the camera parameters and points */

    /* Cameras */
    for (int i = 0; i < num_images; i++) {
	m_image_data[i].m_camera.m_adjusted = false;
    }

    for (int i = 0; i < curr_num_cameras; i++) {
		int img = added_order[i];

		m_image_data[img].m_camera.m_adjusted = true;
		memcpy(m_image_data[img].m_camera.m_R, cameras[i].R, 
			   9 * sizeof(double));

        matrix_product(3, 3, 3, 1, 
                       cameras[i].R, cameras[i].t,
                       m_image_data[img].m_camera.m_t);

        matrix_scale(3, 1, 
                     m_image_data[img].m_camera.m_t, -1.0, 
                     m_image_data[img].m_camera.m_t);	    

		m_image_data[img].m_camera.m_focal = cameras[i].f;

		m_image_data[img].m_camera.Finalize();
		}

    /* Points */
    for (int i = 0; i < curr_num_pts; i++) {
	/* Check if the point is visible in any view */
	if ((int) pt_views[i].size() == 0) 
	    continue; /* Invisible */
	
	PointData pdata;
	pdata.m_pos[0] = Vx(points[i]);
	pdata.m_pos[1] = Vy(points[i]);
	pdata.m_pos[2] = Vz(points[i]);

	pdata.m_color[0] = (float) Vx(colors[i]);
	pdata.m_color[1] = (float) Vy(colors[i]);
	pdata.m_color[2] = (float) Vz(colors[i]);

#if 1
	for (int j = 0; j < (int) pt_views[i].size(); j++) {
	    int v = pt_views[i][j].first;
	    int vnew = added_order[v];
	    pdata.m_views.push_back(ImageKey(vnew, pt_views[i][j].second));
	}
#else
	pdata.m_views = pt_views[i];
#endif

	m_point_data.push_back(pdata);
    }

    delete [] added_order;
    delete [] added_order_inv;

    SetMatchesFromPoints();

    bool *image_mask = new bool[num_images];

    for (int i = 0; i < num_images; i++) {
	if (m_image_data[i].m_camera.m_adjusted)
	    image_mask[i] = true;
	else 
	    image_mask[i] = false;
    }
}