如何獲得物體的主要方向?


問題來源為網友提供的資料,原文地址為:《Object Orientation, Principal Component Analysis & OpenCV》

問題描述:
對於這樣的圖像(2副,采用了背投光),如何獲得上面工件的主要方向
pca_test1  
pca_test2
 
主要思路:
1、分別獲得每個工件的輪廓;
2、處理每個輪廓, 采用pca(主成分分析)方法,獲得所有輪廓點的集合的中點,主要方向等信息;
3、繪圖並返回結果。
 
注:pca相關函數請查看
 
代碼略解:
1、讀入圖片,尋找輪廓;
//讀入圖像,轉換為灰度
    Mat img  = imread( "e:/sandbox/pca1.jpg");
    Mat bw;
    cvtColor(img, bw, COLOR_BGR2GRAY);
     //閾值處理
    threshold(bw, bw,  150255, CV_THRESH_BINARY);
     //尋找輪廓
    vector <vector <Point >  > contours;
    vector <Vec4i > hierarchy;
    findContours(bw, contours, hierarchy, CV_RETR_LIST, CV_CHAIN_APPROX_NONE);
2、首先以大小篩選輪廓;
//輪廓分析,找到工件
     for (size_t i  =  0; i  < contours.size();  ++i)
    {
         //計算輪廓大小
         double area  = contourArea(contours[i]);
         //去除過小或者過大的輪廓區域(科學計數法表示)
         if (area  <  1e2  ||  1e5  < area)  continue;
         //繪制輪廓
        drawContours(img, contours, i, CV_RGB( 25500),  28, hierarchy,  0);
         //尋找每一個輪廓的方向
        getOrientation(contours[i], img);
    }
3、單獨處理每個輪廓,分析其主要方向,繪制結果
//獲得構建的主要方向
double getOrientation(vector <Point >  &pts, Mat  &img)
{
     //構建pca數據。這里做的是將輪廓點的x和y作為兩個維壓到data_pts中去。
    Mat data_pts  = Mat(pts.size(),  2, CV_64FC1); //使用mat來保存數據,也是為了后面pca處理需要
     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;
    }
     //執行PCA分析
    PCA pca_analysis(data_pts, Mat(), CV_PCA_DATA_AS_ROW);
     //獲得最主要分量,在本例中,對應的就是輪廓中點,也是圖像中點
    Point pos  = Point(pca_analysis.mean.at < double >( 00),pca_analysis.mean.at < double >( 01));
     //存儲特征向量和特征值
    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, 0); //注意,這個地方原代碼寫錯了
    }
     //在輪廓/圖像中點繪制小圓
    circle(img, pos,  3, CV_RGB( 2550255),  2);
     //計算出直線,在主要方向上繪制直線
    line(img, pos, pos  +  0. 02  * Point(eigen_vecs[ 0].x  * eigen_val[ 0], eigen_vecs[ 0].y  * eigen_val[ 0]) , CV_RGB( 2552550));
    line(img, pos, pos  +  0. 02  * Point(eigen_vecs[ 1].x  * eigen_val[ 1], eigen_vecs[ 1].y  * eigen_val[ 1]) , CV_RGB( 0255255));
     //返回角度結果
     return atan2(eigen_vecs[ 0].y, eigen_vecs[ 0].x);
}
結果展示:
感謝關注,希望有所幫助。
提供的這個gif錄屏軟件,非常好用。

 


免責聲明!

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



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