• OPENCV 求轮廓方向


    #include<opencv2opencv.hpp>
    using namespace cv;
    using namespace std;
    
    double calcPCAorientation(vector<Point>&pts, Mat &image);
    
    int main(int arc, char** argv)
    {
        Mat src = imread("3.jpg");
        namedWindow("input", WINDOW_AUTOSIZE);
        imshow("input", src);
        Mat gray, binary;
        cvtColor(src, gray, COLOR_BGR2GRAY);
        threshold(gray, binary, 0, 255, THRESH_BINARY | THRESH_OTSU);
        //imshow("binary", binary);
    
        vector<vector<Point>>contours;
        findContours(binary, contours, RETR_LIST, CHAIN_APPROX_NONE);
        Mat result = src.clone();
        for (int i = 0; i < contours.size(); i++) {
            double area = contourArea(contours[i]);
            if (area > 1e5 || area < 1e2)continue;
            drawContours(result, contours, i, Scalar(0, 0, 255),1);
            calcPCAorientation(contours[i], result);
        }
        imshow("result", result);
    
        waitKey(0);
        return 0;
    }
    
    double calcPCAorientation(vector<Point>&pts, Mat &image) 
    {
        int size = pts.size();
        Mat data_pts = Mat(size, 2, CV_64FC1);
        for (int i = 0; i < size; i++) {
            data_pts.at<double>(i, 0) = pts[i].x;
            data_pts.at<double>(i, 1) = pts[i].y;
        }
        //PCA
        PCA pca_analysis(data_pts, Mat(), PCA::DATA_AS_ROW);
        Point cnt = Point(pca_analysis.mean.at<double>(0, 0), pca_analysis.mean.at<double>(0, 1));//平均值
        circle(image, cnt, 2, Scalar(0, 255, 0), 2);
    
        vector<Point2d>vecs(2);//特征向量
        vector<double>vals(2);//特征值
        for (int i = 0; i < 2; i++) 
        {
            vals[i] = pca_analysis.eigenvalues.at<double>(i, 0);
            vecs[i] = Point2d(pca_analysis.eigenvectors.at<double>(i, 0), pca_analysis.eigenvectors.at<double>(i, 1));
        }
        Point p1 = cnt + Point(static_cast<int>(vecs[0].x * 320), static_cast<int>(vecs[0].y * 315));//原本是300
        Point p2 = cnt - Point(static_cast<int>(vecs[1].x * 100), static_cast<int>(vecs[1].y * 100));//50
        //即将原直角坐标系中的数据在下面新的一组基中表示,使得数据特征最大化
        line(image, cnt, p1, Scalar(255, 0, 0), 1);//主特征方向
        line(image, cnt, p2, Scalar(0, 255, 0), 1);//与主特征垂直方向
        double angle = atan2(vecs[0].y, vecs[0].x);
        printf("angle:%.2f
    ", 180 * angle / CV_PI);
        printf("%d,%d
    ", vals[0], vals[1]);
        return angle;
    }

  • 相关阅读:
    python-登录小游戏
    easyclick 学习
    PYQT5 学习
    Pycharm之QT配置
    标贴打印机的基本使用
    开发遇到的问题及其解决
    Datatable 数据源
    JIRA操作之JQL
    类视图函数 VIEW
    前端基础
  • 原文地址:https://www.cnblogs.com/hsy1941/p/12001962.html
Copyright © 2020-2023  润新知