得到二值图像的目的是为了后面的分析
基本概念解释
-图像联通组件
-四邻域与八邻域联通
ccl联通组件标记
通过四邻域和八邻域来对图像进行边缘寻找与噪声处理的功能
常见算法来寻找联通组件
-基于像素扫描方法
-基于块扫描的方法
-两步法扫描
- API: OpenCV中支持连通组件扫描的API有两个,一个是带统计信息
connectedComponentsWithStats
一个不带统计信息connectedComponents
- 黑色背景
1. 整体功能 • connectedComponentsWithStats是OpenCV中用于图像分析的一个重要函数,主要用于对图像中的连通区域进行标记、统计相关信息和计算质心。 2. 输入参数(重点是前两个) • image:这是进行连通区域分析的基础。通常是一幅经过预处理的二值图像,例如,通过阈值分割得到的图像,其中白色(非零)像素表示前景物体,黑色(零)像素表示背景。函数会根据这些前景像素的分布来确定连通区域。 • labels:在调用函数之前就创建好的一个矩阵,用于存储连通区域的标签信息。它的尺寸和image相同,数据类型为CV_32S(前面提到过这个类型的好处)。在函数执行过程中,每个像素会被赋予一个标签值,代表它所属的连通区域。 3. 输出参数(重点是中间两个) • stats:这是一个矩阵,每一行代表一个连通区域(背景区域通常不包含在内)。这个矩阵包含了非常有用的统计信息,比如连通区域的外接矩形的左上角坐标(x和y)、宽度、高度和面积等。这些信息可以用于后续对连通区域的形状、大小等特征的分析。 • centroids:用于存储每个连通区域(不包括背景)的质心坐标。质心坐标可以帮助确定物体在图像中的中心位置,对于目标跟踪、物体定位等应用场景很有帮助。 4. 连通性参数 • 函数中的8参数用于指定连通性。8连通性意味着一个像素与其周围的8个像素(上下左右、四个对角)都被认为是连通的;如果是4连通性,一个像素只与其上下左右4个像素连通。这个参数会影响连通区域的划分结果。 5. 数据类型和算法参数 • CV_32S参数是为了确保labels矩阵的数据类型和函数内部的处理要求相匹配,保证标签能够正确存储。CCL_DEFAULT参数通常用于指定使用默认的连通组件标记算法,在大多数情况下不需要改变这个参数,它可以保证算法以比较合理的方式运行。
方便个人理解我将源代码分为三部分,基于当前的学习阶段,我将代码敲完之后发现25个物体被识别成了27个,后来发现右边又很小的一条白条,所以此API对于黑底背景十分敏感。
第一步思路先将图像转化为灰度图像后进行高斯模糊,可以更好地帮助进行二值化。
int main(int argc, char** argv) {
Mat src = imread("C:/newword/image/3.png");
if (src.empty()) {
printf("could not find image file");
return -1;
}
namedWindow("input", WINDOW_AUTOSIZE);
imshow("input", src);
GaussianBlur(src, src, Size(3, 3), 0);
Mat gray, binary;
cvtColor(src, gray, COLOR_BGR2GRAY);to那个
threshold(gray, binary, 0, 255, THRESH_BINARY | THRESH_OTSU);
imshow("binary", binary);
后面需要将目标图像中的关键信息用连通组件进行寻找,首先要建立一个新的同等规模的图像,将其初始化,规模为32s,之后将目标图像用connectedComponentsWithStats函数进行连通寻找,我们想要将目标图像中的关键信息的颜色改变;那就需要建立同等规模的三通道容器,里面包含了BGR元素,首先将元素背景设置为黑色,之后将经过连通寻找后的图像从1开始遍历,并将连通其中的颜色随机化,注:此代码只有标记功能没有上色功能
void ccl_stats_demo(Mat& image) {
Mat labels = Mat::zeros(image.size(), CV_32S);//创建了一个与给定图像 image 尺寸相同的矩阵 labels,数据类型为 CV_32S(32 位有符号整数),并且初始值全为零。
Mat stats, centroids;
int num_labels = connectedComponentsWithStats(image, labels, stats, centroids, 8, CV_32S, CCL_DEFAULT);
vector<Vec3b> colorTable(num_labels);//vector动态数组库,vec3b三通道,color table容器
colorTable[0] = Vec3b(0, 0, 0);//将背景设置为黑色
for (int i = 1; i < num_labels; i++) {
colorTable[i] = Vec3b(rng.uniform(0, 256), rng.uniform(0, 256), rng.uniform(0, 256));
}
下面代码是将刚标记的连通图进行上色
Mat result = Mat::zeros(image.size(), CV_8UC3);
int w = result.cols;
int h = result.rows;
for (int row = 0; row < h; row++) {
for (int col = 0; col < w; col++) {
int label = labels.at<int>(row, col);
result.at<Vec3b>(row, col) = colorTable[label];//上色
}
}
最后将连通标记上色后的图片用矩形框出来,并显示左上角信息与原点位置
for (int i = 1; i < num_labels; i++) {
int cx = centroids.at<double>(i, 0);
int cy = centroids.at<double>(i, 1);
int x = stats.at<int>(i, CC_STAT_LEFT);
int y = stats.at<int>(i, CC_STAT_TOP);
int width = stats.at<int>(i, CC_STAT_WIDTH);
int height = stats.at<int>(i, CC_STAT_HEIGHT);
int area = stats.at<int>(i, CC_STAT_AREA);
circle(result, Point(cx, cy), 3, Scalar(0, 0, 255), 2, 8, 0);//circle(result, Point(cx, cy), 3, Scalar(0, 0, 255), 2, 8, 0);:在结果图像result上,以质心坐标(cx, cy)为圆心,绘制一个半径为 3 的红色(Scalar(0, 0, 255))圆圈,线宽为 2,采用 8 连接方式。这个圆圈标记了连通区域的质心位置。
Rect box(x, y, width, height);
rectangle(result, box, Scalar(0, 255, 0), 2, 8);//Rect box(x, y, width, height);和rectangle(result, box, Scalar(0, 255, 0), 2, 8);:创建一个以(x, y)为左上角坐标,宽度为width,高度为height的矩形box,然后在结果图像上绘制一个绿色(Scalar(0, 255, 0))的矩形框,线宽为 2,采用 8 连接方式。这个矩形框标记了连通区域的外接矩形。rectangle(图像矩阵, 矩形区域, 颜色, 线宽, 线类型, 偏移量)。例如代码中rectangle(result, box, Scalar(0, 255, 0), 2, 8);,result是要绘制矩形的图像,box是一个Rect类型的矩形区域对象,Scalar(0, 255, 0)表示绿色的颜色,2是线宽,8是线类型(连接方式)。
putText(result, format("%d", area), Point(x, y), FONT_HERSHEY_PLAIN, 1.0, Scalar(0, 255, 0), 1);
}
putText(result, format("number: %d", num_labels - 1), Point(10, 10), FONT_HERSHEY_PLAIN, 1.0, Scalar(0, 255, 0), 1);//
一、第一个putText
1. 参数解释
• result:要在其上绘制文本的图像。
• format("%d", area):要绘制的文本内容,这里是将整数area(可能是某个连通区域的面积值)格式化为字符串。
• Point(x, y):文本在图像上的位置坐标,这里的坐标通常是与某个连通区域相关的位置,比如外接矩形的左上角坐标。
• FONT_HERSHEY_PLAIN:字体类型,这里表示使用一种简单的字体风格。
• 1.0:字体大小。
• Scalar(0, 255, 0):文本的颜色,这里是绿色。
• 1:文本的线宽。
2. 作用
• 在结果图像上,在特定位置(与连通区域相关的位置)绘制文本,显示该连通区域的面积值。
二、第二个putText
1. 参数解释
• result:同样是要在其上绘制文本的图像。
• format("number: %d", num_labels - 1):要绘制的文本内容,这里显示的是“number: ”加上连通区域的数量减 1。
• Point(10, 10):文本在图像上的位置坐标,这里是固定的坐标(10, 10)。
• FONT_HERSHEY_PLAIN:字体类型。
• 1.0:字体大小。
• Scalar(0, 255, 0):文本的颜色,绿色。
• 1:文本的线宽。
2. 作用
• 在结果图像上的固定位置(10, 10)绘制文本,显示连通区域的总数(排除背景区域后的数量)。
printf("total labels : %d \n", (num_labels - 1));
imshow("CCL demo", result);
}