文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

OpenCV实现图像连通域

2024-04-02 19:55

关注

图像的连通域是指图像中具有相同像素值并且位置相邻的像素组成的区域,连通域分析是指在图像中寻找出彼此互相独立的连通域并将其标记出来。

一般情况下,一个连通域内只包含一个像素值,因此为了防止像素值波动对提取不同连通域的影响,连通域分析常处理的是二值化后的图像。

4-邻域和8-邻域:

常用的图像邻域分析法有两遍扫描法种子填充法。两遍扫描法会遍历两次图像,第一次遍历图像时会给每一个非0像素赋予一个数字标签,当某个像素的上方和左侧邻域内的像素已经有数字标签时,取两者中的最小值作为当前像素的标签,否则赋予当前像素一个新的数字标签。第一次遍历图像的时候同一个连通域可能会被赋予一个或者多个不同的标签。

种子填充法源于计算机图像学,常用于对某些图形进行填充。该方法首先将所有非0像素放到一个集合中,之后在集合中随机选出一个像素作为种子像素,根据邻域关系不断扩充种子像素所在的连通域,并在集合中删除掉扩充出的像素,直到种子像素所在的连通域无法扩充,之后再从集合中随机选取一个像素作为新的种子像素,重复上述过程直到集合中没有像素。


CV_EXPORTS_AS(connectedComponentsWithAlgorithm) int connectedComponents(InputArray image, OutputArray labels,
                                           int connectivity, int ltype, int ccltype);

该函数用于计算二值图像中连通域的个数,并在图像中将不同的连通域用不同的数字标签标记出,其中标签0表示图像中的背景区域,同时函数具有一个int类型的返回数据,用于表示图像中连通域的数目。函数的第一个参数是待标记连通域的输入图像,函数要求输入图像必须是数据类型为CV_8U的单通道灰度图像,而且最好是经过二值化的二值图像。函数第二个参数是标记连通域后的输出图像,图像尺寸与第一个参数的输入图像尺寸相同,图像的数据类型与函数的第四个参数相关。函数第三个参数是统计连通域时选择的邻域种类,函数支持两种邻域,分别用4表示4-邻域,8表示8-邻域。函数第四个参数为输出图像的数据类型,可以选择的参数为CV_32S和CV_16U两种。函数的最后一个参数是标记连通域时使用算法的标志,可以选择的参数及含义在表给出,目前只支持Grana(BBDT)和Wu(SAUF)两种算法。 

OpenCV 还给出了简单的函数形式


int connectedComponents(InputArray image, OutputArray labels,
                                     int connectivity = 8, int ltype = CV_32S);

该函数原型只有四个参数,前两个参数分别表示输入图像和输出图像,第三个参数表示统计连通域时选择的邻域种类,分别用4表示4-邻域,8表示8-邻域,参数的默认值为8。最后一个参数表示输出图像的数据类型,可以选择的参数为CV_32S和CV_16U两种,参数的默认值为CV_32S。该函数原型有两个参数具有默认值,在使用时最少只需要两个参数,极大的方便了函数的调用。

进一步统计每个连通域的中心位置、矩形区域大小、区域面积等信息

复杂的


CV_EXPORTS_AS(connectedComponentsWithStatsWithAlgorithm) int connectedComponentsWithStats(InputArray image, OutputArray labels,
                              OutputArray stats, OutputArray centroids,
                              int connectivity, int ltype, int ccltype);

