【opencv高级教程】OpenCV 基础数据类型与泛型操作:从“原子“到“工具箱“的完整图谱

ROS2教程写作指南:面向实战的故障驱动型教程设计 ROS教程本质是解决开发者真实问题的知识传递工程,其核心在于将抽象概念(如TF2坐标变换、自定义Msg)锚定在高频报错场景中,通过故障驱动设计、版本决策树、最小可运行单元(MRU)和错误前置化等方法,提升可复现性与新手友好度。技术原理需服务于工程落地——例如ROS2中rclpy的spin机制差异直接影响节点稳定性,Humble与Foxy的QoS策略不兼容会导致topic通信静默失败。这类教程广泛应用于高校机器人教学、工业AGV迁移培训及开源驱动文档建设,尤其适合Ubuntu 22.04+ROS2 Humbl 阅读详情

OpenCV 基础数据类型与泛型操作:从"原子"到"工具箱"的完整图谱

本文参考 OpenCV 官方文档 及 OpenCV 4.x 教程 撰写。


1. 为什么我们要从"原子"开始?

别急,我知道你可能已经迫不及待想直接上手 cv::Mat 做图像处理了。但想想看——如果不知道构成图像的"原子"是什么,我们又怎么理解图像背后的数学呢?

OpenCV 的 core 模块就像一张精密的乐高图纸。cv::Mat 是那座宏伟的城堡,而 Point_、Size_、Rect_、Scalar_、Matx、Vec……这些基础类型,就是那些最小的积木块。它们虽然不起眼,但每一个都承载着特定的几何语义和运算规则。

在这篇文章里,我们将一起探索 OpenCV 的基础数据类型体系,从最基础的几何点开始,层层深入到小型矩阵、标量颜色,以及辅助工具类。每节只解决一个认知疑点,用对话式的语气,像朋友聊天一样带你探索。


2. 整体架构:OpenCV 基础类型的"家族树"

在继续之前,让我们先看看 OpenCV 基础类型的整体架构。如果画成图,会是什么样子呢?

OpenCV core 基础类型

几何点与向量

区域描述

标量与颜色

小型矩阵与栈上优化

辅助工具类

Point_<T> 2D/3D

点积/叉积/夹角

距离/投影计算

Size_<T> 宽高

Rect_<T> 矩形

RotatedRect 旋转矩形

Range 半开区间

Scalar_<T> 四通道

BGR/RGB/HSV 颜色

广播规则

Matx<T,m,n> 固定矩阵

Vec<T,cn> 固定向量

栈上零堆分配优势

TermCriteria 终止条件

PCA/SVD 特征分解

RNG 随机数生成

现在我们已经了解了整体架构,接下来让我们从最小的积木块——几何点开始探索。


3. 几何点与向量类型

3.1 Point_/Point2f/Point3f 的坐标运算重载与范数计算

听起来抽象对吧?一个"点"能有多复杂?但在计算机视觉里,一个像素坐标 (x, y) 不仅仅是一个位置,它还是一个向量——可以从原点出发,有方向、有长度。

OpenCV 用模板类 Point_<T> 来表示这种几何点。Point2i(整数坐标)、Point2f(浮点坐标)、Point3f(三维坐标)都是它的具体化身。

第一步:创建点

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

// 创建二维浮点坐标点
Point2f p1(3.0f, 4.0f);   // 就像平面上的一个位置
Point2f p2(1.0f, 2.0f);

// 三维点
Point3f p3d(1.0f, 2.0f, 2.0f);

第二步:算术运算重载

OpenCV 为 Point_ 重载了全套算术运算符,让它们可以像数字一样直接加减乘除:

// 向量加减:就像力的合成
Point2f p_add = p1 + p2;        // (4.0, 6.0) —— 两个向量的"合力"
Point2f p_sub = p1 - p2;        // (2.0, 2.0) —— 从p2指向p1的向量

// 标量乘法:缩放向量长度
Point2f p_mul = p1 * 2.0f;      // (6.0, 8.0) —— 长度翻倍,方向不变
Point2f p_div = p1 / 2.0f;      // (1.5, 2.0) —— 长度减半

第三步:范数计算——向量的"长度"

如果画成图,一个从原点出发到 (3, 4) 的向量,它的长度是多少?根据勾股定理,是 sqrt(3² + 4²) = 5。这就是 L2 范数。

// L2范数(欧几里得距离)—— 最常用的"长度"
float norm_l2 = norm(p1);       // 5.0

// L1范数(曼哈顿距离)—— 各分量绝对值之和
float norm_l1 = norm(p1, NORM_L1);  // |3| + |4| = 7.0

// L∞范数(切比雪夫距离)—— 最大分量
float norm_inf = norm(p1, NORM_INF); // max(|3|, |4|) = 4.0

范数可视化

L∞范数 = 4

L1范数 = 7

L2范数 = 5

sqrt(3²+4²)

3

4

max(3,4)=4

(0,4)

原点

P(3,4)

(3,0)

在继续之前,让我们看看这些范数在实际使用中意味着什么:

  • L2 范数:计算两点之间的直线距离,用于最近邻搜索
  • L1 范数:对异常值不敏感,用于鲁棒估计
  • L∞ 范数:判断是否在正方形区域内,用于快速边界检测

3.2 点积/叉积与向量夹角的几何意义实现

现在我们已经了解了点的坐标运算,接下来看看更高级的操作——点积和叉积。

点积(Dot Product)—— 衡量"方向一致性"

两个向量的点积,几何意义是:一个向量在另一个向量方向上的投影长度,乘以另一个向量的长度。

如果画成图,就像一束光垂直照射在一个斜面上,投影的长度就是点积的一部分。

Point3f a(1.0f, 0.0f, 0.0f);  // x轴单位向量
Point3f b(0.0f, 1.0f, 0.0f);  // y轴单位向量
Point3f c(1.0f, 1.0f, 0.0f);  // 45度方向

// 点积
float dot_ab = a.dot(b);        // 0.0 —— 垂直向量点积为0!
float dot_ac = a.dot(c);        // 1.0 —— 有夹角,点积为正

叉积(Cross Product)—— 生成"垂直向量"

叉积只在三维空间中定义,结果是同时垂直于两个输入向量的新向量。方向遵循右手定则。

// 叉积 —— 仅3D点支持
Point3f cross_ab = a.cross(b);  // (0, 0, 1) —— z轴方向

点积与叉积的几何意义

叉积 a×b

点积 a·c > 0

点积 a·b = 0

垂直

夹角 < 90°

右手定则

(0,0,1)

向量 a

原点

向量 b

向量 c

投影为0

投影为正

向量夹角计算——从点积到角度

// 夹角公式: cos(θ) = (a·b) / (|a|*|b|)
float angle_ab = acos(a.dot(b) / (norm(a) * norm(b))) * 180.0 / CV_PI;  // 90°
float angle_ac = acos(a.dot(c) / (norm(a) * norm(c))) * 180.0 / CV_PI;  // 45°

