Opencv C++图像处理:矩阵Mat + 随机数RNG + 计算耗时 + 鼠标事件

1、C++的数据类型+字节数+取值范围

数据类型 字节数 取值范围
bool型(布尔型) 1 [0 or 1]
BOOL型(int型) 4 [TRUE or FALSE]
sbyte型(有符号8位整数) 1 [128 ~ 127]
bytet型(无符号8位整数)8U 2 [0 ~ 255]
short型(有符号16位整数)16S 2 [-32,768 ~ 32,767]
ushort型(无符号16位整数)16U 2 [0 ~ 65,535]
int型(有符号32位整数)32S 4 [-2,147,483 ~ 2,147,483,647]
uint型(无符号32位整数) 4 [0 ~ 4,294,967,295]
long型(64位有符号整数) 8 [9,223,372,036,854,775,808 ~ 9,223,372,036,854,775,807]
ulong型(64位无符号整数) 8 [0 ~ 18,446,744,073,709,551,615]
float型(32位单精度实数)32F 4 [3.4E+10的负38次方 ~ 3.4E+10的38次方]
double型(64位双精度实数)64F 8 [1.7E+10的负308次方 ~ 1.7E+10的正308次方]
指针 4

注意:int,float,double占多少个字节是由编译器决定的,不同的编译器,规定也不一样。ANSI标准定义int是占2个字节。

2、Mat对象:n 维单/多通道的密集矩阵

Mat(n-dimensional dense array class): 用于存储数值、向量、矩阵、灰度或彩色图像、体素体积、向量场、点云、张量、直方图。
Mat类:创建并访问二维、三维、四维、五维矩阵
Mat类:矩阵相乘——点乘、dot、mul运算详解

OpenCV C++使用 Mat 来存储图像数据,而 Mat 由多个像素点组成。常规图像的存储格式是8(8bite),即一个像素点占用8个字节空间。

图像的数据格式由两个部分组成:存储格式 + 通道数。包括:CV_{
    
    8U, 16S, 16U, 32S, 32F, 64F}C{
    
    1, 2, 3, 4}。
		(1)存储格式包括:	8U(unsigned char), 16S(short int), 16U(unsigned short int), 
							32S(signed int), 32F(float), 64F(double)2)通道数包括:C{
    
    1, 2, 3, 4}。
					其中,通道数代表每个像素点能存放多少个像素值。如:RGB彩色图中,每个像素点都有三个像素值。
							C1(单通道图像)。如:灰度图。一般图像是8(8bite)存储格式,即CV_8UC1。
							C3(3通道图像)。如:RGB彩色图
							C4(4通道图像)。如:带有透明度通道的RGB图像
							
例如:CV_8UC3表示8位无符号整型三通道矩阵
		00、假设3通道矩阵Mat=(100, 100, 3)
		11、RGB图像有100 x 100 x 3=30000个像素点
		22、每个像素点在内存空间所占的空间大小是8(8bite),即CV_8;。
		33、每个像素点都存放3个值。
  • 提问:
    在对图像的像素处理时,为什么要把读取图像时的CV_8UC3(Vec3b)转换成CV_32F(Vec3F),且处理完之后还需要转换回CV_8UC3(Vec3b)无符号整型?
  • 回答:
    8U取值范围=[0, 255],16U=[0, 65535],32f=[3.4E+10的负38次方 ~ 3.4E+10的38次方]。
    (1)对像素进行图像处理时,无需转换可以直接处理。
    (2)对像素进行数学计算时,需要保持高精度,避免信息损失。

2.1、创建 Mat 矩阵

函数说明:cv::Mat M_temp(row, column, data_type, cv::Scalar(0, 0, 255))
输入参数:		
				row					矩阵的行。
				column				矩阵的列。
				data_type			图像的数据格式。
				Scalar(0, 0, 255)	初始化RGB的像素值。表示R/G全为0,B全为255//
cv::Mat img1(480, 640, CV_8UC3);		//新建矩阵
cv::Mat img2(img1);						//复制矩阵

cv::Mat img7 = cv::Mat::zeros(rows, cols, CV_8UC3); 		//值全0矩阵。
cv::Mat img8 = cv::Mat::ones(rows, cols, CV_64FC1); 		//值全1矩阵。
cv::Mat img9 = cv::Mat::eye(rows, cols, CV_16SC2); 			//单位矩阵。		

2.2、获取像素1:img.at(y,x)