该函数能够在图像中不同连通域标记标签的同时统计每个连通域的中心位置、矩形区域大小、区域面积等信息。函数的前两个参数含义与connectedComponents()函数的前两个参数含义一致,都是输入图像和输出图像。函数的第三个参数为每个连通域统计信息矩阵,如果图像中有N个连通域,那么该参数输出的矩阵尺寸为N×5,矩阵中每一行分别保存每个连通域的统计特性,详细的统计特性在表中给出,如果想读取包含第i个连通域的边界框的水平长度,可以通过stats.at(i, CC_STAT_WIDTH)或者stats.at(i, 0)进行读取。函数的第四个参数为每个连通域质心的坐标,如果图像中有N个连通域,那么该参数输出的矩阵尺寸为N×2,矩阵中每一行分别保存每个连通域质心的x坐标和y坐标,可以通过centroids.at(i, 0)和 centroids.at(i, 1) 分别读取第i个连通域质心的x坐标和y坐标。函数第五个参数是统计连通域时选择的邻域种类,函数支持两种邻域,分别用4表示4-邻域,8表示8-邻域。函数第六个参数为输出图像的数据类型,可以选择的参数为CV_32S和CV_16U两种。函数的最后一个参数是标记连通域使用的算法,可以选择的参数在上表给出,目前只支持Grana(BBDT)和Wu(SAUF)两种算法。 

简单的


int connectedComponentsWithStats(InputArray image, OutputArray labels,
                                              OutputArray stats, OutputArray centroids,
                                              int connectivity = 8, int ltype = CV_32S);

该函数原型只有六个参数,前两个参数分别表示输入图像和输出图像,第三个参数表示每个连通域的统计信息,第四个参数表示每个连通域的质心位置。后两个参数分别表示统计连通域时选择的邻域种类,分别用4表示4-邻域,8表示8-邻域,参数的默认值为8。最后一个参数表示输出图像的数据类型,可以选择的参数为CV_32S和CV_16U两种,参数的默认值为CV_32S。该函数原型有两个参数具有默认值,在使用时最少只需要四个参数,极大的方便了函数的调用。

简单示例


//
// Created by smallflyfly on 2021/6/16.
//
 
#include "opencv2/opencv.hpp"
#include "opencv2/highgui.hpp"
 
#include <iostream>
 
using namespace std;
using namespace cv;
 
int main() {
 
    Mat im = imread("rice.jfif");
    Mat gray;
    cvtColor(im, gray, CV_BGR2GRAY);
//    resize(im, im, Size(0, 0), 0.5, 0.5);
 
    imshow("im", im);
 
    Mat im1;
    threshold(gray, im1, 125, 255, THRESH_BINARY);
 
    imshow("im1", im1);
//    waitKey(0);
 
    RNG rng(10010);
    Mat out;
    int num = connectedComponents(im1, out, 8, CV_16U);
    vector<Vec3b> colors;
    for (int i=0; i<num; i++) {
        // 使用均匀分布的随机确定颜色
        Vec3b vec = Vec3b(rng.uniform(0, 256), rng.uniform(0, 256), rng.uniform(0, 256));
        colors.push_back(vec);
    }
    Mat result = Mat::zeros(im.size(), im.type());
    for (int i = 0; i < im.rows; ++i) {
        for (int j = 0; j < im.cols; ++j) {
            int label = out.at<uint16_t>(i, j);
            if (label == 0) {
                continue;
            }
            result.at<Vec3b>(i, j) = colors[label];
        }
    }
 
    imshow("result", result);
 
    Mat labels, stats, centroids;
    int count = connectedComponentsWithStats(im1, labels, stats, centroids, 8);
    cout << count << endl;
 
    for (int i = 1; i < count; ++i) {
        int x = centroids.at<double>(i, 0);
        int y = centroids.at<double>(i, 1);
        cout << x << " " << y << endl;
        circle(im, Point(x, y), 2, Scalar(0, 0, 255), -1);
        int xmin = stats.at<int>(i, CC_STAT_LEFT);
        int ymin = 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);
 
        Rect rect(xmin, ymin, w, h);
        rectangle(im, rect, Scalar(0, 255, 255), 2);
        putText(im, to_string(i), Point(x+5, y), FONT_HERSHEY_SCRIPT_SIMPLEX, 1, Scalar(0, 0, 255), 2);
    }
 
    imshow("im", im);
 
    waitKey(0);
    destroyAllWindows();
 
    return 0;
 
}

简单双色图效果比较明显  百度图片搜的 

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持编程网。

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