OpenCV入门(4):初识之基础数据结构

对图像的处理,就是对数据结构的处理,OpenCV 中常用的数据结构 cv::Matcv::Veccv::Pointcv::Scalarcv::Sizecv::Rect,最基础常用的颜色颜色空间转换函数 cvtColor()

一、基础图像矩阵容器:cv::Mat

这是 OpenCV 中最常用的数据结构,用于存储图像或矩阵。cv::Mat 是一个类,可以存储多维数组,并且可以存储任意类型的数据(如 8 位、16 位、32 位等)。Mat 对象可以表示单通道、多通道的图像或矩阵。

cv::Mat 的详细介绍和示例,具体可查看我的上篇博客: OpenCV学习(3):基础图像容器Mat详解

二、容器:cv::Vec

Vec 是一个模板类,主要用于存储数值向量。


用法

(1)可用它来定义任意类型的向量

Vec<double, 8> myVector; // 定义一个存放8个double型变量的向量

(2)使用 [] 访问 Vec 向量成员

myVector[0]=0;

(3)可使用以下预定义的类型

typedef Vec<uchar, 2> Vec2b;
typedef Vec<uchar, 3> Vec3b;
typedef Vec<uchar, 4> Vec4b;
typedef Vec<short, 2> Vec2s;
typedef Vec<short, 3> Vec3s;
typedef Vec<short, 4> Vec4s;
typedef Vec<int, 2> Vec2i;
typedef Vec<int, 3> Vec3i;
typedef Vec<int, 4> Vec4i;
typedef Vec<float, 2> Vec2f;
typedef Vec<float, 3> Vec3f;
typedef Vec<float, 4> Vec4f;
typedef Vec<float, 6> Vec6f;
typedef Vec<double, 2> Vec2d;
typedef Vec<double, 3> Vec3d;
typedef Vec<double, 4> Vec4d;
typedef Vec<double, 6> Vec6d;

(4)Vec 支持的运算如下:

v1 = v2 + v3
v1 = v2 - v3
v1 = v2 * scale
v1 = scale * v2
v1 = -v2
v1 += v2
v1 == v2, v1 != v2
norm(v1) (euclidean norm)

示例代码

(1)向量定义与元素的访问

cv::Vec<double, 8>  myVector;
for(int i=0; i<myVector.rows;i++)
	myVector[i] = i;
cout << "myVector= " << myVector << endl;
cout << "myVector[0]= " << myVector[0] << endl;
cout << "myVector[3]= " << myVector[3] << endl;

运行结果:

myVector= [0, 1, 2, 3, 4, 5, 6, 7]
myVector[0]= 0
myVector[3]= 3

(2)基本运算

cv::Vec<int, 6> v1,v2,v3;
for(int i=0; i<v2.rows;i++){ // v2.rows返回向量v2的行数
  v2[i] = i;
  v3[i] = i+1;
}

v1 = v2 + v3;
cout <<"v2       = "<< v2 << endl;
cout << "v3       = " << v3 << endl;
cout << "v1=v2+v3= " << v1 << endl;
cout << "v1=v2*2  = " << v2*2 << endl;
cout << "v1=-v2   = " << -v2 << endl;
cout << "v1==v2   = " << (v1==v2) << endl;
cout << "v1!=v2   = " << (v1!=v2) << endl;
cout << "norm(v2)= " << norm(v2) << endl;

运行结果:

v2       = [0, 1, 2, 3, 4, 5]
v3       = [1, 2, 3, 4, 5, 6]
v1 = v2+v3 = [1, 3, 5, 7, 9, 11]
v1 = v2*2  = [0, 2, 4, 6, 8, 10]
v1 = -v2   = [0, -1, -2, -3, -4, -5]
v1 == v2   = 0
v1 != v2   = 1
norm(v2) = 7.4162

三、颜色:cv::Scalar

cv::Scalar 是一个从 Vec 类引出的模板类,是一个可存放 4 个元素的向量,广泛用于传递和读取图像中的像素值。初始化时注意颜色顺序为 BGRA,而非我们一般默认的 RGBA。


用法

可使用 [] 访问 Scalar 值。或使用如下方式定义 BGR 三个通道的值。

cv:: Scalar( B, G, R )

// 黑色
Scalar();
// 蓝色
Scalar(255);
// 绿色
Scalar(0, 255);
// 红色
Scalar(0, 0, 255);

示例代码

彩色图像的每个像素对应三个部分:RGB 三个通道。因此包含彩色图像的 cv::Mat 类会返回一个向量,向量中包含三个 8 位的数值。OpenCV 为这样的短向量定义了一种类型,即我们上述的 cv::Vec3b。这个向量包含三个无符号字符 (unsigned character) 类型的数据。

OpenCV 存储通道次序为:蓝色、绿色、红色即 BGR。因此,访问彩色像素中元素的方法如下:

cv::Mat pImg = cv::imread("./demo1.jpg",1);
if(!pImg.data)
return 0;
int x = 100, y = 100;
cv::Scalar pixel=pImg.at<Vec3b>(x,y);
cout << "B chanel of pixel is = " << pixel.val[0] << endl;
cout << "G chanel of pixel is = " << pixel.val[1] << endl;
cout << "R chanel of pixel is = " << pixel.val[2] << endl;

运行结果:

B chanel of pixel is = 195
G chanel of pixel is = 220
R chanel of pixel is = 224

四、点:cv::Point

cv::Point 是一个结构体,用于表示二维点。它通常用于表示图像中的像素位置。例如,Point_<int> 可以用来表示一个点的整数坐标。


用法

(1)图像坐标

对图像而言,我们可以这样定义:

cv::Point point;
point.x = 20;
point.y = 40;

