1、概述
案例:使用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.找到轮廓方向角度
2、代码示例
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);
3、图像演示
本文福利,莬费领取Qt开发学习资料包、技术视频,内容包括(C++语言基础,Qt编程入门,QT信号与槽机制,QT界面开发-图像绘制,QT网络,QT数据库编程,QT项目实战,QSS,OpenCV,Quick模块,面试题等等)↓↓↓↓↓↓见下面↓↓文章底部点击莬费领取↓↓