Opencv的数据结构

文章目录

  • [1. 基本数据类型](#1. 基本数据类型)
    • [1.1 cv::Vec向量](#1.1 cv::Vec向量)
      • [1.1.1 cv::Vec类可以定义任意类型的向量](#1.1.1 cv::Vec类可以定义任意类型的向量)
      • [1.1.2 cv::Vec类也可以使用以下预定义的类型:](#1.1.2 cv::Vec类也可以使用以下预定义的类型:)
      • [1.1.3 cv::Vec类支持的运算](#1.1.3 cv::Vec类支持的运算)
      • [1.1.4 cv::Vec类初始化与基本运算示例代码](#1.1.4 cv::Vec类初始化与基本运算示例代码)
      • [1.1.5 实际应用示例](#1.1.5 实际应用示例)
    • [1.2. cv::Matx<>尺寸矩阵](#1.2. cv::Matx<>尺寸矩阵)
      • 1.2.1模板定义
      • [1.2.2 常见类型别名](#1.2.2 常见类型别名)
      • [1.2.3 基本操作](#1.2.3 基本操作)
    • [1.3 cv::Point类](#1.3 cv::Point类)
      • [1.3.1 模板定义](#1.3.1 模板定义)
      • [1.3.2 常见类型](#1.3.2 常见类型)
      • [1.3.3 创建与初始化](#1.3.3 创建与初始化)
      • [1.3.4 成员变量](#1.3.4 成员变量)
      • [1.3.5 常用操作符](#1.3.5 常用操作符)
      • [1.3.6 常用函数](#1.3.6 常用函数)
      • [1.3.7 与图像绘制配合使用](#1.3.7 与图像绘制配合使用)
      • [1.3.8 与其他类型转换](#1.3.8 与其他类型转换)
      • [1.3.9 cv:Point类操作示例](#1.3.9 cv:Point类操作示例)
    • [1.4 cv::Scalar类](#1.4 cv::Scalar类)
      • [1.4.1 模板定义](#1.4.1 模板定义)
      • [1.4.2 常用构造方式](#1.4.2 常用构造方式)
      • [1.4.3 常用场景](#1.4.3 常用场景)
      • [1.4.4 成员变量和访问方式](#1.4.4 成员变量和访问方式)
      • [1.4.5 常见转换](#1.4.5 常见转换)
      • [1.4.6 实际案例](#1.4.6 实际案例)
    • [1.5 cv::Size类](#1.5 cv::Size类)
      • [1.5.1 模板定义](#1.5.1 模板定义)
      • [1.5.2 构造与初始化](#1.5.2 构造与初始化)
      • [1.5.3 成员变量](#1.5.3 成员变量)
      • [1.5.4 常用操作](#1.5.4 常用操作)
      • [1.5.5 常用场景示例](#1.5.5 常用场景示例)
    • [1.6 cv::Rect类](#1.6 cv::Rect类)
      • [1.6.1 模板定义](#1.6.1 模板定义)
      • [1.6.2 成员含义](#1.6.2 成员含义)
      • [1.6.3 构造方式](#1.6.3 构造方式)
      • [1.6.4 常用操作](#1.6.4 常用操作)
      • [1.6.5 矩形运算符重载](#1.6.5 矩形运算符重载)
      • [1.6.6 与其他类型配合使用](#1.6.6 与其他类型配合使用)
      • [1.6.7 常用函数](#1.6.7 常用函数)
    • [1.7 cv::RotatedRect类](#1.7 cv::RotatedRect类)
      • [1.7.1 基本操作示例](#1.7.1 基本操作示例)
    • [1.8 cv::Mat类型](#1.8 cv::Mat类型)
      • [1.8.1 图像数据类型](#1.8.1 图像数据类型)
      • [1.8.2 图像深度类型](#1.8.2 图像深度类型)
      • [1.8.3 基本操作示例](#1.8.3 基本操作示例)
  • 2.参考链接

1. 基本数据类型

OpenCV基本数据类型可分为三大类

1.基本数据类型 :该类型直接由C++的数据类型(int或float等)组装起来,包括简单的向量和矩阵;

2.助手对象 :这些对象表示更抽象的概念,如垃圾收集指针类等,用于表示切片的范围对象,以及对某些算法终止条件的抽象等。

3.大型数组类型:包括cv::Mat、cv::Vec、cv::Point、cv::Scalar、cv::Size和cv::Rect、cv::RotatedRect等等,不同类型有不同的构造方式和操作

1.1 cv::Vec向量

1.固定向量类,需要提前知道变量长度

2.模板,可以存储任意数据类型

3.存在多种预定义的类型(其他数据类型也有相关特性)

cv::Vec 类外,还有固定维度的向量类cv::Matx

cv::Matx 类可用来处理固定大小的小维度矩阵运算。在计算机视觉中,有许多2×2、3×3和少量4×4的矩阵,以及用于各类变换的矩阵,都可以使用cv::Matx 类来表示。

值得注意的是,无论cv::Vec类,还是cv::Matx类,在编译时都需要知道变量的长度,这使得计算变得十分高效。

1.1.1 cv::Vec类可以定义任意类型的向量

cpp 复制代码
cv::Vec<double,3>myVector;//定义一个存放3个double型变量的向量
cv::Vec3d v3d(x0,x1x2);

1.1.2 cv::Vec类也可以使用以下预定义的类型:

cv::Vec<T, cn> 是 OpenCV 中的一个模板类,用于表示固定长度的向量,常用于图像处理和计算机视觉中的坐标、颜色、法线等数据的存储。

cpp 复制代码
template<typename _Tp, int cn>
class Vec;

_Tp:元素类型,如 uchar、int、float、double 等;

cn:元素个数(通道数),比如 RGB 就是 3,RGBA 就是 4。

cpp 复制代码
// 源码中的预定义
/** @name Shorter aliases for the most popular specializations of Vec<T,n>
  @{
*/
typedef Vec<uchar, 2> Vec2b;  即2个uchar 类型的元素
typedef Vec<uchar, 3> Vec3b; 常用于存储图像中的 RGB/BGR 颜色。
typedef Vec<uchar, 4> Vec4b; 常用于存储带有 Alpha 通道的 RGBA/BGRA 颜色。

typedef Vec<short, 2> Vec2s;
typedef Vec<short, 3> Vec3s;
typedef Vec<short, 4> Vec4s;

typedef Vec<ushort, 2> Vec2w;
typedef Vec<ushort, 3> Vec3w;
typedef Vec<ushort, 4> Vec4w;

typedef Vec<int, 2> Vec2i;
typedef Vec<int, 3> Vec3i;
typedef Vec<int, 4> Vec4i;
typedef Vec<int, 6> Vec6i;
typedef Vec<int, 8> Vec8i;

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;  4个double,可用于RGBA
typedef Vec<double, 6> Vec6d;
/** @} */

1.1.3 cv::Vec类支持的运算

cpp 复制代码
cv::Vec3f a(1.0f, 2.0f, 3.0f);
cv::Vec3f b(2.0f, 4.0f, 6.0f);
cv::Vec3f c = a + b;       // 加法
cv::Vec3f d = b - a;       // 减法
cv::Vec3f e = a * 2.0f;    // 数乘
float dot = a.dot(b);      // 点乘
float len = cv::norm(a);   // 求范数(欧几里得长度)

1.1.4 cv::Vec类初始化与基本运算示例代码

cpp 复制代码
#include<iostream>
// #include "stdafx.h"
#include <opencv2/opencv.hpp>

using namespace std;
int main(){
    cv::Vec<int, 3> myVec;
    for(int i = 0; i<3;i++)
        myVec[i] = i;
    cv::Vec3i v3i(0,1,2);
    cv::Vec2d v2d(1.2,2.4);
    cv::Vec2d v2d_1(v2d);

    cout<< "myVec[0] = " << myVec[0]  <<endl;
    cout<< "myVec[1] = " << myVec[1]  <<endl;
    cout<< "myVec[2] = " << myVec[2]  <<endl;

    cout << "v3i[0] = " << v3i[0] <<endl;
    cout << "v3i[1] = " << v3i[1] <<endl;
    cout << "v3i[2] = " << v3i[2] <<endl;
    
    cout << "v2d[0] = " << v2d[0] << endl; 
    cout << "v2d[1] = " << v2d[1] << endl;

    cout << "v2d_1[0] = " << v2d_1[0] << endl; 
    cout << "v2d_1[1] = " << v2d_1[1] << endl; 

    cv::Vec3f v1(1,0,0);
    cv::Vec3f v2(1,1,0);
    cv::Vec3f v3;

    cout << "v1:" << v1 << endl;
    cout << "v2:" << v2 << endl;

    cout << "v1·v2:" << v1.dot(v2) << endl;
    cout << "v1×v2:" << v1.cross(v2) <<endl;

    cout << "v1-v2:" << v1-v2 << endl;
    cout << "v1*v2:" << v1*v2 << endl;

    cout << "v1==v2:" << (v1==v2) << endl;
    cout << "v1!=v2:" << (v1!=v2) << endl;

    // system("PAUSE");
    return 0;

}                                                                                                                                                                              

运行后屏幕输出如下:

1.1.5 实际应用示例

示例1:图像反色(按通道逐像素操作)

cpp 复制代码
cv::Mat img = cv::imread("test.jpg");
for (int y = 0; y < img.rows; y++)
 {
    for (int x = 0; x < img.cols; x++) 
    {
        cv::Vec3b& pixel = img.at<cv::Vec3b>(y, x);
        pixel[0] = 255 - pixel[0]; // B
        pixel[1] = 255 - pixel[1]; // G
        pixel[2] = 255 - pixel[2]; // R
    }
}

示例2:颜色线性变换(加权变换)

cpp 复制代码
cv::Vec3f color(0.1f, 0.2f, 0.3f);
float weight = 2.0f;
cv::Vec3f result = color * weight; // 每个通道乘以权重

1.2. cv::Matx<>尺寸矩阵

注:cv::Matx类是cv:Vec类的基类

cv::Matx<> 是 OpenCV 提供的一个固定尺寸矩阵模板类,用于数学运算中表示小型矩阵(比如 2×2、3×3、4×4、6×6 等),适合做变换矩阵(如旋转、缩放、投影),在图像几何变换、相机标定、三维重建等领域广泛使用。

1.2.1模板定义

cpp 复制代码
template<typename _Tp, int m, int n>
class Matx;

_Tp:元素类型,如 float、double 等;

m:行数;

n:列数;

1.2.2 常见类型别名

也可以自定义别名:

cpp 复制代码
typedef cv::Matx<float, 2, 3> Matx23f;

1.2.3 基本操作

构造函数初始化

csharp 复制代码
cv::Matx33f mat1(1, 0, 0,
                 0, 1, 0,
                 0, 0, 1); // 单位矩阵

cv::Matx22d mat2(1.5, 2.0,
                 3.0, 4.5);

使用 zeros()、ones()、eye() 等静态函数

cpp 复制代码
auto m1 = cv::Matx33f::zeros(); // 全 0
auto m2 = cv::Matx22d::ones();  // 全 1
auto m3 = cv::Matx33f::eye();   // 单位矩阵

访问元素

cpp 复制代码
cv::Matx22f mat(1.0f, 2.0f,
                3.0f, 4.0f);

float a = mat(0, 1); // 第1行第2列

矩阵乘法

cpp 复制代码
cv::Matx22f A(1, 2, 3, 4);
cv::Matx22f B(5, 6, 7, 8);
cv::Matx22f C = A * B; // 矩阵乘法

与向量相乘

cpp 复制代码
cv::Matx33f R(1, 0, 0,
              0, 1, 0,
              0, 0, 1);
cv::Vec3f v(1, 2, 3);
cv::Vec3f result = R * v; // 矩阵乘向量

转置与逆

cpp 复制代码
auto R = cv::Matx33f::eye();
auto Rt = R.t();     // 转置
auto Rinv = R.inv(); // 逆矩阵(如果可逆)

1.3 cv::Point类

cv::Point 是OpenCV 中用于表示二维坐标点的结构,适用于图像处理中的像素坐标、点的位置、几何形状的顶点等场景,是使用非常广泛的基础数据结构之一。

1.与固定向量类密切相关的是cv::Point类(点类),它是一个用来存放2个或3个int或float等基本类型值的容器。

2.cv::Point类是从它们自己的模板中派生的,并非来自固定向量类。

1.3.1 模板定义

cpp 复制代码
template<typename _Tp> class Point_;
// 预定义
typedef Point_<int> Point;      // cv::Point 是 int 类型
typedef Point_<float> Point2f;  // 浮点型点
typedef Point_<double> Point2d; // 双精度点
typedef Point_<int> Point2i;
typedef Point_<int64> Point2l;

typedef Point3_<int> Point3i;
typedef Point3_<float> Point3f;
typedef Point3_<double> Point3d;

1.3.2 常见类型


cv::Point类支持的构造方式与示例

1.3.3 创建与初始化

cpp 复制代码
cv::Point pt1(100, 50);         // 整数坐标点
cv::Point2f pt2(100.5f, 50.2f); // 浮点坐标点
cv::Point2d pt3 = cv::Point2d(200.1, 300.6); // double 坐标

1.3.4 成员变量

cpp 复制代码
cv::Point pt(10, 20);
int x = pt.x;
int y = pt.y;

1.3.5 常用操作符

cpp 复制代码
cv::Point 支持常见算术运算和比较运算:
cv::Point a(10, 20);
cv::Point b(5, 8);

cv::Point c = a + b;    // (15, 28)
cv::Point d = a - b;    // (5, 12)
cv::Point e = a * 2;    // (20, 40)
cv::Point f = a / 2;    // (5, 10)
bool isEqual = (a == b); // false

1.3.6 常用函数

距离计算:

cpp 复制代码
cv::Point2f p1(0, 0), p2(3, 4);
float dist = cv::norm(p1 - p2); // 欧几里得距离,结果是 5.0

点是否在图像内

cpp 复制代码
cv::Point pt(100, 50);
cv::Size imgSize = img.size();
bool isInside = (pt.x >= 0 && pt.y >= 0 && pt.x < imgSize.width && pt.y < imgSize.height);

1.3.7 与图像绘制配合使用

画线:

cpp 复制代码
cv::line(img, cv::Point(10, 10), cv::Point(100, 100), cv::Scalar(0, 255, 0), 2);

画圆:

cpp 复制代码
cv::circle(img, cv::Point(50, 50), 20, cv::Scalar(255, 0, 0), -1); // 实心圆

画多边形:

cpp 复制代码
std::vector<cv::Point> pts = { {10,10}, {100,50}, {50,100} };
cv::polylines(img, pts, true, cv::Scalar(0,0,255), 2);

1.3.8 与其他类型转换

cv::Point ↔ cv::Vec2i

cpp 复制代码
cv::Point pt(10, 20);
cv::Vec2i vec(pt.x, pt.y);
cv::Point pt2(vec[0], vec[1]);

cv::Point2f ↔ cv::Matx

cpp 复制代码
cv::Point2f pt(1.2f, 3.4f);
cv::Matx21f mat(pt.x, pt.y);

1.3.9 cv:Point类操作示例

cpp 复制代码
#include<iostream>
#include "opencv.hpp"

using namespace std;
int main()
{    
    cv::Point p1(1,2);
    cv::Point p2(3, 4);
    cout << "p1 = " << "(" << p1.x << ", " << p1.y << ")" <<  endl;
    cout << "p2 = " << "(" << p2.x << ", " << p2.y << ")" <<  endl << endl;

    cv::Point3f p3(1.1, 2.4, 3.6);
    cout << "p3.x = " << p3.x << endl;  
    cout << "p3.y = " << p3.y << endl;
    cout << "p3.z = " << p3.z << endl<<endl;

    cv::Point3f p4(p3);
    cout << "p4.x = " << p4.x << endl;
    cout << "p4.y = " << p4.y << endl;
    cout << "p4.z = " << p4.z << endl<<endl;

    //计算
    cv::Point p = p1 + p2;
    cout << "p1 + p2 =  " << "(" << p.x << ", " << p.y << ")" << endl;
    cout << "p1 . p2 = " << p1.dot(p2) << endl;
    cout << "p3×p4 = " << p3.cross(p4) << endl << endl;

    cv::Rect2i rect(0,0,3,3);
    cout << "rect" << rect << endl;
    cout << "p1.inside(rect)  = " << p1.inside(rect) << endl;
    cout << "p2.inside(rect)  = " << p2.inside(rect) << endl;
    // system("PAUSE");
    return 0;
}

示例输出结果如下:

1.4 cv::Scalar类

cv::Scalar类 (标量类)实际上是一个四维双精度向量类。有一些特殊的成员函数与计算机视觉中使用的4分量向量相关。用途如下:

1.4.1 模板定义

cpp 复制代码
template<typename _Tp> class Scalar_;
typedef Scalar_<double> Scalar;

cv::Scalar 实际上是 cv::Scalar_ 的别名,因此所有值默认是 double 类型。它可以表示一个最多包含 4 个元素的向量:

而cv::Scalar类定义如下:

cpp 复制代码
cv::Scalar(double v0 = 0, double v1 = 0, double v2 = 0, double v3 = 0)
cpp 复制代码
cv::Scalar(v0);             // 1 通道
cv::Scalar(v0, v1);         // 2 通道
cv::Scalar(v0, v1, v2);     // 3 通道
cv::Scalar(v0, v1, v2, v3); // 4 通道

1.4.2 常用构造方式

cpp 复制代码
cv::Scalar gray(128);               // 单通道灰度值
cv::Scalar bgr(255, 0, 0);          // BGR 颜色(蓝色)
cv::Scalar bgra(0, 255, 0, 128);    // BGRA 颜色(绿色 + 透明度128)

注意:OpenCV 默认颜色顺序是 BGR,不是 RGB。

1.4.3 常用场景

设置颜色(用于绘图)

cpp 复制代码
cv::line(img, cv::Point(0, 0), cv::Point(100, 100), cv::Scalar(0, 0, 255), 2); // 红色线
cv::rectangle(img, cv::Rect(50, 50, 100, 100), cv::Scalar(0, 255, 0), -1);    // 绿色填充矩形

图像填充

cpp 复制代码
cv::Mat img(300, 300, CV_8UC3, cv::Scalar(100, 150, 200)); // B=100, G=150, R=200

作为返回值,例如 mean() 平均颜色:

cpp 复制代码
cv::Scalar avgColor = cv::mean(img);
double blue = avgColor[0];
double green = avgColor[1];
double red = avgColor[2];

1.4.4 成员变量和访问方式

cpp 复制代码
cv::Scalar color(10, 20, 30, 40);

double b = color[0];  // 通常是 Blue
double g = color[1];  // Green
double r = color[2];  // Red
double a = color[3];  // Alpha(透明度)

cv::Scalar 也重载了常见的运算符:

cpp 复制代码
cv::Scalar a(10, 20, 30);
cv::Scalar b(1, 2, 3);
cv::Scalar c = a + b; // (11, 22, 33)
cv::Scalar d = a * 2; // (20, 40, 60)

1.4.5 常见转换

Scalar → Vec3b

cpp 复制代码
cv::Scalar color(255, 100, 50);
cv::Vec3b vec((uchar)color[0], (uchar)color[1], (uchar)color[2]);

Vec3b → Scalar

cpp 复制代码
cv::Vec3b v(100, 150, 200);
cv::Scalar color(v[0], v[1], v[2]);

1.4.6 实际案例

示例1:设置背景色

cpp 复制代码
cv::Mat bg(200, 200, CV_8UC3, cv::Scalar(200, 100, 50)); // BGR
cv::imshow("Background", bg);

示例2:获取图像区域平均颜色

cpp 复制代码
cv::Rect roi(100, 100, 50, 50);
cv::Mat patch = img(roi);
cv::Scalar meanColor = cv::mean(patch);
std::cout << "Mean BGR: " << meanColor << std::endl;

1.5 cv::Size类

cv::Size 是 OpenCV 中的一个轻量级类,用于表示二维尺寸(宽度和高度),常用于:

表示图像或窗口大小

表示矩形区域的尺寸(宽×高)

图像缩放、创建等操作中的参数传递

1.5.1 模板定义

cpp 复制代码
template<typename _Tp> class Size_;
typedef Size_<int> Size;         // 默认整型
typedef Size_<float> Size2f;     // 浮点型尺寸
typedef Size_<double> Size2d;    // 双精度尺寸

所以 cv::Size 实际上是 cv::Size_ 的别名,使用最多。

1.5.2 构造与初始化

cpp 复制代码
cv::Size size1(640, 480);       // 宽=640,高=480
cv::Size2f size2f(320.5f, 240); // 浮点尺寸
cv::Size2d size2d(1280.0, 720.0); // 双精度尺寸

注意:cv::Size(width, height),第一个参数是宽度,第二个是高度。

1.5.3 成员变量

cpp 复制代码
cv::Size sz(100, 50);
int w = sz.width;
int h = sz.height;

1.5.4 常用操作

面积计算:

cpp 复制代码
int area = sz.area(); // = width * height

尺寸比较:

cpp 复制代码
cv::Size a(640, 480), b(640, 480);
bool same = (a == b); // true

加减乘除(宽和高分别运算):

cpp 复制代码
cv::Size sz1(100, 50);
cv::Size sz2 = sz1 + cv::Size(20, 10);  // (120, 60)
cv::Size sz3 = sz1 * 2;                 // (200, 100)

1.5.5 常用场景示例

创建指定尺寸的图像

cpp 复制代码
cv::Size imgSize(640, 480);
cv::Mat img(imgSize, CV_8UC3, cv::Scalar(0, 0, 0)); // 黑色图像

图像缩放时指定目标尺寸

cpp 复制代码
cv::Mat img = cv::imread("test.jpg");
cv::Size newSize(320, 240);
cv::Mat resized;
cv::resize(img, resized, newSize);

获取图像尺寸

cpp 复制代码
cv::Mat img = cv::imread("test.jpg");
cv::Size sz = img.size();
int w = sz.width;
int h = sz.height;

将图像缩小为原来的一半

cpp 复制代码
cv::Mat img = cv::imread("test.jpg");
cv::Size halfSize(img.cols / 2, img.rows / 2);
cv::Mat small;
cv::resize(img, small, halfSize);

1.6 cv::Rect类

cv::Rect 是 OpenCV 中用于表示矩形区域的核心数据结构,广泛应用于图像处理中的:

cpp 复制代码
1.ROI(感兴趣区域)选取
2.矩形绘制
3.人脸、物体检测框表示
4.区域相交、包含判断等几何操作

1.cv::Rect 类(矩形类)包括cv::Point 类的成员x和y(表示矩形的左上角)以及cv::Size 类的成员width和height(表示矩形的大小)。

2.矩形类不从cv::Pointcv::Size类继承,因此也不会继承它们相应的运算。

1.6.1 模板定义

cpp 复制代码
template<typename _Tp> class Rect_;
typedef Rect_<int> Rect;        // 默认整型坐标(像素)
typedef Rect_<float> Rect2f;    // 浮点型矩形
typedef Rect_<double> Rect2d;   // 双精度矩形

1.6.2 成员含义

cv::Rect 中包含四个成员变量:

cpp 复制代码
cv::Rect r;
int x = r.x;         // 左上角横坐标
int y = r.y;         // 左上角纵坐标
int w = r.width;     // 宽度
int h = r.height;    // 高度

(x, y) 表示左上角坐标,width、height 表示尺寸。

1.6.3 构造方式

cpp 复制代码
cv::Rect r1(10, 20, 100, 50);                    // x=10, y=20, width=100, height=50
cv::Rect r2(cv::Point(10, 20), cv::Size(100, 50)); // 从点和尺寸构造

1.6.4 常用操作

访问图像中的 ROI

cpp 复制代码
cv::Mat img = cv::imread("test.jpg");
cv::Rect roi(100, 100, 200, 150);
cv::Mat cropped = img(roi); // 直接通过 Rect 提取区域

绘制矩形框

cpp 复制代码
cv::rectangle(img, cv::Rect(50, 50, 100, 100), cv::Scalar(0, 255, 0), 2);

判断点是否在矩形内

cpp 复制代码
cv::Point pt(60, 60);
cv::Rect box(50, 50, 100, 100);
bool inside = box.contains(pt); // true

两个矩形求交集、并集

cpp 复制代码
cv::Rect r1(10, 10, 100, 100);
cv::Rect r2(50, 50, 100, 100);
cv::Rect intersect = r1 & r2; // 求交集
cv::Rect unioned   = r1 | r2; // 求并集

防止越界,访问图像 ROI 时,建议先判断是否越界:

cpp 复制代码
cv::Rect roi(100, 100, 300, 200);
roi = roi & cv::Rect(0, 0, img.cols, img.rows); // 裁剪到图像范围内

高亮显示图像中央区域

cpp 复制代码
cv::Mat img = cv::imread("test.jpg");
cv::Rect centerBox(img.cols / 4, img.rows / 4, img.cols / 2, img.rows / 2);
cv::rectangle(img, centerBox, cv::Scalar(0, 0, 255), 2); // 红框

1.6.5 矩形运算符重载


cv::Rect类支持的重载操作与示例   而cv::Rect类的重载操作示例如下:

cpp 复制代码
#include<iostream>
#include<opencv2/opencv.hpp>
using namespace std;
int main(){
    cv::Mat I,B, temp;
    I = cv::Mat::zeros(300,400,CV_8UC3);  // 创建一个黑色的画布
    B = I.clone();
    cv::Rect r1 = cv::Rect(60,60,200,100);  // 赋值构造
    cv::Rect r2 = cv::Rect(cv::Point(140,120),cv::Size(200,100));   // 通过点和高宽构造
    cv::rectangle(I, r1, cv::Scalar(0,255,0),2);                    // 在画布I上显示r1,颜色为(0,255,0),线宽为2
    cv::rectangle(I, r2, cv::Scalar(0,0,255), 2);
    cv::imshow("rectangle",I);
    cv::waitKey();

    temp = I.clone();
    cv::Rect r3 = r1 & r2;  // 交集
    cv::rectangle(temp, r3, cv::Scalar(255,0,0),2);
    cv::imshow("Intersection", temp);
    cv::waitKey();

    temp = I.clone();
    cv::Rect r4 = r1 | r2;  // 并集
    cv::rectangle(temp, r4, cv::Scalar(255,0,0),2);
    cv::imshow("Minimum area rectangle", temp);
    cv::waitKey();

    temp = B.clone();
    cv::Rect rs(r1);  
    rs += cv::Size(-30,60); // 增大
    cv::rectangle(temp, r1, cv::Scalar(0,255,0),2);
    cv::rectangle(temp, rs, cv::Scalar(255,0,0),2);
    cv::imshow("Enlarge", temp);
    cv::waitKey();    

    temp = B.clone();
    cv::Rect rt(r1);  
    rt += cv::Point(30,60); // 平移
    cv::rectangle(temp, r1, cv::Scalar(0,255,0),2);
    cv::rectangle(temp, rt, cv::Scalar(255,0,0),2);
    cv::imshow("Translate", temp);
    cv::waitKey();    

    cv::Point p(80,80);
    cv::Point q(20,20);
    cout << "r1:" << r1 << endl;
    cout << "r2:" << r2 << endl;
    cout << "r1 == r2:" << (r1 == r2) << endl;
    cout << "r1 contains p:" << r1.contains(p) << endl;
    cout << "r1 contains q:" << r1.contains(q) << endl;

    return 0;
}

示例代码运行结果如下图:

而示例代码输出结果如下图:

1.6.6 与其他类型配合使用

与 cv::Point 配合

cpp 复制代码
cv::Rect r(10, 10, 100, 100);
cv::Point center = (r.tl() + r.br()) * 0.5; // tl(): 左上角, br(): 右下角

与 cv::Size 配合

cpp 复制代码
cv::Rect roi(cv::Point(20, 30), cv::Size(100, 80));

1.6.7 常用函数

1.7 cv::RotatedRect类

1.有向矩形类,包含一个名为center的Point2f变量,一个名为size的cv::Size2f变量,以及一个名为angle的浮点数变量,表示矩形围绕中心的旋转。

2.与cv::Rect的区别:cv::RotatedRect类的位置相对于其center,而cv::Rect类的位置相对于其左上角。

cv::RotatedRect类支持的构造方式与示例

1.7.1 基本操作示例

cpp 复制代码
#include<iostream>
#include<opencv2/opencv.hpp>
using namespace std;

// RotatedRect的位置在center,Rect位置在左上角

int main(){
    cv::Mat I;
    I = cv::Mat(300,400,CV_8UC3, cv::Scalar(255,255,255)); // 白色画布
    cv::Point2f center(200, 150);
    cv::Size2f size(180, 120);  //W, H
    float angle = 30.0;
    cv::RotatedRect rRect(center, size, angle);
    cout<< "center" << rRect.center <<endl; // 其余成员同理
    cv::Point2f vertices[4];
    rRect.points(vertices);     // 获取4个角点
    for(int i = 0; i<4; i++){   // 逐条边绘制
        cv::line(I, vertices[i], vertices[(i+1)%4], cv::Scalar(255,0,0),2);
    } 
    cv::circle(I,center,2,cv::Scalar(0,0,0),2);     // 原点,第三个参数是半径
    cv::Rect boundingRect = rRect.boundingRect();   // 获取外接矩形
    cv::rectangle(I, boundingRect, cv::Scalar(0,0,255),2);
    cv::imshow(" rotated rectangle", I);
    cv::waitKey(0);
    return 0;
}

示例代码运行效果如下图:

1.8 cv::Mat类型

图像像素数据本身也是有数据类型的, 图像像素的数据类型可能是字节型、 整型、 浮点型等。 而图像的深度又与图像数据类型息息相关。 Mat对象提供了如下两个方法分别用于获取图像的类型与深度。

1.8.1 图像数据类型

type()返回的是OpenCV支持的图像枚举类型, OpenCV中支持的图像数据类型如下图:

每个类型以"CV_"开头, 中间的字母表示数据类型, 字母前面的数字表示该数据的长度, 字母后面的数字表示该图像的通道数目。

这里以CV_8UC3为例进行解释: 8表示数据长度为8位; UC表示数据类型为无符号字节型; 3表示三通道,

1.8.2 图像深度类型

depth()返回OpenCV支持的图像深度类型, OpenCV中支持的图像数据深度类型如下图:

1.8.3 基本操作示例

cpp 复制代码
#include<iostream>
#include<opencv2/opencv.hpp>
using namespace std;
using namespace cv;

int main(){
    // 非赋值构造
    Mat a(Size(4,3),CV_8UC1, Scalar(255)); // 单通道
    Mat b = Mat(Size(4,3), CV_8UC3, Scalar(0,1,2)); // 三通道
    cout << "a=" << endl << a << endl << endl;
    cout << "b=" << endl << b << endl << endl;
    Mat mz = Mat::zeros(cv::Size(2,2), CV_8UC1);    //全零矩阵
    Mat mo = Mat::ones(Size(2,2), CV_8UC1);     // 全1矩阵
    Mat me = Mat::eye(Size(4,3), CV_32FC1);     // 对角线为1的矩阵
    cout << "mz=" << endl << mz << endl << endl;
    cout << "mo=" << endl << mo << endl << endl;
    cout << "me=" << endl << me << endl << endl;
    // system("pause");
    Mat m0 = Mat::ones(Size(3,3), CV_8UC1);     // 全1矩阵
    Mat m1 = Mat::eye(3,3, CV_8UC1);     // 全1矩阵

    cout << "m0=" << endl << m0 << endl << endl;
    cout << "m1=" << endl << m1 << endl << endl;
    cout << "m0+m1=" << endl << m0+m1 << endl << endl;
    cout << "m0.*m1" << endl << (m0.mul(m1)) << endl << endl;
    cout << "m0./m1" << endl << (m0/m1) << endl << endl;
    cout << "m0<m1" << endl << (m0 < m1) << endl << endl;
    cout << "m0<=m1" << endl << (m0 <= m1) << endl << endl;

    Mat image = imread("D:/workspaces/opencv/opencv-learning/1.jpg",1);
    Rect roi(Point(80,80),Size(120,160));
    Mat mat_roi(image, roi);
    Mat mat_range(image, Range(80, 80+160),Range(80, 80+120));

    namedWindow("image",WINDOW_NORMAL);

    imshow("image", image);
    
    imshow("roi", mat_roi);
    imshow("mat_range", mat_range);
    waitKey();
    return 0;
}

示例代码运行结果如下图所示。

而安装Image Watch插件后,可以看到内存中的图,便于调试程序,用Image Watch插件查看图像如下图:

2.参考链接

1.了解OpenCV的数据类型

2.OpenCV4机器学习算法原理与编程实战---书中代码解析

3.cv::Scalar()

相关推荐
Jooolin6 小时前
【C++】C++11出来之后,到目前为止官方都做了些什么更新?
数据结构·c++·ai编程
Ka1Yan6 小时前
[算法] 双指针:本质是“分治思维“——从基础原理到实战的深度解析
java·开发语言·数据结构·算法·面试
蓝风破云7 小时前
模拟实现STL中的list容器
c语言·数据结构·c++·链表·迭代器·list·iterator
DjangoJason7 小时前
每日算法题【二叉树】:二叉树的最大深度、翻转二叉树、平衡二叉树
数据结构·算法·链表
云泽8088 小时前
深入解析数据结构之单链表
数据结构
西红柿维生素9 小时前
Junior Engineer浅谈CAS
java·开发语言·数据结构
lxl13079 小时前
学习数据结构(15)插入排序+选择排序(上)
数据结构·学习·排序算法
PAQQ10 小时前
使用node-red+opencv+mqtt实现相机图像云端查看
人工智能·opencv·计算机视觉
Jooolin10 小时前
大名鼎鼎的哈希表,真的好用吗?
数据结构·c++·ai编程