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可以接受以下类型的输入数据:
- cv::Mat:用于表示图像或矩阵数据。
- std::vector:用于表示标准C++ STL容器的数据,如std::vectorcv::Point,std::vectorcv::Vec3f等。
- 数组:可以接受指向数据的指针和数据的大小。
- cv::InputArrayOfArrays:用于表示多个InputArray的数组,用于处理多通道数据或多个数据块。
- 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;
}
相关文章:

OpenCV简介
OpenCV简介 OpenCV(开源计算机视觉库:http://opencv.org)是一个开源库,包含数百种计算机视觉算法。OpenCV 具有模块化结构,主要包括下列模块: 核心功能(core) - 定义基本数据结构的…...
Windows下编译qt-src-5.15.10
首先从镜像站点下载qt源码: https://download.qt.io/static/mirrorlist/ 下载QT的镜像站点 下载源码后解压到 F: 盘 创建编译目录F:\qtbuild 打开VS2019的 X64 Native Tools Command Prompt for VS 2019 进入到源码目录 cd F:\qt-everywher…...
有关linux排查服务器资源问题
查看 磁盘占用 df -h 进入到某一个文件夹下 查看对应文件夹占用 du -sh /usr...
【设计模式】Head First 设计模式——观察者模式 C++实现
设计模式最大的作用就是在变化和稳定中间寻找隔离点,然后分离它们,从而管理变化。将变化像小兔子一样关到笼子里,让它在笼子里随便跳,而不至于跳出来把你整个房间给污染掉。 设计思想 主题对象(出版者)管理…...

【ES】笔记-Promise基本使用
笔记-基本使用 一、初始Promise1. 抽象表达:2. 具体表达:为什么要用 Promise?promise的基本流程 二、fs读取文件三、AJAX请求四、Promise封装fs模块五、util.promisify方法六、Promise封装AJAX操作 一、初始Promise 1. 抽象表达: 1. Promise 是一门新的技术(ES6 规范) 2. Pr…...

服务器数据恢复-reiserfs文件系统损坏如何恢复数据?
服务器数据恢复环境: 一台IBM X系列服务器,4块SAS硬盘组建一组RAID5阵列,采用的reiserfs文件系统。服务器操作系统分区结构:boot分区LVM卷swap分区(按照前后顺序)。LVM卷中直接划分了一个reiserfs文件系统&…...

直播预告:把脉2023年下半场—主动防御邮箱盗号威胁
长期以来,承载着大量敏感数据的企业是黑产团伙的首要攻击目标。Coremail结合多年以来的邮件防护经验发现,黑产团伙针对企业邮箱账号安全的两大攻击方式为暴力破解和钓鱼邮件攻击。 一、企业邮箱安全现状 01、使用弱密码 企业员工使用弱密码让黑产团伙有…...

专题:平面、空间直线参数方程下的切线斜率问题
本文研究平面、空间直线在参数方程形式下,切线斜率(即导数)如何表示的问题。 如上图所示。 设 y f ( x ) , x φ ( t ) , y ψ ( t ) 当 t t 0 时, x x 0 , y y 0 ,即点 A 坐…...

JavaScript—对象与构造方法
目录 json对象(字面值) js中对象是什么? 如何使用? 关联数组 js对象和C#对象有什么区别? 构造函数 什么是构造方法? 如何使用构造方法? 如何添加成员? 对象的动态成员 正则…...
微信小程序社区户口管理的系统设计与实现
摘要 我国的户口管理制度由来已久,我国对于合法居民在新生儿的出生、户口的落地、迁移以及户口的注销上都有着详细的管理条例进行约束。通过户口的管理可以更好地对我国的居民人数进行有效的内容统计,在进行人口普查的过程中也能够实现更好的、更加精准的…...

闲人闲谈PS之四十六——网络生产全流程
惯例闲话:下半年已开始块行情似乎又是一波大涨,很多朋友委托我介绍PS顾问,很多朋友已经上了能源系统项目,这就造成装备制造的PS又是极度紧缺,rate也还可以,搞的自己也有点心痒痒。这种逆势大涨,…...

如何在VR头显端实现低延迟的RTSP或RTMP播放
技术背景 VR(虚拟现实技术)给我们带来身临其境的视觉体验,广泛的应用于城市规划、教育培训、工业仿真、房地产、水利电力、室内设计、文旅、军事等众多领域,常用的行业比如: 教育行业:VR头显可以用于教育…...

【工具类】提高办公效率(兼具有趣、好玩)
1 Wormhole 免费免注册登录在线、不限速文件传输 Simple, private file sharing https://wormhole.app/ 2 ALL to ALL 在线格式转换 免费、免注册登录 国内最全类型的在线文件转换平台,免费、快速,无须下载安装任何软件。 https://www.alltoall.net/ …...

navicat连接数据库的方法(易懂)
1.首页要先下载Navicat 官网下载即可 2.下载完点击进入 找到左上角的连接 3.点击选择MySQL... 4.点击进入开始连接数据库...

收支明细管理实操:如何准确记录并修改收支明细?
宣传软文: 在日常生活中,收支明细的管理至关重要,无论是个人还是企业。准确的记录不仅能有效管理财务,还能提供清晰的依据以供分析和决策。但在实际操作中,可能出现记录错误的情况。本文将详细介绍如何记录和修改收支明…...
SSL证书的工作原理是怎样的?
传统的网络通信采用的是HTTP传输协议,数据全程公开暴露,很容易被第三方监听和窃取,对用户和网站的数据安全造成很大威胁。为了保护用户的数据安全,SSL证书逐渐普及并应用于政府和企业网站之中,成为了提升数据安全水平&…...
Java发送请求到第三方(RestTemplate方法)
Get请求 try {RestTemplate restTemplate = new RestTemplate();//设置请求头HttpHeaders headers = new HttpHeaders();headers.add("Authorization", "Bearer token");headers.add("User-Agent", "Mozilla/5.0");HttpEntity entity…...

CentOS 7 Nacos 设置开机自动重启
一、说明 Nacos如果是手动启动的话,在服务器宕机或者重启后,没有自动运行,影响很多业务系统,需要每次手动执行命令 startup.sh -m standalone,才能启动 Nacos 服务,不能像docker服务一样,使用 …...

安防监控平台EasyCVR视频汇聚平台增加首页告警类型的详细介绍
安防监控/视频集中存储/云存储EasyCVR视频汇聚平台,可支持海量视频的轻量化接入与汇聚管理。平台能提供视频存储磁盘阵列、视频监控直播、视频轮播、视频录像、云存储、回放与检索、智能告警、服务器集群、语音对讲、云台控制、电子地图、平台级联、H.265自动转码等…...

构建安全可信、稳定可靠的RISC-V安全体系
安全之安全(security)博客目录导读 2023 RISC-V中国峰会 安全相关议题汇总 说明:本文参考RISC-V 2023中国峰会如下议题,版权归原作者所有。...
蓝桥杯 2024 15届国赛 A组 儿童节快乐
P10576 [蓝桥杯 2024 国 A] 儿童节快乐 题目描述 五彩斑斓的气球在蓝天下悠然飘荡,轻快的音乐在耳边持续回荡,小朋友们手牵着手一同畅快欢笑。在这样一片安乐祥和的氛围下,六一来了。 今天是六一儿童节,小蓝老师为了让大家在节…...

Java-41 深入浅出 Spring - 声明式事务的支持 事务配置 XML模式 XML+注解模式
点一下关注吧!!!非常感谢!!持续更新!!! 🚀 AI篇持续更新中!(长期更新) 目前2025年06月05日更新到: AI炼丹日志-28 - Aud…...
Neo4j 集群管理:原理、技术与最佳实践深度解析
Neo4j 的集群技术是其企业级高可用性、可扩展性和容错能力的核心。通过深入分析官方文档,本文将系统阐述其集群管理的核心原理、关键技术、实用技巧和行业最佳实践。 Neo4j 的 Causal Clustering 架构提供了一个强大而灵活的基石,用于构建高可用、可扩展且一致的图数据库服务…...
Linux云原生安全:零信任架构与机密计算
Linux云原生安全:零信任架构与机密计算 构建坚不可摧的云原生防御体系 引言:云原生安全的范式革命 随着云原生技术的普及,安全边界正在从传统的网络边界向工作负载内部转移。Gartner预测,到2025年,零信任架构将成为超…...
今日科技热点速览
🔥 今日科技热点速览 🎮 任天堂Switch 2 正式发售 任天堂新一代游戏主机 Switch 2 今日正式上线发售,主打更强图形性能与沉浸式体验,支持多模态交互,受到全球玩家热捧 。 🤖 人工智能持续突破 DeepSeek-R1&…...

IoT/HCIP实验-3/LiteOS操作系统内核实验(任务、内存、信号量、CMSIS..)
文章目录 概述HelloWorld 工程C/C配置编译器主配置Makefile脚本烧录器主配置运行结果程序调用栈 任务管理实验实验结果osal 系统适配层osal_task_create 其他实验实验源码内存管理实验互斥锁实验信号量实验 CMISIS接口实验还是得JlINKCMSIS 简介LiteOS->CMSIS任务间消息交互…...

IT供电系统绝缘监测及故障定位解决方案
随着新能源的快速发展,光伏电站、储能系统及充电设备已广泛应用于现代能源网络。在光伏领域,IT供电系统凭借其持续供电性好、安全性高等优势成为光伏首选,但在长期运行中,例如老化、潮湿、隐裂、机械损伤等问题会影响光伏板绝缘层…...
rnn判断string中第一次出现a的下标
# coding:utf8 import torch import torch.nn as nn import numpy as np import random import json""" 基于pytorch的网络编写 实现一个RNN网络完成多分类任务 判断字符 a 第一次出现在字符串中的位置 """class TorchModel(nn.Module):def __in…...
LangChain知识库管理后端接口:数据库操作详解—— 构建本地知识库系统的基础《二》
这段 Python 代码是一个完整的 知识库数据库操作模块,用于对本地知识库系统中的知识库进行增删改查(CRUD)操作。它基于 SQLAlchemy ORM 框架 和一个自定义的装饰器 with_session 实现数据库会话管理。 📘 一、整体功能概述 该模块…...

Python Ovito统计金刚石结构数量
大家好,我是小马老师。 本文介绍python ovito方法统计金刚石结构的方法。 Ovito Identify diamond structure命令可以识别和统计金刚石结构,但是无法直接输出结构的变化情况。 本文使用python调用ovito包的方法,可以持续统计各步的金刚石结构,具体代码如下: from ovito…...