这在训练/实际使用中意味着什么?在特征匹配中,我们常用点积来判断两个特征向量的相似度——点积越大,方向越接近,特征越相似。


3.3 点到线段距离、点到直线投影的公式推导

别急,这个听起来复杂,但如果我们把它拆解成几步,其实很直观。

问题:给定一个点 P 和一条线段 AB,怎么找到 P 到 AB 的最短距离?

如果画成图,最短距离一定是 P 到 AB 的垂线。但这里有个陷阱——垂足可能落在线段之外!

点到线段距离

投影在线段外

投影在线段内

垂线

最短距离到端点

P'

A

B

P(5,5)

投影点 Q

公式推导:

  1. 计算向量 AP = P - A,AB = B - A
  2. 投影参数 t = (AP · AB) / |AB|² —— 表示 P 在 AB 方向上的"进度"
  3. 如果 t < 0,最近点是 A;如果 t > 1,最近点是 B;否则是投影点 A + AB * t
Point2f p(5.0f, 5.0f);
Point2f line_start(0.0f, 0.0f);
Point2f line_end(10.0f, 0.0f);  // x轴上的线段

// 第一步:计算向量
Point2f AP = p - line_start;
Point2f AB = line_end - line_start;

// 第二步:计算投影参数 t
float t = AP.dot(AB) / AB.dot(AB);  // 投影参数 [0, 1]

// 第三步:判断最近点位置
Point2f closest;
if (t < 0) closest = line_start;           // 垂足在A左侧
else if (t > 1) closest = line_end;        // 垂足在B右侧
else closest = line_start + AB * t;        // 垂足在线段内

// 第四步:计算距离
float dist = norm(p - closest);

这在实际使用中意味着什么?在碰撞检测、最近邻搜索、路径规划中,点到线段的距离是最基础的运算之一。


4. 区域描述类型

4.1 Size_ 的宽高语义与面积/宽高比计算

现在我们已经了解了点的运算,接下来看看如何描述一个区域的大小。

Size_<T> 就是专门干这个的——它只有两个成员:width 和 height。听起来简单,但这里有个微妙的语义问题:width 和 height 到底代表什么?

在 OpenCV 中,width 是水平方向的跨度,height 是垂直方向的跨度。这和数学中的坐标系是一致的。

Size2f sz(800.0f, 600.0f);  // width=800, height=600

// 面积计算
float area = sz.area();      // 800 * 600 = 480000

// 宽高比(Aspect Ratio)—— 视频压缩、图像缩放的核心参数
float aspect_ratio = (float)sz.width / sz.height;  // 4:3 = 1.333...

// 缩放操作
Size2f sz_scaled = sz * 0.5f;  // (400, 300)
Size2f sz_div = sz / 2.0f;     // (400, 300)

Size 的语义

宽高比

面积

×

×

÷

÷

aspect = 1.333

Size(800,600)

width = 800

height = 600

area = 480000

Size 与 Point 的关系:Size 可以看作是从原点出发的向量,终点坐标就是 (width, height)。所以 Size 和 Point 之间可以相互转换。


4.2 Rect_ 的 tl()/br()/交集/并集/包含判定运算

如果 Point 是位置,Size 是大小,那 Rect 就是位置和大小的结合——一个矩形区域。

Rect r1(100, 100, 200, 150);  // x=100, y=100, width=200, height=150

Rect 的结构

+width

+height

Rect(100,100,200,150)

tl() = (100,100)

br() = (300,250)

width = 200

height = 150

交集与并集——两个矩形的"重叠"与"合并"

Rect r1(100, 100, 200, 150);
Rect r2(150, 120, 200, 200);

// 交集(&)—— 两个矩形重叠的区域
Rect r_inter = r1 & r2;
// 结果: x=150, y=120, width=150, height=130

// 并集(|)—— 能包围两个矩形的最小矩形
Rect r_union = r1 | r2;
// 结果: x=100, y=100, width=250, height=220

交集与并集

并集 |

交集 &

最小包围矩形

r1

重叠区域

r2

包含判定——点在不在矩形内?

Point pt_inside(200, 200);
Point pt_outside(50, 50);

bool contains_inside = r1.contains(pt_inside);   // true
bool contains_outside = r1.contains(pt_outside);   // false

矩形平移与缩放

// 平移:加上一个 Point
Rect r_moved = r1 + Point(50, 30);  // 向右50, 向下30

// 缩放:乘以一个标量(注意:只缩放宽高,不缩放位置)
Rect r_scaled = r1 * 2;  // width=400, height=300, x,y 不变

这在实际使用中意味着什么?在目标检测中,Rect 是边界框(Bounding Box)的标准表示;在图像裁剪中,Rect 定义了 ROI(感兴趣区域)。


4.3 RotatedRect 的最小外接矩形与四个顶点提取(boxPoints)

听起来抽象对吧?普通的 Rect 只能表示"正放"的矩形,但现实中的物体往往是倾斜的。怎么办?

RotatedRect 就是为了解决这个问题而生的。它有三个参数:

  • center:旋转中心
  • size:宽高(注意:这里的 size 是旋转前的原始宽高)
  • angle:旋转角度(顺时针,单位度)

RotatedRect 的结构

四个顶点

v[0]

center

size(width,height)

angle

v[1]

v[2]

v[3]

// 构造旋转矩形
Point2f center(400.0f, 300.0f);
Size2f size(200.0f, 100.0f);
float angle = 30.0f;  // 顺时针旋转30度

RotatedRect rRect(center, size, angle);

// 提取四个顶点
Point2f vertices[4];
rRect.points(vertices);

// 或者用 boxPoints 函数
Mat boxPts;
boxPoints(rRect, boxPts);  // 输出 4x2 矩阵

最小外接矩形(minAreaRect)

给定一组轮廓点,找到能包围它们的最小面积旋转矩形:

vector<Point> contour;
// ... 填充轮廓点 ...

RotatedRect minRect = minAreaRect(contour);

// 外接正矩形(bounding box)
Rect bbox = minRect.boundingRect();

这在实际使用中意味着什么?在文本检测、车牌识别中,物体往往是倾斜的,RotatedRect 能给出更紧凑的包围框,减少背景干扰。


4.4 Range 的半开区间 [start, end) 约定与切片操作

别急,这个看似简单,但有一个容易踩坑的地方——半开区间。

OpenCV 的 Range 表示 [start, end),即包含 start,不包含 end。这和 Python 的切片规则一致,但和 MATLAB 的闭区间不同。

Range [10, 50)

不包含

包含

50

start=10

end=50

10

11

...

49

Range r(10, 50);  // [10, 50) -> 包含索引 10..49,共40个元素

// 大小计算
int size = r.size();  // 40

