天天看點

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

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

問題描述:

對于這樣的圖像(2副,采用了背投光),如何獲得上面工件的主要方向

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

主要思路:

1、分别獲得每個工件的輪廓;

2、處理每個輪廓,采用pca(主成分分析)方法,獲得所有輪廓點的集合的中點,主要方向等資訊;

3、繪圖并傳回結果。

注:pca相關函數請檢視

https://docs.opencv.org/master/d3/d8d/classcv_1_1PCA.html

代碼略解:

1、讀入圖檔,尋找輪廓;

//讀入圖像,轉換為灰階

    Mat img = imread("e:/sandbox/pca1.jpg");

    Mat bw;

    cvtColor(img, bw, COLOR_BGR2GRAY);

    //門檻值處理

    threshold(bw, bw, 150, 255, 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(255, 0, 0), 2, 8, 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>(0, 0),pca_analysis.mean.at<double>(0, 1));

    //存儲特征向量和特征值

    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(255, 0, 255), 2);

    //計算出直線,在主要方向上繪制直線

    line(img, pos, pos + 0.02 * Point(eigen_vecs[0].x * eigen_val[0], eigen_vecs[0].y * eigen_val[0]) , CV_RGB(255, 255, 0));

    line(img, pos, pos + 0.02 * Point(eigen_vecs[1].x * eigen_val[1], eigen_vecs[1].y * eigen_val[1]) , CV_RGB(0, 255, 255));

    //傳回角度結果

    return atan2(eigen_vecs[0].y, eigen_vecs[0].x);

}

結果展示:

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

感謝關注,希望有所幫助。

此外,特别感謝:

https://github.com/NickeManarin/ScreenToGif/wiki/Help

提供的這個gif錄屏軟體,非常好用。

目前方向:圖像拼接融合、圖像識别

聯系方式:[email protected]

繼續閱讀