或者:

cv::Point point = Point(20, 40);

或者:

cv::Point Point(20, 40);

点的坐标基础类型还有浮点型以及他基础类型。


(2)或使用如下预定义:

typedef Point_<int> Point2i;
typedef Point2i Point;
typedef Point_<float> Point2f;
typedef Point_<double> Point2d;

(3)基本运算

pt1 = pt2 + pt3;
pt1 = pt2 - pt3;
pt1 = pt2 * a;
pt1 = a * pt2;
pt1 += pt2;
pt1 -= pt2;
pt1 *= a;
double value = norm(pt); // L2 norm
pt1 == pt2;
pt1 != pt2;

示例代码

(1)设置坐标点

cv::Mat pImg = cv::imread("./demo1.jpg",1);
if(!pImg.data)
	return 0;
cv::Point pt;
pt.x = 278;
pt.y = 269;
// 或者
//cv::Point  pt (278,269);
cv::Scalar pix = pImg.at<Vec3b>(pt);
cout << "pix(" << pt.x << "," << pt.y <<") = " << pix << endl;

运行结果:

pix(278,269) = [159, 190, 193, 0]

(2)各类运算

cv::Point pt1(10,20);
cv::Point pt2(2,3);
cout << "pt1     = " << pt1 << endl;
cout << "pt2     = " << pt2 << endl;
cout << "pt1 + pt2 = " << pt1 + pt2 << endl;
cout << "pt1 += pt2= " << (pt1 += pt2) << endl;
cout << "pt1 - pt2 = " << pt1 - pt2 << endl;
cout << "pt2 * 2   = " << pt2 * 2 << endl;

运行结果:

pt1     = [10, 20]
pt2     = [2, 3]
pt1 + pt2 = [12, 23]
pt1 += pt2 = [12, 23]
pt1 - pt2 = [10, 20]
pt2 * 2   = [4, 6]

五、大小:cv::Size

cv::Size 是一个结构体,用于表示图像或矩阵的尺寸,即宽度和高度。例如,Size(640, 480) 表示一个宽度为 640 像素、高度为 480 像素的图像或矩阵。


用法

cv::Size size(int w, int h);
// 或者
cv::Size size;
size.width = w;
size.height = h;

示例代码

cv::Size size1(6,3);
cv::Size size2;
size2.width = 4;
size2.height = 2;
cv::Mat mat1(size1,CV_8UC1,cv::Scalar(0));
cv::Mat mat2(size2,CV_8UC3,cv::Scalar(1,2,3));
cout << "mat1 = " << endl << mat1 << endl;
cout << endl << "mat2 = " << endl << mat2 << endl;

运行结果:

mat1 = 
[  0,   0,   0,   0,   0,   0;
   0,   0,   0,   0,   0,   0;
   0,   0,   0,   0,   0,   0]

mat2 = 
[  1,   2,   3,   1,   2,   3,   1,   2,   3,   1,   2,   3;
   1,   2,   3,   1,   2,   3,   1,   2,   3,   1,   2,   3]

六、矩形:cv::Rect

cv::Rect 是一个结构体,用于表示矩形区域。它包含矩形左上角的坐标(x, y)和矩形的宽度(width)和高度(height)。该类有几个基础函数:

  • Size():返回 Size 类型
  • area():返回矩形的面积
  • contains(Point):判断点是否在矩形内
  • inside(Rect):判断矩形是否在该矩形内
  • tl():返回左上角点的坐标
  • br():返回右下角点的坐标

用法

求矩阵的交集和并集,可以直接使用如下:

Rect rect = rect1 & rect2;
Rect rect = rect1 | rect2;

让矩形平移,可以直接使用加减 Point:

Rect rectShift = rect + point;

让矩形缩放,可以直接使用加减 Size;

Rect rectShift = rect + size;

示例代码

cv::Mat pImg = cv::imread("./demo1.jpg",1);
cv::Rect rect(280,100,150,150); // (x,y)=(180,200),w=200,height=200
cv::Mat roi = cv::Mat(pImg, rect);
cv::Mat pImgRect = pImg.clone();
cv::rectangle(pImgRect, rect, cv::Scalar(0,255,0),2);
cv::imshow("original image with rectangle", pImgRect);
cv::imshow("roi", roi);

运行结果:

Blog_OpenCV_Learnl_6.png


七、旋转矩形:cv::RotatedRect

还有一种特殊的矩形称为 RotatedRect。这个类通过中心点,宽度和高度和旋转角度来表示一个旋转的矩形。


用法

旋转矩形类的构造函数:

RotatedRect(const Point2f& center, const Size2f& size, float angle);

参数:

  • center:中心点坐标 Point2f 类型
  • size:矩形的宽度和高度,Size2f 类型
  • angle:顺时针方向的旋转角度(单位°),float 类型

Blog_OpenCV_Learnl_7.png


示例代码

cv::Point2f center(100,100);
cv::Size2f size(100,50);
float angle = 45; // try 10, 30, 45

RotatedRect rRect(center, size,  angle);
cv::Mat image(200,200,CV_8UC3,cv::Scalar(0));

Point2f vertices[4];
rRect.points(vertices);
for (int i = 0; i < 4; i++)
    line(image, vertices[i], vertices[(i+1)%4], Scalar(0,255,0));

Rect brect = rRect.boundingRect();
rectangle(image, brect, Scalar(255,0,0));

imshow("rectangles", image);

旋转 45 度后的效果图:
Blog_OpenCV_Learnl_8.png


参考:

OpenCV—基本数据结构与示例_opencv vec3b vec3i-CSDN博客


posted @ 2025-07-21 11:28  fengMisaka  阅读(33)  评论(0)    收藏  举报