// 特殊Range:表示全部
Range all_range = Range::all();

// 在Mat切片中的应用
Mat img = Mat::zeros(100, 100, CV_8UC3);
Mat roi = img(Range(20, 80), Range(30, 70));  // 行[20,80), 列[30,70)
// ROI 尺寸 = 60x40

// 交集运算
Range r1(10, 50);
Range r2(30, 70);
Range r_inter = r1 & r2;  // [30, 50)

这在实际使用中意味着什么?半开区间的约定让切片操作更加安全——Range(a, b) + Range(b, c) = Range(a, c),不会出现重复或遗漏的元素。


5. 标量与颜色表示

5.1 Scalar_ 的四通道泛型存储与算术运算类型提升

现在我们已经了解了区域描述类型,接下来看看 OpenCV 如何表示颜色和标量值。

Scalar_<T> 是 Vec<T, 4> 的派生类,固定四通道。为什么是四通道?因为图像处理中常见的颜色空间(BGR、RGB、RGBA、HSV)最多需要四个分量。

Scalar_<T> 四通道结构

B

G

R

A

Scalar

[0] = val[0]

[1] = val[1]

[2] = val[2]

[3] = val[3]

蓝色通道

绿色通道

红色通道

Alpha通道

Scalar s1(10, 20, 30, 40);       // (B=10, G=20, R=30, A=40)
Scalar s2(5, 5, 5, 5);

// 算术运算
Scalar s_add = s1 + s2;          // (15, 25, 35, 45)
Scalar s_mul = s1 * 2.0;         // (20, 40, 60, 80)

// 点积(四通道对应相乘求和)
double dot_val = s1.dot(s2);     // 10*5 + 20*5 + 30*5 + 40*5 = 500

类型提升:当 int 类型的 Scalar 与 double 运算时,结果会自动提升为 double:

Scalar s_int(1, 2, 3, 4);
Scalar s_double = s_int * 1.5;   // 结果变为 double 类型: (1.5, 3.0, 4.5, 6.0)

5.2 常用颜色常量的跨空间定义(BGR/RGB/HSV)

OpenCV 默认使用 BGR 顺序,这和大多数图像库的 RGB 顺序相反。这是一个历史遗留问题,但已经成为约定。

颜色空间对比

HSV

H=0

S=255

V=255

RGB

R=255

G=0

B=0

BGR

B=255

G=0

R=0

// BGR 颜色常量
Scalar color_red(0, 0, 255);       // BGR: 纯红
Scalar color_green(0, 255, 0);     // BGR: 纯绿
Scalar color_blue(255, 0, 0);      // BGR: 纯蓝
Scalar color_white(255, 255, 255); // BGR: 白色

// HSV 颜色空间
// Hue: 0-179 (OpenCV 将 0-360 映射到 0-179)
// Saturation: 0-255
// Value: 0-255
Scalar hsv_red(0, 255, 255);       // 红色在HSV
Scalar hsv_green(60, 255, 255);    // 绿色在HSV
Scalar hsv_blue(120, 255, 255);   // 蓝色在HSV

// 颜色空间转换
Mat bgr_red(1, 1, CV_8UC3, color_red);
Mat hsv_converted;
cvtColor(bgr_red, hsv_converted, COLOR_BGR2HSV);

这在实际使用中意味着什么?在肤色检测、颜色跟踪中,HSV 空间比 BGR 更稳定,因为亮度(V)和颜色信息(H、S)分离了。


5.3 多通道 Scalar 与 Mat 逐元素运算的广播规则

如果画成图,Scalar 与 Mat 的运算就像一台广播站,把 Scalar 的每个通道值"广播"到 Mat 的对应通道上。

广播规则

广播到

广播到

广播到

Mat(3x3, 3通道)

通道0

通道1

通道2

Scalar(10,20,30)

10

20

30

Mat img = Mat::ones(3, 3, CV_8UC3) * 100;  // 所有像素值=100

// 逐通道相加:B+10, G+20, R+30
Scalar add_val(10, 20, 30);
Mat result = img + add_val;

// 单通道Scalar广播到所有通道
Scalar uniform_add(50);  // 所有通道+50
Mat result2 = img + uniform_add;

// 逐元素乘法(注意溢出)
Scalar mul_val(1.2, 1.0, 0.8);
Mat result3 = img.mul(mul_val);

这在实际使用中意味着什么?广播规则让图像的亮度调整、白平衡校正变得极其简洁——一行代码就能完成全图的通道级调整。


6. 小型矩阵与栈上优化

6.1 Matx 固定维度矩阵:行列式/逆/转置的编译期优化

现在我们已经了解了标量和颜色,接下来看看 OpenCV 如何处理小型矩阵运算。

Matx<T, m, n> 是一个模板类,维度在编译期确定。这和 Mat(运行期确定维度)有本质区别。

Matx vs Mat

Mat

运行期确定: ?x?

堆上分配

动态调度

Matx<float,3,3>

编译期确定: 3x3

栈上分配: 36 bytes

内联优化

// 3x3 浮点矩阵
Matx33f m33(1, 2, 3,
            0, 1, 4,
            5, 6, 0);

// 行列式
float det = m33.det();

// 逆矩阵
Matx33f m33_inv = m33.inv();

// 转置
Matx33f m33_t = m33.t();

// 矩阵乘法
Matx33f m33_2(1, 0, 0,
              0, 2, 0,
              0, 0, 3);
Matx33f m33_mul = m33 * m33_2;

// 解线性方程组 Ax = b
Vec3f b(1, 2, 3);
Vec3f x = m33.solve(b);  // 使用LU分解求解

4x4 矩阵——3D 图形变换的标配

// 平移矩阵
Matx44f m44(1, 0, 0, 10,
            0, 1, 0, 20,
            0, 0, 1, 30,
            0, 0, 0, 1);

这在实际使用中意味着什么?在相机标定、3D 重建中,Matx33f 表示内参矩阵,Matx44f 表示外参矩阵,编译期优化让这些高频运算速度提升数倍。


6.2 Vec 固定向量与跨通道数据映射(reshape 语义)

Vec<T, cn> 是 Matx<T, cn, 1> 的派生类——本质上是一个固定通道数的列向量。

Vec 的结构

B

G

R

Vec3b

[0] = 100

[1] = 150

[2] = 200

蓝色

绿色

红色

// 像素表示
Vec3b pixel(100, 150, 200);  // 3通道uchar (BGR像素)
Vec4f rgba(1.0f, 0.5f, 0.0f, 1.0f);  // 4通道float (RGBA)

// 通道访问
uchar blue = pixel[0];
uchar green = pixel[1];
uchar red = pixel[2];

// 与Scalar的转换
Scalar s = pixel;  // Vec3b -> Scalar (通道扩展为4)

// reshape语义: Vec可以看作小型Mat
Mat m_from_vec(pixel);  // 1x1 CV_8UC3 Mat