(0)CV_8UC1(uchar):8位无符号整型单通道矩阵。
(1)CV_8UC3(Vec3b):8位无符号整型三通道矩阵。
(2)CV_32FC3(Vec3F):32位浮点型三通道矩阵。

cv::Mat img = cv::Mat::ones(240, 320, CV_8UC1);				//创建单通道Mat矩阵
cv::Mat img1 = cv::Mat::ones(480, 640, CV_8UC3);			//创建多通道Mat矩阵

float elem = img.at<uchar>(10, 10);							//获取(单通道)像素点的像素值:img.at<uchar>(y,x)
cv::Vec3b elem = img1.at<cv::Vec3b>(10, 10);				//获取(多通道)像素点的像素值:img.at<cv::Vec3b>(y,x)
elem_B = elem[0]; 			//蓝色通道数值(全255)
elem_G = elem[1]; 			//绿色通道数值(全255)
elem_R = elem[2]; 			//红色通道数值(全0)

2.3、获取像素2(防止颜色溢出):saturate_cast(y,x)

可以解决边界溢出:若像素值大于255,则赋值255;若像素值小于0,则赋值0。

//原理如下
if (data_value < 0) 
	data_value = 0; 
else if (data_value > 255) 
	data_value = 255;
#include <opencv2/opencv.hpp>
//using namespace cv;
//using namespace std;

int main(int argc, const char* argv[]) 
{
    
    
    //(1)读取图像
    std::string img_path = "test.jpg";
    cv::Mat src = cv::imread(img_path, 1);

    //(2)判断图像是否读取成功
    if (!src.data)
    {
    
    
        std::cout << "can't read image!" << std::endl;
        return -1;
    }
    
    //(3)获取元素
    cv::Mat dst1, dst2;
	dst1 = cv::Mat::zeros(src.size(), src.type());	
	dst2 = cv::Mat::zeros(src.size(), src.type());

	//三个for循环:dst(i,j) =a * src(i,j) + b
	for (int y = 0; y < src.rows; y++)
	{
    
    
		for (int x = 0; x < src.cols; x++)
		{
    
    
			for (int c = 0; c < 3; c++)		//三个通道
			{
    
    
				dst1.at<cv::Vec3b>(y, x)[c] = src.at<cv::Vec3b>(y, x)[c] * 2;								//不饱和滤除
				dst2.at<cv::Vec3b>(y, x)[c] = cv::saturate_cast<uchar>(src.at<cv::Vec3b>(y, x)[c] * 2);		//饱和滤除
			}
		}
	}
	
	//(4)显示图像
	cv::imshow("src", src);
	cv::imshow("dst1", dst1);
	cv::imshow("dst2", dst2);

	cv::waitKey(0);
	return 0;
}

2.4、Mat矩阵常用属性

cv::Mat img(320, 320, CV_8UC3, cv::Scalar(255, 255, 0));		//创建320×320的3通道彩色图像。

Mat.rows 				获取矩阵 行数
Mat.cols 				获取矩阵 列数
Mat.dims 				获取矩阵 维数(单通道是二维,多通道是三维)
Mat.channels() 			获取矩阵 通道数
Mat.size();				获取矩阵 大小
Mat.total() 			获取矩阵 面积=[行数*列数](与通道数无关)
Mat.depth()				获取矩阵 存储格式(返回0~6):enum{
    
    CV_8U=0, CV_8S=1, CV_16U=2, CV_16S=3, CV_32S=4, CV_32F=5, CV_64F=6}  

Mat.row(0) 				获取矩阵 第一行元素组成的数组。
Mat.col(0) 				获取矩阵 第一列元素组成的数组。
Mat.rowRange(0, 10)		获取矩阵 第0-10行元素组成的数组。
Mat.colRange(0, 10)		获取矩阵 第0-10列元素组成的数组。

Mat.empty();			判断矩阵是否为空,若为空,则返回true。
Mat.clone()				复制矩阵并赋值给新矩阵。

Mat.setTo(0);						将矩阵全部设置为指定值(0)。如:src.setTo(0, src<10);当src中的某个像素值小于10,就将该值设置成0。
MatA.copyTo(MatB)					将矩阵A复制到矩阵B中。
Mat.convertTo(img, CV_32F)			将img的数据格式转换为CV_32F。
Mat.push_back()						将一个或多个元素添加到矩阵底部。其类型和列数必须与Mat矩阵中的相同。

3、基本数据类型

3.1、Point类:cv::Point()

cv::Point类由两个部分组成:cv::Point{
    
    2, 3}{
    
    b, s, i, f, d}。
		(1)维度			23代表维度(分别代表2个点、3个点)
		(2)存储类型		b 表示无符号字符
							s 表示短整型
							i 表示32位整型
							f 表示32位浮点数
							d 表示64位浮点数
							
Point类支持的操作:
		默认构造函数:		cv::Point2i p;	
							cv::Point3i p;
		复制构造函数:		cv::Point3f p2(p1);
		值构造函数:			cv::Point2i(x0,x1);
							cv::Point3d p(x0,x1,x2);
		构造固定向量类:		cv::Vec3f p;
		成员访问:			p.x, p.y;
		点乘:				float x = p1.dot(p2);
		双精度点乘:			double x =p1.ddot(p2);
		叉乘:				p1.cross(p2)

3.2、Scalar类:cv::Scalar()

cv::Scalar本质上是一个四维向量,其可以产生任意四元素的向量,一般是double类型。

Scalar类支持的操作:
		默认构造函数:				cv::Scalar s;
		复制构造函数:				cv::Scalar s2(s1);
		值构造函数:					cv::Scalar s(x0);
									cv::Scalar s(x0, x1, x2, x3);
		返回所有元素都为标量k:		cv::Scalar::all(k)		
		
		元素相乘:					s1.mul(s2);
		(四元数)共轭:				s.conj();		//return cv::Scalar(s0,-s1,-s2,-s2)
		(四元数)真值测试:			s.isReal();		//return ture, if s1==s2==s3==0.

3.3、Size类:cv::Size()

Size类支持的操作:
		默认构造函数:		cv::Size sz; 
							cv::Size2i sz;
							cv::Size2f sz;
		复制构造函数:		cv::Size sz2(sz1);
		值构造函数:			cv::Size2f sz(w,h);
		成员访问:			sz.width, sz.height;
		计算面积:			sz.area();

3.4、Rect类:cv::Rect()

Rect类包含:		
			(1)Point类的成员(x, y)。				矩形左上角
			(2)Size类的成员(width, height)。		代表矩形的大小

4.1 Rect类支持的操作:
		默认构造函数:			cv::Rect r;
		复制构造函数:			cv::Rect r2(r1);
		值构造函数:				cv::Rect(x, y, w, h);
		由起始点和大小构造:		cv::Rect(p, sz);
		由两个对角构造:			cv::Rect(p1, p2);
		成员访问:				r.x, r.y, r.width, r.height;
		计算面积:				r.area();
		提取左上角和右下角:		r.tl(), r.br();
		判断p点是否在矩形r内:	r.contains(p);

4.2 Rect类的覆写操作:
		矩形r1和矩形r2的交集:			cv::Rect r3 = r1&r2; r1 &= r2;
		矩形r1和矩形r2的并集:			cv::Rect r3 = r1|r2; r1 |= r2;
		平移矩形r x个数量:				cv::Rect rx = r+x; r += x;
		扩大矩形r s大小:				cv::Rect rs = r+s; r += s;
		比较矩形r1和矩形r2是否相等:		bool eq = (r1 == r2);
		比较矩形r1和矩形r2是否不相等:	bool ne = (r1 != r2);

3.5、Matx类:cv::Matx()

固定矩阵类(Matx类):
		是为了使编译时就已知矩阵的维度而设计,其内部所有数据都是在堆栈上分配的。
		其是Opencv的c++接口基本类型的核心。
		其继承于固定矩阵类。而其他的类:要么继承于固定向量类,要么转换成固定向量类。
		其是一个模板cv::Matx<>,但独立的矩阵通常通过别名分配。别名的基础格式为cv::Matx{
    
    1,2,3,4,5,6}{
    
    1,2,3,4,5,6}{
    
    f,d}5.1 Matx类支持的操作:
		默认构造函数:		cv::Matx33f m22f;
							cv::Matx43d m43d;
		复制构造函数:		cv::Matx22d m22d(n22d);
		值构造函数:			cv::Matx21f m(x0,x1);
		含相同元素的矩阵:	m33f = cv::Matx33f::all(x);
		全零矩阵:			m23d = cv::Matx23d::zeros();
		元素全是1的矩阵:	m16f = cv::Matx16f::ones();
		单位矩阵:			m33f = cv::Matx33f::eye();
		均匀分布矩阵:		m33f = cv::Matx33f::randu(min,max);
		正态分布矩阵:		m33f = cv::Matx33f::nrandu(mean,variance);
		成员访问:			m(i,j), m(i);

矩阵能正常的进行加减乘除:
		点积:						float x = m1.dot(m2);
		双精度点积:					double x = m1.ddot(m2);
		变换操作符:					m44f = (Matx44f) m44d;
		提取(i, j)处的2*2子矩阵:	m44f.get_minor<2,2>(i, j);
		提取第i行或者j列:			m14f = m44f.row(i),m41f = m44f.col(j);
		提取矩阵的对角线:			m41f = m44f.diag();
		计算矩阵转置:				n44f = m44f.t();
		计算矩阵的逆:				n44f = m44f.inv(method);
		每个元素的乘法:				m1.mul(m2);

3.6、Vec类:cv::Vec()

6.1 Vec类支持的操作:
		默认构造函数:		cv::Vec2s v2s;
		复制构造函数:		cv::Vec3f u3f(v3f);
		值构造函数:			cv::Vec2f v2f(x0,x1);
		成员访问:			v4f[i]; v3w(j);		//[] 和()都是可以的
		向量叉乘:			v3f, cross(u3f);

3.7、Range类:cv::Range()

cv::Range类:用于确定一个连续的整数序列。

函数说明:cv::Range(int start,int end)
输入参数:
		start		起始点
		end			终止点
		
备注:左闭右开,与Python的range()类似。
举例:cv::Range rng(0, 4)		包含[0,1,2,3],但是不包含4

4、随机数:cv::RNG

(1)cv::RNG rng(int seed);使用随机数种子seed产生一个64位的随机整数,默认-1。计算机产生的随机数都是伪随机数,是根据种子点seed和特定算法计算出来的。所以,只要种子数一定,算法一定,则每次产生的随机数也是一定的。用系统时间做种子点

(2)cv::RNG rng((unsigned)time(NULL)); 用系统时间作为种子点,需添加头文件#include <time.h>

4.1、生成一个随机数:cv::RNG::uniform() + cv::RNG::gaussian()

基于随机数的3种生成方法:

cv::RNG rng(int seed) 				使用随机数种子seed产生一个64位随机整数,默认-1。
	
(1)cv::RNG::uniform(a, b):		返回一个[a,b)范围的均匀分布的随机数。a, b的数据类型要一致,而且必须是intfloatdouble中的一种,默认是int。
(2)cv::RNG::gaussian(σ):			返回一个均值为0,标准差为σ的随机数。若要产生均值为λ,标准差为σ的随机数:λ+RNG::gaussian(σ)
#include<opencv2\opencv.hpp>
#include <string>
//using namespace cv;
//using namespace std;

int main(int argc,char* argv[])
{
    
    
	cv::RNG rng(-1);
	int randomNumber1 = rng;
	double randomNumber2 = rng.uniform(0,99);  		
	double randomNumber3 = rng.gaussian(2);			
	
	std::cout << "randomNumber1=" << randomNumber1 << std::endl;		//randomNumber=130063606
	std::cout << "randomNumber2=" << randomNumber2 << std::endl;		//randomNumber=14
	std::cout << "randomNumber3=" << randomNumber3 << std::endl;		//randomNumber=-1.40186
	return 0;
}

4.2、获取下一个随机数:next + operator

1)	cv::RNG:: next 			返回下一个64位随机整数。
(2)	cv::RNG:: operator 		返回下一个指定类型的随机数。
#include<opencv2\opencv.hpp>
#include <string>
//using namespace cv;
//using namespace std;

