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 类和函数都放在命名空间中。因此,若要从代码访问此功能,请使用说明符cvcv::或指令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<>cv::saturate_cast<>时,很难将接口和实现分开。这对于基本算法来说可能很好,但对于计算机视觉库来说却不好,因为单个算法可能跨越数千行代码。正因为如此,也为了简化其他语言(如 Python、Java、Matlab)的绑定开发,这些语言根本没有模板或模板功能有限,当前的 OpenCV 实现基于多态性和模板上的运行时调度。在那些运行时调度速度太慢(如像素访问运算符)、不可能(通用实现)或非常不方便()的地方,当前的实现引入了小模板类、方法和函数。在当前 OpenCV 版本中的其他任何地方,模板的使用都是有限的。

因此,库可以操作的一组固定的原始数据类型有限。也就是说,数组元素应具有以下类型之一:

  • 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::Matstd::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   ​编辑

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/764788.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

vCenter 6.5为虚拟机添加GPU直通

参考&#xff1a;Dell文档 如何为GPU直通启用VMware虚拟机。 | Dell 中国

lvs+keepalived+nginx实现高可用

主机&#xff1a;192.168.199.132 备机&#xff1a;192.168.199.133 真实服务器1&#xff1a;192.168.199.134 真实服务器2&#xff1a;192.168.199.135 问题&#xff1a; 防火墙没关 132配置ipvsadm进行dr模式 132配置keepalived.conf 133配置ipvsadm进行dr模式 133配置ke…

手机网页关键词视频爬虫采集软件可导出视频分享链接|视频无水印批量下载工具

全新音视频批量下载工具&#xff0c;为您解放视频管理烦恼&#xff01; 现如今&#xff0c;音上涌现出大量精彩的视频内容&#xff0c;但是要想高效地获取、管理和分享这些视频却是一件颇具挑战的事情。针对这一难题&#xff0c;我们自主研发了全新的音视频批量下载工具&#x…

CISP 4.2备考之《安全支撑技术》知识点总结

文章目录 第一节 密码技术第二节 标识和身份鉴别技术第三节 访问控制技术 第一节 密码技术 密码学发展阶段&#xff1a;古典、近代、现代和公钥密码学及特点。 密码系统组成&#xff1a;明文、加密、密钥、解密、密文。 柯克霍夫原则&#xff1a;密钥保密&#xff0c;算法公开…

文章解读与仿真程序复现思路——中国电机工程学报EI\CSCD\北大核心《基于合作博弈与矩阵半张量积的多园区综合能源系统协同优化运行方法》

本专栏栏目提供文章与程序复现思路&#xff0c;具体已有的论文与论文源程序可翻阅本博主免费的专栏栏目《论文与完整程序》 论文与完整源程序_电网论文源程序的博客-CSDN博客https://blog.csdn.net/liang674027206/category_12531414.html 电网论文源程序-CSDN博客电网论文源…

Day42:WEB攻防-PHP应用MYSQL架构SQL注入跨库查询文件读写权限操作

目录 PHP-MYSQL-Web组成架构 PHP-MYSQL-SQL常规查询 手工注入 PHP-MYSQL-SQL跨库查询 跨库注入 PHP-MYSQL-SQL文件读写 知识点&#xff1a; 1、PHP-MYSQL-SQL注入-常规查询 2、PHP-MYSQL-SQL注入-跨库查询 3、PHP-MYSQL-SQL注入-文件读写 MYSQL注入&#xff1a;&#xff…

什么是PLC物联网关?PLC物联网关有哪些功能?

在数字化浪潮的推动下&#xff0c;工业物联网&#xff08;IIoT&#xff09;正逐步成为推动制造业智能化转型的关键力量。而在这一变革中&#xff0c;PLC物联网关扮演着至关重要的角色。今天&#xff0c;就让我们一起走进PLC物联网关的世界&#xff0c;了解它的定义、功能&#…

计算机组成原理 例题集

补码的规格化表示是小数点后一位与符号位不同&#xff1a;数符为0,这个数就是正数,正数补码就是其本身,其最高有效位(阶码使用标准移码的话规格化后尾数最高有效位就是小数点后第一位)必定为1,数符0和最高有效位的1相异.数符为1,这个数就是个负数,求负数的补码有一步叫按位取反…

在服务器(Ubuntu20.04)安装用户级别的cuda11.8(以及仿照前面教程安装cuda11.3后安装cudnn和pytorch1.9.0)

