赞
踩
11.1 BasicLinearTransforms.cpp
调整输入图像的对比度和亮度,并显示原始图像和调整后的图像。程序中主要包含以下步骤:
读取用户输入的图像并做相应的错误处理。
创建一个新的图像矩阵用于存放调整对比度和亮度后的图像。
获取用户从命令行输入的对比度控制参数 alpha 和亮度控制参数 beta。
对原始图像中的每一个像素进行运算 new_image(i,j) = alpha*image(i,j) + beta
调整对比度和亮度。获取新的图像。
展示原始图像和新的图像。
程序挂起等待用户输入,一旦有输入,程序结束。
- /**
- * @file BasicLinearTransforms.cpp
- * @brief 简单的程序用于调整图像的对比度和亮度
- * @author OpenCV团队
- */
-
-
- // 引入头文件
- #include "opencv2/imgcodecs.hpp"
- #include "opencv2/highgui.hpp" //<-- 用于图像显示
- #include <iostream> //<-- C++标准库中的输入/输出头文件
-
-
- // 在此处,我们没有在全局范围内使用 "using namespace std;",是为了避免在 C++17 中 beta 变量与 std::beta产生冲突
- using std::cin;
- using std::cout;
- using std::endl;
- using namespace cv; // <-- 使用OpenCV中被封装在cv::下的所有的类和函数
-
-
-
-
- /**
- * @function main
- * @brief 主函数
- */
- int main( int argc, char** argv )
- {
- /// 读取用户输入的图像文件
- //! [basic-linear-transform-load]
- CommandLineParser parser( argc, argv, "{@input | lena.jpg | input image}" );
- Mat image = imread( samples::findFile( parser.get<String>( "@input" ) ) );
- if( image.empty() ) //<-- 判断图像是否读取成功
- {
- // 如果图像未被成功读取,则显示错误信息并返回-1,程序结束
- cout << "Could not open or find the image!\n" << endl;
- cout << "Usage: " << argv[0] << " <Input image>" << endl;
- return -1;
- }
- //! [basic-linear-transform-load]
-
-
- // 创建新的图像,准备存放调整对比度和亮度之后的图像
- //! [basic-linear-transform-output]
- Mat new_image = Mat::zeros( image.size(), image.type() );
- //! [basic-linear-transform-output]
-
-
- // 定义调整对比度和亮度的参数
- //! [basic-linear-transform-parameters]
- double alpha = 1.0; /*< 用于控制对比度的简单参数 */
- int beta = 0; /*< 用于控制亮度的简单参数 */
-
-
- /// 初始化值
- cout << " Basic Linear Transforms " << endl;
- cout << "-------------------------" << endl;
- cout << "* Enter the alpha value [1.0-3.0]: "; cin >> alpha; //<-- 从控制台获取alpha值
- cout << "* Enter the beta value [0-100]: "; cin >> beta; //<-- 从控制台获取beta值
- //! [basic-linear-transform-parameters]
-
-
- /// 执行操作 new_image(i,j) = alpha*image(i,j) + beta
- /// 我们本可以简单的使用函数:image.convertTo(new_image, -1, alpha, beta); 来实现上述操作,
- /// 但我们希望通过这个例子,展示出如何访问像素 :)
- //! [basic-linear-transform-operation]
- for( int y = 0; y < image.rows; y++ ) { //<-- 遍历图像的所有行
- for( int x = 0; x < image.cols; x++ ) { //<-- 遍历图像的所有列
- for( int c = 0; c < image.channels(); c++ ) { //<-- 遍历图像的每个通道
- new_image.at<Vec3b>(y,x)[c] =
- saturate_cast<uchar>( alpha*image.at<Vec3b>(y,x)[c] + beta ); //<-- 对原图像的每一个像素值执行操作调整对比度和亮度,saturate_cast<uchar>是为了确保计算结果落在uchar的取值范围
- }
- }
- }
- //! [basic-linear-transform-operation]
-
-
- // 展示图像
- //! [basic-linear-transform-display]
- imshow("Original Image", image); // 显示原始图像
- imshow("New Image", new_image); // 显示调整后的图像
-
-
- // 等待用户按键,这样做是为了防止程序运行完后立即退出,无法显示图像
- waitKey();
- //! [basic-linear-transform-display]
- return 0; //正常结束程序
- }
11.2 Morphology_1.cpp
这段由OpenCV团队编写,对一张图片进行腐蚀和膨胀操作的C++代码。腐蚀操作会减小图像区域,膨胀操作会增大图像区域。主要通过设定腐蚀元素和膨胀元素的类型以及内核大小,然后调用库函数进行腐蚀或者膨胀操作,来改变图像的性质。可以视为一种提取图像特征的方法,常应用于图像二值化、边缘检测、消除噪声等图像处理操作中。
- /**
- * @file Morphology_1.cpp
- * @brief Erosion and Dilation sample code 腐蚀与膨胀的样例代码
- * @author OpenCV team
- */
-
-
- #include "opencv2/imgproc.hpp" //包含OpenCV库头文件
- #include "opencv2/highgui.hpp" //包含OpenCV高级用户界面的头文件
- #include <iostream>
-
-
- using namespace cv;
- using namespace std;
-
-
- /// Global variables 定义全局变量
- Mat src, erosion_dst, dilation_dst;
-
-
- int erosion_elem = 0;
- int erosion_size = 0;
- int dilation_elem = 0;
- int dilation_size = 0;
- int const max_elem = 2;
- int const max_kernel_size = 21;
-
-
- /** Function Headers 函数的声明(函数的原型) */
- void Erosion( int, void* ); // 腐蚀函数
- void Dilation( int, void* ); // 膨胀函数
-
-
- /**
- * @function main 主函数
- */
- int main( int argc, char** argv )
- {
- /// Load an image, 加载图片
- CommandLineParser parser( argc, argv, "{@input | LinuxLogo.jpg | input image}" );
- src = imread( samples::findFile( parser.get<String>( "@input" ) ), IMREAD_COLOR );
- if( src.empty() )
- {
- cout << "Could not open or find the image!\n" << endl; //若图片为空,打印错误信息
- cout << "Usage: " << argv[0] << " <Input image>" << endl;
- return -1;
- }
-
-
- /// Create windows 创建窗口
- namedWindow( "Erosion Demo", WINDOW_AUTOSIZE );
- namedWindow( "Dilation Demo", WINDOW_AUTOSIZE );
- moveWindow( "Dilation Demo", src.cols, 0 );
-
-
- /// Create Erosion Trackbar 创建腐蚀的滑动条
- createTrackbar( "Element:\n 0: Rect \n 1: Cross \n 2: Ellipse", "Erosion Demo",
- &erosion_elem, max_elem,
- Erosion );
-
-
- createTrackbar( "Kernel size:\n 2n +1", "Erosion Demo",
- &erosion_size, max_kernel_size,
- Erosion );
-
-
- /// Create Dilation Trackbar 创建膨胀的滑动条
- createTrackbar( "Element:\n 0: Rect \n 1: Cross \n 2: Ellipse", "Dilation Demo",
- &dilation_elem, max_elem,
- Dilation );
-
-
- createTrackbar( "Kernel size:\n 2n +1", "Dilation Demo",
- &dilation_size, max_kernel_size,
- Dilation );
-
-
- /// Default start 默认开始
- Erosion( 0, 0 );
- Dilation( 0, 0 );
-
-
- waitKey(0); //等待用户按键操作
- return 0;
- }
-
-
- /**
- * @function Erosion 腐蚀函数
- */
- void Erosion( int, void* )
- {
- int erosion_type = 0;
- if( erosion_elem == 0 ){ erosion_type = MORPH_RECT; } //如果元素类型为0,腐蚀的类型为MORPH_RECT
- else if( erosion_elem == 1 ){ erosion_type = MORPH_CROSS; } //如果元素类型为1,腐蚀的类型为MORPH_CROSS
- else if( erosion_elem == 2) { erosion_type = MORPH_ELLIPSE; } //如果元素类型为2,腐蚀的类型为MORPH_ELLIPSE
-
-
- //![kernel]
- Mat element = getStructuringElement( erosion_type, //生成预定义形状的结构元素
- Size( 2*erosion_size + 1, 2*erosion_size+1 ),
- Point( erosion_size, erosion_size ) );
- //![kernel]
-
-
- /// Apply the erosion operation 进行腐蚀操作
- erode( src, erosion_dst, element );
- imshow( "Erosion Demo", erosion_dst ); //显示腐蚀的效果
- }
-
-
- /**
- * @function Dilation 膨胀函数
- */
- void Dilation( int, void* )
- {
- int dilation_type = 0;
- if( dilation_elem == 0 ){ dilation_type = MORPH_RECT; } //如果元素类型为0,膨胀的类型为MORPH_RECT
- else if( dilation_elem == 1 ){ dilation_type = MORPH_CROSS; } //如果元素类型为1,膨胀的类型为MORPH_CROSS
- else if( dilation_elem == 2) { dilation_type = MORPH_ELLIPSE; } //如果元素类型为2,膨胀的类型为MORPH_ELLIPSE
-
-
- Mat element = getStructuringElement( dilation_type, //生成预定义形状的结构元素
- Size( 2*dilation_size + 1, 2*dilation_size+1 ),
- Point( dilation_size, dilation_size ) );
-
-
- /// Apply the dilation operation 进行膨胀操作
- dilate( src, dilation_dst, element );
- imshow( "Dilation Demo", dilation_dst ); //显示膨胀的效果
- }
11.3 Morphology_2.cpp
这段代码的主要功能是实现形态学操作,如:开运算、闭运算、形态学梯度、顶帽运算和黑帽运算,用户可以自行选择操作类型及形状和大小的结构元素,以观察不同设置下的形态学操作效果
- /**
- * @file Morphology_2.cpp
- * @brief 封装了一些形态学变换的高级示例代码
- * @author OpenCV团队
- */
-
-
- #include "opencv2/imgproc.hpp" //包含了图像处理方面的函数和类
- #include "opencv2/imgcodecs.hpp" //包含了图像编码/解码方面的函数和类
- #include "opencv2/highgui.hpp" //包含了图像显示方面的函数和类
- #include <iostream> //标准输入输出库
-
-
- using namespace cv; //使用OpenCV的命名空间
-
-
- /// 全局变量
- Mat src, dst; //定义两个Mat类型的变量,src和dst,分别用来存储原图和处理后的图像
-
-
- int morph_elem = 0; //定义一个变量,用于切换形态学处理的内核类型
- int morph_size = 0; //定义一个变量,用于改变形态学处理的内核大小
- int morph_operator = 0; //定义一个变量,用于切换不同的形态学操作
- int const max_operator = 4; //定义操作类型的最大值
- int const max_elem = 2; //定义内核类型的最大值
- int const max_kernel_size = 21; //定义内核大小的最大值
-
-
- const char* window_name = "Morphology Transformations Demo"; //定义程序窗口的标题
-
-
- /** 函数声明 */
- void Morphology_Operations( int, void* );
-
-
- /**
- * @function main
- */
- int main( int argc, char** argv )
- {
- //![load]
- CommandLineParser parser( argc, argv, "{@input | baboon.jpg | 输入图片}" );
-
- //使用parser获取的参数,从文件加载图像到src,加载方式为色彩图像
- src = imread( samples::findFile( parser.get<String>( "@input" ) ), IMREAD_COLOR );
-
- //如果原图为空,则输出错误信息并返回
- if (src.empty())
- {
- std::cout << "无法打开或找到图像!\n" << std::endl;
- std::cout << "使用方法: " << argv[0] << " <输入图像>" << std::endl;
- return EXIT_FAILURE;
- }
- //![load]
-
-
- //![window]
- namedWindow( window_name, WINDOW_AUTOSIZE ); //创建一个名为window_name的窗口,窗口大小自适应图像大小
- //![window]
-
-
- //![create_trackbar1]
- /// 创建滚动条来选择形态学操作类型
- createTrackbar("Operator:\n 0: 开运算 - 1: 闭运算 \n 2: 形态学梯度 - 3: 顶帽运算 \n 4: 黑帽运算", window_name, &morph_operator, max_operator, Morphology_Operations );
- //![create_trackbar1]
-
-
- //![create_trackbar2]
- /// 创建滚动条来选择内核类型
- createTrackbar( "Element:\n 0: 矩形 - 1: 十字形 - 2: 椭圆形", window_name,
- &morph_elem, max_elem,
- Morphology_Operations );
- //![create_trackbar2]
-
-
- //![create_trackbar3]
- /// 创建滚动条来选择内核大小
- createTrackbar( "Kernel size:\n 2n +1", window_name,
- &morph_size, max_kernel_size,
- Morphology_Operations );
- //![create_trackbar3]
-
-
- /// 默认开始
- Morphology_Operations( 0, 0 ); //调用形态学操作处理函数
-
-
- waitKey(0); //等待用户按键
- return 0; //程序正常退出
- }
-
-
- //![morphology_operations]
- /**
- * @function Morphology_Operations
- */
- void Morphology_Operations( int, void* )
- {
- // 在MORPH_X中:2,3,4,5和6
- //![operation]
- int operation = morph_operator + 2; //根据用户选择,确定形态学操作的类型
- //![operation]
-
-
- //构建指定类型和大小的内核元素
- Mat element = getStructuringElement( morph_elem, Size( 2*morph_size + 1, 2*morph_size+1 ), Point( morph_size, morph_size ) );
-
-
- /// 应用指定的形态学操作
- morphologyEx( src, dst, operation, element ); //执行形态学操作
- imshow( window_name, dst ); //在窗口中显示处理后的图像
- }
- //![morphology_operations]
11.4 Threshold.cpp
代码主要实现了在给定图像上应用不同类型的阈值处理,并通过创建的滑动条手动选择阈值类型以及阈值大小,进而观察不同阈值类型和大小对图像处理效果的影响。阈值处理通常应用于图像分割、特征提取等操作,是计算机视觉领域的基本技术之一。
- /**
- * @file Threshold.cpp
- * @brief 这是一个示例代码,演示如何使用OpenCV提供的各种阈值策略
- * @author OpenCV团队
- */
-
-
- #include "opencv2/imgproc.hpp" // 引用OpenCV库处理图像处理部分
- #include "opencv2/imgcodecs.hpp" // 用于处理图像编码和解码带
- #include "opencv2/highgui.hpp" // 提供创建窗口,加载图像等与高级图形用户界面相关的功能
- #include <iostream> // 引用标准输入输出库
-
-
- using namespace cv; // 使用命名空间cv,方便代码中直接用OpenCV函数
- using std::cout; // 使用标准命名空间中的cout
-
-
- /// 全局变量
- int threshold_value = 0; // 阈值
- int threshold_type = 3; // 阈值类型
- int const max_value = 255; // 最大值常数
- int const max_type = 4; // 最大类型常数
- int const max_binary_value = 255; // 二值图像最大像素值
-
-
- Mat src, src_gray, dst; // 声明原图、灰度图和目标图像矩阵
- const char* window_name = "Threshold Demo"; // 窗口名称
-
-
- const char* trackbar_type = "Type: \n 0: Binary \n 1: Binary Inverted \n 2: Truncate \n 3: To Zero \n 4: To Zero Inverted";
- const char* trackbar_value = "Value"; // 滑动条上显示的提示文字
-
-
- //![阈值处理函数]
- /**
- * @function Threshold_Demo
- */
- static void Threshold_Demo( int, void* )
- {
- /* 0: Binary 二值阈值
- 1: Binary Inverted 反转二值阈值
- 2: Threshold Truncated 截断阈值
- 3: Threshold to Zero 零设置阈值
- 4: Threshold to Zero Inverted 反转零设置阈值
- */
- threshold( src_gray, dst, threshold_value, max_binary_value, threshold_type ); // 应用阈值进行图像分割
- imshow( window_name, dst ); // 显示处理后的图像
- }
- //![阈值处理函数]
-
-
- /**
- * @function main
- */
- int main( int argc, char** argv )
- {
- //! [load]
- String imageName("stuff.jpg"); // 默认图像文件名
- if (argc > 1)
- {
- imageName = argv[1]; // 如果有输入参数,第一个参数作为图像文件名
- }
- src = imread( samples::findFile( imageName ), IMREAD_COLOR ); // 读取图像文件
-
-
- if (src.empty())
- {
- cout << "Cannot read the image: " << imageName << std::endl; // 如果图像读取失败,打印错误信息
- return -1;
- }
-
-
- cvtColor( src, src_gray, COLOR_BGR2GRAY ); // 将图像转化为灰度图
- //! [load]
-
-
- //! [window]
- namedWindow( window_name, WINDOW_AUTOSIZE ); // 创建窗口用以显示结果
- //! [window]
-
-
- //! [trackbar]
- createTrackbar( trackbar_type,
- window_name, &threshold_type,
- max_type, Threshold_Demo ); // 创建滑动条以选择阈值类型
-
-
- createTrackbar( trackbar_value,
- window_name, &threshold_value,
- max_value, Threshold_Demo ); // 创建滑动条以选择阈值大小
- //! [trackbar]
-
-
- Threshold_Demo( 0, 0 ); // 初始化并调用阈值处理函数
-
-
- /// 等待用户操作结束程序
- waitKey();
- return 0;
- }
如何确定使用哪种阈值处理方式来处理图像?
阈值处理是图像处理中的哪一步骤?
阈值处理可以在哪些应用场景中使用?
阈值处理如何在目标检测中应用?
11.5 Threshold_inRange.cpp
这段代码的功能是通过设定HSV色彩空间的阈值来检测颜色,并利用滑动条可实时调整阈值,用以监测摄像头(或者视频)中特定颜色的物体,用于实时颜色追踪的应用。
- #include "opencv2/imgproc.hpp" // 引入opencv图像处理库
- #include "opencv2/highgui.hpp" // 引入opencv高级GUI库
- #include "opencv2/videoio.hpp" // 引入opencv的视频输入输出库
- #include <iostream> // 引入标准输入输出库
-
-
- using namespace cv; // 使用命名空间cv,opencv核心库中的所有函数和方法都被定义在cv的命名空间下(包含图像处理、数据结构等主要模块)
-
-
- /** 全局变量 */
- const int max_value_H = 360/2; // 定义 HSV 色调的最大值
- const int max_value = 255; // 定义 HSV 饱和度和亮度的最大值
- const String window_capture_name = "Video Capture"; // 定义视频捕获窗口的名称
- const String window_detection_name = "Object Detection"; // 定义物体检测窗口的名称
- int low_H = 0, low_S = 0, low_V = 0; // 定义 HSV 颜色空间分别对应色调、饱和度和亮度的最低阈值
- int high_H = max_value_H, high_S = max_value, high_V = max_value; // 定义 HSV 颜色空间分别对应色调、饱和度和亮度的最高阈值
-
-
- //! [low]
- static void on_low_H_thresh_trackbar(int, void *) // 当滑动条的值改变时,调用此回调函数,更新低阈值
- {
- low_H = min(high_H-1, low_H); // 确保低阈值总是小于高阈值
- setTrackbarPos("Low H", window_detection_name, low_H); // 设置滑动条的位置
- }
- //! [low]
-
-
- //! [high]
- static void on_high_H_thresh_trackbar(int, void *) // 当滑动条的值改变时,调用此回调函数,更新高阈值
- {
- high_H = max(high_H, low_H+1); // 确保高阈值总是大于低阈值
- setTrackbarPos("High H", window_detection_name, high_H); // 设置滑动条的位置
- }
-
-
- static void on_low_S_thresh_trackbar(int, void *) // 更新饱和度的低阈值
- {
- low_S = min(high_S-1, low_S);
- setTrackbarPos("Low S", window_detection_name, low_S);
- }
-
-
- static void on_high_S_thresh_trackbar(int, void *) // 更新饱和度的高阈值
- {
- high_S = max(high_S, low_S+1);
- setTrackbarPos("High S", window_detection_name, high_S);
- }
-
-
- static void on_low_V_thresh_trackbar(int, void *) // 更新亮度的低阈值
- {
- low_V = min(high_V-1, low_V);
- setTrackbarPos("Low V", window_detection_name, low_V);
- }
-
-
- static void on_high_V_thresh_trackbar(int, void *) // 更新亮度的高阈值
- {
- high_V = max(high_V, low_V+1);
- setTrackbarPos("High V", window_detection_name, high_V);
- }
-
-
- int main(int argc, char* argv[]) // 主函数
- {
- //! [cap]
- VideoCapture cap(argc > 1 ? atoi(argv[1]) : 0); // 创建视频捕获对象,如果程序有参数,使用参数作为视频源,否则使用默认摄像头
- //! [cap]
-
-
- //! [window]
- namedWindow(window_capture_name); // 创建视频捕获窗口
- namedWindow(window_detection_name); // 创建物体检测窗口
- //! [window]
-
-
- //! [trackbar]
- // 创建滑动条,并设置HSV值的阈值
- createTrackbar("Low H", window_detection_name, &low_H, max_value_H, on_low_H_thresh_trackbar);
- createTrackbar("High H", window_detection_name, &high_H, max_value_H, on_high_H_thresh_trackbar);
- createTrackbar("Low S", window_detection_name, &low_S, max_value, on_low_S_thresh_trackbar);
- createTrackbar("High S", window_detection_name, &high_S, max_value, on_high_S_thresh_trackbar);
- createTrackbar("Low V", window_detection_name, &low_V, max_value, on_low_V_thresh_trackbar);
- createTrackbar("High V", window_detection_name, &high_V, max_value, on_high_V_thresh_trackbar);
- //! [trackbar]
-
-
- Mat frame, frame_HSV, frame_threshold; // 定义三个Mat对象,用于存储原始帧,HSV色彩空间帧和阈值帧
- while (true) { // 循环处理每一帧
- //! [while]
- cap >> frame; // 读取一帧
- if(frame.empty()) // 如果帧为空说明视频已经结束
- {
- break;
- }
-
-
- cvtColor(frame, frame_HSV, COLOR_BGR2HSV); // 将原始帧从BGR色彩空间转换到HSV色彩空间
- inRange(frame_HSV, Scalar(low_H, low_S, low_V), Scalar(high_H, high_S, high_V), frame_threshold); // 通过HSV阈值,对帧进行二值化处理
- //! [while]
-
-
- //! [show]
- imshow(window_capture_name, frame); // 显示原始帧
- imshow(window_detection_name, frame_threshold); // 显示二值化处理后的帧
- //! [show]
-
-
- char key = (char) waitKey(30); // 等待键盘输入,如果按下'q'或者ESC键,跳出循环
- if (key == 'q' || key == 27)
- {
- break;
- }
- }
- return 0;
- }
Threshold_Tutorial_Theory_Base_Figure
Threshold_Tutorial_Theory_Binary.png
Threshold_Tutorial_Theory_Binary_Inverted.png
Threshold_Tutorial_Theory_Truncate.png
Threshold_Tutorial_Theory_Zero.png
Threshold_Tutorial_Theory_Zero_Inverted.png
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。