OpenCV简介

OpenCV简介

OpenCV(开源计算机视觉库:http://opencv.org)是一个开源库,包含数百种计算机视觉算法。OpenCV 具有模块化结构,主要包括下列模块:

  • 核心功能(core) - 定义基本数据结构的紧凑模块,包括密集多维数组 Mat 和所有其他模块使用的基本函数。
  • 图像处理( imgproc) - 图像处理模块,包括线性和非线性图像过滤、几何图像变换(调整大小、仿射和透视变形、基于通用表的重新映射)、颜色空间转换、直方图等。
  • 视频分析( video ) - 视频分析模块,包括运动估计、背景扣除和对象跟踪算法。
  • 相机校准和 3D 重建( calib3d ) -基本多视图几何算法、单立体相机校准、物体姿态估计、立体对应算法和 3D 重建元素。
  • 2D 特征框架( features2d ) -显着特征检测器、描述符和描述符匹配器。
  • 对象检测( objdetect ) -检测预定义类的对象和实例(例如,面部、眼睛、杯子、人、汽车等)。
  • 高级 GUI ( highgui ) - 一个易于使用的界面,具有简单的UI 功能。
  • 视频 I/O ( videoio ) - 一个易于使用的视频捕获和视频编解码器接口。
  • …一些其他帮助模块,例如 FLANN 和 Google 测试包装器、Python 绑定等。

当前的 OpenCV 实现是完全可重新输入的。也就是说,不同类实例的相同函数或相同方法可以从不同线程调用。此外,相同的 Mat 可以在不同的线程中使用,因为引用计数操作使用特定于体系结构的原子指令

API概念

命名空间

opencv 的所有类和函数都存放在 cv 命名空间中。因此,要引用 opencv 的代码,需要增加作用域运算符 cv::,在项目开发中,建议不用使用 using namespace cv 定义作用域范围,可能会引起某些的冲突。jpg是一个有损压缩算法,在平时使用时尽量避免使用。

自动内存管理

OpenCV的内存管理机制类似 Shared_ptr, Mat 对象只有当引用计数为 0,其内存空间才会真正得销毁,当一个 Mat 实例被拷贝时,内存并不会真正的发生复制行为,而是将改对象的引用计数增加 1, 可以使用 cv::Mat::clone 进行实际 “全复制”。

// create a big 8Mb matrix
Mat A(1000, 1000, CV_64F);
// create another header for the same matrix;
// this is an instant operation, regardless of the matrix size.
Mat B = A;
// create another header for the 3-rd row of A; no data is copied either
Mat C = B.row(3);
// now create a separate copy of the matrix
Mat D = B.clone();
// copy the 5-th row of B to C, that is, copy the 5-th row of A
// to the 3-rd row of A.
B.row(5).copyTo(C);
// now let A and D share the data; after that the modified version
// of A is still referenced by B and C.
A = D;
// now make B an empty matrix (which references no memory buffers),
// but the modified version of A will still be referenced by C,
// despite that C is just a single row of the original A
B.release();
// finally, make a full copy of C. As a result, the big modified
// matrix will be deallocated, since it is not referenced by anyone
C = C.clone();

对于用户自定义的数据类型,opencv 提供了 cv:Ptr 进行管理,其机制和刚刚的描述一致。

# 普通指针定义
T* ptr = new T(....);# opencv 提供的管理方式
cv::Ptr prt(new T(...));
cv::Ptr ptr = cv::makePtr<T>(...);

Ptr封装了一个 T 实例的指针和该指针引用计数器,更多的细节在 cv::Ptr 。

对输出数据自动分配内存

opencv可以为输出数据类型自动 分配 和 重分配 内存,其 size 和 type 取决于输入数据的 size 和 type。同时,可为输出数据指定额外的参数。

#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;
}

上面的代码通过输出重定向符 >> 自动为 frame 实例分配内存,因为视频的视频的帧分辨率和位深已通过 video capturing module处理并获知。 edges 的内存被函数 cvtColor 函数自动分配,它和输入具有相同的 size 和 bit-depth。通道数经过 cv::COLOR_BGR2GRAY处理并设为1(彩色图变为灰度图)。frame 和 edges 在第一次执行时分配内存并具有相同的帧分辨率,当分辨率改变时,frame 和 edges 的内存会被自动的重新分配。

该技术的关键组件是 cv::Mat::create 方法。如果数组已经具有指定的大小和类型,则该方法不执行任何操作。否则,它释放先前分配的数据(如果有)(这部分涉及递减引用计数器并将其与零进行比较,释放掉无用的内存),然后分配所需大小的新缓冲区。

某些例如的函数需要注意,例如 cv::mixChannels, cv::RNG::fill等,他们不能分配输出数据,我们不得不手动执行。

饱和度算法

这一节主要想介绍OpenCV的存储方式,以及可能产生的错误。因为opencv对像素的存储是以紧凑的、每通道 8 位或 16 位的形式进行编码,值的范围非常有限,对图像的某些处理(如色彩空间转换、亮度/对比度调整、锐化、复杂插值(双三次、Lanczos))很可能产生超出可用范围的值,这样就会产生图像伪影。为了解决这个问题,需要使用饱和度算法。例如,存储变量或计算结果(r)到一个8位图像时,使用下列公式,找到在0-255范围内最接近的值:
f ( x , y ) = m i n ( m a x ( r o u n d ( r ) , 0 ) , 255 ) f(x,y) = min(max(round(r), 0), 255) f(x,y)=min(max(round(r),0),255)
这个函数在opencv的库中已经做了实现:

I.at<uchar>(y,x)=saturate_cast<uchar>(r);

其中,cv::uchar 代表8位无符号整形
在这里插入图片描述
右图出现了视觉伪影

OpenCV的模板使用受限

模板如果广泛使用会增加编译时间和代码大小,单独使用模板也很难将接口和实现分开。对于opencv视觉库来说,如果使用模板可能某个算法会跨越上千行代码。OpenCV实现了基于多态性和模板上的运行时调度,以简化和其他语言的绑定开发。OpenCV在运行时调度太慢的地方(像素访问运算符),在某些不使用模板不能实现(cv:Ptr<>)、或不易于实现的地方(cv::saturate_cast<>)引入了模板类、方法、和函数。

opencv可以操作的数据类型有限。也就是说,数组元素应该具有以下类型之一:

  • 8 位无符号整数 (uchar)
  • 8 位有符号整数 (schar)
  • 16 位无符号整数 (ushort)
  • 16 位有符号整数(短)
  • 32 位有符号整数 (int)
  • 32位浮点数(float)
  • 64 位浮点数(双精度)
  • 由多个元素组成的元组,其中所有元素都具有相同的类型(上述类型之一)。其元素为此类元组的数组称为多通道数组,与元素为标量值的单通道数组相反。最大可能的通道数由CV_CN_MAX常量定义,当前设置为 512。

可以使用以下选项指定多通道(n 通道)类型:

  • CV_8UC1 … CV_64FC4常量(通道数1-4)
  • CV_8UC(n) … CV_64FC(n) or CV_MAKETYPE(CV_8U, n) … CV_MAKETYPE(CV_64F, n) 通道数大于4或未知时的语法

Note:
CV_32FC1 == CV_32F, CV_32FC2 == CV_32FC(2) == CV_MAKETYPE(CV_32F, 2), 和CV_MAKETYPE(depth, n) == ((depth&7) + ((n-1)<<3). 这意味着常量类型由深度(取最低 3 位)和通道数减 1(取接下来的log2(CV_CN_MAX)位)构成。

# 3x3的浮点数单通道矩阵
Mat mat(3,3,CV_32F)# 10x1的浮点数双通道矩阵
Mat cmatx(10,1,CV_64FC2)# 3通道图像
Mat img(Size(1920, 1080), CV_8UC3)#单通道图像,和img的大小、通道数据类型相同
Mat grayscale(img.size(), CV_MAKETYPE(img.depth(), 1));

输入输出数组

在某些情况下,使用std::vector<>(例如,对于点集)或cv::Matx<>(对于 3x3 单应性矩阵等)更方便。为了避免 API 中出现许多重复,引入了特殊的“代理”类。基本“代理”类是cv::InputArray。它用于在函数输入上传递只读数组。派生自InputArray类cv::OutputArray用于指定函数的输出数组。通常,您不应该关心那些中间类型(并且您不应该显式声明这些类型的变量),它都会自动工作。您可以假设您始终可以使用cv::Mat、std::vector<>、cv::Matx<>或来代替 InputArray cv::Vec<>/ OutputArray cv::Scalar。当函数具有可选的输入或输出数组,而您没有或不需要时,请传递cv::noArray()。

InputArray可以接受以下类型的输入数据:

  1. cv::Mat:用于表示图像或矩阵数据。
  2. std::vector:用于表示标准C++ STL容器的数据,如std::vectorcv::Point,std::vectorcv::Vec3f等。
  3. 数组:可以接受指向数据的指针和数据的大小。
  4. cv::InputArrayOfArrays:用于表示多个InputArray的数组,用于处理多通道数据或多个数据块。
  5. cv::cuda::GpuMat:用于表示GPU上的图像或矩阵数据(仅适用于使用OpenCV的CUDA模块)。
void processImage(cv::InputArray input) {cv::Mat image = input.getMat(); // 获取输入图像的Mat对象// 进行图像处理操作
}

在调用processImage函数时,可以传递图像、矩阵或其他支持的数据类型作为参数,OpenCV会自动处理它们,并将其转换为相应的cv::Mat对象,方便你进行图像处理操作。使用InputArray可以使函数接受更加灵活的输入数据类型,增加代码的可重用性和可扩展性。

错误处理

OpenCV 使用异常来表示严重错误。当输入数据具有正确的格式并且属于指定的值范围,但由于某种原因算法无法成功(例如优化算法没有收敛)时,它返回一个特殊的错误代码(通常只是一个布尔变量)。OpenCV 使用异常来表示严重错误。当输入数据具有正确的格式并且属于指定的值范围,但由于某种原因算法无法成功(例如优化算法没有收敛)时,它返回一个特殊的错误代码(通常只是一个布尔变量)。

通常使用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;
}

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

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

相关文章

基于swing的旅游管理系统java jsp旅行团信息mysql源代码

本项目为前几天收费帮学妹做的一个项目&#xff0c;Java EE JSP项目&#xff0c;在工作环境中基本使用不到&#xff0c;但是很多学校把这个当作编程入门的项目来做&#xff0c;故分享出本项目供初学者参考。 一、项目描述 基于swing的旅游管理系统 系统有1权限&#xff1a;管…

ppt转pdf免费的工具哪个好用?ppt在线转pdf的方法分享

在工作和学习中&#xff0c;将PPT文件转换为PDF格式具有重要意义。PDF文件的大小较小&#xff0c;适用于各种平台和设备&#xff0c;保持了原始文件的内容和格式&#xff0c;具有广泛的可读性和兼容性。那么小编就来为大家详细地说一说“ppt转pdf免费的工具哪个好用?ppt在线转…

【Linux】Linux工具

Yan-英杰的主页 悟已往之不谏 知来者之可追 C程序员&#xff0c;2024届电子信息研究生 目录 一、Linux安装软件&#xff1a; 1.yum安装 2.Linux和Windows文件互传 问题: 3.yum卸载软件 二、vim编辑器 1.命令模式 2.vim配置项说明 3.vim操作总结 一、Linux安装软件&#…

Python使用 YOLO_NAS_S 模型进行目标检测并保存预测到的主体图片

一、前言&#xff1a; 使用 YOLO_NAS_S 模型进行目标检测&#xff0c;并保存预测到的主体图片 安装包&#xff1a; pip install super_gradients pip install omegaconf pip install hydra-core pip install boto3 pip install stringcase pip install typing-extensions pi…

怎样快速选择正确的可视化图表?

数据可视化的图表类型十分丰富&#xff0c;好的图表可以有效、清晰地呈现数据的信息。对于用户而言&#xff0c;选择正确的图表是十分关键的&#xff0c;不仅可以达到“一图胜千言”的效果&#xff0c;而且会直接影响分析的结果。 用户选择正确的数据可视化图表前&#xff0c;…

Dataset的简单使用

Pytorch 给我们提供了一个方法&#xff0c;方便我们加载数据&#xff0c;我们可以使用这个框架&#xff0c;去加载我们的数据。看下伪代码&#xff1a; # # # Input pipeline for custom dataset # # ## You should build your custom datas…

React笔记(一)初识React

一、React概述 1、什么是react react的官网:React 用于构建用户界面的 JavaScript 库&#xff0c;它也是一个渐进式的用于构建用户界面的javascript框架 2、主要特征 声明式&#xff1a;使用原生JS编写的页面存在着开发效率低下、性能较差的情况&#xff0c;使用react大家就…

C++ DAY6

一、菱形继承 又叫钻石继承&#xff0c;由公共子类派生出多个中间子类&#xff0c;又由多个中间子类派生出汇聚子类&#xff0c;汇聚子类会 从中间子类得到从公共基类继承下来的多个成员。 A --------公共基类/ \B C ------- 中间子类\ /D -------…

高忆管理:科创板代码多少开头?

科创板在上海证券买卖所正式开市&#xff0c;这是我国股票商场上的一次重磅改革。科创板旨在推进我国科技立异式企业的发展&#xff0c;招引更多高科技企业到A股上市。那么&#xff0c;科创板的代码多少最初呢&#xff1f;这个问题也让许多投资者和重视者非常重视。接下来&…