// 向量运算
Vec3f v1(1, 2, 3);
Vec3f v2(4, 5, 6);
Vec3f v_add = v1 + v2;
float v_dot = v1.dot(v2);  // 32

这在实际使用中意味着什么?Vec3b 是访问图像像素的最常用类型——img.at<Vec3b>(y, x) 返回一个像素的 BGR 值。


6.3 栈上对象相对于 Mat 的零堆分配性能优势

如果画成图,栈上分配就像把东西放在手边的桌子上,随拿随用;堆上分配就像去仓库取货,需要走一段路。

内存分配对比

堆上对象

Mat(1000x1000x3): 3MB

malloc/new开销

可能的缓存未命中

栈上对象

Point2f: 8 bytes

零分配开销

Vec3b: 3 bytes

Matx33f: 36 bytes

CPU缓存友好

// 栈上分配 (零堆分配)
Point2f p_stack(100, 200);       // 8 bytes on stack
Vec3b pixel_stack(100, 150, 200); // 3 bytes on stack
Matx33f m33_stack;                // 36 bytes on stack

// Mat 是堆上分配 (动态内存)
Mat m_heap(1000, 1000, CV_8UC3);  // 3MB on heap

性能优势场景:

  1. 实时图像处理中的像素级运算
  2. 3D 图形变换中的 4x4 矩阵乘法
  3. 特征点描述子的向量运算
  4. 颜色空间转换的逐像素计算

这在实际使用中意味着什么?在嵌入式设备或实时系统中,减少堆分配能显著降低延迟和内存碎片。


7. 辅助工具类

7.1 TermCriteria 的 MAX_ITER/MAX_EPS 组合终止条件

现在我们已经了解了基础数据类型,接下来看看 OpenCV 提供的"控制旋钮"——终止条件。

TermCriteria 用于控制迭代算法的终止。它就像汽车的"刹车系统"——告诉算法什么时候该停下来。

TermCriteria 终止条件

最多迭代100次

精度 < 1e-6

TermCriteria

MAX_ITER

EPS

计数终止

精度终止

组合: 满足任一即终止

// 仅最大迭代次数
TermCriteria tc_iter(TermCriteria::MAX_ITER, 100, 0);

// 仅精度阈值
TermCriteria tc_eps(TermCriteria::EPS, 0, 1e-6);

// 组合条件: 满足任一即终止
TermCriteria tc_both(TermCriteria::MAX_ITER + TermCriteria::EPS, 100, 1e-6);

// 实际应用: K-means聚类
Mat data(100, 2, CV_32F);
randn(data, 0, 1);

Mat labels, centers;
double compactness = kmeans(data, 5, labels, 
                             TermCriteria(TermCriteria::MAX_ITER + TermCriteria::EPS, 
                                          100, 0.01),
                             10, KMEANS_RANDOM_CENTERS, centers);

这在实际使用中意味着什么?组合终止条件让算法既不会跑太久(MAX_ITER),也不会在已经收敛时继续浪费计算(EPS)。


7.2 PCA/SVD 的轻量级封装与特征分解接口

PCA(主成分分析)—— 找到数据最重要的方向

如果画成图,PCA 就像把一团散乱的点,找到一条能最好概括它们分布方向的直线。

PCA 几何意义

投影

散乱的二维数据

PCA分析

特征向量1: 主方向

特征向量2: 次方向

特征值: 各方向的重要性

一维表示

// 生成示例数据
Mat data(100, 2, CV_32F);
randn(data, Scalar(50, 50), Scalar(20, 10));

// PCA 主成分分析
PCA pca(data, Mat(), PCA::DATA_AS_ROW, 2);

cout << "均值 = " << pca.mean << endl;
cout << "特征向量 =\n" << pca.eigenvectors << endl;
cout << "特征值 = " << pca.eigenvalues << endl;

// 投影到主成分空间
Mat projected;
pca.project(data.row(0), projected);

// 重构
Mat reconstructed;
pca.backProject(projected, reconstructed);

SVD(奇异值分解)—— 矩阵的"解剖刀"

Mat A(3, 3, CV_32F);
randu(A, -10, 10);

SVD svd(A, SVD::FULL_UV);  // 完整SVD

cout << "U =\n" << svd.u << endl;
cout << "W (奇异值) = " << svd.w.t() << endl;
cout << "Vt =\n" << svd.vt << endl;

// 验证: A = U * W * Vt
Mat W_diag = Mat::zeros(3, 3, CV_32F);
W_diag.at<float>(0,0) = svd.w.at<float>(0);
W_diag.at<float>(1,1) = svd.w.at<float>(1);
W_diag.at<float>(2,2) = svd.w.at<float>(2);

Mat A_reconstructed = svd.u * W_diag * svd.vt;

// SVD 解线性方程组 Ax = b
Mat b(3, 1, CV_32F, {1, 2, 3});
Mat x_svd = svd.solve(b);

这在实际使用中意味着什么?PCA 用于降维和特征提取,SVD 用于求解病态方程组和矩阵低秩近似。


7.3 RNG 随机数生成器:种子复现与多种分布采样

RNG(Random Number Generator)—— 可复现的随机性

如果画成图,RNG 就像一个精密的骰子机器——给定相同的种子,它总是产生相同的序列。这在实验复现中至关重要。

RNG 种子复现

完全相同

seed = 12345

RNG rng1

RNG rng2

序列: 42, 17, 89...

序列: 42, 17, 89...

// 确定性种子,保证可复现
uint64 seed = 12345;
RNG rng(seed);

// 均匀分布整数 [0, 100)
int val = rng.uniform(0, 100);

// 均匀分布浮点数 [0, 1)
float fval = rng.uniform(0.0f, 1.0f);

// 高斯分布 (正态分布)
double gval = rng.gaussian(1.0);  // 标准差=1

// 种子复现验证
RNG rng2(seed);
// rng 和 rng2 将产生完全相同的序列

// 填充随机矩阵
Mat random_mat(3, 3, CV_32F);
rng.fill(random_mat, RNG::UNIFORM, 0.0f, 1.0f);

Mat gaussian_mat(3, 3, CV_32F);
rng.fill(gaussian_mat, RNG::NORMAL, 0.0f, 1.0f);

// 随机打乱数组
vector<int> indices = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
randShuffle(indices, 1.0, &rng);

这在实际使用中意味着什么?在深度学习的数据增强、RANSAC 随机采样一致性算法中,可复现的随机性是实验对比的基础。


8. 完整代码汇总

#include <opencv2/opencv.hpp>
#include <iostream>
#include <vector>

using namespace cv;
using namespace std;

// ==================== 1.3.1 几何点与向量类型 ====================

