opencv PCA 主轴方向角度范围

PCA 主轴方向角度,范围    [-45,135] 
点集排序(从左到右、从右至左)不同,角度在-45度时有差异

double calLineOrientationInDegree(const vector<Point>& pts)
{
    //Construct a buffer used by the pca analysis
    int sz = static_cast<int>(pts.size());
    Mat data_pts = Mat(sz, 2, CV_64F);
    for (int i = 0; i < data_pts.rows; i++)
    {
        data_pts.at<double>(i, 0) = pts[i].x;
        data_pts.at<double>(i, 1) = pts[i].y;
    }
    //Perform PCA analysis
    PCA pca_analysis(data_pts, Mat(), PCA::DATA_AS_ROW);
    //Store the center of the object
    Point2d cntr = Point2d(static_cast<double>(pca_analysis.mean.at<double>(0, 0)),
        static_cast<double>(pca_analysis.mean.at<double>(0, 1)));
    //Store the eigenvalues and eigenvectors
    vector<Point2d> eigen_vecs(2);
    vector<double> eigen_val(2);
    for (int i = 0; i < 2; i++)
    {
        eigen_vecs[i] = Point2d(pca_analysis.eigenvectors.at<double>(i, 0),
            pca_analysis.eigenvectors.at<double>(i, 1));
        eigen_val[i] = pca_analysis.eigenvalues.at<double>(i);
    }
    
    eigenVecs = eigen_vecs;
    double angle = atan2(eigen_vecs[0].y, eigen_vecs[0].x) * 180 / 3.1415926; // orientation in degrees 
    return angle;
}

// 测试PCA 主轴角度范围
// 点集从左到右,从右到左
void test_PCA_mainAxis_AngleRange()
{
    // 构造点集
    double angle = 10;
    //int ang = 135;
    for (int ang = 0;ang < 365;ang += 5)
    {
        angle = ang;
        cv::Mat white(1000, 1000, CV_8UC3, Scalar(255, 255, 255));
        std::vector<cv::Point> pts;
        pts.clear();
        double vsin = sin(angle / 180.0 * 3.1415926);
        double vcos = cos(angle / 180.0 * 3.1415926);
        Point offset(300, 300);
        for (int i = 0;i < 200;i++)
        {

            int px = int(double(i) * vcos) + offset.x;
            int py = int(double(i) * vsin) + offset.y;

            Point pt(px, py);
            pts.push_back(pt);
            circle(white, pt, 3, Scalar(0, 0, 255), -1);
        }
        // 排序 
        std::sort(pts.begin(), pts.end(), [](Point& p1, Point& p2) {
            return p1.x < p2.x;
            });

        // 计算pca 角度
        double pac_angle = calLineOrientationInDegree(pts);
        cv::putText(white, cv::format("%.1f", pac_angle), Point(30, 30), cv::FONT_HERSHEY_PLAIN, 2, Scalar(255, 0, 20), 2);

        // 从右向左
        std::sort(pts.begin(), pts.end(), [](Point& p1, Point& p2) {
            return p1.x > p2.x;
            });
        double pac_angle2 = calLineOrientationInDegree(pts);
        cv::putText(white, cv::format("%.1f", pac_angle2), Point(130, 30), cv::FONT_HERSHEY_PLAIN, 2, Scalar(25, 0, 220), 2);

        // show pts
        cv::imshow("xx", white);

        //cv::waitKey(0);
        while (1)
        {
            if (cv::waitKey(10) == 27)
            {
                cv::destroyAllWindows();
                break;
            }
        }
    }
}

 

posted @   哈库拉  阅读(20)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 因为Apifox不支持离线,我果断选择了Apipost!
· 通过 API 将Deepseek响应流式内容输出到前端
点击右上角即可分享
微信分享提示