svd求解刚性转变换矩阵

1 篇文章 0 订阅
1 篇文章 0 订阅

//#include <stdio.h>
//#include <iostream>
//#include <opencv2/opencv.hpp>
//#include <Eigen/Dense>
//
//using namespace Eigen;
//using namespace cv;
//using namespace std;
//
//#define M_PI 3.1415926
//
//void GetPoints(vector<string> fileNames, std::vector<std::vector<Point>>& groupPoints, int Length, int Threshold);
//void Defined_MB_POINT(Eigen::Vector3d MB_POINTS[4]);
//void svdSolveMatrix(Eigen::Vector3d pointInB[4], Eigen::Vector3d pointInA[4], Eigen::Matrix4d& result, double& error);
//void solveMatrix(Eigen::Vector3d pointInB[4], Eigen::Vector3d pointInA[4], Eigen::Matrix4f& result, double& error);
//void solveResult(Eigen::Vector3d pointInB[4], Eigen::Vector3d pointInA[4]);
//int main()
//{
//
//    // 1.0 通过手动标定的点获取点的相关坐标参数, 并实现图像的预处理发过程,主要包括质点中心的计算
//    vector<string> fileNames = {
//    "D:\\imgs\\4.7.jpg",
//      "D:\\imgs\\5.5.jpg",
//      "D:\\imgs\\6.3.jpg",
//      "D:\\imgs\\7.1.jpg",
//      "D:\\imgs\\7.9.jpg",
//      "D:\\imgs\\8.7.jpg",
//      "D:\\imgs\\9.5.jpg"
//    };
//
//    std::vector<std::vector<Point>> groupPoints;
//
//    GetPoints(fileNames, groupPoints, 7, 60);
//
//
//    // 2.0 通过坐标参数与实际距离参数 , 计算spacing
//
//    // 3.0 建立适配矩阵, 该矩阵的建立需要四个点, 采用齐次坐标系表示
//
//
//    waitKey(0);
//    return 0;
//}
//
//
//void GetPoints(vector<string> fileNames, std::vector<std::vector<Point>>& groupPoints, int Length, int Threshold)
//{
//    vector<Mat>  images;
//    Mat m;
//    for (int i = 0; i < Length; i++)
//    {
//        m = imread(fileNames[i], 1);
//        images.push_back(m);
//        //cout << fileNames[i] << endl;
//    }
//    //cout << endl << endl;
//
//
//    // 定义图像的大小
//    int imageWidth = 812, imageHeight = 640;
//
//
//
//    /*将图像二值化*/
//
//    for (int k = 0; k < Length; k++)
//    {
//
//        for (int i = 0; i < images[k].rows; i++)
//        {
//            for (int j = 0; j < images[k].cols; j++)
//            {
//                if (images[k].at<Vec3b>(i, j)[0] < Threshold)
//                {
//                    images[k].at<Vec3b>(i, j)[0] = 0;
//                    images[k].at<Vec3b>(i, j)[1] = 0;
//                    images[k].at<Vec3b>(i, j)[2] = 0;
//                }
//                else {
//                    images[k].at<Vec3b>(i, j)[0] = 255;
//                    images[k].at<Vec3b>(i, j)[1] = 255;
//                    images[k].at<Vec3b>(i, j)[2] = 255;
//                }
//            }
//        }
//    }
//
//    /* 定义图像的截取大小中心, 超声图像就是从该位置截取的*/
//    long Width = 500, height = 450, X = 50, Y = 100;
//    vector<Mat>  oris;
//
//    for (int i = 0; i < Length; i++)
//    {
//        Mat grayimg(images[i], Rect(X, Y, Width, height));
//        oris.push_back(grayimg);
//    }
//
//    /* 找到图像的轮廓, 并求解质心*/
//    vector<vector<Point>>  contours;
//    Moments moment;
//
//    Mat thr, gray;
//    Point p;
//    for (int i = 0; i < Length; i++)
//    {
//        vector<Point> groupPoint;
//        cvtColor(oris[i], gray, COLOR_BGR2GRAY);
//        findContours(gray, contours, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE, Point(0, 0));
//
//        for (int i = 0; i < contours.size(); i++)
//        {
//            Mat temp(contours.at(i));
//            moment = moments(temp, false);
//            if (moment.m00 != 0)//除数不能为0
//            {
//                p.x = cvRound(moment.m10 / moment.m00) + X;//计算重心横坐标
//                p.y = cvRound(moment.m01 / moment.m00) + Y;//计算重心纵坐标
//            }
//            groupPoint.push_back(p);
//        }
//        groupPoints.push_back(groupPoint);
//    }
//
//
//    // 求解像素比
//    double spaxing[7];
//    double read_long = sqrt(5 * 5 + 40 * 40);
//    double read_long1 = sqrt(10 * 10 + 30 * 30);
//    for (int i = 0; i < groupPoints.size(); i++)
//    {
//        for (int j = 0; j < groupPoints[i].size(); j++)
//        {
//            Scalar color(0, 0, 255);
//            circle(images[i], groupPoints[i][j], 3, color, 1, 8);
//            cv::putText(images[i], std::to_string(j), groupPoints[i][j], cv::FONT_HERSHEY_SIMPLEX, 0.45, CV_RGB(255, 230, 0), 1.8);
//        }
//        cv::line(images[i], groupPoints[i][0], groupPoints[i][1], cv::Scalar(255, 255, 0), 1);
//        /*任意取两点计算其实际的像素距离*/
//        double L_IMGGE = sqrt(pow(groupPoints[i][0].x - groupPoints[i][1].x, 2) + pow(groupPoints[i][0].y - groupPoints[i][1].y, 2));
//        double L_IMGGE1 = sqrt(pow(groupPoints[i][2].x - groupPoints[i][3].x, 2) + pow(groupPoints[i][2].y - groupPoints[i][3].y, 2));
//        //spaxing[i] = read_long / L_IMGGE;
//
//        spaxing[i] = ((read_long / L_IMGGE) + (read_long1 / L_IMGGE1)) / 2;
//        cout << read_long / L_IMGGE << "   " << read_long1 / L_IMGGE1 << endl;
//        //cout << spaxing[i] << "  ";
//
//        spaxing[i] = 
//        //imshow(std::to_string(i + 1), images[i]);
//    }
//
//
//    //====================求解同步长为0.8 的像素比增长因子=============================
//    cout << "像素比增长因子:" << endl;
//    for (int i = 0; i < Length; i++)
//    {
//        cout << spaxing[i] << "  ";
//        /*if (i > 0)
//        {
//            cout << spaxing[i] - spaxing[i - 1] << "   ";
//        }        */
//    }
//    cout << endl;
//
//    //=================================================================================
//
//
//
//    /* 定义图像的坐标点(已经计算完成 groupPoints)*/
//    // 将图像坐标根据0,1 两个点做对称变换
//
//    for (int i = 0; i < groupPoints.size(); i++)
//    {
//        double x_axi = groupPoints[i][0].x + (groupPoints[i][1].x - groupPoints[i][0].x) / 2;
//        for (int j = 0; j < 4; j++)
//        {
//            double distance = abs(groupPoints[i][j].x - x_axi);
//
//            if (groupPoints[i][j].x < x_axi) {
//                groupPoints[i][j].x = groupPoints[i][j].x + 2 * distance;
//            }
//            else {
//                groupPoints[i][j].x = groupPoints[i][j].x - 2 * distance;
//            }
//
//            Scalar color(0, 255, 255);
//            circle(images[i], groupPoints[i][j], 3, color, 1, 8);
//            cv::putText(images[i], std::to_string(j), groupPoints[i][j], cv::FONT_HERSHEY_SIMPLEX, 0.45, CV_RGB(255, 230, 0), 1.8);
//            imshow(std::to_string(i + 1), images[i]);
//        }
//    }
//
//    /*定义模板的坐标点===============================================================*/
//    Eigen::Vector3d MB_POINTS[4];
//    Defined_MB_POINT(MB_POINTS);
//    //=================================================================================
//
//    // 像素比参数
//    double spacingPix[7] = { 0.100476 , 0.115214 , 0.130149, 0.144649 , 0.159711 , 0.176296 , 0.190192 };
//    Eigen::Vector3d  US_POINTS[7][4];
//
//    // 原始的对角矩阵无法实现坐标系的转换,因此需要通过-(Y-y)
//    /*Matrix3d dialog;
//    dialog << 1, 0, 0,
//        0, -1, 0,
//        0, 0, 1;*/
//
//    for (int j = 0; j < Length; j++)
//    {
//        //cout << endl << "图像" << j + 1 << " 的超声点矩阵:" << endl;
//        for (int i = 0; i < 4; i++)
//        {
//            double values[3] = { groupPoints[j][i].x,groupPoints[j][i].y,0 };
//            values[1] = values[1] - imageHeight; // 将坐标系从左上变换为左下
//            US_POINTS[j][i] = Eigen::Vector3d(values) * spaxing[i];
//
//            //US_POINTS[j][i] = dialog * Eigen::Vector3d(values) * spacingPix[i];
//            //cout << US_POINTS[j][i].transpose() << " 1" << endl;
//        }
//
//        //Eigen::Matrix4f result;
//        Eigen::Matrix4d result;
//        double error;
//
//        /*实现匹配*/
//        //svdSolveMatrix(US_POINTS[j], MB_POINTS, result, error);
//        //solveMatrix(US_POINTS[j], MB_POINTS, result, error);
//        
//
//        solveResult(US_POINTS[j], MB_POINTS);
//        /*
//        cout << endl << "转换矩阵T:" << endl;
//        cout << result << endl << endl;
//        */
//
//        
//    }
//}
//
//
//
//void Defined_MB_POINT(Eigen::Vector3d MB_POINTS[4])
//{
//    /*下边框距离3.5mm*/
//    /*左右边框距离10mm*/
//
//    double A1[3] = { 60.2,8.8,0 };
//    double A2[3] = { 20.2,13.8,0 };
//    double A3[3] = { 45.2,18.8,0 };
//    double A4[3] = { 15.2,28.8,0 };
//
//    MB_POINTS[0] = Eigen::Vector3d(A1);
//    MB_POINTS[1] = Eigen::Vector3d(A2);
//    MB_POINTS[2] = Eigen::Vector3d(A3);
//    MB_POINTS[3] = Eigen::Vector3d(A4);
//
//    Matrix3d dialog;
//    dialog << 1, 0, 0,
//        0, -1, 0,
//        0, 0, 1;
//
//    //  x 不变,y和z旋转90
//    // 1.0 旋转 : 定义旋转向量
//    Eigen::Vector3d ea(M_PI / 2, 0, -M_PI / 24);
//    //Eigen::Vector3d ea(0, 0, 0);
//    Eigen::Matrix3d rotationMatrix;
//    rotationMatrix = Eigen::AngleAxisd(ea[0], Eigen::Vector3d::UnitX())
//        * Eigen::AngleAxisd(ea[1], Eigen::Vector3d::UnitY())
//        * Eigen::AngleAxisd(ea[2], Eigen::Vector3d::UnitZ());
//
//    /*
//      5.5 深度   Vector3d ea(M_PI / 2, 0, -M_PI / 32)
//       6.3 深度     Vector3d ea(M_PI / 2, 0, -M_PI / 30)
//       7.1 深度 Vector3d ea(M_PI / 2, 0, -M_PI / 26)
//        7.9 深度
//    */
//
//    //cout << "体模:" << endl;
//    /*转化到世界坐标系中*/
//    for (int i = 0; i < 4; i++)
//    {
//        MB_POINTS[i] = rotationMatrix  * MB_POINTS[i];
//        //MB_POINTS[i] = rotationMatrix * dialog * MB_POINTS[i];
//        //cout << MB_POINTS[i].transpose() << " 1" << endl;
//    }
//}
//
//
///*
//  求解两个坐标系之间的转换矩阵
//*/
//void solveResult(Eigen::Vector3d pointInB[4], Eigen::Vector3d pointInA[4])
//{
//
//    /*
//       数据转换, 定义两个数据结构类型
//    */
//    std::vector<cv::Point3f> srcPoints;
//    std::vector<cv::Point3f>  dstPoints;
//
//
//    for (int i : {0, 1, 2})
//    {
//        srcPoints.push_back(cv::Point3f(pointInB[i](0), pointInB[i](1), pointInB[i](2)));
//        dstPoints.push_back(cv::Point3f(pointInA[i](0), pointInA[i](1), pointInA[i](2)));
//    }
//
//
//
//    //==============================================
//    double srcSumX = 0.0f;
//    double srcSumY = 0.0f;
//    double srcSumZ = 0.0f;
//
//    double dstSumX = 0.0f;
//    double dstSumY = 0.0f;
//    double dstSumZ = 0.0f;    
//
//    int pointsNum = srcPoints.size();
//    for (int i = 0; i < pointsNum; ++i)
//    {
//        srcSumX += srcPoints[i].x;
//        srcSumY += srcPoints[i].y;
//        srcSumZ += srcPoints[i].z;
//
//        dstSumX += dstPoints[i].x;
//        dstSumY += dstPoints[i].y;
//        dstSumZ += dstPoints[i].z;
//    }
//
//    cv::Point3d centerSrc, centerDst;
//
//    centerSrc.x = double(srcSumX / pointsNum);
//    centerSrc.y = double(srcSumY / pointsNum);
//    centerSrc.z = double(srcSumZ / pointsNum);
//
//    centerDst.x = double(dstSumX / pointsNum);
//    centerDst.y = double(dstSumY / pointsNum);
//    centerDst.z = double(dstSumZ / pointsNum);
//
//    //Mat::Mat(int rows, int cols, int type)
//    cv::Mat srcMat(3, pointsNum, CV_64FC1);
//    cv::Mat dstMat(3, pointsNum, CV_64FC1);
//
//    for (int i = 0; i < pointsNum; ++i)//N组点
//    {
//        //三行
//        srcMat.at<double>(0, i) = srcPoints[i].x - centerSrc.x;
//        srcMat.at<double>(1, i) = srcPoints[i].y - centerSrc.y;
//        srcMat.at<double>(2, i) = srcPoints[i].z - centerSrc.z;
//
//        dstMat.at<double>(0, i) = dstPoints[i].x - centerDst.x;
//        dstMat.at<double>(1, i) = dstPoints[i].y - centerDst.y;
//        dstMat.at<double>(2, i) = dstPoints[i].z - centerDst.z;
//
//    }
//
//    cv::Mat matS = srcMat * dstMat.t();
//
//    cv::Mat matU, matW, matV;
//    cv::SVDecomp(matS, matW, matU, matV);
//
//    cv::Mat matTemp = matU * matV;
//    double det = cv::determinant(matTemp);//行列式的值
//
//    double datM[] = { 1, 0, 0, 0, 1, 0, 0, 0, det };
//    cv::Mat matM(3, 3, CV_64FC1, datM);
//
//    cv::Mat matR = matV.t() * matM * matU.t();
//
//    double* datR = (double*)(matR.data);
//    double delta_X = centerDst.x - (centerSrc.x * datR[0] + centerSrc.y * datR[1] + centerSrc.z * datR[2]);
//    double delta_Y = centerDst.y - (centerSrc.x * datR[3] + centerSrc.y * datR[4] + centerSrc.z * datR[5]);
//    double delta_Z = centerDst.z - (centerSrc.x * datR[6] + centerSrc.y * datR[7] + centerSrc.z * datR[8]);
//
//
//    //生成RT齐次矩阵(4*4)
//    cv::Mat R_T = (cv::Mat_<double>(4, 4) <<
//        matR.at<double>(0, 0), matR.at<double>(0, 1), matR.at<double>(0, 2), delta_X,
//        matR.at<double>(1, 0), matR.at<double>(1, 1), matR.at<double>(1, 2), delta_Y,
//        matR.at<double>(2, 0), matR.at<double>(2, 1), matR.at<double>(2, 2), delta_Z,
//        0, 0, 0, 1
//        );
//
//    cout << "========================";
//    cout << endl << R_T << endl;
//
//}
//
//void solveMatrix(Eigen::Vector3d pointInB[4], Eigen::Vector3d pointInA[4], Eigen::Matrix4f& result, double& error)
//{
//    // 求解超声 和 模板矩阵的平均中心
//
//    Eigen::Matrix4f B;
//    Eigen::Matrix4f A;
//    Eigen::Matrix4f repmat_A;
//    Eigen::Matrix4f repmat_B;
//
//    Eigen::Matrix4f H;
//
//    // 将数组转化为矩阵
//    for (int i : {0, 1, 2, 3})
//    {
//        B.row(i) << pointInB[i](0), pointInB[i](1), pointInB[i](2), 1;
//        A.row(i) << pointInA[i](0), pointInA[i](1), pointInA[i](2), 1;
//    }
//
//    // 求解平均中心
//    Eigen::Vector4f centriod_A;
//    Eigen::Vector4f centriod_B;
//    for (int i : {0, 1, 2, 3})
//    {
//        float  value = (float)((A.row(0) + A.row(1) + A.row(2) + A.row(3)) / 4)[i];
//        centriod_A(i) = value;
//        value = (float)((B.row(0) + B.row(1) + B.row(2) + B.row(3)) / 4)[i];
//        centriod_B(i) = value;
//    }
//
//    //创建均值矩阵
//    for (int i : {0, 1, 2, 3})
//    {
//        repmat_A.row(i) << centriod_A(0), centriod_A(1), centriod_A(2), centriod_A(3);
//        repmat_B.row(i) << centriod_B(0), centriod_B(1), centriod_B(2), centriod_B(3);
//    }
//
//    // 创建均值矩阵的原理在于将所有的点移动到原点。
//
//    H = (A - repmat_A).transpose() * (B - repmat_B);
//
//    MatrixXf Hm;
//
//    std::vector < std::vector < float >> vec;
//    const int rows{ 4 }, cols{ 4 };
//    for (int i : {0, 1, 2, 3})
//    {
//        std::vector<float> vec1;
//        for (int j : {0, 1, 2, 3})
//        {
//            vec1.push_back((float)H.row(i)[j]);
//        }
//        vec.push_back(vec1);
//    }
//
//    std::vector<float> vec_;
//    for (int i = 0; i < rows; ++i) {
//        vec_.insert(vec_.begin() + i * cols, vec[i].begin(), vec[i].end());
//    }
//    Eigen::Map<Eigen::Matrix<float, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor>> m(vec_.data(), rows, cols);
//
//    Eigen::JacobiSVD<Eigen::MatrixXf> svd(m, Eigen::ComputeFullV | Eigen::ComputeFullU); // ComputeThinU | ComputeThinV
//    Eigen::MatrixXf singular_values = svd.singularValues();
//    Eigen::MatrixXf left_singular_vectors = svd.matrixU();
//    Eigen::MatrixXf right_singular_vectors = svd.matrixV();
//
//
//    Eigen::MatrixXf  R = right_singular_vectors * left_singular_vectors.transpose();
//
//    //cout << "determinant:" << R.determinant() << endl;
//
//    cout << "====================" << endl;
//
//    if (R.determinant() < 0)
//    {
//        //cout << "V" << right_singular_vectors << endl;
//        for (int i = 0; i < 4; i++)
//        {
//            right_singular_vectors.row(i)(2) = -1 * right_singular_vectors.row(i)(2);
//        }
//        //cout << "-V" << right_singular_vectors << endl;
//        R = right_singular_vectors * left_singular_vectors.transpose();
//    }
//
//    Eigen::Vector4f t = -R * centriod_A + centriod_A;
//
//    R.row(0)(3) = t(0);
//    R.row(1)(3) = t(1);
//    R.row(2)(3) = t(2);
//    R.row(3)(3) = 1;
//    cout << endl << R << endl << endl;
//}
//
//void svdSolveMatrix(Eigen::Vector3d pointInB[4], Eigen::Vector3d pointInA[4], Eigen::Matrix4d& result, double& error)
//{
//    //解空间
//    Eigen::Vector4d r1, r2, r3, r4;
//
//    系数矩阵
//    Eigen::Matrix4d matrix;
//
//    //超声的z轴数据均为0 ,因此矩阵的第三列的值没有办法解出来,通过z轴 = x 和 y的叉乘即可得出    
//    for (int i : {0, 1, 2, 3})
//    {
//        matrix.row(i) << pointInB[i](0), pointInB[i](1), pointInB[i](2), 1.0;
//    }
//
//    Eigen::Vector4d vector1;
//    vector1 << pointInA[0](0), pointInA[1](0), pointInA[2](0), pointInA[3](0);
//
//    Eigen::Vector4d vector2;
//    vector2 << pointInA[0](1), pointInA[1](1), pointInA[2](1), pointInA[3](1);
//
//    Eigen::Vector4d vector3;
//    vector3 << pointInA[0](2), pointInA[1](2), pointInA[2](2), pointInA[3](2);
//
//    r1 = matrix.colPivHouseholderQr().solve(vector1);
//    r2 = matrix.colPivHouseholderQr().solve(vector2);
//    r3 = matrix.colPivHouseholderQr().solve(vector3);
//
//    result.row(0) << r1(0), r1(1), r1(2), r1(3);
//    result.row(1) << r2(0), r2(1), r2(2), r2(3);
//    result.row(2) << r3(0), r3(1), r3(2), r3(3);
//    result.row(3) << 0, 0, 0, 1;
//
//
//    /* 求解z空间向量*/
//    Eigen::Vector3d v1, v2, v3;
//    v1 << r1(0), r2(0), r3(0);
//    v1.normalize();
//
//    v2 << r1(1), r2(1), r3(1);
//    v2.normalize();
//
//    v3 = v1.cross(v2);
//
//    result(0, 2) = v3(0);
//    result(1, 2) = v3(1);
//    result(2, 2) = v3(2);
//
//    cout << endl << result << endl << endl;
//
//
//}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值