• 如何获得物体的主要方向?


    问题来源为网友提供的资料,原文地址为:《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录屏软件,非常好用。
  • 相关阅读:
    远程访问Linux的常见方式
    GIT的安装与使用
    01_c语言学习之gcc
    车轮——项目 --- 云笔记
    python 基于ubuntu16.04 建立虚拟环境
    利用msfvenom生成木马
    msfvenom参数简介
    kali linux修改更新源及更新
    记通过mysql数据库成功入侵到服务器内部的渗透实战
    UML 几种关系:泛化、关联
  • 原文地址:https://www.cnblogs.com/jsxyhelu/p/7690699.html
Copyright © 2020-2023  润新知