Пример #1
0
Mat leastSquaresTransform(vector<R3> & src, vector<R3> & dst, vector<int> & indexes)
{
	//M x src = dst
	Mat ret;
	Mat src_m = Mat::zeros(4, indexes.size(), CV_32FC1);
	Mat dst_m = Mat::zeros(4, indexes.size(), CV_32FC1);
	for(int i = 0; i < indexes.size(); i++)
	{
		src_m.at<float>(0, i) = src[i].x;
		src_m.at<float>(1, i) = src[i].y;
		src_m.at<float>(2, i) = src[i].z;
		src_m.at<float>(3, i) = 1.0f;

		int j = indexes[i];

		dst_m.at<float>(0, i) = dst[j].x;
		dst_m.at<float>(1, i) = dst[j].y;
		dst_m.at<float>(2, i) = dst[j].z;
		dst_m.at<float>(3, i) = 1.0f;
	}
	//src^T x M^T = dst^T
	src_m = src_m.t();
	dst_m = dst_m.t();
	Mat Mt = least_squares(src_m, dst_m);
	Mat M = Mt.t();
	return M.clone();
}
Пример #2
0
QPair<Vector3D,Vector3D> calcBestAxisThroughPoints( const QVector<Vector3D>& points )
{
    float a[3], b[3];
    int n = points.count();
    QVector<float> buf;
    buf.resize(3*n);
    for (int i = 0; i < n; i++) {
        buf[i] = points[i].x;
        buf[n + i] = points[i].y;
        buf[2*n + i] = points[i].z;
    }

    least_squares(n, buf.data(), a, b);
    least_squares(n, buf.data() + n, a + 1, b + 1);
    least_squares(n, buf.data() + 2*n, a + 2, b + 2);

    Vector3D pointA(b[0], b[1], b[2]);
    Vector3D pointB(a[0]*(n-1) + b[0], a[1]*(n-1) + b[1], a[2]*(n-1) + b[2]);

    return QPair<Vector3D,Vector3D>(pointA, pointB);
}
Пример #3
0
static int find_affine(int np, double *pts1, double *pts2, double *mat) {
  const int np2 = np * 2;
  double *a = (double *)aom_malloc(sizeof(*a) * (np2 * 7 + 42));
  double *b = a + np2 * 6;
  double *temp = b + np2;
  int i;
  double sx, sy, dx, dy;

  double T1[9], T2[9];
  normalize_homography(pts1, np, T1);
  normalize_homography(pts2, np, T2);

  for (i = 0; i < np; ++i) {
    dx = *(pts2++);
    dy = *(pts2++);
    sx = *(pts1++);
    sy = *(pts1++);

    a[i * 2 * 6 + 0] = sx;
    a[i * 2 * 6 + 1] = sy;
    a[i * 2 * 6 + 2] = 0;
    a[i * 2 * 6 + 3] = 0;
    a[i * 2 * 6 + 4] = 1;
    a[i * 2 * 6 + 5] = 0;
    a[(i * 2 + 1) * 6 + 0] = 0;
    a[(i * 2 + 1) * 6 + 1] = 0;
    a[(i * 2 + 1) * 6 + 2] = sx;
    a[(i * 2 + 1) * 6 + 3] = sy;
    a[(i * 2 + 1) * 6 + 4] = 0;
    a[(i * 2 + 1) * 6 + 5] = 1;

    b[2 * i] = dx;
    b[2 * i + 1] = dy;
  }
  if (!least_squares(6, a, np2, 6, b, temp, mat)) {
    aom_free(a);
    return 1;
  }
  denormalize_affine_reorder(mat, T1, T2);
  aom_free(a);
  return 0;
}
// Use bundle adjustment to compute global alignment from initial
// alignment.
int bundleAdjust(const vector<FeatureSet> &fs, MotionModel m, float f, int width, int height, const AlignMatrix &am, vector<CTransform3x3> &ms, int bundleAdjustIters) {
	int n = ms.size();
	int nEqs = 0;
	double lastTotalError = 0;
	double lambda = 1;
	CVector3 p,q;
	vector<CTransform3x3> msTemp(n);

	// count the total number of inliers
	for (int i=0; i<n; i++) {
		for (int j=0; j<n; j++) {
			nEqs += 3*am[i][j].inliers.size();
		}
	}

	// compute the initial total error
	for (int i=0; i<n; i++) {
		for (int j=0; j<n; j++) {
			int s = am[i][j].inliers.size();
			for (int k=0; k<s; k++) {
				int index1 = am[i][j].inliers[k];
				int index2 = am[i][j].matches[index1].id - 1;

				p[0] = fs[i][index1].x - (width/2.0);
				p[1] = fs[i][index1].y - (height/2.0);
				p[2] = f;

				q[0] = fs[j][index2].x - (width/2.0);
				q[1] = fs[j][index2].y - (height/2.0);
				q[2] = f;

				p = ms[i].Transpose() * p.Normalize();
				q = ms[j].Transpose() * q.Normalize();

				lastTotalError += pow(p[0]-q[0],2);
				lastTotalError += pow(p[1]-q[1],2);
				lastTotalError += pow(p[2]-q[2],2);
			}
		}
	}

	printf("initial error %f\n", f*sqrt(3*lastTotalError/nEqs));

	// create the least squares matrices
	matrix A(nEqs);
	for (int i=0; i<nEqs; i++) {
		A[i].resize(3*n);
		for (int j=0; j<3*n; j++) {
			A[i][j] = 0;
		}
	}
	vector<double> b(nEqs);

	for (int iter=0; iter<bundleAdjustIters; iter++) {
		printf("performing iteration %d of bundle adjustment, ", iter);

		int currentEq = 0;
		double totalError = 0;

		// clear the A matrix
		for (int i=0; i<nEqs; i++)
			for (int j=0; j<3*n; j++)
				A[i][j] = 0;

		// fill in the entries
		for (int i=0; i<n; i++) {
			for (int j=0; j<n; j++) {
				int s = am[i][j].inliers.size();
				for (int k=0; k<s; k++) {
					int index1 = am[i][j].inliers[k];
					int index2 = am[i][j].matches[index1].id - 1;

					int var1 = 3*i;
					int var2 = 3*j;

					// BEGIN TODO
					// fill in the three equations for this match
					//
					// that is, fill in the entries for the rows
					// A[currentEq], A[currentEq+1], and A[currentEq+2]
					//
					// hint: only columns var1, var1+1, var1+2, and
					// columns var2, var2+1, var2+2 will be nonzero


					// END TODO

					currentEq += 3;
				}
			}
		}

		// solve the system of equations
		vector<double> x;
		least_squares(A,b,x,lambda);

		// update the rotation matrices
		for (int i=0; i<n; i++) {
			double wx = x[3*i+0];
			double wy = x[3*i+1];
			double wz = x[3*i+2];

			// BEGIN TODO
			// update the ith rotation matrix
			// and store it in msTemp[i]
			//
			// you'll need to use the Rodriguez rule from the slides


			// END TODO
		}

		// compute the new total error
		for (int i=0; i<n; i++) {
			for (int j=0; j<n; j++) {
				int s = am[i][j].inliers.size();
				for (int k=0; k<s; k++) {
					int index1 = am[i][j].inliers[k];
					int index2 = am[i][j].matches[index1].id - 1;

					p[0] = fs[i][index1].x - (width/2.0);
					p[1] = fs[i][index1].y - (height/2.0);
					p[2] = f;

					q[0] = fs[j][index2].x - (width/2.0);
					q[1] = fs[j][index2].y - (height/2.0);
					q[2] = f;

					p = msTemp[i].Transpose() * p.Normalize();
					q = msTemp[j].Transpose() * q.Normalize();

					totalError += pow(p[0]-q[0],2);
					totalError += pow(p[1]-q[1],2);
					totalError += pow(p[2]-q[2],2);
				}
			}
		}

		if (totalError > lastTotalError) {
			// error increased, don't use new transformations
			lambda *= 10;
			printf("error increased to %f, increasing lambda to %f\n", f*sqrt(3*totalError/nEqs), lambda);
		}
		else if (totalError < lastTotalError) {
			// error decreased, use new transformations
			lambda /= 10;
			ms = msTemp;
			lastTotalError = totalError;
			printf("error decreased to %f, decreasing lambda to %f\n", f*sqrt(3*totalError/nEqs), lambda);
		}
		else {
			// error converged, we can stop
			printf("error converged at %f\n", f*sqrt(3*totalError/nEqs));
			break;
		}
	}

	return 0;
}
Пример #5
0
void calculate_cell_reconstruction_matrices(int n_variables, double *weight_exponent, int *maximum_order, struct FACE *face, int n_cells, struct CELL *cell, struct ZONE *zone)
{
	int c, u, i, j, k, l;

	int order, n_powers, n_stencil;

	//find the overall maximum order
	int maximum_maximum_order = 0;
	for(u = 0; u < n_variables; u ++) if(maximum_order[u] > maximum_maximum_order) maximum_maximum_order = maximum_order[u];

	//cell structure allocation
	for(c = 0; c < n_cells; c ++) exit_if_false(cell_matrix_new(n_variables, &cell[c]),"allocating cell matrices");

	//numerics values
	double **matrix, *weight;
	int n_constraints, *constraint;
	exit_if_false(allocate_double_matrix(&matrix,ORDER_TO_POWERS(maximum_maximum_order),MAX_STENCIL),"allocating matrix");
	exit_if_false(allocate_integer_vector(&constraint,MAX_STENCIL),"allocating constraints");
	exit_if_false(allocate_double_vector(&weight,MAX_STENCIL),"allocating weights");

	//stencil element properties
	int s_id, s_index;
	struct ZONE *s_zone;
	char s_location, *s_condition;
	double s_area, *s_centroid, s_weight;

	//integration
	double x[2];
	int differential[2], d;

	//CV polygon
	int n_polygon;
	double ***polygon;
	exit_if_false(allocate_double_pointer_matrix(&polygon,MAX(MAX_CELL_FACES,4),2),"allocating polygon memory");

	for(c = 0; c < n_cells; c ++)
	{
		for(u = 0; u < n_variables; u ++)
		{
			//problem size
			order = cell[c].order[u];
			n_powers = ORDER_TO_POWERS(order);
			n_stencil = cell[c].n_stencil[u];
			n_constraints = 0;

			for(i = 0; i < n_stencil; i ++)
			{
				//stencil element properties
				s_id = cell[c].stencil[u][i];
				s_index = ID_TO_INDEX(s_id);
				s_zone = &zone[ID_TO_ZONE(s_id)];
				s_location = s_zone->location;
				s_condition = s_zone->condition;

				if(s_location == 'f') {
					s_centroid = face[s_index].centroid;
					s_area = face[s_index].area;
				} else if(s_location == 'c') {
					s_centroid = cell[s_index].centroid;
					s_area = cell[s_index].area;
				} else exit_if_false(0,"recognising zone location");

				s_weight  = (s_centroid[0] - cell[c].centroid[0])*(s_centroid[0] - cell[c].centroid[0]);
				s_weight += (s_centroid[1] - cell[c].centroid[1])*(s_centroid[1] - cell[c].centroid[1]);
				s_weight  = 1.0/pow(s_weight,0.5*weight_exponent[u]);
				if(s_location == 'c' && s_index == c) s_weight = 1.0;

				weight[i] = s_weight;

				//unknown and dirichlet conditions have zero differentiation
				differential[0] = differential[1] = 0;
				//other conditions have differential determined from numbers of x and y-s in the condition string
				if(s_condition[0] != 'u' && s_condition[0] != 'd')
				{
					j = 0;
					while(s_condition[j] != '\0')
					{
						differential[0] += (s_condition[j] == 'x');
						differential[1] += (s_condition[j] == 'y');
						j ++;
					}
				}

				//index for the determined differential
				d = differential_index[differential[0]][differential[1]];

				//unknowns
				if(s_condition[0] == 'u')
				{
					/*//fit unknowns to centroid points
					x[0] = s_centroid[0] - cell[c].centroid[0];
					x[1] = s_centroid[1] - cell[c].centroid[1];

					for(j = 0; j < n_powers; j ++)
					{
						matrix[j][i] = polynomial_coefficient[d][j]*
							integer_power(x[0],polynomial_power_x[d][j])*
							integer_power(x[1],polynomial_power_y[d][j])*
							s_weight;
					}*/

					//fit unknowns to CV average
					n_polygon = generate_control_volume_polygon(polygon, s_index, s_location, face, cell);

					for(j = 0; j < n_powers; j ++) matrix[j][i] = 0.0;

					for(j = 0; j <= order; j ++) 
					{
						for(k = 0; k < n_polygon; k ++)
						{
							x[0] =  0.5*polygon[k][0][0]*(1.0 - gauss_x[order][j]) +
								0.5*polygon[k][1][0]*(1.0 + gauss_x[order][j]) -
								cell[c].centroid[0];
							x[1] =  0.5*polygon[k][0][1]*(1.0 - gauss_x[order][j]) +
								0.5*polygon[k][1][1]*(1.0 + gauss_x[order][j]) -
								cell[c].centroid[1];

							for(l = 0; l < n_powers; l ++)
							{
								//[face integral of polynomial integrated wrt x] * [x normal] / [CV area]
								
								matrix[l][i] += polynomial_coefficient[d][l] *
									(1.0 / (polynomial_power_x[d][l] + 1.0)) *
									integer_power(x[0],polynomial_power_x[d][l]+1) *
									integer_power(x[1],polynomial_power_y[d][l]) *
									s_weight * gauss_w[order][j] * 0.5 *
									(polygon[k][1][1] - polygon[k][0][1]) / s_area;
							}
						}
					}
				}

				//knowns
				else
				{
					//known faces fit to face average
					if(s_location == 'f')
					{
						for(j = 0; j < n_powers; j ++) matrix[j][i] = 0.0;

						for(j = 0; j < order; j ++)
						{
							x[0] =  0.5*face[s_index].node[0]->x[0]*(1.0 - gauss_x[order-1][j]) +
								0.5*face[s_index].node[1]->x[0]*(1.0 + gauss_x[order-1][j]) - 
								cell[c].centroid[0];
							x[1] =  0.5*face[s_index].node[0]->x[1]*(1.0 - gauss_x[order-1][j]) +
								0.5*face[s_index].node[1]->x[1]*(1.0 + gauss_x[order-1][j]) -
								cell[c].centroid[1];

							for(k = 0; k < n_powers; k ++)
							{
								matrix[k][i] += polynomial_coefficient[d][k] *
									integer_power(x[0],polynomial_power_x[d][k]) *
									integer_power(x[1],polynomial_power_y[d][k]) *
									s_weight*gauss_w[order-1][j]*0.5;
							}
						}
					}

					//cells need implementing
					//if(s_location == 'c')
					//{
					//}
				}

				//constraints are the centre cell and any dirichlet boundaries
				if((s_location == 'c' && s_index == c) || s_condition[0] == 'd') constraint[n_constraints++] = i;
			}

			//solve
			if(n_constraints > 0)
				exit_if_false(constrained_least_squares(n_stencil,n_powers,matrix,n_constraints,constraint) == LS_SUCCESS, "doing CLS calculation");
			else
				exit_if_false(least_squares(n_stencil,n_powers,matrix) == LS_SUCCESS,"doing LS calculation");

			//multiply by the weights
			for(i = 0; i < n_powers; i ++) for(j = 0; j < n_stencil; j ++) matrix[i][j] *= weight[j];

			//store in the cell structure
			for(i = 0; i < n_powers; i ++) for(j = 0; j < n_stencil; j ++) cell[c].matrix[u][i][j] = matrix[i][j];
		}
	}

	//clean up
	free_matrix((void**)matrix);
	free_vector(constraint);
	free_vector(weight);
	free_matrix((void**)polygon);
}