コード例 #1
1
ファイル: icp.cpp プロジェクト: caomw/opencv-rgbd
ICP_API float __stdcall ICP(Point3f *verts1, Point3f *verts2, int nVerts1, int nVerts2, float *R, float *t, int maxIter)
{
	PointCloud cloud1;
	cloud1.pts = vector<Point3f>(verts1, verts1 + nVerts1);

	cv::Mat matR(3, 3, CV_32F, R);
	cv::Mat matT(1, 3, CV_32F, t);

	cv::Mat verts2Mat(nVerts2, 3, CV_32F, (float*)verts2);

	float error = 1;

	for (int iter = 0; iter < maxIter; iter++)
	{
		vector<Point3f> matched1, matched2;

		vector<float> distances(nVerts2);
		vector<size_t> indices(nVerts2);
		FindClosestPointForEach(cloud1, verts2Mat, distances, indices);

		vector<float> matchDistances;
		vector<int> matchIdxs(nVerts1, -1);
		for (int i = 0; i < nVerts2; i++)
		{
			int pos = matchIdxs[indices[i]];

			if (pos != -1)
			{
				if (matchDistances[pos] < distances[i])
					continue;
			}

			Point3f temp;
			temp.X = verts2Mat.at<float>(i, 0);
			temp.Y = verts2Mat.at<float>(i, 1);
			temp.Z = verts2Mat.at<float>(i, 2);

			if (pos == -1)
			{
				matched1.push_back(verts1[indices[i]]);
				matched2.push_back(temp);

				matchDistances.push_back(distances[i]);

				matchIdxs[indices[i]] = matched1.size() - 1;
			}
			else
			{
				matched2[pos] = temp;
				matchDistances[pos] = distances[i];
			}
		}

		RejectOutlierMatches(matched1, matched2, matchDistances, 2.5);

		//error = 0;
		//for (int i = 0; i < matchDistances.size(); i++)
		//{
		//	error += sqrt(matchDistances[i]);
		//}
		//error /= matchDistances.size();
		//cout << error << endl;

		cv::Mat matched1MatCv(matched1.size(), 3, CV_32F, matched1.data());
		cv::Mat matched2MatCv(matched2.size(), 3, CV_32F, matched2.data());
		cv::Mat tempT;
		cv::reduce(matched1MatCv - matched2MatCv, tempT, 0, CV_REDUCE_AVG);

		for (int i = 0; i < verts2Mat.rows; i++)
		{
			verts2Mat.row(i) += tempT;
		}
		for (int i = 0; i < matched2MatCv.rows; i++)
		{
			matched2MatCv.row(i) += tempT;
		}

		cv::Mat M = matched2MatCv.t() * matched1MatCv;
		cv::SVD svd;
		svd(M);
		cv::Mat tempR = svd.u * svd.vt;

		double det = cv::determinant(tempR);
		if (det < 0)
		{
			cv::Mat temp = cv::Mat::eye(3, 3, CV_32F);
			temp.at<float>(2, 2) = -1;
			tempR = svd.u * temp * svd.vt;
		}

		verts2Mat = verts2Mat * tempR;

		matT += tempT * matR.t();
		matR = matR * tempR;
	}

	memcpy(verts2, verts2Mat.data, verts2Mat.rows * sizeof(float) * 3);

	memcpy(R, matR.data, 9 * sizeof(float));
	memcpy(t, matT.data, 3 * sizeof(float));

	return error;
}
コード例 #2
0
ファイル: ajmath.cpp プロジェクト: Ajdorr/ajLib
VectorN& leastSquaresApproximation(VectorN &x,
                                  VectorN &y,
                                  unsigned int deg)
{
    unsigned int i, j;
    unsigned int dim = x.dim();
    deg++; // this is because we need an extra spot

    if (x.dim() != y.dim()) {
        // cerr << "leastSquaresApproximation: Dimensions do not match" << endl;
        return y;
    }

    Matrix mat(dim, deg);
    for (i = 0; i < dim; i++) {
        mat[i][0] = 1;
        for (j = 1; j < deg; j++) {
            mat[i][j] = mat[i][j-1]*x[i];
        }
    }

    Matrix matT(mat);
    matT.trans();

    // cout << mat << endl << endl;
    // cout << matT << endl;
    // cout << sol << endl << endl;

    y *= matT;
    // cout << sol << endl;

    (matT*mat).rref(y);

    return y;
}