OpenCV中如何获得物体的主要方向

Posted OpenCV学堂

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了OpenCV中如何获得物体的主要方向相关的知识,希望对你有一定的参考价值。

问题来源为网友提供的资料,原文为:《Object Orientation, Principal Component Analysis & OpenCV》

问题描述:

对于这样的图像(2副,采用了背投光),如何获得上面工件的主要方向

OpenCV中如何获得物体的主要方向

主要思路:

1.分别获得每个工件的轮廓; 2.处理每个轮廓,采用pca(主成分分析)方法,获得所有轮廓点的集合的中点,主要方向等信息; 3.绘图并返回结果。

注:PCA相关函数请查看

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

代码略解:1.读入图片,寻找轮廓;

 
   
   
 
  1. //读入图像,转换为灰度

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

  3. Mat bw;

  4. cvtColor(img, bw, COLOR_BGR2GRAY);

  5. //阈值处理

  6. threshold(bw, bw, 150, 255, CV_THRESH_BINARY);

  7. //寻找轮廓

  8. vector<vector<Point> > contours;

  9. vector<Vec4i> hierarchy;

  10. findContours(bw, contours, hierarchy, CV_RETR_LIST, CV_CHAIN_APPROX_NONE);

2.首先以大小筛选轮廓;

 
   
   
 
  1. //轮廓分析,找到工件

  2.    for (size_t i = 0; i < contours.size(); ++i)

  3.    {

  4.        //计算轮廓大小

  5.        double area = contourArea(contours[i]);

  6.        //去除过小或者过大的轮廓区域(科学计数法表示)

  7.        if (area < 1e2 || 1e5 < area) continue;

  8.        //绘制轮廓

  9.        drawContours(img, contours, i, CV_RGB(255, 0, 0), 2, 8, hierarchy, 0);

  10.        //寻找每一个轮廓的方向

  11.        getOrientation(contours[i], img);

  12.    }

3.单独处理每个轮廓,分析其主要方向,绘制结果

 
   
   
 
  1. //获得构建的主要方向

  2. double getOrientation(vector<Point> &pts, Mat &img)

  3. {

  4.    //构建pca数据。这里做的是将轮廓点的x和y作为两个维压到data_pts中去。

  5.    Mat data_pts = Mat(pts.size(), 2, CV_64FC1);//使用mat来保存数据,也是为了后面pca处理需要

  6.    for (int i = 0; i < data_pts.rows; ++i)

  7.    {

  8.        data_pts.at<double>(i, 0) = pts[i].x;

  9.        data_pts.at<double>(i, 1) = pts[i].y;

  10.    }

  11.    //执行PCA分析

  12.    PCA pca_analysis(data_pts, Mat(), CV_PCA_DATA_AS_ROW);

  13.    //获得最主要分量,在本例中,对应的就是轮廓中点,也是图像中点

  14.    Point pos = Point(pca_analysis.mean.at<double>(0, 0),pca_analysis.mean.at<double>(0, 1));

  15.    //存储特征向量和特征值

  16.    vector<Point2d> eigen_vecs(2);

  17.    vector<double> eigen_val(2);

  18.    for (int i = 0; i < 2; ++i)

  19.    {

  20.        eigen_vecs[i] = Point2d(pca_analysis.eigenvectors.at<double>(i, 0),pca_analysis.eigenvectors.at<double>(i, 1));

  21.        eigen_val[i] = pca_analysis.eigenvalues.at<double>(i,0);//注意,这个地方原代码写错了

  22.    }

  23.    //在轮廓/图像中点绘制小圆

  24.    circle(img, pos, 3, CV_RGB(255, 0, 255), 2);

  25.    //计算出直线,在主要方向上绘制直线

  26.    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));

  27.    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));

  28.    //返回角度结果

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

  30. }

结果展示:

作者博客: jsxyhelu.cnblogs.com

更多相关阅读






远飞者当换其新羽

善筑者先清其旧基


关注【OpenCV学堂】

长按或者扫码二维码即可关注


以上是关于OpenCV中如何获得物体的主要方向的主要内容,如果未能解决你的问题,请参考以下文章

如何检测物体边框 opencv

OpenCV 乘以对象进/出计数

opencv实战——PCA算法的应用

openCV android 获取描绘物体轮廓的点坐标

opencv函数如何把视频图像中运动的物体给框住

unity如何获得二维坐标