#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);
int nLabels = connectedComponents(bw, labelImage, 8);
The End