opencv學習之路(39)、PCA


一、PCA理論介紹

網上已經有許多介紹pca原理的博客,這里就不重復介紹了。詳情可參考

http://blog.csdn.net/zhongkelee/article/details/44064401

計算過程

數據互換

二、opencv代碼

#include<opencv2/opencv.hpp>
using namespace cv;
using namespace std;

void calcPCAOrientation(vector<Point>&pts, Mat &image){
    int size = static_cast<int>(pts.size());//static_cast強制類型轉換
    Mat data_pts = Mat(size,2,CV_64FC1);//size個對象,2個維度(即平面坐標x,y)
    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(data_pts, Mat(), CV_PCA_DATA_AS_ROW);
    //獲取均值(中心)位置
    Point cnt = Point(static_cast<int>(pca.mean.at<double>(0, 0)),
                      static_cast<int>(pca.mean.at<double>(0, 1)));
    circle(image,cnt,2,Scalar(0,255,0),2,8,0);

    vector<Point2d>vecs(2);
    vector<double>vals(2);
    for (int i = 0; i < 2; i++)
    {
        vals[i] = pca.eigenvalues.at<double>(i, 0);//特征值
        cout << "" << i << "個特征值:" << vals[i]<<endl;
        vecs[i] = Point2d(pca.eigenvectors.at<double>(i, 0),    //特征向量
                         (pca.eigenvectors.at<double>(i, 1)));
    }
    Point p1 = cnt + 0.02*Point(static_cast<int>(vecs[0].x*vals[0]), static_cast<int>(vecs[0].y*vals[0]));
    Point p2  = cnt - 0.05*Point(static_cast<int>(vecs[1].x*vals[1]), static_cast<int>(vecs[1].y*vals[1]));

    line(image, cnt, p1, Scalar(255, 0, 0), 2, 8, 0);
    line(image, cnt, p2, Scalar(255, 255, 0), 2, 8, 0);

    double angle = atan2(vecs[0].y,vecs[0].x);
    cout << "angle:" << 180 * (angle / CV_PI)<<endl;
}

void main()
{
    Mat src = imread("E://2.jpg");
    imshow("src", src);
    Mat gray, binary;
    cvtColor(src, gray,CV_BGR2GRAY);
    threshold(gray, binary,0,255, THRESH_BINARY|THRESH_OTSU);//自動閾值:OTSU找到一個它認為最好的閾值
    //imshow("binary", binary);

    //輪廓提取
    vector<Vec4i>hierarchy;
    vector<vector<Point>>contours;
    findContours(binary, contours, hierarchy, 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;//面積大於10^5或者小於10^2的輪廓,不要
        drawContours(result, contours, i, Scalar(0, 0, 255), 2, 8);

        calcPCAOrientation(contours[i], result);//調用PCA
    }
    imshow("contours result", result);

    waitKey(0);
}      

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM