滑动条的创建和使用
创建:
int createTrackbar(conststring& trackbarname, conststring& winname,
int* value, int count, TrackbarCallback onChange=0,void* userdata=0);
第一个参数,轨迹条名字。
第二个参数,窗口名字,表示轨迹条会依附到哪个窗口上。与setMouseCallback类似,窗口应由namedWindow创建。
第三个参数,一个指向整形的指针,表示滑块的位置。创建时,滑块的初始位置就是该变量的值。
第四个参数,count,表示滑块可以达到的最大位置的值。滑块最小位置的值始终默认为0。
第五个参数,onChange,它有默认值0,这是一个指向回调函数的指针。这个函数的原型必须是void aaaa(int ,void* );其中
第1个参数是轨迹条的位置,第2个参数是用户数据。如果回调是NULL指针,则表示没有回调函数的调用。
第六个参数,void* userdata,也有默认值0。这个参数是用户传给回调函数的数据,用来处理轨迹条事件。如果第三个参数value是
全局变量,完全可以不管这个参数。
回调函数指一个通过函数指针调用的函数。如果我们把函数的指针作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数,
就称其为回调函数。
// 轨迹条创建.cpp : 定义控制台应用程序的入口点。 // #include "stdafx.h" using namespace std; using namespace cv; int value; double alpha_value, beta_value;//透明度比例,混合比例 Mat pc1, pc2; void onChange(int ,void*) { Mat frame; alpha_value = (double) value / 100; beta_value = 1.0 - alpha_value; addWeighted(pc1, alpha_value, pc2, beta_value, 0.0, frame); imshow("test", frame); } int main() { pc1 = imread("1.jpg"); pc2 = imread("2.jpg"); value = 50; namedWindow("test", WINDOW_AUTOSIZE); createTrackbar("对比度", "test", &value, 100, onChange); onChange(value, 0); waitKey(0); return 0; }
我写的时候因为图片太大,效果一般。注意两张图片必须大小一致。
获取当前轨迹条的位置:getTrackbarPos():
int getTrackbarPos(conststring& trackbarname,conststring& winname);
第一个参数,轨迹条的名字;第二个参数,窗口的名字。
接14日的Mat类型学习。
之前的Mat类型使用一直都是作为图像的载体,今天学习的用法是作为一般意义上的“矩阵”来说的。
对二维矩阵,要显示其实际值可以通过“<<”来实现。
创建Mat对象的方法:
(一)使用Mat构造函数
对于二维多通道图像,首先要定义其行数和列数。然后指定存储元素的数据类型以及每个矩阵点的通道数。
栗子:Mat M(2,2,CV_8UC3,Scalar(0,0,255));
(二)在C/C++中使用构造函数进行初始化
int sz[3]={2,2,2};
Mat L(3,sz,,CV_8UC,Scalar::all(0));
(三)为已存在的IplImage指针创建信息头
IplImage* img=cvLoadImage("1.jpg",1);
Mat mtx(img);
(四)Create函数
M.create(4,4,CV_8UC(2));
需要注意的是这种方法不能为矩阵设初值,只是在改变尺寸时重新为矩阵数据开辟内存。
(五)采用Matlab式的初始化方式
zeros(),ones(),eye()
Mat E=Mat::zeros(4,4,CV_64F);
另外两种只需替换zeros。
(六)对小矩阵使用逗号分隔式初始化函数
Mat C=(Mat_<double>(3,3) << 0,-1,0,-1,5,-1,0,-1,0,-1,0);
这也是已知唯一一种可以为矩阵设置初始值的构造方法。
(七)为已存在的对象创建新信息头
使用成员函数clone()或copyTo()为一个已存在的Mat对象创建一个新的信息头。
Mat RowClone=C.row(1).clone();
Mat类格式化输出方法:
默认的输出方式就是用“<<”输出。
其他风格的输出方式在opencv3里相当方便了:
cout << format(M, Formatter::FMT_ ); 下划线之后会出现一些内容。
PYTHON是指Python风格,CSV是逗号分隔风格,NUMPY是numpy风格,C是C语言风格。
二维点:
Point2f p(6,2);
三维点:
Point3f p3f(8,2,0);
定义和输出基于Mat的std::vector:
vector<float> v;
v.push_back(3);
v.push_back(5);
如上即压入数据的操作。想输出也很简单,只需:
cout << Mat(v); 即可。
定义和输出std::vector点:
在这里的vector就符合它名称的含义:向量。
在vector中,数据以点的形式存储。可以存储二维或者三维点。
vector<Point2f> points(20);
for (size_t i=0; i<points.size(); i++) points[i]=Point2f((float) i*3, (float) i%7);
cout << points;
常用的数据结构和函数:
点的表示:Point类
Point类表示了二维坐标系下的点。用法如下:
Point p; p.x=10; p.y=8;
或者Point p=Point(10,8);
又因为OpenCV内置的设计,Point_<int>/Point2i/Point相互等价,Point_<float>/Point2f互相等价。
颜色的表示:Scalar类
Scalar表示具有四个元素的数组,在OpenCV中被大量用来传递像素值,如RGB颜色值。对于Scalar()函数来说,如果用不到第四个参数,
就没必要写出来,OpenCV会认为我们只想要三个参数。
如下栗子:Scalar(a,b,c);
那么定义的RGB颜色值:红色分量为c,绿色为b,蓝色为a。
尺寸的表示:Size类
通过在OpenCV中转到定义……可以发现Size_<int>/Size2i/Size三个类型名等价。
于是构造的话……就:
_size=Size(5,5);
矩形的表示:Rect类
这个类的成员变量有x,y,width,height,分别为左上角点的坐标和矩形的宽高。
常用的成员函数:
Size():返回值为Size;
area():返回值为面积;
contains(Point):判断点是否在矩形内;
inside(Rect):判断矩形是否在该矩形内;
tl():返回左上角坐标;
br():返回右下角坐标;
矩阵甚至支持位运算操作:
求两个矩形的交:Rect rect=rect1 & rect2;
求并:Rect rect=rect1 | rect2;
如果想让矩形进行平移和缩放操作,甚至可以这样写:
Rect rectshift=rect+point;
Rect rectScale=rect+size;
颜色空间转换:cvtColor()函数
这个函数可以用来实现RGB、HSV、HSI等颜色空间的转换。
void cvtColor(InputArray src,OutputArray dst, int code, int dstCn=0);
第一个参数为输入图像,第二个参数为输出图像,第三个参数为颜色空间转换的标识符,第四个参数为目标图像的通道数,若
该参数是0,表示目标图像取源图像的通道数。可以看出,第四个参数默认令目标图像选择源图像的通道数。
晚上试验了一下昨天写的数传程序。发送端接USB转TTL和无线数传模块,接收端接接收模块就可以实现数据传输了。在昨天代码的基础上增加了文件读入。
USB转TTL、232:
进行转换的原因是单片机通信接口的电平逻辑和PC机通信接口的电平逻辑不同。
USB接口有USB规则……好吧这个规则能讲一本书,日后再仔细研究。
这里我要通过LAPTOP的USB借口与不带电平转换芯片的单片机通信。
方法就是购买USB转TTL模块,插到USB接口(甚至不用装驱动)。之后将模块和无线数传模块相连,单片机连接收模块即可。