connectedComponentsWithStats函数的应用
上一篇文章讲了connectedComponebts函数的使用,该函数功能有限,无法进行计数和区域标记计算,但是OpenCV提供了一个函数可以对连通域进行计数和区域的面积计算,该函数为connectedComponentsWithStats。
首先看一下函数介绍
connectedComponentsWithStats(
InputArray image,
OutputArray labels,
OUtputArray stats,
OutputArray centroids,
int connectivity = 8,
int lType = CV_32S
)
image:待标记不同连通域的单通道图像,数据类型必须为CV_8U
labels:标记不同连通域后的输出图像,与输入图像具有相同的尺寸
stats:不同连通域的统计信息矩阵,矩阵的数据类型为CV_32S。矩阵中第i行为标签为i的连通域的统计特征。
centroids:每个连通域的质心坐标,数据类型为CV_64F
connectivity:统计连通域时使用的邻域种类,4邻域或者8邻域
ltype:输出图像的数据类型,目前只支持CV_32S和CV_16U。
下面给出我的测试图像
下面是使用OpenCV4.1自带函数的计算代码
#include
#include
#include
#include
#include
#include
#include
using namespace std;
using namespace cv;
void calCountAndArea() {
//system("color F1");
Mat image = imread("11.png");
if (image.empty()) {
cout << "请确认图像路径是否正确!" << endl;
return;
}
Mat imageGray,imageBW;
cvtColor(image, imageGray, COLOR_BGR2GRAY);
threshold(imageGray, imageBW, 55, 200, THRESH_BINARY);
//时间作为随机种子防止重复
RNG rng(time(NULL));
Mat outImage, stats, centroids;
int count = connectedComponentsWithStats(imageBW, outImage, stats, centroids, 8, CV_16U);
vector<Vec3b> colors;
for (int i = 0; i < count; i++) {
Vec3b vec3 = Vec3b(rng.uniform(0, 256), rng.uniform(0, 256), rng.uniform(0, 256));
colors.push_back(vec3);
}
Mat dst = Mat::zeros(imageGray.size(), imageGray.type());
int width = dst.cols;
int height = dst.rows;
for (int i = 1; i < count; i++) {
//找到连通域的质心
int center_x = centroids.at<double>(i, 0);
int center_y = centroids.at<double>(i, 1);
//矩形的点和边
int x = stats.at<int>(i, CC_STAT_LEFT);
int y = stats.at<int>(i, CC_STAT_TOP);
int w = stats.at<int>(i, CC_STAT_WIDTH);
int h = stats.at<int>(i, CC_STAT_HEIGHT);
int area = stats.at<int>(i, CC_STAT_AREA);
//绘制中心点
circle(image, Point(center_x, center_y), 2, Scalar(0, 255, 122), 2, 8, 0);
//外接矩形
Rect rect(x, y, w, h);
rectangle(image, rect, colors[i], 1, 8, 0);
//putText(image, format("%d", i), Point(center_x, center_y), FONT_HERSHEY_COMPLEX, 0.5, Scalar(0, 0, 255), 1);
cout << "count:" << i << " area:" << area << endl;
}
imshow("org", image);
namedWindow("org", 0);
waitKey(0);
}
int main(){
calCountAndArea();
}