Java简便集成工作流(activiti),通用审批系统

前言 activiti工作流引擎项目&#xff0c;企业erp、oa、hr、crm等企事业办公系统轻松落地&#xff0c;请假审批demo从流程绘制到审批结束实例。 一、项目形式 springbootvueactiviti集成了activiti在线编辑器&#xff0c;流行的前后端分离部署开发模式&#xff0c;快速开发平…

用NeRFMeshing精确提取NeRF网络中的3D网格

准确的 3D 场景和对象重建对于机器人、摄影测量和 AR/VR 等各种应用至关重要。 NeRF 在合成新颖视图方面取得了成功&#xff0c;但在准确表示底层几何方面存在不足。 推荐&#xff1a;用 NSDT编辑器 快速搭建可编程3D场景 我们已经看到了最新的进展&#xff0c;例如 NVIDIA 的…

Ansible学习笔记(二)

3.ansible的使用示例&#xff08;playbook&#xff09; 1.创建mysql 账户和mysql 组的 playbook ---#create mysql user and group - hosts: allremote_user: roottasks:- name: create groupgroup: namemysql systemyes gid306- name: create useruser: namemysql systemyes…

【FreeRTOS】【STM32】中断详细介绍

文章目录 一、三种优先级的概念辨析1. 先理清楚两个概念&#xff1a;CPU 和 MPU2. Cortex-M3 内核与 STM32F1XX 控制器有什么关系3. 优先级的概念辨析① Cortex-M3 内核和 STM32F1XX 的中断优先级② FreeRTOS 的任务的优先级 二、 Cortex-M3 内核的中断优先级1. 中断编号2. 优先…

Prometheus关于微服务的监控

在微服务架构下随着服务越来越多,定位问题也变得越来越复杂,因此监控服务的运行状态以及针对异常状态及时的发出告警也成为微服务治理不可或缺的一环。服务的监控主要有日志监控、调用链路监控、指标监控等几种类型方式,其中指标监控在整个微服务监控中比重最高,也是实际生…

kafka学习笔记

1、kafka是什么&#xff1f; kafka是一个高吞吐&#xff0c;分布式&#xff0c;基于发布/订阅的消息系统&#xff0c;最大的特性就是可以实时的处理大量的数据以满足各种需求场景&#xff1a;日志收集&#xff0c;离线和在线的消息消费&#xff0c;等等 2、kakfa的基础架构&am…

SMC_TRAFO_GantryCutter2 (FB) 带刀片旋向龙门

裁布机&#xff1a;刀片按XY走向&#xff0c;偏转刀片角度。 pi&#xff1a;目标位置矢量&#xff08;x&#xff0c;y&#xff09;&#xff0c;插值器的输出 v&#xff1a;当前路径切线的矢量&#xff0c;插值器的输出 dOffsetX&#xff1a; x轴的附加偏移 dOffsetY&#xf…

NeRFMeshing - 精确提取NeRF中的3D网格

准确的 3D 场景和对象重建对于机器人、摄影测量和 AR/VR 等各种应用至关重要。 NeRF 在合成新颖视图方面取得了成功&#xff0c;但在准确表示底层几何方面存在不足。 推荐&#xff1a;用 NSDT编辑器 快速搭建可编程3D场景 我们已经看到了最新的进展&#xff0c;例如 NVIDIA 的 …

基于 xhr 实现 axios

基于 xhr 实现 axios 上面我们讲到二次封装 axios &#xff0c;但是现在我们尝试完全脱离 axios&#xff0c;自己实现一个 axios&#xff0c;由于 axios 底层是基于 xhr 做了二次封装&#xff0c;所以我们也可以尝试一下。 xhr 二次封装 src/plugins/xhr.js /*** 请求拦截器…

新能源电驱动总成相关标准简介

新能源电驱动总成相关标准简介 电驱动系统标准体系是电动汽车标准体系中重要的组成部分&#xff0c;其制定和更新对于保障电动汽车的使用性能和安全性能具有非常重要的作用。 随着电动汽车行业的快速发展和普及&#xff0c;电驱动系统的重要性也越来越凸显。为了确保电动汽车的…

循环神经网络(RNN) | 项目还不成熟 |还在初级阶段

一&#xff0c;定义 循环神经网络&#xff08;Recurrent Neural Network&#xff0c;RNN&#xff09;是一种深度学习神经网络架构&#xff0c;专门设计用于处理序列数据&#xff0c;如时间序列数据、自然语言文本等&#xff08;一般用来解决序列问题&#xff09;。 因为它们具…