void demo_point_operations() {
    cout << "\n=== 1.3.1.1 Point 坐标运算重载与范数 ===" << endl;

    Point2f p1(3.0f, 4.0f);
    Point2f p2(1.0f, 2.0f);

    Point2f p_add = p1 + p2;
    Point2f p_sub = p1 - p2;
    Point2f p_mul = p1 * 2.0f;
    Point2f p_div = p1 / 2.0f;

    float norm_l2 = norm(p1);
    float norm_l1 = norm(p1, NORM_L1);
    float norm_inf = norm(p1, NORM_INF);

    cout << "p1 = " << p1 << ", p2 = " << p2 << endl;
    cout << "p1 + p2 = " << p_add << endl;
    cout << "p1 - p2 = " << p_sub << endl;
    cout << "p1 * 2 = " << p_mul << endl;
    cout << "L2 norm = " << norm_l2 << endl;
    cout << "L1 norm = " << norm_l1 << endl;
    cout << "L∞ norm = " << norm_inf << endl;

    Point3f p3d(1.0f, 2.0f, 2.0f);
    cout << "\nPoint3f = " << p3d << ", norm = " << norm(p3d) << endl;
}

void demo_dot_cross_angle() {
    cout << "\n=== 1.3.1.2 点积/叉积与向量夹角 ===" << endl;

    Point3f a(1.0f, 0.0f, 0.0f);
    Point3f b(0.0f, 1.0f, 0.0f);
    Point3f c(1.0f, 1.0f, 0.0f);

    float dot_ab = a.dot(b);
    float dot_ac = a.dot(c);
    Point3f cross_ab = a.cross(b);

    float angle_ab = acos(a.dot(b) / (norm(a) * norm(b))) * 180.0 / CV_PI;
    float angle_ac = acos(a.dot(c) / (norm(a) * norm(c))) * 180.0 / CV_PI;

    cout << "a·b = " << dot_ab << ", a×b = " << cross_ab << endl;
    cout << "夹角(a,b) = " << angle_ab << "°" << endl;
    cout << "夹角(a,c) = " << angle_ac << "°" << endl;
}

void demo_distance_projection() {
    cout << "\n=== 1.3.1.3 点到线段距离与投影 ===" << endl;

    Point2f p(5.0f, 5.0f);
    Point2f line_start(0.0f, 0.0f);
    Point2f line_end(10.0f, 0.0f);

    Point2f AP = p - line_start;
    Point2f AB = line_end - line_start;
    float t = AP.dot(AB) / AB.dot(AB);

    Point2f closest;
    if (t < 0) closest = line_start;
    else if (t > 1) closest = line_end;
    else closest = line_start + AB * t;

    float dist = norm(p - closest);

    cout << "点 P = " << p << endl;
    cout << "投影参数 t = " << t << endl;
    cout << "最近点 = " << closest << endl;
    cout << "点到线段距离 = " << dist << endl;
}

// ==================== 1.3.2 区域描述类型 ====================

void demo_size_operations() {
    cout << "\n=== 1.3.2.1 Size_ 宽高语义 ===" << endl;

    Size2f sz(800.0f, 600.0f);
    cout << "Size = " << sz << endl;
    cout << "面积 = " << sz.area() << endl;
    cout << "宽高比 = " << sz.width / sz.height << endl;
    cout << "缩放0.5 = " << sz * 0.5f << endl;
}

void demo_rect_operations() {
    cout << "\n=== 1.3.2.2 Rect_ 操作运算 ===" << endl;

    Rect r1(100, 100, 200, 150);
    Rect r2(150, 120, 200, 200);

    cout << "r1 = " << r1 << endl;
    cout << "tl = " << r1.tl() << ", br = " << r1.br() << endl;
    cout << "交集 = " << (r1 & r2) << endl;
    cout << "并集 = " << (r1 | r2) << endl;
    cout << "contains(200,200) = " << r1.contains(Point(200, 200)) << endl;
    cout << "r1 + Point(50,30) = " << (r1 + Point(50, 30)) << endl;
}

void demo_rotated_rect() {
    cout << "\n=== 1.3.2.3 RotatedRect ===" << endl;

    RotatedRect rRect(Point2f(400, 300), Size2f(200, 100), 30.0f);
    cout << "中心 = " << rRect.center << ", 尺寸 = " << rRect.size 
         << ", 角度 = " << rRect.angle << "°" << endl;

    Point2f vertices[4];
    rRect.points(vertices);
    for (int i = 0; i < 4; i++)
        cout << "顶点[" << i << "] = " << vertices[i] << endl;

    vector<Point> contour = {Point(100,100), Point(200,80), 
                             Point(250,150), Point(180,200), Point(90,180)};
    RotatedRect minRect = minAreaRect(contour);
    cout << "\n最小外接矩形: 中心=" << minRect.center 
         << ", 尺寸=" << minRect.size << endl;
}

void demo_range() {
    cout << "\n=== 1.3.2.4 Range 半开区间 ===" << endl;

    Range r(10, 50);
    cout << "Range(10,50): size=" << r.size() << ", [" << r.start 
         << ", " << r.end << ")" << endl;

    Range r1(10, 50), r2(30, 70);
    cout << "交集 = [" << (r1 & r2).start << ", " << (r1 & r2).end << ")" << endl;
}

// ==================== 1.3.3 标量与颜色表示 ====================

void demo_scalar_operations() {
    cout << "\n=== 1.3.3.1 Scalar_ 四通道 ===" << endl;

    Scalar s1(10, 20, 30, 40);
    Scalar s2(5, 5, 5, 5);

    cout << "s1 = " << s1 << endl;
    cout << "s1 + s2 = " << (s1 + s2) << endl;
    cout << "s1 * 2 = " << (s1 * 2.0) << endl;
    cout << "s1·s2 = " << s1.dot(s2) << endl;

    Scalar s_int(1, 2, 3, 4);
    cout << "类型提升: " << (s_int * 1.5) << endl;
}

void demo_color_constants() {
    cout << "\n=== 1.3.3.2 颜色常量 ===" << endl;

    Scalar red(0, 0, 255), green(0, 255, 0), blue(255, 0, 0);
    cout << "BGR 红=" << red << " 绿=" << green << " 蓝=" << blue << endl;

    Mat bgr_red(1, 1, CV_8UC3, red);
    Mat hsv;
    cvtColor(bgr_red, hsv, COLOR_BGR2HSV);
    cout << "BGR红转HSV = " << hsv.at<Vec3b>(0,0) << endl;
}

void demo_scalar_broadcast() {
    cout << "\n=== 1.3.3.3 广播规则 ===" << endl;

    Mat img = Mat::ones(2, 2, CV_8UC3) * 100;
    Scalar add_val(10, 20, 30);
    Mat result = img + add_val;

    cout << "原始 = " << img.at<Vec3b>(0,0) << endl;
    cout << "Scalar = " << add_val << endl;
    cout << "相加后 = " << result.at<Vec3b>(0,0) << endl;
}