int main(int argc,char* argv[])
{
    
    
	cv::RNG rng(-1);  
	int randomNumber = rng.next();		//返回下一个随机整数,即N1.next();  
	 
	//返回下一个指定类型的随机数  
	int randomNumber1 = rng.operator uchar();         //返回下一个无符号字符数  
	int randomNumber2 = rng.operator schar();         //返回下一个有符号字符数  
	int randomNumber3 = rng.operator ushort();        //返回下一个无符号短型  
	int randomNumber4 = rng.operator short int();     //返回下一个短整型数  
	int randomNumber5 = rng.operator int();           //返回下一个整型数  
	int randomNumber6 = rng.operator unsigned int();  //返回下一个无符号整型数  
	int randomNumber7 = rng.operator float();         //返回下一个浮点数  
	int randomNumber8 = rng.operator double();        //返回下一个double型数  
	int randomNumber9 = rng.operator ()();            //和rng.next( )等价  
	int randomNumber10 = rng.operator ()(100);        //返回[0,100)范围内的随机数  
	
	std::cout << "randomNumber=" << randomNumber << std::endl;		//randomNumber=130063605
	std::cout << "randomNumber1=" << randomNumber1 << std::endl;		//randomNumber=156
	std::cout << "randomNumber2=" << randomNumber2 << std::endl;		//randomNumber=-116
	std::cout << "randomNumber3=" << randomNumber3 << std::endl;		//randomNumber=24389
	std::cout << "randomNumber4=" << randomNumber4 << std::endl;		//randomNumber=31943
	std::cout << "randomNumber5=" << randomNumber5 << std::endl;		//randomNumber=-1348951784
	std::cout << "randomNumber6=" << randomNumber6 << std::endl;		//randomNumber=94037301
	std::cout << "randomNumber7=" << randomNumber7 << std::endl;		//randomNumber=0
	std::cout << "randomNumber8=" << randomNumber8 << std::endl;		//randomNumber=0
	std::cout << "randomNumber9=" << randomNumber9 << std::endl;		//randomNumber=776868985
	std::cout << "randomNumber10=" << randomNumber10 << std::endl;		//randomNumber=94
	return 0;
}

4.3、用随机数填充矩阵:cv::RNG::fill()

函数说明:void fill( InputOutputArray mat, int distType, InputArray a, InputArray b, bool saturateRange=false );
输入参数:
			(1)mat 			输入矩阵。2D或N维矩阵,最多支持4通道,超过4通道先用reshape()改变结构。
			(2)distType 		分布类型。
						cv::RNG::UNIFORM		均匀分布。
						cv::RNG::NORMAL			高斯分布。
			(3)a 				第一分布参数。均匀分布时表示一个下边界(闭区间),正态分布时表示平均值。
			(4)b 				第二分布参数。均匀分布时表示一个上边界(开区间),正态分布时表示标准差。
			(5)saturateRange=false 	只针对均匀分布有效。当为真的时候,会先把产生随机数的范围变换到数据类型的范围,再产生随机数。如果为假,会先产生随机数,再进行截断到数据类型的有效区间。
#include<opencv2\opencv.hpp>
#include <string>
//using namespace cv;
//using namespace std;

int main(int argc,char* argv[])
{
    
    
	cv::RNG rng(-1);
	
	cv::Mat_<int>fillM1(3, 3);			//新建3x3矩阵,int类型
	cv::Mat_<double>fillM2(3, 3);		//新建3x3矩阵,double类型

	rng.fill(fillM1, cv::RNG::UNIFORM, 1, 100);		//随机生成[1,100)均匀分布的int数,并填充fillM。
	rng.fill(fillM2, cv::RNG::NORMAL, 1, 3);		//随机生成均值为1,标准差为3的double数,并填fillN。
	
	std::cout << "filM = " << fillM1 << std::endl;  
	std::cout << "filN = " << fillM2 << std::endl;  
	
	return 0;
}

5、计算消费时间函数

5.1、耗时:cv::getTickCount()

函数说明:int64 cv::getTickCount();
函数作用:通过读取函数调用前后的时间刻度,来计算执行该函数所损耗的时间。

5.2、频率:cv::getTickFrequency()

函数说明:double cv::getTickFrequency();
函数作用:将损耗时间除以该函数(频率)以进行单位转换,返回时间的刻度数单位:秒。

5.3、实战案例

#include <opencv2/opencv.hpp>
//using namespace cv;
//using namespace std;

int main(int argc, const char* argv[]) 
{
    
    
	double count1 = cv::getTickCount();
	
	//处理
	//处理
	//处理
	
	double count2 = cv::getTickCount();
	double time_consume = (count2 - count1) / cv::getTickFrequency();
	std::cout << "耗时:" << time_consume << std::endl;
}

6、鼠标与轨迹条操作

【OpenCV】OpenCV基础教程(11)—— HighGUI图形用户界面

6.1、鼠标事件的回调函数:cv::MouseCallback

采用回调函数来处理鼠标事件。首先创建一个回调函数,并输入回调函数触发事件以及触发位置。函数还需要被告知用户是否在触发鼠标事件的同时触发了Shift或者Alt等键。

