ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

OpenCV之发现轮廓中心点位置及轮廓方向

2022-05-05 22:04:17  阅读:331  来源: 互联网

标签:PCA OpenCV result 中心点 vals 轮廓 vecs


一、概述

  案例:使用PCA发现轮廓的中心点位置及轮廓方向

  PAC API介绍:

PCA(InputArray data, InputArray mean, int flags, int maxComponents = 0);
data:输入数据,一般是轮廓点集合
mean:数据均值如果为空则自动计算
flags:数据的提供方式,分为行和列两种
maxComponents:保留多少特征值(默认保留全部)

PCA的方法:
mean:均值数据,其中第一个数据即为数据集的中心点
eigenvalues:特征值集合
eigenvectors:特征向量集合

  算法实现步骤:

    1.载入输入图像

    2.图像灰度化

    3.图像二值化

    4.使用findContours发现轮廓

    5.循环绘制轮廓

    6.循环使用PCA检测每个轮廓

      6.1.初始化PCA

      6.2.找到轮廓中心点

      6.3.绘制轮廓中心点

      6.4.根据特征向量及特征值找到向量坐标

      6.5.绘制向量直线

      6.6.找到轮廓方向角度

 

二、代码示例

  Mat src = imread(filePath);
    if(src.empty()){
        qDebug()<<"输入图像为空";
        return;
    }
    imshow("src",src);

    Mat gray,binary;
    cvtColor(src,gray,COLOR_BGR2GRAY);//灰度化
    //二值化
    threshold(gray,binary,0,255,THRESH_BINARY|THRESH_OTSU);
    imshow("binary",binary);
    //发现轮廓
    vector<vector<Point>> contours;
    vector<Vec4i> heri;
    findContours(binary,contours,RETR_LIST,CHAIN_APPROX_NONE);
    Mat result = src.clone();//clone一个副本
    for(size_t i = 0;i<contours.size();i++){
        //过滤掉面积较小的区域
        double area = contourArea(contours[i]);
        if (area > 1e5 || area < 1e2) continue;
        drawContours(result,contours,i,Scalar(0,0,255),3,LINE_8);//绘制轮廓
        pcaAnalyze(contours[i],result);
    }
    imshow("result",result);

}

/**
 * 使用PCA分析轮廓,找到中心点位置以及轮廓方向
 * @brief Face_PCA::pcaAnalyze
 * @param points
 * @param result
 */
void Face_PCA::pcaAnalyze(vector<Point> &points,Mat &result){
    int size = points.size();
    Mat data_pts = Mat(size,2,CV_64FC1);
    for(int i=0;i<size;i++){
        data_pts.at<double>(i,0) = points[i].x;
        data_pts.at<double>(i,1) = points[i].y;
    }
    qDebug()<<"开始pca分析";
    //使用PCA进行分析
    PCA pca_analyze(data_pts,Mat(),PCA::DATA_AS_ROW);//实例化PCA
    //找出轮廓的圆心:均值数据的第一个值即为数据中心点
    Point center = Point(pca_analyze.mean.at<double>(0,0),pca_analyze.mean.at<double>(0,1));
    //绘制轮廓中心点
    circle(result,center,3,Scalar(0,0,255),3,LINE_8);
    qDebug()<<"准备利用pca寻找轮廓方向";
    //找出并绘制出轮廓方向
    vector<Point2d> vecs(2);//特征向量
    vector<double> vals(2);//特征值
    for(int i=0;i<2;i++){
        vals[i] = pca_analyze.eigenvalues.at<double>(i,0);
        vecs[i] = Point2d(pca_analyze.eigenvectors.at<double>(i,0),pca_analyze.eigenvectors.at<double>(i,1));
    }

    Point p1 = center+ 0.02*Point(static_cast<int>(vecs[0].x*vals[0]), static_cast<int>(vecs[0].y*vals[0]));
    Point p2 = center - 0.05*Point(static_cast<int>(vecs[1].x*vals[1]), static_cast<int>(vecs[1].y*vals[1]));
    line(result,center,p1,Scalar(0,255,0),3,LINE_8);
    line(result,center,p2,Scalar(0,255,0),3,LINE_8);

    double angle = atan2(vecs[0].y,vecs[0].x);
    qDebug()<<"角度:"<<180*(angle/CV_PI);

 

三、图像演示

 

标签:PCA,OpenCV,result,中心点,vals,轮廓,vecs
来源: https://www.cnblogs.com/tony-yang-flutter/p/16226542.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有