1、cuda11.8的下载 首先在cuda官网下载我们需要的cuda版本&#xff0c;这里我下载的是cuda11.8&#xff08;我的最高支持cuda12.0&#xff09; 这里我直接使用wget命令下载不了&#xff0c;于是我直接在浏览器输入后面的链接下载到本地&#xff0c;之后再上传至服务器的&am…

Springboot+vue的四川美食分享网站+数据库+报告+免费远程调试

项目介绍: Springbootvue的四川美食分享网站。Javaee项目&#xff0c;springboot vue前后端分离项目 本文设计了一个基于Springbootvue的前后端分离的四川美食分享网站&#xff0c;采用M&#xff08;model&#xff09;V&#xff08;view&#xff09;C&#xff08;controller&am…

python网络相册设计与实现flask-django-nodejs-php

此系统设计主要采用的是python语言来进行开发&#xff0c;采用django框架技术&#xff0c;框架分为三层&#xff0c;分别是控制层Controller&#xff0c;业务处理层Service&#xff0c;持久层dao&#xff0c;能够采用多层次管理开发&#xff0c;对于各个模块设计制作有一定的安…

【Java基础】了解Java安全体系JCA,使用BouncyCastle的ED25519算法生成密钥对、数据签名

文章目录 一.Java安全体系结构二.JCA和JCE三.CSP(加密服务提供程序)与Engine类1.CSP2.Engine类如何使用引擎类 四.查看当前JDK支持的算法服务提供商(Provider)五.BouncyCastle是什么六.如何使用BouncyCastle&#xff1f;七.bouncycastle实现ED25519工具类 一.Java安全体系结构 …

python文学名著分享系统的设计与实现flask-django-nodejs-php

在此基础上&#xff0c;结合现有文学名著分享体系的特点&#xff0c;运用新技术&#xff0c;构建了以python为基础的文学名著分享信息化管理体系。首先&#xff0c;以需求为依据&#xff0c;根据需求分析结果进行了系统的设计&#xff0c;并将其划分为管理员和用户二种角色和多…

NIVision-相机图像采集

应用场景 上位机与工业相机通讯&#xff0c;控制相机抓取图像。 工业相机的通讯接口大多为USB口或网口。 USB口则直接将通讯线缆插入上位机USB端口&#xff0c;打开MAX中设备与接口一栏可以看到电脑给相机分配的资源名称&#xff1b;网口则需要将网线连接相机和上位机&#xf…

(附源码)基于Spring Boot + Vue 在线网课学习系统的设计与实现

前言 &#x1f497;博主介绍&#xff1a;✌专注于Java、小程序技术领域和毕业项目实战✌&#x1f497; &#x1f447;&#x1f3fb; 精彩专栏 推荐订阅&#x1f447;&#x1f3fb; 2024年Java精品实战案例《100套》 &#x1f345;文末获取源码联系&#x1f345; &#x1f31…

Llama 2 模型

非常清楚&#xff01;&#xff01;&#xff01;Llama 2详解 - 知乎 (zhihu.com)https://zhuanlan.zhihu.com/p/649756898?utm_campaignshareopn&utm_mediumsocial&utm_psn1754103877518098432&utm_sourcewechat_session一些补充理解&#xff1a; 序列化&#xff…

使用阿里CICD流水线打包Java项目到阿里的docker镜像私仓,并自动部署到服务器启动服务

文章目录 使用阿里CICD流水线打包Java项目到阿里的docker镜像私仓&#xff0c;并自动部署到服务器启动服务1、功能原理实现2、将自己的Java项目通过Git上传到阿里的代码仓库中&#xff0c;也可以通过绑定Gitee或者GitHub账号进行导入3、创建自己的阿里云镜像私仓3、进入阿里的C…

【3DsMax】展UV记录

目录 一、概念 二、边的颜色 三、UV的连续性 四、合理的划分UV接缝 五、总结 一、概念 展uv的概念可以理解为把三维的模型铺平展成一个平面&#xff0c;然后在这个平面上去绘制图案。 二、边的颜色 我们先创建一个长方体&#xff0c;然后在修改器列表中添加“UVW展开”…

数据透视进阶:切片器关联与二次计算

切片器 右键切片器--选择报表连接 将想要连接的表关联在切片器 二次计算

工具类|将Entity对象转为Vo/Bo对象,并指定字段绑定

工具类|将Entity对象转为Vo/Bo对象&#xff0c;并指定字段绑定 实体类&#xff1a;People和Student,Student的三个字段和People意义一样&#xff0c;但是字段名不完全一样&#xff0c;要实现对象拷贝可使用如下工具类&#xff0c;用到了反射。 People.java Data AllArgsConst…