// ==================== 1.3.4 小型矩阵与栈上优化 ====================

void demo_matx_operations() {
    cout << "\n=== 1.3.4.1 Matx 固定矩阵 ===" << endl;

    Matx33f m33(1, 2, 3, 0, 1, 4, 5, 6, 0);
    cout << "m33 =\n" << m33 << endl;
    cout << "det = " << m33.det() << endl;
    cout << "inv =\n" << m33.inv() << endl;
    cout << "transpose =\n" << m33.t() << endl;

    Vec3f b(1, 2, 3);
    Vec3f x = m33.solve(b);
    cout << "解 Ax=b, x = " << x << endl;
}

void demo_vec_operations() {
    cout << "\n=== 1.3.4.2 Vec 固定向量 ===" << endl;

    Vec3b pixel(100, 150, 200);
    Vec3f v1(1, 2, 3), v2(4, 5, 6);

    cout << "Vec3b = " << pixel << endl;
    cout << "v1 + v2 = " << (v1 + v2) << endl;
    cout << "v1·v2 = " << v1.dot(v2) << endl;

    Scalar s = pixel;
    cout << "Vec3b->Scalar = " << s << endl;
}

void demo_stack_vs_heap() {
    cout << "\n=== 1.3.4.3 栈上对象性能优势 ===" << endl;

    Point2f p(100, 200);
    Vec3b px(100, 150, 200);
    Matx33f m;

    cout << "Point2f: " << sizeof(p) << " bytes (栈)" << endl;
    cout << "Vec3b: " << sizeof(px) << " bytes (栈)" << endl;
    cout << "Matx33f: " << sizeof(m) << " bytes (栈)" << endl;
    cout << "Mat(1000x1000x3): " << (1000*1000*3/1024) << " KB (堆)" << endl;
}

// ==================== 1.3.5 辅助工具类 ====================

void demo_term_criteria() {
    cout << "\n=== 1.3.5.1 TermCriteria ===" << endl;

    TermCriteria tc(TermCriteria::MAX_ITER + TermCriteria::EPS, 100, 1e-6);
    cout << "组合条件: maxCount=100 或 epsilon=1e-6" << endl;

    Mat data(50, 2, CV_32F);
    randn(data, 0, 1);
    Mat labels, centers;
    kmeans(data, 3, labels, tc, 5, KMEANS_RANDOM_CENTERS, centers);
    cout << "K-means 中心点数 = " << centers.rows << endl;
}

void demo_pca_svd() {
    cout << "\n=== 1.3.5.2 PCA/SVD ===" << endl;

    Mat data(50, 2, CV_32F);
    randn(data, Scalar(50, 50), Scalar(20, 10));

    PCA pca(data, Mat(), PCA::DATA_AS_ROW, 2);
    cout << "PCA 均值=" << pca.mean << endl;
    cout << "特征值=" << pca.eigenvalues.t() << endl;

    Mat A = (Mat_<float>(3,3) << 1, 2, 3, 4, 5, 6, 7, 8, 10);
    SVD svd(A, SVD::FULL_UV);
    cout << "\nSVD 奇异值=" << svd.w.t() << endl;
}

void demo_rng() {
    cout << "\n=== 1.3.5.3 RNG 随机数 ===" << endl;

    RNG rng(12345);
    cout << "种子=12345" << endl;
    cout << "uniform(0,100): ";
    for (int i = 0; i < 5; i++) cout << rng.uniform(0, 100) << " ";
    cout << endl;

    RNG rng2(12345);
    cout << "复现验证: ";
    for (int i = 0; i < 5; i++) {
        int v1 = rng.uniform(0, 100);
        int v2 = rng2.uniform(0, 100);
        cout << (v1 == v2 ? "✓" : "✗") << " ";
    }
    cout << endl;
}

// ==================== 主函数 ====================
int main() {
    demo_point_operations();
    demo_dot_cross_angle();
    demo_distance_projection();
    demo_size_operations();
    demo_rect_operations();
    demo_rotated_rect();
    demo_range();
    demo_scalar_operations();
    demo_color_constants();
    demo_scalar_broadcast();
    demo_matx_operations();
    demo_vec_operations();
    demo_stack_vs_heap();
    demo_term_criteria();
    demo_pca_svd();
    demo_rng();

    return 0;
}

9. 闭环总结:这在实际使用中意味着什么?

现在我们已经走完了 OpenCV 基础数据类型的完整旅程。让我们回顾一下这些"原子"在真实世界中的角色:

类型实际应用场景
Point_像素坐标、特征点位置、3D 点云
Size_图像尺寸、窗口大小、特征描述子维度
Rect_目标检测边界框、ROI 裁剪区域
RotatedRect倾斜文本检测、车牌定位
Scalar_颜色值、像素强度、多通道偏移量
Matx相机内参/外参矩阵、仿射变换
Vec像素值访问、特征描述子
TermCriteria迭代算法控制(K-means、MeanShift)
PCA/SVD降维、特征提取、方程组求解
RNG数据增强、RANSAC、随机采样

推荐阅读:


本文采用对话式技术写作风格,旨在降低学习焦虑。如有疑问,欢迎一起探讨!

OpenCV 4.5.2版本新特性解析:教程、API与例程的深度整合 本文深入解析OpenCV 4.5.2版本的新特性,重点介绍教程、API与例程的深度整合。新版OpenCV通过多语言并行展示、交互式教程和智能API文档优化,显著提升开发者体验。同时,示例代码库的重构和性能基准测试功能为计算机视觉任务提供了更高效的学习和开发支持。 阅读详情

相关推荐

中国AI模型开源的三大实践路径:能力原子化、工程栈与场景验证

大模型开源已从单纯释放权重,演进为围绕真实产业需求的能力供给体系。其核心原理在于将通用智能解耦为可验证、可部署、可演进的模块化能力单元,通过能力原子化、工程栈开源和场景验证三类范式,显著降低企业AI应用的时间成本与试错风险。这种路径重构不仅提升了中文语境下的专业领域适配精度,更在制造业质检、法律服务、政务热线等典型场景中实现从‘能用’到‘好用’的跨越。尤其在金融、医疗、司法等高合规要求领域,开源项目正以数据脱敏规范、模块化治理协议和场景分层许可证等方式,平衡开放性与可控性,推动AI技术真正下沉至中小企业一线

chikuai9995的博客 648

可控自动化知识图谱构建:从PDF到可运营图谱的6周落地实践

知识图谱是一种将实体、关系与语义结构化表达的技术体系,其核心价值在于支撑智能搜索、推理决策与知识复用。然而传统构建方式高度依赖人工标注、规则编写与专家校验,导致成本高、周期长、难以持续更新。随着大模型、多模态OCR和图数据库技术成熟,‘可控自动化’成为更务实的演进路径——即在预处理、知识抽取、图谱治理三层中嵌入人机协同机制,以规则+微调模型+LLM提示构成混合引擎,在保障可解释性与精度前提下提升覆盖率与迭代速度。本文聚焦电力设备维修报告等典型非结构化数据场景,详解如何用动态Schema推断、语义增强切片、置

