OpenCV与Eigen (C++)【学习备忘】

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


可点击OpenCV来自简书 /// OpenCV官网
OpenCV中的单位
棋盘格边长尺寸:mm
【机器视觉】

OPENCV

一、各个模块简介

1、 OpenCV4.10.0库功能全解

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数据结构,请点击

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
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值