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 //<-- 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( "@input" ) ) );

if( image.empty() ) //<-- 判断图像是否读取成功

{

// 如果图像未被成功读取,则显示错误信息并返回-1,程序结束

cout << "Could not open or find the image!\n" << endl;

cout << "Usage: " << argv[0] << " " << 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(y,x)[c] =

saturate_cast( alpha*image.at(y,x)[c] + beta ); //<-- 对原图像的每一个像素值执行操作调整对比度和亮度,saturate_cast是为了确保计算结果落在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

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( "@input" ) ), IMREAD_COLOR );

if( src.empty() )

{

cout << "Could not open or find the image!\n" << endl; //若图片为空,打印错误信息

cout << "Usage: " << argv[0] << " " << 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 //标准输入输出库

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( "@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 // 引用标准输入输出库

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 // 引入标准输入输出库

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

相关链接

评论可见,请评论后查看内容,谢谢!!!评论后请刷新页面。