OpenCV 介绍使用
返回:OpenCV系列文章目录(持续更新中......)
上一篇:OpenCV4.9.0开源计算机视觉库使用简要说明
下一篇:
OpenCV(开源计算机视觉库:http://opencv.org)是一个开源库,包含数百种计算机视觉算法。该文档描述了所谓的OpenCV 2.x API,它本质上是一个C++ API,而不是基于C的OpenCV 1.x API(自OpenCV 2.4发布以来,C API已被弃用,并且没有使用“C”编译器进行测试)
OpenCV 具有模块化结构,这意味着该包包含多个共享或静态库。提供以下模块:
- 核心功能(core) - 定义基本数据结构的紧凑模块,包括密集的多维数组 Mat 和所有其他模块使用的基本功能。
- 图像处理 (imgproc) - 一个图像处理模块,包括线性和非线性图像过滤、几何图像变换(调整大小、仿射和透视变形、基于表格的通用重映射)、色彩空间转换、直方图等。
- 视频分析(视频) - 一个视频分析模块,包括运动估计、背景减法和对象跟踪算法。
- 相机校准和 3D 重建 (calib3d) - 基本的多视图几何算法、单视图和立体相机校准、物体姿态估计、立体对应算法和 3D 重建元素。
- 2D 特征框架 (features2d) - 显著特征检测器、描述符和描述符匹配器。
- 对象检测 (objdetect) - 检测对象和预定义类的实例(例如,人脸、眼睛、杯子、人、汽车等)。
- 高级 GUI (highgui) - 简单 UI 功能的易于使用的界面。
- 视频 I/O (videoio) - 一个易于使用的视频捕获和视频编解码器界面。
- ...其他一些帮助程序模块,例如 FLANN 和 Google 测试包装器、Python 绑定等。
本文档的后续章节描述了每个模块的功能。但首先,请确保熟悉库中彻底使用的常见 API 概念。
API 概念
cv 命名空间
有 OpenCV 类和函数都放在命名空间中。因此,若要从代码访问此功能,请使用说明符cv
cv::
或指令using namespace cv
:
#include "opencv2/core.hpp"...
cv::Mat H = cv::findHomography(points1, points2, cv::RANSAC, 5);
...
或
#include "opencv2/core.hpp"
using namespace cv;...
Mat H = findHomography(points1, points2, RANSAC, 5 );
...
自动内存管理
OpenCV 会自动处理所有内存。
首先,std::vector、cv::Mat 以及函数和方法使用的其他数据结构具有在需要时释放底层内存缓冲区的析构函数。这意味着析构函数并不总是像 Mat 那样取消分配缓冲区。它们考虑了可能的数据共享。析构函数递减与矩阵数据缓冲区关联的引用计数器。当且仅当引用计数器达到零时,即当没有其他结构引用同一缓冲区时,缓冲区才会被释放。同样,当复制 Mat 实例时,不会真正复制任何实际数据。相反,引用计数器是递增的,以记住同一数据的另一个所有者。还有 cv::Mat::clone 方法,用于创建矩阵数据的完整副本。请参阅以下示例:
// 创建一个8Mb大图片矩阵
Mat A(1000, 1000, CV_64F);
// 为同一矩阵创建另一个句柄;
// 无论矩阵大小如何,这都是即时操作
Mat B = A;
//为A的第3行创建另一个句柄;也不会复制任何数据
Mat C = B.row(3);
//现在创建一个独立的矩阵副本
Mat D = B.clone();
// 将B的第5行复制到C,即复制A的第5行
// 到 A 的第 3 行。
B.row(5).copyTo(C);
// 现在让 A 和 D 共享数据;之后是修改后的版本
//尽管C只是原始A的一行
A = D;
//现在使B成为一个空矩阵(它不引用内存缓冲区),
// 但A的修改版本仍将被C引用,
// 最后,制作C的完整副本。结果,大修改了
B.release();
//最后,制作C的完整副本。结果,大修改了
//矩阵将被解除分配,因为它不会被任何人引用
C = C.clone();
你可以看到,垫子和其他基本结构的使用很简单。但是,在不考虑自动内存管理的情况下创建的高级类甚至用户数据类型呢?对于他们来说,OpenCV 提供了类似于 C++11 中的 std::shared_ptr 的 cv::P tr 模板类。因此,不要使用普通指针:
T* ptr = new T(...);
您可以使用:
Ptr<T> ptr(new T(...));
或:
Ptr<T> ptr = makePtr<T>(...);
Ptr<T>
封装指向 T 实例的指针和与指针关联的引用计数器。有关详细信息,请参阅 cv::P tr 描述。
自动分配输出数据
OpenCV 会自动释放内存,并且大多数时候会自动为输出函数参数分配内存。因此,如果函数有一个或多个输入数组(cv::Mat 实例)和一些输出数组,则输出数组将自动分配或重新分配。输出数组的大小和类型由输入数组的大小和类型决定。如果需要,这些函数会采用额外的参数来帮助确定输出数组属性。
如下列:
#include "opencv2/imgproc.hpp"
#include "opencv2/highgui.hpp"
using namespace cv;
int main(int, char**)
{
VideoCapture cap(0);
if(!cap.isOpened()) return -1;
Mat frame, edges;
namedWindow("edges", WINDOW_AUTOSIZE);
for(;;)
{
cap >> frame;
cvtColor(frame, edges, COLOR_BGR2GRAY);
GaussianBlur(edges, edges, Size(7,7), 1.5, 1.5);
Canny(edges, edges, 0, 30, 3);
imshow("edges", edges);
if(waitKey(30) >= 0) break;
}
return 0;
}
由于视频帧分辨率和位深度对视频捕获模块是已知的,因此阵列帧由操作员自动分配。阵列边缘由 cvtColor 函数自动分配。它与输入数组具有相同的大小和位深度。通道数为 1,因为传递了颜色转换代码 cv::COLOR_BGR2GRAY,这意味着颜色到灰度的转换。请注意,在循环体的第一次执行期间,帧和边缘只分配一次,因为所有下一个视频帧都具有相同的分辨率。如果以某种方式更改视频分辨率,则会自动重新分配阵列。>>
该技术的关键组件是 cv::Mat::create 方法。它采用所需的数组大小和类型。如果数组已具有指定的大小和类型,则该方法不执行任何操作。否则,它会释放以前分配的数据(如果有)(这部分涉及递减引用计数器并将其与零进行比较),然后分配所需大小的新缓冲区。大多数函数为每个输出数组调用 cv::Mat::create 方法,因此实现了自动输出数据分配。
此方案的一些值得注意的例外是 cv::mixChannels、cv::RNG::fill 以及其他一些函数和方法。他们无法分配输出数组,因此您必须提前执行此操作。
饱和算术
作为一个计算机视觉库,OpenCV 处理了很多图像像素,这些像素通常以紧凑的每通道 8 位或 16 位形式编码,因此具有有限的值范围。此外,对图像的某些操作(如色彩空间转换、亮度/对比度调整、锐化、复杂插值(双立方、Lanczos))可能会产生超出可用范围的值。如果仅存储结果的最低 8 (16) 位,则会导致视觉伪影,并可能影响进一步的图像分析。为了解决这个问题,使用了所谓的饱和算术。例如,要将操作结果 r 存储到 8 位图像中,请在 0..255 范围内找到最接近的值:
I(x,y)=min(max(round(r),0),255)
类似的规则也适用于 8 位有符号类型、16 位有符号类型和无符号类型。此cv::saturate_cast<>语义在库中随处可见。在 C++ 代码中,它是使用类似于标准 C++ 强制转换操作的函数完成的。请参阅下面提供的公式的实现
I.at<uchar>(y, x) = saturate_cast<uchar>(r);
其中 cv::uchar 是 OpenCV 8 位无符号整数类型。在优化的SIMD代码中,使用了paddusb、packuswb等SSE2指令。它们有助于实现与 C++ 代码中完全相同的行为。
注意
当结果为 32 位整数时,不应用饱和度。
固定像素类型。模板的使用有限
模板是 C++ 的一项重要功能,它支持实现非常强大、高效且安全的数据结构和算法。但是,模板的广泛使用可能会大大增加编译时间和代码大小。此外,当专门使用模板
cv::Ptr
<>
时,很难将接口和实现分开。这对于基本算法来说可能很好,但对于计算机视觉库来说却不好,因为单个算法可能跨越数千行代码。正因为如此,也为了简化其他语言(如 Python、Java、Matlab)的绑定开发,这些语言根本没有模板或模板功能有限,当前的 OpenCV 实现基于多态性和模板上的运行时调度。在那些运行时调度速度太慢(如像素访问运算符)、不可能(通用实现)或非常不方便()的地方,当前的实现引入了小模板类、方法和函数。在当前 OpenCV 版本中的其他任何地方,模板的使用都是有限的。cv::saturate_cast
<>
因此,库可以操作的一组固定的原始数据类型有限。也就是说,数组元素应具有以下类型之一:
- 8-bit unsigned integer (uchar)
- 8-bit signed integer (schar)
- 16-bit unsigned integer (ushort)
- 16-bit signed integer (short)
- 32-bit signed integer (int)
- 32-bit floating-point number (float)
- 64-bit floating-point number (double)
- 多个元素的元组,其中所有元素都具有相同的类型(上述元素之一)。元素为此类元组的数组称为多通道数组,与单通道数组相反,单通道数组的元素为标量值。最大可能的通道数由 CV_CN_MAX 常量定义,该常量当前设置为 512。
对于这些基本类型,将应用以下枚举:
enum { CV_8U=0, CV_8S=1, CV_16U=2, CV_16S=3, CV_32S=4, CV_32F=5, CV_64F=6 };
可以使用以下选项指定多通道(n-channel)类型:
- CV_8UC1 ... CV_64FC4 常量(对于从1到4的多个通道)
- CV_8UC(n) ... CV_64FC(n) or CV_MAKETYPE(CV_8U, n) ... CV_MAKETYPE(CV_64F, n)宏,当通道数超过 4 个或编译时未知
注意:
CV_32FC1 == CV_32F, CV_32FC2 == CV_32FC(2) == CV_MAKETYPE(CV_32F, 2)
, and CV_MAKETYPE(depth, n) == ((depth&7) + ((n-1)<<3)
. 这意味着常量类型是由深度(取最低 3 位)和通道数减去 1(取下一位)形成的 log2(CV_CN_MAX)
bits.
例子:
Mat mtx(3, 3, CV_32F); // make a 3x3 floating-point matrix
Mat cmtx(10, 1, CV_64FC2); // make a 10x1 2-channel floating-point
// matrix (10-element complex vector)
Mat img(Size(1920, 1080), CV_8UC3); // make a 3-channel (color) image
// of 1920 columns and 1080 rows.
Mat grayscale(img.size(), CV_MAKETYPE(img.depth(), 1)); // make a 1-channel image of
// the same size and same
// channel type as img
具有更复杂元素的数组不能使用 OpenCV 构建或处理。此外,每个函数或方法只能处理所有可能的数组类型的子集。通常,算法越复杂,支持的格式子集就越小。请参阅以下此类限制的典型示例:
- 人脸检测算法仅适用于 8 位灰度或彩色图像。
- 线性代数函数和大多数机器学习算法仅适用于浮点数组。
- 基本函数,如cv::add,支持所有类型。
- 色彩空间转换函数支持 8 位无符号、16 位无符号和 32 位浮点类型。
每个函数支持的类型子集都是根据实际需求定义的,将来可以根据用户请求进行扩展。
输入数组和输出数组
许多 OpenCV 函数处理密集的二维或多维数值数组。通常,此类函数cv::Mat
用作参数,但在某些情况下,std::vector<>使用起来更方便(例如,对于点集)或cv::Matx<>(用于 3x3 单调矩阵等)。为了避免 API 中出现许多重复项,引入了特殊的“代理”类。基“代理”类是 cv::InputArray。它用于在函数输入上传递只读数组。派生自 InputArray 类 cv::OutputArray 用于指定函数的输出数组。通常,你不应该关心那些中间类型(你不应该显式声明这些类型的变量)——它们都会自动工作。您可以假定始终可以使用 cv::Mat
, std::vector<>
, cv::Matx<>
, cv::Vec<>
或 cv::Scalar
. 来代替 InputArray/OutputArray。当函数具有可选的输入或输出数组,而您没有或不需要输入或输出数组时,请传递 cv::noArray().
错误处理
OpenCV 使用异常来发出严重错误的信号。当输入数据格式正确且属于指定值范围,但算法由于某种原因无法成功(例如,优化算法未收敛)时,它会返回一个特殊的错误代码(通常只是一个布尔变量)。
异常可以是 cv::Exception 类或其派生的实例。反过来,cv::Exception 是 的派生词。因此,可以使用其他标准 C++ 库组件在代码中优雅地处理它。std::exception
通常使用宏CV_Error(errcode, description)
或其类似 printf 的 CV_Error_(errcode, (printf-spec, printf-args))
变体引发异常,或者使用 CV_Assert(condition) 宏来检查条件并在不满足异常时引发异常。对于性能关键代码,有 CV_DbgAssert(condition) 仅保留在调试配置中。由于自动内存管理,所有中间缓冲区都会在突然发生错误时自动释放。如果需要,只需添加 try 语句即可捕获异常:
try
{
... // call OpenCV
}
catch (const cv::Exception& e)
{
const char* err_msg = e.what();
std::cout << "exception caught: " << err_msg << std::endl;
}
多线程和可再输入性
当前的 OpenCV 实现是完全可重新输入的。也就是说,可以从不同的线程调用不同类实例的相同函数或相同方法。此外,相同的 Mat 可以在不同的线程中使用,因为引用计数操作使用特定于体系结构的原子指令。
参考文献:
1、《Introduction》 --Generated on Wed Dec 27 2023 21:56:11 for OpenCV by 编辑
相关文章:

OpenCV 介绍使用
返回:OpenCV系列文章目录(持续更新中......) 上一篇:OpenCV4.9.0开源计算机视觉库使用简要说明 下一篇: OpenCV(开源计算机视觉库:http://opencv.org)是一个开源库,包含数百种计算机视觉算法。…...
Python 10个面试题实例
当然!以下是10个Python面试题及其示例解决方案的中题目: 1.反转字符串: string "Hello, World!" reversed_string string[::-1] print(reversed_string)2.检查字符串是否为回文: def is_palindrome(string):return string string[::-1]r…...

Python:熟悉简单的skfuzzy构建接近生活事件的模糊控制器”(附带详细注释说明)+ 测试结果
参考资料:https: // blog.csdn.net / shelgi / article / details / 126908418 ————通过下面这个例子,终于能理解一点模糊理论的应用了,感谢原作。 熟悉简单的skfuzzy构建接近生活事件的模糊控制器 假设下面这样的场景, 我们希望构建一套…...

opencv函数使用查找
opencv官方文档地址:https://docs.opencv.org/4.x/index.html 先选对应的版本opencv-python 以这个函数为例子 model cv2.face.LBPHFaceRecognizer.create() 点开后找face类的LBP里面就有create函数的用法...
使用 pypdf 快速切分 PDF 文件
categories: [Python] tags: Python MacOS 写在前面 最近有小伙伴问我怎么把 PDF 文档切分成两个大小相近的 PDF文档, 要是在 mac 上, 直接无脑预览就行了, 但是这样不够跨平台, 之后我也尝试过 pymupdf, 但是奈何不支持 arm 架构, 后来还是用 Python 原生的 pypdf 了. 有 AI…...

Avalonia(11.0.2)+.NET6 打包运行到银河麒麟V10桌面系统
操作系统配置 项目结构 .net版本 这次我们是在银河麒麟V10系统上打包运行Avalonia(11.0.2)+.NET6.0的程序 开始打包 准备Linux下的桌面快捷方式以及图标 调整AvaloniaApplication2.Desktop.csproj的配置项,重点看下图红色线圈出来的部分,里面涉及到了LinuxPath的设置。完整的配…...

Mac nvm install failed python: not found
报错 $>./configure --prefix/Users/xxx/.nvm/versions/node/v12.22.12 < ./configure: line 3: exec: python: not found nvm: install v12.22.12 failed!解决方法 到 App 文件夹,并且打开 cd /System/Applications/Utilities/ open .记得改完 Rosetta 之…...

C语言基础知识复习(考研)
(1)C语言文件操作 1 什么是文件 文件有不同的类型,在程序设计中,主要用到两种文件: (1)程序文件。包括源程序文件(后缀为.c)、目标文件(后缀为.obj)、可执行这种文件的内容是程序代码。 (2)数据文件。文件的内容不是…...

Prometheus Grafana 配置仪表板
#grafana# 其实grafana提供了丰富的Prometheus数据源的仪表板,基本上主流的都有,通过下面官方地址可查阅 Dashboards | Grafana Labs 这里举例说明,配置node_exporter仪表板 首先,在上面的网站搜索 node 可以查到蛮多的仪表板…...

docker 哲学 - 网络桥接器、容器网络接口 、容器间的通信方式
1、解释 docker0 veth eth 2、vethXX 和 ethXX 是肯定一一对应吗 比如 eth1 对应 veth1 3、如果 A容器使用 默认创建方式 。定义他内部网络为 eth0,容器B使用 --network 连上 已创建的网络 172.89.2.1 。此时假设 B的 ip是 172.89.2.2 ,容器网络接口是 e…...

Python 将HTML转为PDF、图片、XML、XPS格式
网页内容是信息传播的主要形式之一。在Web开发中,有时候我们需要将HTML文件以不同的格式保存或分享,比如PDF、图片(如PNG或JPEG)、XML或XPS等。这些格式各有优势,适合不同的用途。在这篇文章中,我们将介绍如…...

排序算法记录(冒泡+快排+归并)
文章目录 前言冒泡排序快速排序归并排序 前言 冒泡 快排 归并,这三种排序算法太过经典,但又很容易忘了。虽然一开始接触雀氏这些算法雀氏有些头大,但时间长了也还好。主要是回忆这些算法干了啥很耗时间。 如果在笔试时要写一个o(nlogn)的…...

简单聊聊如何更优雅地初始化对象:构造函数、Builder模式和静态工厂方法比较
大家好,我是G探险者。 在平时的java编程中,你肯定会有过对一些实体对象进行初始化的set操作,有的对象的属性较少可能还好点,当一个对象拥有许多属性时,通常的初始化方式可能显得笨拙而不直观,代码写的很不…...

跳过mysql权限验证来修改密码-GPT纯享版
建议重新配置一遍,弄成功好多次了,每次都出bug,又要重新弄,不是过期就是又登不进去了,我服了 电脑配置MySQL环境(详细)这个哥们的10min配完,轻轻松松, 旧方法ÿ…...

Vue3快速上手(十七)Vue3之状态管理Pinia
一、简介 Pinia官网:https://pinia.vuejs.org/zh/ 从官网截图里可以直接看到,pinia是一个vuejs的状态(数据)管理工具。功能性同vuex。logo是小菠萝。它是一个集中式状态管理工具。就是将多个组件共用的数据管理起来,重复利用。有点类似缓存的意思。 二、Pinia环境搭建 …...

时序预测 | Matlab实现BiTCN-GRU双向时间卷积神经网络结合门控循环单元时间序列预测
时序预测 | Matlab实现BiTCN-GRU双向时间卷积神经网络结合门控循环单元时间序列预测 目录 时序预测 | Matlab实现BiTCN-GRU双向时间卷积神经网络结合门控循环单元时间序列预测预测效果基本介绍程序设计参考资料 预测效果 基本介绍 1.Matlab实现BiTCN-GRU双向时间卷积神经网络结…...

学习笔记Day14:Linux下软件安装
软件安装 Anaconda 所有语言的包(package)、依赖(dependency)和环境(environment)管理器,类似应用商店 Conda < Miniconda < Anaconda(有交互界面) Linux下Miniconda即可 安装Miniconda 搜索北外/清华miniconda镜像网站ÿ…...

【CXL协议-事务层之CXL.io(3)】
3.1 CXL.io CXL.io 为 I/O 设备提供非一致的加载/存储接口。 图 14 显示了 CXL.io 事务层在 Flex Bus 分层结构中的位置。 交易类型、交易数据包格式、基于信用的流量控制、虚拟通道管理和交易排序规则遵循PCIe定义; 请参阅 有关详细信息,请参阅 PCI Ex…...

如何自己构建 Ollama 模型
如何自己构建 Ollama 模型 0. 引言1. 下载原始模型2. 创建 Modelfile 文件3. 构建 Ollama 模型4. 运行自构建的 Ollama 模型 0. 引言 针对模型新出的大模型,可能 Ollama Models Library 不提供,或者会在今后的某个时点提供。还有可能 Ollama Models Lib…...
5.84 BCC工具之tcpretrans.py解读
一,工具简介 tcpretrans工具追踪内核TCP重传函数,以显示这些重传的详细信息。 它专门用于追踪TCP重传事件。在网络通信中,重传是由于数据包丢失、损坏或延迟到达而需要重新发送的情况。tcpretrans通过利用Linux内核中的BPF(Berkeley Packet Filter)机制,能够实时捕获和…...
conda相比python好处
Conda 作为 Python 的环境和包管理工具,相比原生 Python 生态(如 pip 虚拟环境)有许多独特优势,尤其在多项目管理、依赖处理和跨平台兼容性等方面表现更优。以下是 Conda 的核心好处: 一、一站式环境管理:…...

stm32G473的flash模式是单bank还是双bank?
今天突然有人stm32G473的flash模式是单bank还是双bank?由于时间太久,我真忘记了。搜搜发现,还真有人和我一样。见下面的链接:https://shequ.stmicroelectronics.cn/forum.php?modviewthread&tid644563 根据STM32G4系列参考手…...

抖音增长新引擎:品融电商,一站式全案代运营领跑者
抖音增长新引擎:品融电商,一站式全案代运营领跑者 在抖音这个日活超7亿的流量汪洋中,品牌如何破浪前行?自建团队成本高、效果难控;碎片化运营又难成合力——这正是许多企业面临的增长困局。品融电商以「抖音全案代运营…...

2.Vue编写一个app
1.src中重要的组成 1.1main.ts // 引入createApp用于创建应用 import { createApp } from "vue"; // 引用App根组件 import App from ./App.vue;createApp(App).mount(#app)1.2 App.vue 其中要写三种标签 <template> <!--html--> </template>…...

CVE-2020-17519源码分析与漏洞复现(Flink 任意文件读取)
漏洞概览 漏洞名称:Apache Flink REST API 任意文件读取漏洞CVE编号:CVE-2020-17519CVSS评分:7.5影响版本:Apache Flink 1.11.0、1.11.1、1.11.2修复版本:≥ 1.11.3 或 ≥ 1.12.0漏洞类型:路径遍历&#x…...
MySQL 部分重点知识篇
一、数据库对象 1. 主键 定义 :主键是用于唯一标识表中每一行记录的字段或字段组合。它具有唯一性和非空性特点。 作用 :确保数据的完整性,便于数据的查询和管理。 示例 :在学生信息表中,学号可以作为主键ÿ…...

【LeetCode】算法详解#6 ---除自身以外数组的乘积
1.题目介绍 给定一个整数数组 nums,返回 数组 answer ,其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。 题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。 请 不要使用除法,且在 O…...

【Post-process】【VBA】ETABS VBA FrameObj.GetNameList and write to EXCEL
ETABS API实战:导出框架元素数据到Excel 在结构工程师的日常工作中,经常需要从ETABS模型中提取框架元素信息进行后续分析。手动复制粘贴不仅耗时,还容易出错。今天我们来用简单的VBA代码实现自动化导出。 🎯 我们要实现什么? 一键点击,就能将ETABS中所有框架元素的基…...
在鸿蒙HarmonyOS 5中使用DevEco Studio实现指南针功能
指南针功能是许多位置服务应用的基础功能之一。下面我将详细介绍如何在HarmonyOS 5中使用DevEco Studio实现指南针功能。 1. 开发环境准备 确保已安装DevEco Studio 3.1或更高版本确保项目使用的是HarmonyOS 5.0 SDK在项目的module.json5中配置必要的权限 2. 权限配置 在mo…...
怎么开发一个网络协议模块(C语言框架)之(六) ——通用对象池总结(核心)
+---------------------------+ | operEntryTbl[] | ← 操作对象池 (对象数组) +---------------------------+ | 0 | 1 | 2 | ... | N-1 | +---------------------------+↓ 初始化时全部加入 +------------------------+ +-------------------------+ | …...