【opencv】示例-connected_components.cpp 连通组件检测

发布于:2024-04-11 ⋅ 阅读:(158) ⋅ 点赞:(0)

dbed73fadf2418fd42eab6bcff063167.png

4a6b33528b1435732151b2f158bb1561.png

#include <opencv2/core/utility.hpp> // 包含OpenCV核心功能相关的头文件
#include "opencv2/imgproc.hpp" // 包含OpenCV图像处理相关的头文件
#include "opencv2/imgcodecs.hpp" // 包含OpenCV图像编码解码相关的头文件
#include "opencv2/highgui.hpp" // 包含OpenCV的GUI相关的头文件
#include <iostream> // 包含标准输入输出流相关的头文件


using namespace cv; // 使用cv命名空间,简化代码中OpenCV函数的书写
using namespace std; // 使用std命名空间


Mat img; // 声明一个Mat类型的变量img用来存储图像数据
int threshval = 100; // 定义一个阈值变量并初始化为100


// 声明回调函数on_trackbar用于滑动条的回调
static void on_trackbar(int, void*)
{
    // 根据阈值将图像进行二值化处理
    Mat bw = threshval < 128 ? (img < threshval) : (img > threshval);
    // 声明并初始化连通组件标记图
    Mat labelImage(img.size(), CV_32S);
    // 调用connectedComponents函数计算连通组件并返回组件数量
    int nLabels = connectedComponents(bw, labelImage, 8);
    // 定义颜色向量数组,用于存储每个连通组件的颜色
    std::vector<Vec3b> colors(nLabels);
    // 第一个组件(背景)颜色设为黑色
    colors[0] = Vec3b(0, 0, 0);
    // 为每个连通组件生成随机颜色
    for(int label = 1; label < nLabels; ++label){
        colors[label] = Vec3b( (rand()&255), (rand()&255), (rand()&255) );
    }
    // 声明存储最终结果的彩色图像
    Mat dst(img.size(), CV_8UC3);
    // 遍历每个像素,将连通组件对应的颜色填充到dst图像中
    for (int r = 0; r < dst.rows; ++r) { // 使用for循环遍历每一行
        for (int c = 0; c < dst.cols; ++c) { // 内层for循环遍历每一列
            int label = labelImage.at<int>(r, c); // 获取当前像素位置的标签值
            Vec3b& pixel = dst.at<Vec3b>(r, c); // 获取待赋值的目标图像的当前像素位置的引用
            pixel = colors[label]; // 将对应标签的颜色赋给当前像素位置
        }
    }
    // 显示连通组件的结果图像
    imshow( "Connected Components", dst );
}


// 主函数
int main( int argc, const char** argv )
{
    // 解析命令行参数
    CommandLineParser parser(argc, argv, "{@image|stuff.jpg|image for converting to a grayscale}");
    // 打印程序相关信息
    parser.about("\nThis program demonstrates connected components and use of the trackbar\n");
    parser.printMessage();
    // 输出相关提示信息
    cout << "\nThe image is converted to grayscale and displayed, another image has a trackbar\n"
            "that controls thresholding and thereby the extracted contours which are drawn in color\n";
    
    // 获取输入的图像文件名
    String inputImage = parser.get<string>(0);
    // 读取图像文件为灰度图
    img = imread(samples::findFile(inputImage), IMREAD_GRAYSCALE);
    
    // 检查图像是否读取成功
    if(img.empty())
    {
        cout << "Could not read input image file: " << inputImage << endl;
        // 图像读取失败,返回退出码
        return EXIT_FAILURE;
    }


    // 显示原始图片窗口
    imshow( "Image", img );


    // 创建一个新的窗口用于显示连通组件处理的结果
    namedWindow( "Connected Components", WINDOW_AUTOSIZE);
    // 创建滑动条并关联到on_trackbar回调函数
    createTrackbar( "Threshold", "Connected Components", &threshval, 255, on_trackbar );
    // 初始调用滑动条的回调函数进行处理
    on_trackbar(threshval, 0);


    // 等待用户按键
    waitKey(0);
    // 正常退出程序
    return EXIT_SUCCESS;
}

此段代码展示了如何使用OpenCV库进行连通组件检测,并将结果显示在带有滑动条的窗口中,用户可以通过滑动条调整阈值,以改变连通组件检测的结果。代码分别包括了图像的读取、窗口的创建、滑动条的创建及其回调函数的编写,并在窗口中展示原始图像和连通组件的结果。使用Trackbar(滑动条)可以动态地控制图像的二值化阈值,进而观察到不同阈值下连通组件的变化。

Mat bw = threshval < 128 ? (img < threshval) : (img > threshval);

6f3487e74f9ad6e4743cb16acb28f4d2.png

1db75f941fcdd2439cc270c8406305bf.png

int nLabels = connectedComponents(bw, labelImage, 8);

da35ae41e62c0c438e33a3535e588038.png

The End


网站公告

今日签到

点亮在社区的每一天
去签到