可点击OpenCV来自简书 /// OpenCV官网
OpenCV中的单位
棋盘格边长尺寸:mm
【机器视觉】
OPENCV
一、各个模块简介
1、 OpenCV4.10.0库功能全解
opencv的头文件
#include "opencv2/core/core_c.h"
#include "opencv2/core/core.hpp"
#include "opencv2/flann/miniflann.hpp"
#include "opencv2/imgproc/imgproc_c.h"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/photo/photo.hpp"
#include "opencv2/video/video.hpp"
#include "opencv2/features2d/features2d.hpp"
#include "opencv2/objdetect/objdetect.hpp"
#include "opencv2/calib3d/calib3d.hpp"
#include "opencv2/ml/ml.hpp"
#include "opencv2/highgui/highgui_c.h"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/contrib/contrib.hpp"
【calib3d】:其实就是就是Calibration(校准)加3D这两个词的组合缩写。这个模块主要是相机校准和三维重建相关的内容。基本的多视角几何算法,单个立体摄像头标定,物体姿态估计,立体相似性算法,3D信息的重建等等。
【contrib】:也就是Contributed/Experimental Stuf的缩写, 该模块包含了一些最近添加的不太稳定的可选功能,不用去多管。2.4.8之后有新型人脸识别, 立体匹配 ,人工视网膜模型等技术。
【core】: 核心功能模块,尤其是底层数据结构和算法函数。包含如下内容:
(1)OpenCV基本数据结构
(2)动态数据结构
(3)绘图函数
(4)数组操作相关函数
(5)辅助功能与系统函数和宏
【imgproc】: Image和Processing这两个单词的缩写组合。图像处理模块,这个模块包含了如下内容:
(1)线性和非线性的图像滤波
(2)图像的几何变换
(3)其它(Miscellaneous)图像转换
(4)直方图相关
(5)结构分析和形状描述
(6)运动分析和对象跟踪
(7)特征检测
【features2d】: d也就是Features2D, 2D功能框架 ,包含兴趣点检测子、描述子以及兴趣点匹配框架。包含如下内容:
(1)特征检测和描述
(2)特征检测器(Feature Detectors)通用接口
(3)描述符提取器(Descriptor Extractors)通用接口
(4)描述符匹配器(Descriptor Matchers)通用接口
(5)通用描述符(Generic Descriptor)匹配器通用接口
【flann】: Fast Library for Approximate Nearest Neighbors,高维的近似近邻快速搜索算法库, 包含两个部分:快速近似最近邻搜索和聚类。
【gpu】: 运用GPU加速的计算机视觉模块。
【highgui】: 也就是high gui,高层GUI图形用户界面,包含媒体的I / O输入输出, 视频捕捉、图像和视频的编码解码、图形交互界面的接口等内容。
【legacy】: 一些已经废弃的代码库,保留下来作为向下兼容。
【ml】: Machine Learning,机器学习模块, 基本上是统计模型和分类算法,包含如下内容:
(1)统计模型 (Statistical Models)
(2)一般贝叶斯分类器 (Normal Bayes Classifier)
(3)K-近邻 (K-NearestNeighbors)
(4)支持向量机 (Support Vector Machines)
(5)决策树 (Decision Trees)
(6)提升(Boosting)
(7)梯度提高树(Gradient Boosted Trees)
(8)随机树 (Random Trees)
(9)超随机树 (Extremely randomized trees)
(10)期望最大化 (Expectation Maximization)
(11)神经网络 (Neural Networks)
(12)MLData
【nonfree】: 也就是一些具有专利的算法模块 ,包含特征检测和GPU相关的内容。最好不要商用,可能会被告哦。
【objdetect】: 目标检测模块,包含Cascade Classification(级联分类)和Latent SVM这两个部分。
【ocl】: 即OpenCL-accelerated Computer Vision,运用OpenCL加速的计算机视觉组件模块。
【photo】: 也就是Computational Photography,包含图像修复和图像去噪两部分。
【stitching】: images stitching,图像拼接模块,包含如下部分:
(1)拼接流水线
(2)特点寻找和匹配图像
(3)估计旋转
(4)自动校准
(5)图片歪斜
(6)接缝估测
(7)曝光补偿
(8)图片混合
【superres】: SuperResolution,超分辨率技术的相关功能模块。
【ts】: opencv测试相关代码,不用去管他。
【video】: 视频分析组件,该模块包括运动估计,背景分离,对象跟踪等视频处理相关内容。
【Videostab】: Video stabilization,视频稳定相关的组件。
二 、数据类型与类对象
1 、数据类型(点类、size类、向量类、矩形类、指针类、异常类等)
6种数据类型在库中一般缩写为b=unsigned char, w=unsigned short, s=short,
i=int, f=float, d=double。
1.1 cv::Point类
优势:简单而且开销小。必要时,可转换为固定向量类或者固定矩阵类。
cv::Point{
2,3}{
b,s,i,f,d}
1.2 cv::Size类
Size类在实际操作时与Point类相似,而且可以与Point类互相转换。
两者区别在于Point类的数据成员是x和y,而Size类中对应的成员是width和height。
Size类的3个别名分别是cv::Size, cv::Size2i, cv::Size2f(其中前两个是等价的)。
1.3 cv::Scalar类
cv::Scalar直接从固定向量类模板实例中继承而来。
cv::Scalar是四维双精度向量的快速表示。
1.4 cv::Rect类
矩形类包含Point类的成员x和y(矩形左上角)和Size类的成员width和height(代表了矩形的大小)。
1.5 cv::RotatedRect类
该类包含一个中心点cv::Point2f、一个大小cv::Size2f和一个额外的角度float的容器。
1.6 固定矩阵类
固定矩阵类是为编译时就已知维度的矩阵打造的,这也是称为“固定”的原因。
因为它们内部的所有数据都是在堆栈上分配的,所以它们的分配和清除很快。
固定矩阵类实际上是一个模板,这个模板称为cv::Matx<>,但独立的矩阵通常
通过别名分配。这些别名的基础格式是cv::Matx{
1,2,..6}{
1,2,..6}{
f,d}。
1.7 固定向量类
固定向量类是从固定矩阵类派生出来的。
固定向量模板cv::Vec{
2,3,4,6}{
b,s,w,i,f,d}。
固定向量类的最主要便利是它可以通过单个数索引各项,以及几个特定的额外的函数使常规矩阵运算有意义(比如叉乘)。
1.8 复数类
OpenCV中的复数类与STL复数类模板complex< >不一样,但与之兼容,可以相互转换。它们最大的区别在于成员获取。在STL类中,实部和虚部是通过成员函数real()和imag()获取的,而在OpenCV中,直接通过成员变量re和im获取。
复数类模板的别名是cv::Complexf和cv::Complexd,分别是单精度和双精度复数的别名。
1.9 辅助对象——cv::TermCriteria类
确定算法的终止条件。
cv::TermCriteria有三个成员变量(type,maxCount以及epsilon)
源码结构如下:
struct cv::TermCriteria(
Public:
//成员变量
enum
{
COUNT=1, //计算元素或者迭代次数最小值
MAX_ITER=COUNT, //最大迭代次数
EPS=2 //当满足该精确度时,迭代算法停止
};
//构造函数
TermCriteria::TermCriteria()
TermCriteria::TermCriteria(int type, int maxCount, double epsilon)
TermCriteria::TermCriteria(const CvTermCriteria& criteria)
//参数:
//type – 终止条件类型:
//maxCount – 计算的迭代数或者最大元素数
//epsilon – 当达到要求的精确度或参数的变化范围时,迭代算法停止
//type可选:
//TermCriteria::COUNT //达到最大迭代次数 =TermCriteria::MAX_ITER
//TermCriteria::EPS //达到精度
//TermCriteria::COUNT + TermCriteria::EPS //以上两种同时作为判定条件
);
上一个例子:
cv::TermCriteria criteria = cv::TermCriteria(
cv::TermCriteria::EPS + cv::TermCriteria::COUNT, 10, 0.1);
//COUNT=MAX_ITER(相等)
1.10 辅助对象——cv::Range类
cv::Range类用于确定一个连续的整数序列。构造函数cv::Range(int start, int end)中,范围包含初始值start,但不包含终止值end。
cv::Range类成员函数还有size(), empty()。
1.11 辅助对象——cv::Ptr模板和垃圾收集
指针模板的实例:可以通过调用类似
cv::Ptr<cv::Matx33f> p(new cv::Matx33f)
或
cv::Ptr<cv::Matx33f> p = cv::makePtr<cv::Matx33f>() #这种格式在3.0版本可以,在4.0版本好像不能用了
cv::Ptr<> 是线程安全的。
1.12 辅助对象——cv::Exception类和异常处理
请添加
1.13 辅助对象——cv::DataType<>模板
请添加
2、类对象
2.1 接口类
2.1.1 InputArray或OutputArray接口类
InputArray这个接口类可以是Mat、Mat_<T>、Mat_<T, m, n>、vector<T>、vector<vector<T>>、vector<Mat>。也就意味着当你看refman或者源代码时,如果看见函数的参数类型是InputArray型时,把上诉几种类型作为参数都是可以的。有时候InputArray输入的矩阵是个空参数,你只需要用cv::noArray()作为参数即可,或者很多代码里都用cv::Mat()作为空参。这个类只能作为函数的形参参数使用,不要试图声明一个InputArray类型的变量。如果在你自己编写的函数中形参也想用InputArray,可以传递多类型的参数,在函数的内部可以使_InputArray::getMat()函数将传入的参数转换为Mat的结构,方便你函数内的操作;必要的时候,可能还需要_InputArray::kind()用来区分Mat结构或者vector<>结构,但通常是不需要的。
三、OpenCV中的Mat(矩阵)
1、创建与初始化矩阵
请点击–> 【OpenCV3】cv::Mat的定义与初始化
请点击–> OpenCV Mat类详解和用法
请点击–> Opencv之Mat常用类成员
补充:创建矩阵
C++: void Mat::create(int rows, int cols, int type)
C++: void Mat::create(Size size, int type)
C++: void Mat::create(int ndims, const int* sizes, inttype)
参数:
ndims – 新数组的维数。 rows –新的行数。
cols – 新的列数。 size – 替代新矩阵大小规格:Size(cols, rows)。
type – 新矩阵的类型。 sizes – 指定一个新的阵列形状的整数数组。
示例:
cv::Mat srcImage = cv::imread("D:\\visual studio 2010\\Projects\\remap\\1.jpg");
cv::Mat dstImage;
dstImage.create(srcImage.size(),srcImage.type());
| imread的flags(不止3个) | 解释 |
|---|---|
| IMREAD_UNCHANGED | 如果设置,将加载的图像原样返回(带alpha通道,否则会被裁剪)。忽略EXIF方向。 |
| IMREAD_GRAYSCALE | |
| IMREAD_COLOR | 默认flags |
建立矩阵必须要指定矩阵存储的数据类型,得到矩阵Mat的类型( mat.type() ),图像处理中常用的几种数据类型如下:
CV_8UC{
1,2,3,4} // 8位无符号单通道, 双通道,3通道,4通道
CV_8SC{
1,2,3,4} // 8位短整型单通道, 双通道,3通道,4通道
CV_16UC{
1,2,3,4} // 16位无符号单通道, 双通道,3通道,4通道
CV_16SC{
1,2,3,4} // 16位短整型单通道, 双通道,3通道,4通道
CV_32SC{
1,2,3,4} // 32位短整型单通道, 双通道,3通道,4通道
CV_32FC{
1,2,3,4} // 32位浮点型单通道, 双通道,3通道,4通道
CV_64FC{
1,2,3,4} // 64位浮点型单通道, 双通道,3通道,4通道
!!!!!强调:数组中的数据是按行连续组织的,因此不可以通过这种方式去访问一个指定的列。
int depth = img.depth(); // 获取图像的颜色位数,返回的是枚举类型的值(只针对单通道)
矩阵元素的数据类型:
| C1 | C2 | C3 | C4 | |
|---|---|---|---|---|
| CV_8U | 0 | 8 | 16 | 24 |
| CV_8S | 1 | 9 | 17 | 25 |
| CV_16U | 2 | 10 | 18 | 26 |
| CV_16S | 3 | 11 | 19 | 27 |
| CV_32S | 4 | 12 | 20 | 28 |
| CV_32F | 5 | 13 | 21 | 29 |
| CV_64F | 6 | 14 | 22 | 30 |
表头的 C1, C2, C3, C4 指的是通道(Channel)数,比如灰度图像只有 1 个通道,是 C1;JPEG格式 的 RGB 彩色图像就是 3 个通道,是 C3;PNG 格式的彩色图像除了 RGB 3个通道外,还有一个透明度通道,所以是 C4。大家还会发现 7 怎么没有被定义类型,这个可以看 OpenCV 源码,有如下所示的一行,说明 7 是用来给用户自定义的:
#define CV_USRTYPE1 7
如果仅仅是为了在数值计算前明确数据类型,那么看到这里就可以了;如果是要使用 at 方法访问数据元素,那么还需要下面一步。因为以单通道为例,at 方法接受的是 uchar 这样的数据类型,而非 CV_8U。在已知通道数和每个通道数据类型的情况下,指定给 at 方法的数据类型如下表所示:
| C1 | C2 | C3 | C4 | C6 | |
|---|---|---|---|---|---|
| uchar | uchar | cv::Vec2b | cv::Vec3b | cv::Vec4b | |
| short | short | cv::Vec2s | cv::Vec3s | cv::Vec4s | |
| int | int | cv::Vec2i | cv::Vec3i | cv::Vec4i | |
| float | float | cv::Vec2f | cv::Vec3f | cv::Vec4f | cv::Vec6f |
| double | double | cv::Vec2d | cv::Vec3d | cv::Vec4d | cv::Vec6d |
图像像素、通道操作
三通道彩色图像,则数据类型为Vec3b
cv::Vec3b vec3b = img.at<cv::Vec3b>(0,0);
uchar vec3b0 = img.at<cv::Vec3b>(0,0)[0];//第一个通道,对应于BGR类型的蓝色通道
uchar vec3b1 = img.at<cv::Vec3b>(0,0)[1];//第一个通道,对应于BGR类型的绿色通道
uchar vec3b2 = img.at<cv::Vec3b>(0,0)[2];//第一个通道,对应于BGR类型的红色通道
std::cout << "vec3b = " << vec3b << std::endl;
std::cout << "vec3b0 = " << (int)vec3b0 << std::endl;
std::cout << "vec3b1 = " << (int)vec3b1 << std::endl;
std::cout << "vec3b2 = " << (int)vec3b2 << std::endl;
二值化图像像素操作(数据类型为uchar)
// 这里inputmat是二值化图像的mat
inputmat.at<uchar>(y, x);
2、cv::Mat类函数列表
| cv::Mat函数(全)名称 | 描述 |
|---|---|
| cv::Mat::reshape(int cn, int rows=0) const | reshape函数既可以改变通道数,又可以对矩阵元素进行序列化,改变矩阵的形状 |
| cv::Mat::isContinuous() | 返回bool值,判断存储是否连续,如果矩阵的行之间没有空隙,返回true。补充: Mat的数据部分存储是按照行进行存储的,相同行内的数据是连续存储,行与行之间的存储是否有间隙,可以通过isContinuous函数来判断。对于11或1N矩阵总是连续的,一般使用Mat::create创建的矩阵总是连续的,而如果使用Mat::col、Mat::diag、Mat::rect等提取的矩阵一部分,或者外部分配的数据构造矩阵头,则此类矩阵可能不再连续存储。 |
| cv::Mat::clone() | m1 = m0.clone(); 将m0完全拷贝到m1中,同时拷贝m0中的所有数据,且拷贝的矩阵是连续的。 |
| void cv::Mat::convertTo( OutputArray m, int rtype, double alpha = 1, double beta = 0 ) const | 使用可选缩放将数组转换为另一种数据类型。主要是根据公式: m(x,y)=saturate_cast< rType >(α(∗this)(x,y)+β), m0.convertTo(m1, type, alpha, beta); 用于数据类型转换,但不能转换通道数,转换通道数用函数cv::cvtColor() 。 将m0中的元素转换成type类(CV_32F等)。 |
| cv::Mat::push_back() | m0.push_back(elem); 这些方法将一个或多个元素添加到矩阵的底部。它们模拟STL向量类的相应方法。当elem为Mat时,其类型和列数必须与容器矩阵中的相同。注意: 添加elem时,是深拷贝还是浅拷贝。 |
| cv::Mat::pop_back( size_t nelems = 1) | 该方法从矩阵底部删除一行或多行。 m0.pop_back(n); //从m0尾部移除n行,默认情况下n为1。 |
| cv::Mat::type() | m0.type(); //返回m0中元素的有效类型标识符(如CV_32FC3),不过返回的是一个数字。该方法返回一个矩阵元素类型。这是一个与CvMat类型系统兼容的标识符,如CV_16SC3或16位有符号的3通道数组,等等。 |
| cv::Mat::depth() | m0.depth(); //返回m0中单个通道中元素的有效类型标识符(如CV_32F)。该方法返回矩阵元素深度的标识符(每个单独通道的类型)。例如,对于16位有符号元素数组,该方法返回CV_16S。 |
| cv::Mat::channels() | m0.channels(); //返回m0中元素的通道数目。 |
| cv::Mat::size() | m0.size(); //以cv::Size对象的形式返回m0的大小。 |
| cv::Mat::empty() | m0.empty(); //如果数组中没有元素(如m0.total == 0 或 m0.data == NULL)则返回true。 |
| cv::Mat::ptr | 共有20种构造函数。常用形式: mat.ptr< type>(row)[col] , 对于Mat的ptr函数,返回的是<>中的模板类型指针,指向的是()中的第row行的起点,通常<>中的类型和Mat的元素类型应该一致,然后再用该指针去访问对应col列位置的元素 |
| MatExpr cv::Mat::inv ( int method = DECOMP_LU) const | 求矩阵的逆矩阵,method有3种:cv::DECOMP_LU(默认),cv::DECOMP_SVD,cv::DECOMP_EIG ,cv::DECOMP_CHOLESKY,cv::DECOMP_QR,DECOMP_NORMAL。 |
| Mat cv::Mat::cross (InputArray m) const | 计算两个三元素向量的外积。向量必须是相同形状和大小的3元素浮点向量。结果是与操作数具有相同形状和类型的另一个3元素向量。向量积,数学中又称外积、叉积,物理中称矢积、叉乘,是一种在向量空间中向量的二元运算。与点积不同,它的运算结果是一个向量而不是一个标量。并且两个向量的叉积与这两个向量和垂直。 |
| double cv::Mat::dot ( InputArray m ) const | 用法:A.dot(B) 计算两向量的点乘,又称内积,结果是一个标量。如果矩阵不是单列或单行向量,则使用从上到下从左到右的扫描顺序将它们视为1D向量。矢量必须具有相同的大小和类型。如果矩阵有多个通道,则所有通道的点积相加。 |
| cv::Mat::mul() | 计算两个Mat矩阵对应位元素的乘积,所以要求参与运算的矩阵A的行列和B的行列数一致。 函数原型:C++: MatExpr Mat::mul(InputArray m, double scale=1) const。 用法:Mat AB=A.mul(B); |
| 矩阵乘 A*B | 是以数学运算中矩阵相乘的方式实现的,即Mat矩阵A和B被当做纯粹的矩阵做乘法运算,这就要求A的列数等于B的行数时,才能定义两个矩阵相乘。如A是m×n矩阵,B是n×p矩阵,它们的乘积AB是一个m×p矩阵。 |
| cv::Mat::t() | 矩阵的转置运算 |
| cv::Mat::rowRange() cv::Mat::colRange() |
rowRange为矩阵的指定行区间范围创建一个矩阵头,可取指定行区间元素; colRange为矩阵的指定列区间范围创建一个矩阵头,可取指定列区间元素。from官网 该函数包括左边界,但是不包括右边界。PS:这里的边界指的是下标索引。因为索引为0才表示第一行,而不是索引为1 表示第一行。 |
| Mat Mat::row( int i ) const Mat Mat::col( int j ) const |
创建一个指定行数的矩阵头并返回,新矩阵和原始矩阵共享一份基础数据函数原型,相当于是浅拷贝。 创建一个指定列数的矩阵头并返回,新矩阵和原始矩阵共享一份基础数据函数原型,相当于是浅拷贝。 |
| Mat Mat::diag(int d) const ----- --------static Mat Mat::diag(const Mat& matD) |
提取或创建矩阵对角线。 d: 对角线的索引值,可以是以下的值: d=0 是主对角线; d>0表示下半部的对角线。例如:d=1 对角线是紧挨着住对角线并位于矩阵下方; d<0表示来自矩阵上半部的对角线。例如:d= -1 表示对角线被设置在对角线的上方并紧挨着; matD: 单列用于形成矩阵对角线的列。 |
| void Mat::copyTo(OutputArray m) const void Mat::copyTo(OutputArray m, InputArray mask) const |
和clone相似,将矩阵复制到另一个矩阵中去。 m :目标矩阵。如果它的尺寸和类型不正确,在操作之前会重新分配。 mask: 操作掩码。它的非零元素表示矩阵中某个要被复制。 |
| Mat& Mat::setTo(const Scalar& s, InputArray mask=noArray()) | 功能: 将阵列中所有的或部分的元素设置为指定的值。mask必须为CV_8U型,可以有1个或多个通道。用法:src.setTo(value, mask)。当默认不添加mask的时候,表明mask是一个与原图尺寸大小一致的且元素值==全为非 0 ==的矩阵,因此不加mask的时候,会将原矩阵的像素值全部赋值为value;当带有mask这个参数的时候,对于mask中非零的位置,在src中的对应位置的元素会被置为value值,其他部分不变。例如: 1、有一个Mat src,想将他的值全部设置成0,则可以src.setTo(0); 2、setTo还有更为高级的用法,对于一个已知的src,我们要将其中大于或者小于某个值的像素值设置为指定的值,则可以如下:src.setTo(0,src < 10);这句话的意思是,当src中的某个像素值小于10的时候,就将该值设置成0。 |
| cv::Mat:: | |
| cv::Mat:: | |
| cv::Mat:: | |
| cv::Mat:: | |
| cv::Mat:: | |
| cv::Mat:: | |
| cv::Mat:: | |
| cv::Mat:: | |
| cv::Mat:: | |
| cv::Mat:: | |
| cv::Mat:: | |
| cv::Mat:: | |
| cv::UMat | 它跟Mat有着多数相似的功能和相同的API函数,通过使用UMat对象,OpenCV会自动在支持OpenCL的设备上使用GPU运算,在不支持OpenCL的设备仍然使用CPU运算,这样就避免了程序运行失败,而且统一了接口。 |
3、独立获取数组元素(访问)
请点击-> cv::Mat像素遍历方式(3种)
请点击-> 访问Mat中每个像素的值
4、cv::Mat和std::vector之间的相互转换
1、 cv::Mat转换成std::vector
第(1)种:
cv::Mat mat;
std::vector<type_> vec;
vec = (std::vector<type_>)(mat.reshape(0,1));
reshape函数原型:C++: Mat Mat::reshape(int cn, int rows=0) const
cn

本文全面介绍了OpenCV 4.10.0版本的功能模块、数据类型与类对象,并深入探讨了Mat矩阵的操作方法、图像和视频处理流程。此外,还详细阐述了相机标定的过程与注意事项,以及OpenCV与其他工具如ROS和Qt的联合开发技巧。
最低0.47元/天 解锁文章
3130






