目录
实验原理
实验代码
运行结果
实验原理
在 OpenCV 中,滑动条设计的主要目的是在视频播放帧中选择特定帧,而在调节图像参数时也会经常用到。在使用滑动条前,需要给滑动条赋予一个名字(通常是一个字符串),接下来将直接通过这个名字进行引用。
创建滑动条的函数是 createTrackbar,函数声明如下:
int createTrackbar(const string& trackbarname,
const string& winname, int* value, int count,
TrackbarCallback onChange=0, void* userdata=0)
其中参数
trackbarname 是滑动条的名称;
winname 是滑动条将要添加到父窗口的名称,一旦滑动条创建好,它将被添加到窗口的顶部或底部,滑动条不会挡住任何已经在窗口中的图像,只会让窗口变大,窗口的名称将作为一个窗口的标记,至于滑动条上滑动按钮的确切位置,由操作系统决定,一般都是在最左边;
value 是一个指向整数的指针,这个整数值会随着滑动按钮的移动自动变化;
count 是滑动条可以滑动的最大值;
onChange 是一个指向回调函数的指针,当滑动按钮移动时,回调函数就会自动调用;
userdata 可以是任何类型的指针,一旦回调函数执行,这个参数可以传递给回调函数的 userdata 参数,这样不创建全局变量也可以处理滑动条事件。
回调函数类型 TrackbarCallback 的定义如下:
typedef void(* cv::TrackbarCallback) (int pos, void *userdata);
其中参数
pos表示滚动块的当前位置;
userdata是传给回调函数的可选参数。这个回调函数不是必需的,如果直接赋值为 NULL,就没有回调函数,移动滑动按钮的唯一响应就是 createTrackbar的参数 value 指向的变量值的变化。
除了创建滑动条的函数外,OpenCV 还提供了函数 getTrackbarPos 用于获取滑动块的位置和函数 setTrackbarPos 用于设置滑动条的位置。函数 getTrackbarPos 声明如下:
int getTrackbarPos(const string& trackbarname, const string& winname);
其中参数
trackName 是滑动条的名称,
windowName 是滑动条将要添加到父窗口的名称。
函数返回滑动块的当前位置。
函数 setTrackbarPos 声明如下:
void setTrackbarPos(const string& trackbarname, const string& winname, int pos);
其中参数
trackName 表示滚动条的名称,
windowName 是滑动条将要添加到父窗口的名称,
pos表示要设置的滑动块位置。
erode() 函数用于执行图像的腐蚀操作。腐蚀是一种形态学变换,主要用于去除图像中的小斑点噪声、平滑边界、分离粘连的目标物体等。腐蚀操作的基本思想是使用一个结构元素(structuring element)来探测图像中的每个像素点及其周围区域,根据结构元素的位置和形状来决定是否保留中心像素点。
void erode(InputArray src, OutputArray dst,
InputArray kernel, Point anchor=Point(-1,-1),
int iterations=1, int borderType=BORDER_CONSTANT,
const Scalar& borderValue=Scalar());
参数说明
src: 输入图像。
dst: 输出图像,必须与输入图像具有相同的类型和尺寸。
kernel: 结构元素,定义了如何进行局部操作。可以通过getStructuringElement()函数创建。
anchor: 结构元素的锚点位置,默认为结构元素的中心。
iterations: 腐蚀操作的迭代次数,默认为1。更大的迭代次数会导致更强的腐蚀效果。
borderType: 边界类型,指定了图像边界外的像素如何处理,默认为BORDER_CONSTANT,即常数值。
borderValue: 当边界类型为BORDER_CONSTANT时,指定的常数值。
dilate()函数用于执行图像的膨胀操作。膨胀是另一种形态学变换,主要用于填充目标物体中的小孔洞、扩展边界、连接相邻的目标物体等。膨胀操作的基本思想是使用一个结构元素(structuring element)来探测图像中的每个像素点及其周围区域,根据结构元素的位置和形状来决定是否将中心像素点标记为前景。
void dilate(InputArray src, OutputArray dst,
InputArray kernel, Point anchor=Point(-1,-1),
int iterations=1, int borderType=BORDER_CONSTANT,
const Scalar& borderValue=Scalar());
参数说明
src: 输入图像。
dst: 输出图像,必须与输入图像具有相同的类型和尺寸。
kernel: 结构元素,定义了如何进行局部操作。可以通过getStructuringElement()函数创建。
anchor: 结构元素的锚点位置,默认为结构元素的中心。
iterations: 膨胀操作的迭代次数,默认为1。更大的迭代次数会导致更强的膨胀效果。
borderType: 边界类型,指定了图像边界外的像素如何处理,默认为BORDER_CONSTANT,即常数值。
borderValue: 当边界类型为BORDER_CONSTANT时,指定的常数值。
getStructuringElement()函数用于生成一个结构元素(structuring element),这是进行形态学操作(如腐蚀、膨胀、开运算、闭运算等)时必需的一个组件。结构元素定义了如何对图像中的每个像素点及其邻居进行处理。
Mat getStructuringElement(int shape, Size ksize, Point anchor=Point(-1,-1))
参数说明
shape: 结构元素的形状,可以是以下几种之一:
MORPH_RECT:矩形结构元素。
MORPH_CROSS:十字形结构元素。
MORPH_ELLIPSE:椭圆形结构元素。
MORPH_RECT是最常用的形状,因为它简单且易于理解。
MORPH_CROSS和MORPH_ELLIPSE则可能在某些情况下提供更好的性能或特定的应用效果。
ksize: 结构元素的大小,由一个Size对象定义,通常是一个奇数大小的正方形。例如,Size(3, 3)表示3x3大小的结构元素。
anchor: 结构元素的锚点位置,默认为结构元素的中心。锚点位置决定了结构元素相对于图像中的每个像素点的位置。如果设置了Point(-1, -1),则默认使用结构元素的中心作为锚点。
返回值
返回一个Mat对象,代表生成的结构元素。
实验代码
本例利用滑动块调节设置参数——利用滑动块控制腐蚀和膨胀。
#include "pch.h" // 预编译头文件
#include <opencv2/highgui/highgui_c.h> // 包含旧版的highgui模块
#include <opencv2\opencv.hpp> // 包含整个OpenCV库
//#pragma comment(lib, "opencv_world450d.lib") //引用引入库
using namespace cv;// 使用OpenCV命名空间
#include<iostream>// 输入输出流
using namespace std;// 使用标准命名空间
Mat src, erosion_dst, dilation_dst;// 定义三个Mat对象,分别存储源图像、腐蚀后的图像和膨胀后的图像
int erosion_elem = 0; // 腐蚀操作核类型,默认为0(矩形)
int erosion_size = 0; // 腐蚀操作核大小,默认为0
//假设你正在使用一个3x3的方形结构元素进行腐蚀操作,那么erosion_size就是3
int dilation_elem = 0;// 膨胀操作核类型,默认为0(矩形)
int dilation_size = 0;// 膨胀操作核大小,默认为0
int const max_elem = 2;// 最大的操作核类型数(矩形、十字形、椭圆)
int const max_kernel_size = 21;// 最大的操作核大小
void Erosion(int, void*);//腐蚀滑动条的回调函数
void Dilation(int, void*);//膨胀滑动条的回调函数
int main(int argc, char** argv)
{
src = imread("0901.jpg", IMREAD_COLOR);// 读取图像文件
if (src.empty())// 检查图像是否正确加载
{
cout << "Could not open or find the image!\n" << endl;
//cout << "无法打开或找到图像!\n";
cout << "Usage: " << argv[0] << " <Input image>" << endl;
//cout << "用法: " << argv[0] << " <输入图像>\n";
return -1;
}
namedWindow("Erosion Demo", WINDOW_NORMAL);//腐蚀演示窗口 WINDOW_AUTOSIZE
namedWindow("Dilation Demo", WINDOW_NORMAL);//膨胀演示窗口 WINDOW_NORMAL
//moveWindow("Dilation Demo", src.cols, 0);// 移动膨胀演示窗口到屏幕的适当位置
//怕此处 腐蚀窗口与膨胀窗口重合
/*createTrackbar("Element:\n 0: Rect \n 1: Cross \n 2: Ellipse", "Erosion Demo",
&erosion_elem, max_elem,
Erosion);*/
createTrackbar("元素:\n 0: 矩形 \n 1: 十字形 \n 2: 椭圆", "Erosion Demo", &erosion_elem, max_elem, Erosion);
// 创建腐蚀操作核类型的滚动条
/*createTrackbar("Kernel size:\n 2n +1", "Erosion Demo",
&erosion_size, max_kernel_size,
Erosion);*/
createTrackbar("核大小:\n 2n +1", "Erosion Demo", &erosion_size, max_kernel_size, Erosion);
// 创建腐蚀操作核大小的滚动条
/*createTrackbar("Element:\n 0: Rect \n 1: Cross \n 2: Ellipse", "Dilation Demo",
&dilation_elem, max_elem,
Dilation);*/
createTrackbar("元素:\n 0: 矩形 \n 1: 十字形 \n 2: 椭圆", "Dilation Demo", &dilation_elem, max_elem, Dilation);
// 创建膨胀操作核类型的滚动条
/*createTrackbar("Kernel size:\n 2n +1", "Dilation Demo",
&dilation_size, max_kernel_size,
Dilation);*/
createTrackbar("核大小:\n 2n +1", "Dilation Demo", &dilation_size, max_kernel_size, Dilation);
// 创建膨胀操作核大小的滚动条
Erosion(0, 0);// 初始化腐蚀操作
Dilation(0, 0);// 初始化膨胀操作
waitKey(0);// 等待按键事件
return 0;
}
void Erosion(int, void*)
{
int erosion_type = 0;// 初始化腐蚀类型为矩形
if (erosion_elem == 0)
{
erosion_type = MORPH_RECT; // 初始化腐蚀类型为矩形
}
else if (erosion_elem == 1)
{
erosion_type = MORPH_CROSS;// 如果选择十字形
}
else if (erosion_elem == 2)
{
erosion_type = MORPH_ELLIPSE; // 如果选择椭圆
}
Mat element = getStructuringElement(erosion_type,
Size(2 * erosion_size + 1, 2 * erosion_size + 1),
Point(erosion_size, erosion_size));// 获取腐蚀操作核
erode(src, erosion_dst, element);// 对图像进行腐蚀操作
imshow("Erosion Demo", erosion_dst);// 显示腐蚀后的图像
}
void Dilation(int, void*)
{
int dilation_type = 0;// 初始化膨胀类型为矩形
if (dilation_elem == 0)
{
dilation_type = MORPH_RECT; // 初始化膨胀类型为矩形
}
else if (dilation_elem == 1)
{
dilation_type = MORPH_CROSS;// 初始化膨胀类型为十字形
}
else if (dilation_elem == 2)
{
dilation_type = MORPH_ELLIPSE; // 初始化膨胀类型为椭圆
}
Mat element = getStructuringElement(dilation_type,
Size(2 * dilation_size + 1, 2 * dilation_size + 1),
Point(dilation_size, dilation_size));// 获取腐蚀操作核
dilate(src, dilation_dst, element);// 对图像进行膨胀操作
imshow("Dilation Demo", dilation_dst);// 显示膨胀后的图像
}
在代码中,首先读取 0901.jpg,然后利用函数namedWindow 创建两个窗口。接着利用函数createTrackbar 创建 4 个滑动条,每个窗口上两个滑动条(核的类型 和 核的大小)。Erosion 和 Dilation 都是滑动条的回调函数,用于响应用户滑动按钮这个事件。
函数 erode 和 dilate 分别是 OpenCV 中腐蚀和膨胀图像的函数,图像腐蚀和膨胀是图像学中的两个基本概念。