/****************************
*void cvtColor( InputArray src, OutputArray dst, int code, int dstCn = 0 );
*功能:颜色空间转换函数
*参数:
* src:原图
* dst:保存转换后的图
* dstCn:转换方式
* COLOR_BGR2GRAY:转换成灰度图
*****************************/
cvtColor(src, gray, COLOR_BGR2GRAY);
/**************************
* double threshold( InputArray src, OutputArray dst, double thresh, double maxval, int type );
* 功能:图像的二值化,就是将图像上的像素点的灰度值设置为0或255,也就是将整个图像呈现出明显的只有黑和白的视觉效果。
* 参数:
* src:原图
* dst:转化后的图
* thresh:设定的阈值
* maxval:当灰度值大于(或小于)阈值时将该灰度值赋成的值
* type:当前二值化的方式
* ************************/
threshold(gray, binary, 0, 255, THRESH_BINARY | THRESH_OTSU);
/************************************
* void findContours( InputOutputArray image, OutputArrayOfArrays contours,
* OutputArray hierarchy, int mode, int method, Point offset = Point());
* 功能:轮廓检测
* 参数:
* image:一般是灰度图或者二值化图,多是二值化图
* contours:定义为“vector<vector<Point>> contours”,是一个双重向量,每一组点集就是一个轮廓,有多少轮廓,contours就有多少元素
* hierarchy:定义为“vector<Vec4i> hierarchy”,hierarchy是一个向量,向量内每个元素都是一个包含4个int型的数组
* mode:定义轮廓的检索模式
* CV_RETR_EXTERNAL:只检测最外围轮廓,包含在外围轮廓内的内围轮廓被忽略
* CV_RETR_LIST:检测所有的轮廓,包括内围、外围轮廓,但是检测到的轮廓不建立等级关系
* CV_RETR_CCOMP: 检测所有的轮廓,但所有轮廓只建立两个等级关系
* CV_RETR_TREE: 检测所有轮廓,所有轮廓建立一个等级树结构
* method:定义轮廓的近似方法
* CV_CHAIN_APPROX_NONE:保存物体边界上所有连续的轮廓点到contours向量内;
* CV_CHAIN_APPROX_SIMPLE:仅保存轮廓的拐点信息,把所有轮廓拐点处的点保存入contours向量内,拐点与拐点之间直线段上的信息点不予保留;
* CV_CHAIN_APPROX_TC89_L1:使用teh-Chinl chain 近似算法;
* CV_CHAIN_APPROX_TC89_KCOS:使用teh-Chinl chain 近似算法。
* offset:Point偏移量,所有的轮廓信息相对于原始图像对应点的偏移量,相当于在每一个检测出的轮廓点上加上该偏移量,并且Point还可以是负值!
* ***********************************/
findContours(binary, contours, hireachy, RETR_LIST, CHAIN_APPROX_NONE);
//contourArea:过滤大轮廓
double area = contourArea(contours[i]);
//drawContours:画出轮廓
drawContours(result, contours, i, Scalar(0, 0, 255), 2, 8);
//计算每一个对象的行数
int size = static_cast<int>(pts.size());
Mat data_pts = Mat(size, 2, CV_64FC1);
//通过数组保存每一个对象的x和y坐标
for (int i = 0; i < size; 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 cnt = Point(static_cast<int>(pca_analysis.mean.at<double>(0, 0)),
static_cast<int>(pca_analysis.mean.at<double>(0, 1)));
//画出中心位置,使用绿色标识
circle(image, cnt, 2, Scalar(0, 255, 0), 2, 8, 0);
//获取特征值和特征向量
vector<Point2d> vecs(2);
vector<double> vals(2);
for (int i = 0; i < 2; i++)
{
vals[i] = pca_analysis.eigenvalues.at<double>(i, 0);
printf("Th %d eigen value : %.2f\n", i, vals[i]);
vecs[i] = Point2d(pca_analysis.eigenvectors.at<double>(i, 0), pca_analysis.eigenvectors.at<double>(i, 1));
}
//获取从中心位置到对象方向的延长线以及垂直线
Point p1 = cnt + 0.02*Point(static_cast<int>(vecs[0].x*vals[0]), static_cast<int>(vecs[0].y*vals[0]));
Point p2 = cnt - 0.05*Point(static_cast<int>(vecs[1].x*vals[1]), static_cast<int>(vecs[1].y*vals[1]));
//画出线
line(image, cnt, p1, Scalar(255, 0, 0), 2, 8, 0);
line(image, cnt, p2, Scalar(255, 255, 0), 2, 8, 0);