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;
}

原文地址:https://www.cnblogs.com/hsy1941/p/12001962.html