OpenCv图像处理之常用工具Point、Scalar、Size、Rect和cvtColor介绍
cv::Point操作
Opencv中的数据类型大多由模板类进行创建,为了描述图像中的点(点的坐标等信息),提供了二维点模板类Point_
和三维点模板类Point3_
。由于点类的开销很小,故源码中没有点定义太多的成员函数,Point_可以在平面(二维)中获取x,y的坐标来确定点的位置,Point_3则是通过获取三维空间中x,y,z坐标来确定点的位置。常用的数据(坐标点)类型有int,double,float类型。
下面来看一下源码中Point_和Point3_中对于数据类型的定义
//Point_
typedef Point_<int> Point2i;
typedef Point_<int64> Point2l;
typedef Point_<float> Point2f;
typedef Point_<double> Point2d;
typedef Point2i Point;
//Ponit3_
typedef Point3_<int> Point3i;
typedef Point3_<float> Point3f;
typedef Point3_<double> Point3d;
上述是我从源码库中复制的关于二维点模板类的定义,可以清楚的看到Point_<int>,Point_<int64>,Point_<float>,Point_<double>
这些数据类型都使用了typedef关键字定义,即给他们分别起了一个别名,比如Point_<int>和Point2i
表示的是同一个含义,同理可得,Point3_中的数据类型也是如此。这样做的好处是在实例化对象的时候非常方便。如以下代码
#include <iostream>
#include <opencv2/highgui.hpp>
using namespace std;
using namespace cv;
int main() {
Point2d point2D;
point2D.x = 3.0;
point2D.y = 5.0;
Point3i point3I;
point3I.x = 10;
point3I.y = 20;
point3I.z = 30;
Point2i point2I = Point2i(50, 60);
cout << "point2I.x:" << point2I.x << endl
<< "point2I.y:" << point2I.y << endl;
return 0;
}
输出:
point2I.x:50
point2I.y:60
我们还可以对其进行某些运算操作(三维点可以进行向量和比较操作),这里展示下二维的相加操作
#include <iostream>
#include <opencv2/highgui.hpp>
using namespace std;
using namespace cv;
int main() {
Point2i point2I_zero(10, 20), point2I_one(30, 50);
Point2d point2D = point2I_one + point2I_zero;
cout << "add_x:" << point2D.x << endl
<< "add_y:" << point2D.y << endl;
return 0;
}
输出:
add_x:40
add_y:70
基本操作 | 示例 |
---|---|
默认构造方法 | cv::Point2i point2I_zero; |
拷贝构造方法 | cv::Point2i point2I_zero(point2I_one); |
带初始化值的构造方法 | cv::Point2d point2D_zero(x,y); |
转换到固定向量类 | (cv::Vec3f) p; |
成员访问 | point2I_zero.x; point2I_zero.y; |
点积操作 | float x = point2I_zero.dot(point2I_one) |
双精度点积操作 | double x = point2I_zero.ddot(point2I_one) |
矢量积操作 | point3I_zero.cross(point3I_one)(只针对3维point) |
判断point是否在矩阵A中 | point2I_one.inside(A)(只针对2维point) |
cv::Scalar操作
Scalar(B,G,R,A)
是对通道数进行处理的函数,具体操作看下面的程序
#include <iostream>
#include <opencv2/highgui.hpp>
#include <opencv2/opencv.hpp>
using namespace std;
using namespace cv;
int main() {
Mat frame;
frame = cv::imread("D:/cat.jpg", 3);
//BGR-A A是透明度,(0,0,255)是红色
Scalar scalar(0, 0, 255, 0);
//height*width(rows*cols) MatSize size
cout << "frame.shape:" << frame.size << endl;
rectangle(frame, Rect(373 / 2, 372 / 2, 350, 350), scalar);
imshow("draw_rectangle_frame", frame);
waitKey(0);
}
效果显示
cv::Size操作
Size模版类与对应的Point模版类类似,可以互相转换。他们的区别在于Size模版类中的两个成员变量分别是width,height,而Point模版类中的俩个成员变量分别是x,y。下面看一下源码中Size模版类对于数据类型的定义
typedef Size_<int> Size2i;
typedef Size_<int64> Size2l;
typedef Size_<float> Size2f;
typedef Size_<double> Size2d;
typedef Size2i Size;
和Point_,Point3_一样,都是使用typedef定义的别名,方便实例化。
下面使用一个例子来感受一下Size的用法
#include <iostream>
#include <opencv2/opencv.hpp>
using namespace std;
using namespace cv;
int main() {
Mat frame = imread("D:/cat.jpg", 3);
int width = frame.cols;
int height = frame.rows;
Size size(width, height);
cout << "size.width:" << size.width << endl
<< "size.height:" << size.height << endl;
return 0;
}
输出:
size.width:746
size.height:745
cv::Rect操作
和上述工具类一样Rect也是模板类,下面看一下源码中对于Rect成员的定义
//template<typename _TP>
Rect_(_Tp _x, _Tp _y, _Tp _width, _Tp _height);
_Tp x; //!< x coordinate of the top-left corner
_Tp y; //!< y coordinate of the top-left corner
_Tp width; //!< width of the rectangle
_Tp height; //!< height of the rectangle
typedef Rect_<int> Rect2i;
typedef Rect_<float> Rect2f;
typedef Rect_<double> Rect2d;
typedef Rect2i Rect;
需要注意的是,当Rect()
配合其他截取函数使用时,(x+width)<=img.cols
,(y+height)<=img.rows
函数 | 简介 |
---|---|
size() | 返回Size类型 |
area() | 返回矩形的面积 |
contains(Point) | 判断点是否包含在此矩形内 |
tl() | 返回左上角点的坐标 |
br() | 返回右下角点的坐标 |
cv::cvtColor操作
先看一下源码中的函数原型
CV_EXPORTS_W void cvtColor(InputArray src, OutputArray dst, int code, int dstCn = 0);
参数:
src
输入图像类型cv::Mat
dst
输出图像类型cv::Mat
code
颜色空间转换标识符,从原颜色空间转向目标颜色空间
dstCn
颜色通道数,输出的图像与输入的图像通道数一致
上面参数中提到了颜色空间,那么什么是颜色空间呢?
我们的世界是五彩缤纷的,通过不同的颜色,带给我们不同的视觉盛宴。其实这些不同的颜色,都是可以由基本的颜色组成的,比如我们经常说的光学三原色、颜料三原色,我们可以通过三种颜色的配比,得到不同种各式各样的颜色。我们可以构建一个三维的空间,当每个方向取不同的值,我们就能得到不同的颜色,这个就是颜色空间。
常见的颜色空间有BGR,灰度空间,HSV
等等.
BGR
最常见的就是BGR系列了,其中:
B表示blue,蓝色;
G表示green,绿色;
R表示red,红色;
我们可以通过不同的组合得到不同的颜色;每个取值范围都是0-255,如果用16进制表示就是 0-FF。
BGR系列表示有一定的问题:
1.RGB 颜色空间利用三个颜色分量的线性组合来表示颜色,任何颜色都与这三个分量有关。
2.自然界中,由于光照等问题的影响,颜色发生变化,而是哪个颜色分量和光照都有关,所以图像亮度改变,三个通道的颜色都会改变。
3.人眼睛对不同颜色的敏感程度不同,有时候难以对一个颜色进行区分。
4.适用于图像显示,不适用于图像处理。
灰度空间
灰度空间算是简化的BGR空间,BGR有三个通道,分别表示三个像素分量,灰度空间只有一个通道,取值范围也是0-255,值越大,颜色越趋向于白色,值越小,颜色越趋向于黑色。
HSV
除了BGR系列,我们最常见的是HSV系列了,其中:
1.H表示Hue,色调;用角度度量,取值范围为0°~360°,从红色开始按逆时针方向计算,红色为0°,绿色为120°,蓝色为240°。它们的补色是:黄色为60°,青色为180°,紫色为300°;
2.S表示Saturation,饱和度;一种颜色,可以看成是某种光谱色与白色混合的结果。其中光谱色所占的比例愈大,颜色接近光谱色的程度就愈高,颜色的饱和度也就愈高。饱和度高,颜色则深而艳。光谱色的白光成分为0,饱和度达到最高。通常取值范围为0%~100%,值越大,颜色越饱和。
3.V表示Value,明度;明度表示颜色明亮的程度,对于光源色,明度值与发光体的光亮度有关;对于物体色,此值和物体的透射比或反射比有关。通常取值范围为0%(黑)到100%(白)。
下面看个程序
#include <iostream>
#include <opencv2/opencv.hpp>
using namespace std;
using namespace cv;
int main() {
Mat frame = imread("D:/cat.jpg", 3);
//BGR2HSV
cvtColor(frame, frame, COLOR_HSV2RGB_FULL);
imshow("cvtColor_frame", frame);
waitKey(0);
return 0;
}
#include <iostream>
#include <opencv2/opencv.hpp>
using namespace std;
using namespace cv;
int main() {
Mat frame = imread("D:/cat.jpg", 3);
//BGR2GRAY
cvtColor(frame, frame, COLOR_BGR2GRAY);
imshow("cvtColor_frame", frame);
waitKey(0);
return 0;
}