weixin_30342209的博客 374

NeurIPS 2022四大技术跃迁:动态操作、不确定性建模、模型原子化与韧性评估

在人工智能从‘能力展示’迈向‘真实部署’的关键转折期,‘动态操作’与‘不确定性建模’正取代静态表征成为新一代AI系统的核心范式;‘模型即服务(MaaS)’推动大模型向可组合、可热替换的原子化架构演进;而评估体系也从单一准确率升级为覆盖通信、计算、数据、安全与隐私的多维‘韧性图谱’。这些跃迁并非孤立演进,而是深度耦合——例如动态操作依赖不确定性反馈决策,模型原子化是实现韧性评估的工程基础。对算法工程师而言,掌握这四大跃迁点,意味着能快速识别高潜力论文的技术内核,规避‘实验室完美但工业不可行’的陷阱,并在推荐系

weixin_30239339的博客 348

Better BibTeX引用图谱功能:可视化文献引用关系的完整教程

📚 作为学术研究人员,你是否曾经想要直观地了解文献之间的引用关系?Better BibTeX的引用图谱功能正是为你量身打造的强大工具!这个功能能够将复杂的文献引用网络转换为清晰的图形化表示,让你一眼看清学术脉络。在本教程中,我将详细介绍如何利用这个功能来提升你的研究效率。 ## 🔍 什么是引用图谱功能? Better BibTeX的引用图谱功能是一个创新的文献可视化工具,它基于GraphM

gitblog_00818的博客 911

计算机视觉入门:一站式掌握Python、OpenCV与PyTorch实战

这次我们来看一套号称“2026最新”的计算机视觉入门教程。它打包了Python、OpenCV、深度学习、PyTorch和CV算法,号称100集保姆级内容,目标是让你在短时间内快速上手。对于想进入CV领域的新手,或者需要快速回顾知识体系的开发者,这类整合资源往往能省去大量东拼西凑的时间。 这套教程的核心价值在于其“一站式”和“手把手”的特性。它试图将计算机视觉学习路径上最关键的几个技术栈——从编程语言(Python)、基础图像库(OpenCV)、到深度学习框架(PyTorch)和核心算法(CV)——串联成一个

weixin_29062613的博客 301

Mythos能力模块:Anthropic的语义图谱与分级释放机制解析

语义图谱是支撑大模型深度推理的核心知识组织范式,其原理在于将离散文档映射为跨源概念节点与关系边,实现多跳、可溯源的结构化推理。相比传统RAG依赖检索拼接,语义图谱显著提升长上下文一致性与复杂问题准确率,具备强审计性与工程可控性。该技术已落地法律合同审查、医疗指南协同、工业故障归因等高价值场景,并通过租户级、请求级、内容级三层闸门实现能力分级释放,兼顾安全性、合规性与商业灵活性。Mythos正是Anthropic在该方向的标志性实践。

ajwh64482的博客 364

二、OpenCV入门(基础操作篇)

二、OpenCV入门(基础操作) 目录:二、OpenCV入门(基础操作)一、基本操作1.读取图片cv.read() 一、基本操作 导入模块: import cv2 as cv 1.读取图片 cv.read()

~宪宪的博客 743

工业级自动知识图谱:分层自治架构与落地实践

知识图谱自动化并非端到端黑盒生成,而是面向业务闭环的可控结构化认知建模。其核心原理在于将不确定性分解为可验证、可审计、可干预的分层任务——数据感知层聚焦场景切片与强校验,知识蒸馏层依托小模型+规则熔断保障事实锚定,图谱编排层则通过动态关系权重与决策流实现知识演化。这种‘有限自动’范式显著提升知识新鲜度与决策影响度,广泛应用于金融风控、制造供应链、电商大促等对时效性与合规性双敏感的工业场景。本文深入剖析12个落地生死细节,直击OCR鲁棒性、隐含关系抽取、实体消歧上下文绑定等真实瓶颈。

weixin_30245867的博客 437

OpenCV入门教程(非常详细)从零基础入门到精通,看完这一篇就够了

OpenCV 中有150多种颜色空间转换方法,其中最广泛使用的转换方法有两种,B-G-R↔Gray(灰度图) 和 B-G-R↔HSV(深度色彩的彩色图)在 OpenCV 中,读取和表达图像的方式是B-G-R通道,(Blue-Green-Red)当我们只指定图像对象的行、列下标时,我们就可以获得图像的B-G-R的1×3一维数组。plt.cm.hsv hsv颜色空间, 红-黄-绿-青-蓝-洋红-红。中,读取和表达图像的方式是R-G-B通道,显然,如果想要使。

2501_91113915的博客 2359

音乐频谱灯的硬件艺术:从STM32到SK9822LED的工程美学

本文探讨了基于STM32微控制器和SK9822 LED的音乐频谱灯硬件设计与实现。通过ADC采集音频信号,利用FFT算法进行频谱分析,并驱动LED阵列呈现动态视觉效果,展现了硬件工程与艺术美学的完美融合。

Pepper的专栏 218

AHP层次分析法在项目风险评估中的实战应用(含Excel模板)

本文详细介绍了AHP层次分析法在项目风险评估中的实战应用。通过构建风险层次模型、利用判断矩阵量化主观判断,并结合Excel工具进行权重计算与一致性检验,将模糊的定性风险转化为清晰的量化排序。文章以新产品上线项目为例,提供了完整的分析流程和可操作的Excel模板,帮助项目经理高效识别并优先处理核心风险。

weixin_29061465的博客 572

chatgpt赋能python:Python图谱:一份全面的Python技能地图

本文由chatgpt生成,文章没有在chatgpt生成的基础上进行任何的修改。以上只是chatgpt能力的冰山一角。作为通用的Aigc大模型,只是展现它原本的实力。对于颠覆工作方式的ChatGPT,应该选择拥抱而不是抗拒,未来属于“会用”AI的人。🧡AI职场汇报智能办公文案写作效率提升教程 🧡专注于AI+职场+办公方向。下图是课程的整体大纲下图是AI职场汇报智能办公文案写作效率提升教程中用到的ai工具。

tulingtest的博客 192

中孚保密检查系统彻底卸载指南:绕过口令与清除内核残留

中孚保密检查系统是深度集成于Windows内核的合规管控软件,其卸载涉及用户态口令校验、内核态服务引擎与Ring 0级驱动自保三重机制。理解其基于SHA-256哈希的本地口令验证原理和zfsysflt.sys过滤驱动的加载逻辑,是实现无残留清理的技术前提。该系统具备高权限驻留特性,常规卸载工具无法触达驱动与服务层,易引发蓝屏、启动缓慢及新安全软件冲突等工程问题。典型应用场景包括涉密终端批量清退、安全研究环境重建及误装后紧急退出。本文聚焦‘口令绕过+手动清理’双轨方案,覆盖注册表、服务、驱动、文件与计划任务五