#include <opencv2/highgui.hpp>
函数说明:typedef void(* cv::MouseCallback) (int event, int x, int y, int flags, void *userdata)
输入参数:
				11、event:鼠标事件
								事件名称						数值		说明
								CV_EVENT_MOUSEMOVE			0			指示鼠标指针已在窗口上移动。
								CV_EVENT_LBUTTONDOWN		1			表示按下了鼠标左键。
								CV_EVENT_RBUTTONDOWN		2			表示按下了鼠标右键。
								CV_EVENT_MBUTTONDOWN		3			表示按下了鼠标中键。
								CV_EVENT_LBUTTONUP			4			表示释放了鼠标左键。
								CV_EVENT_RBUTTONUP			5			表示释放了鼠标右键。
								CV_EVENT_MBUTTONUP			6			表示释放了鼠标中键。
								CV_EVENT_LBUTTONDBLCLK		7			表示双击鼠标左键。
								CV_EVENT_RBUTTONDBLCLK		8			表示双击鼠标右键。
								CV_EVENT_MBUTTONDBLCLK		9			表示双击鼠标中键。
				22、(x, y):触发鼠标事件的坐标位置
				33、flags:鼠标状态
								标志名称						数值		说明
								CV_EVENT_FLAG_LBUTTON		1			表示鼠标左键已按下。
								CV_EVENT_FLAG_RBUTTON		2			表示鼠标右键已按下。
								CV_EVENT_FLAG_MBUTTON		4			表示鼠标中键已按下。
								CV_EVENT_FLAG_CTRLKEY		8			表示按下了Ctrl键(8~15)。
								CV_EVENT_FLAG_SHIFTKEY		16			表示按下了Shift键(16~31)。
								CV_EVENT_FLAG_ALTKEY		32			表示按下了Alt键(32~39)44、param:(可选参数)可以以任何结构方式传递额外的参数信息。

6.2、设置鼠标事件的回调函数:cv::setMouseCallback()

#include <opencv2/highgui.hpp>
函数说明:void cv::setMouseCallback(const String &winname, MouseCallback onMouse, void *userdata = (void *)0)
输入参数:
				winname			窗口的名称。
				onMouse			鼠标事件的回调函数。
				userdata		传递给回调的可选参数(默认0)。

6.3、创建轨迹条,并将其附加到指定的窗口:cv::createTrackbar()

  • 创建一个具有指定名称和范围的轨迹条(滑块或范围控件),分配一个变量值作为与轨迹条同步的位置,并指定在轨迹条位置更改时调用的回调函数onChange。
  • 创建的轨迹条将显示在指定的窗口winname中。
#include <opencv2/highgui.hpp>
函数说明:int cv::createTrackbar( const String &trackbarname, const String &winname, int *value, int count, TrackbarCallback onChange = 0, void *userdata = 0 )	
输入参数:
				trackbarname		创建轨迹条的名称。
				winname				作为轨迹条的父窗口的名称。
				value				指向整数变量的可选指针,该变量的值反映滑块的位置。创建时,滑块位置由该变量定义。
				count				滑块的最大位置。最小位置始终为0。
				onChange			指向每当滑块改变位置时要调用的函数的指针(默认0)。这个函数应该被原型化为void Foo(intvoid*),其中第一个参数是轨迹条位置,第二个参数是用户数据(见下一个参数)。如果回调是NULL指针,则不会调用回调,但只更新值。
				userdata			按原样传递给回调的用户数据(默认0)。它可以在不使用全局变量的情况下用于处理轨迹条事件。

6.4、获取指定轨迹条的当前位置:cv::getTrackbarPos()

#include <opencv2/highgui.hpp>
函数说明:int cv::getTrackbarPos(const String &trackbarname, const String &winname)
输入参数:
				trackbarname		轨迹条的名称。
				winname				作为轨迹条的父窗口的名称。
				
备注:如果轨迹条连接到控制面板,winname可以为空。

6.5、设置指定轨迹条在指定窗口中的位置:cv::setTrackbarPos()

#include <opencv2/highgui.hpp>
函数说明:void cv::setTrackbarPos( const String &trackbarname, const String &winname, int pos )	
输入参数:
				trackbarname		轨迹条的名称。
				winname				作为轨迹条的父窗口的名称。
				pos					新的位置。
				
备注:如果轨迹条连接到控制面板,winname可以为空。

猜你喜欢

转载自blog.csdn.net/shinuone/article/details/130835407