/************************************************************************/ // 求解向量和轮廓的交点 // by jsxyhelu(jsxyhelu.cnblogs.com) // 2018/10/05 /************************************************************************/ #
include "stdafx.h" #
include "opencv2/imgcodecs.hpp" #
include "opencv2/highgui.hpp" #
include "opencv2/imgproc.hpp" #
include "opencv2/photo.hpp" using namespace std;
using namespace cv;
//寻找最大外接轮廓 vector
<Point
> FindBigestContour(Mat src){
int max_area_contour_idx
= 0;
double max_area
= - 1;
vector
<vector
<Point
> >contours;
findContours(src,contours,RETR_LIST,CHAIN_APPROX_SIMPLE);
//handle case if no contours are detected CV_Assert(
0 != contours.size());
for (uint i
= 0;i
<contours.size();i
++){
double temp_area
= contourArea(contours[i]);
if (max_area
< temp_area ){
max_area_contour_idx
= i;
max_area
= temp_area;
}
}
return contours[max_area_contour_idx];
}
//程序主要部分 int main(
int argc,
char * * argv )
{
//读入图像,转换为灰度 Mat src
= imread(
"E:/sandbox/cloud.png");
Mat src_gray;
cvtColor(src, src_gray, COLOR_BGR2GRAY);
//阈值处理 Mat threshold_output;
cv
: :threshold(src_gray,threshold_output,
150,
255,THRESH_OTSU
|THRESH_BINARY_INV);
//轮廓分析 vector
<vector
<Point
> > contours;
vector
<Vec4i
> hierarchy;
vector
<Point
> biggestContour
= FindBigestContour(threshold_output);
//寻找最大轮廓 Rect boundRect
= boundingRect( Mat(biggestContour) );
//获得轮廓最小外接矩形 cv
: :rectangle(src,boundRect,Scalar(
0,
0,
255));
//pca分析,求出斜率和经过的一点 Mat data_pts
= Mat(biggestContour.size(),
2, CV_64FC1);
//Construct a buffer used by the pca analysis for (
int i
= 0; i
< data_pts.rows;
++i)
{
data_pts.at
< double >(i,
0)
= biggestContour[i].x;
data_pts.at
< double >(i,
1)
= biggestContour[i].y;
}
PCA pca_analysis(data_pts, Mat(), CV_PCA_DATA_AS_ROW);
//执行PCA运算 Point pos
= Point2f(pca_analysis.mean.at
< double >(
0,
0),
pca_analysis.mean.at
< double >(
0,
1));
//主方向直线经过的一点 vector
<Point2d
> eigen_vecs(
2);
//保存PCA分析结果,其中0组为主方向,1组为垂直方向 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);
}
line(src, pos
- 0.
02 * Point(eigen_vecs[
0].x
* eigen_val[
0],eigen_vecs[
0].y
* eigen_val[
0]),
pos
+ 0.
02 * Point(eigen_vecs[
0].x
* eigen_val[
0],eigen_vecs[
0].y
* eigen_val[
0]) , Scalar(
255,
255,
0));
//绘制概略主方向 //求出主方向直线和外接矩形的交点, float k
= eigen_vecs[
0].y
/eigen_vecs[
0].x;
//斜率 Point2f pt1
= Point2f(boundRect.x,k
*(boundRect.x
- pos.x)
+pos.y);
Point2f pt2
= Point2f((boundRect.x
+boundRect.width),k
*((boundRect.x
+boundRect.width)
-pos.x)
+pos.y);
circle(src,pt1,
5,Scalar(
0,
255,
255),
- 1);
circle(src,pt2,
5,Scalar(
0,
255,
255),
- 1);
//遍历两个交点之间的线段,得出和轮廓的交点 LineIterator it(src, pt1, pt2,
8);
for(
int i
= 0; i
< it.count; i
++,
++it)
{
Point pt(it.pos());
//获得线段上的点 if (abs(pointPolygonTest(biggestContour,pt,
true))
< 1)
circle(src,pt,
5,Scalar(
0,
0,
255),
- 1);
}
waitKey();
return 0;
}