weixin_33508411的博客 1073

[OpenCV] EP2_基础图像变换

涵盖内容:图像翻转、仿射变换(旋转/平移/缩放/剪切)、插值方法(最近邻/双线性/区域插值等)、边缘填充(边界复制/反射/常数填充等)、图像校正(透视变换)

Han_WDNMD的博客 2153

滤波器设计实战:Filter Solutions软件从入门到精通

本文是Filter Solutions滤波器设计软件的实战指南,从入门到精通。通过设计一个低通数字滤波器的完整流程,详细讲解了参数设置、FIR/IIR选择、窗函数及逼近函数应用。文章重点介绍了如何利用这款经典工具高效完成滤波器设计、性能权衡,并将设计成果导出至MATLAB等平台进行实际验证与应用,是信号处理工程师提升效率的实用参考。

weixin_29095049的博客 533

Pandas滚动窗口的妙用:动态计算列数据的最大值

Pandas的滚动窗口(rolling window)功能是数据分析中处理时间序列数据的重要工具。本文通过实例演示了如何使用rolling(window=4).max()计算DataFrame列A的滚动最大值,并将结果存入新列Max_Range。该方法会在4个元素的滑动窗口内计算最大值,前3行因数据不足显示为NaN。这种技术广泛应用于金融分析(如股价波动)、数据平滑和趋势识别等场景,能有效帮助分析数据的动态变化特征。示例展示了从数据准备到结果输出的完整流程,体现了Pandas在处理滑动窗口计算时的高效性和便

m0_74337424的博客 53

OpenCv4学习路线的点亮图谱——需要日常打卡

目录 总体分块 任务拆分 安装教学 课时安排 总体分块 OpenCv IO模块-(图像与视频读写) GUI部分-(窗口与显示) 图像处理基础知识 卷积处理相关 二值图像与图像分析 特征提取与对象检测 视频内容分析与跟踪 OpenCv深度神经网络-DNN模块 案例学习与代码分享 任务拆分 1. IO模块 2. 图像读写 3. 视频读写 4. Ma...

weixin_38715903的博客 2067

windows 配置 libxml2

路径:\libiconv-1.9.2-1-src.zip\src\libiconv\1.9.2\libiconv-1.9.2\include\。执行完后,在当前win32目录中会生成了一个bin.msvc目录,其中就有开发需要的libxml2.lib和libxml2.dll文件。将 libiconv.la 复制到 新建的 lib 目录,并将其改名为 iconv.lib。路径:libiconv-1.9.2-1-bin.zip\lib\。将如下的 iconv.h 复制到新建的 include 目录。

SHELLCODE_8BIT的博客 3887

opencv图谱

http://lib.csdn.net/base/opencv/structure

weixin_41634308的博客 219

2020计算机专业保研夏令营面经:中科院计算所网数机试题目

计算所网络数据科学与技术重点实验室的第一阶段是机试。机试不限程序语言,要求提交源代码。

乔卿的博客 2957

EtherCAT主站IGH-- 49 -- 搭建xenomai系统及自己的IGH主站

以上就是搭建xenomai系统及自己的IGH主站的内容。有不明白的地方欢迎留言;有建议欢迎留言,我后面编写文档好改进。创作不容,如果文档对您有帮助,记得给个赞。

常驻客栈的博客--嵌入式EtherCAT 3167

CRNN OCR与知识图谱结合:从文字识别到知识抽取

卷积层(CNN):负责提取输入图像的局部特征,如笔画、边缘、纹理等;循环层(RNN/LSTM):将CNN输出的特征序列按时间步展开,捕捉字符间的上下文依赖关系;转录层(CTC Loss):使用Connectionist Temporal Classification损失函数,解决输入图像与输出字符序列长度不匹配的问题。无需字符分割:直接对整行文本进行识别,避免因粘连、模糊导致的切分错误;上下文感知能力强:LSTM能记住前序字符信息,有效纠正单字误识(例如“口”与“日”);对中文支持更优。

weixin_42601134的博客 855

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

重新定义视觉智能:探索计算机视觉知识图谱的无限可能

当我们谈论人工智能的未来时,计算机视觉无疑是最具变革性的领域之一。从自动驾驶汽车到医学影像分析,从增强现实到智能监控,计算机视觉正在重新定义机器感知世界的方式。在这个快速发展的领域中,一个精心策划的资源集合显得尤为重要——这就是我们今天要探索的计算机视觉知识图谱项目。 **计算机视觉知识图谱**不仅仅是简单的资源列表,它是一个动态的生态系统,汇集了学术界和工业界最前沿的研究成果。这个项目为开发者

gitblog_00041的博客 356

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

计算机视觉知识图谱:构建你的AI视觉技能树 [特殊字符]

在人工智能浪潮席卷全球的今天,计算机视觉作为AI的"眼睛"正以前所未有的速度重塑我们的世界。从自动驾驶汽车到医学影像诊断,从智能安防到增强现实,计算机视觉技术正在悄然改变着我们的生活和工作方式。然而,面对这个快速发展的领域,如何系统性地掌握核心知识、找到优质学习资源、了解前沿研究方向,成为每个技术爱好者和从业者面临的共同挑战。本文将带你探索计算机视觉的完整知识体系,为你构建一条清晰的学习路径。

gitblog_00243的博客 345

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

知识图谱在图像与视频处理领域的应用

1.背景介绍 图像和视频处理是计算机视觉领域的重要研究方向,它们在人工智能、机器学习、计算机图形等领域有着广泛的应用。知识图谱(Knowledge Graph,KG)是一种以实体和关系为基础的信息组织和表示方式,它可以帮助计算机理解和处理自然语言文本,从而提高自然语言处理(NLP)和计算机视觉的性能。在图像和视频处理领域,知识图谱的应用具有很高的潜力和价值。本文将从以下几个方面进行阐述: 背...

AI天才研究院 1629

OpenCV基础数据结构

导读: OpenCV基础数据结构图谱图像数据结构 IPL 图像: IplImage         |-- int nChannels; // 色彩通道数(1,2,3,4)         |-- int depth; // 象素色深:         | // IPL_DEPTH_8U, IPL_DEPTH_8S,         | // IPL_DEPTH_16U,IPL_DEP

winnie的专栏 1100
上一篇: 【opencv高级教程】1.4 像素级访问与遍历策略
下一篇: 【雷达信号处理前沿:从通感算一体化到生成式智能】59.1 傅里叶神经算子(FNO)原理:从函数空间学习雷达回波映射
VectorShift
博客等级 码龄1年 1840粉丝 1109原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

VectorShift

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值