OpenCV是一个计算机视觉库,其主要重点是处理和操作这些信息。因此,您首先需要熟悉的是 OpenCV 如何存储和处理图像。
Mat
OpenCV 自 2001 年以来一直存在。当时,该库是围绕C接口构建的,为了将图像存储在内存中,他们使用了一个名为IplImage的 C 结构。这是您将在大多数较早的教程和教育材料中看到的内容。这样做的问题是它把 C 语言的所有缺点都摆在了桌面上。最大的问题是手动内存管理。它建立在用户负责处理内存分配和释放的假设之上。虽然这对于较小的程序来说不是问题,但一旦您的代码库增长,处理所有这些而不是专注于解决您的开发目标将更加困难。
幸运的是,C++ 出现并引入了类的概念,通过自动内存管理(或多或少)使用户更容易。好消息是 C++ 与 C 完全兼容,因此在进行更改时不会出现兼容性问题。因此,OpenCV 2.0 引入了一个新的 C++ 接口,它提供了一种新的做事方式,这意味着您无需摆弄内存管理,使您的代码简洁(少写,实现更多)。C++ 接口的主要缺点是目前许多嵌入式开发系统仅支持 C。因此,除非您的目标是嵌入式平台,否则使用旧方法是没有意义的(除非您是受虐狂程序员并且您在找麻烦)。
关于Mat你需要知道的第一件事是你不再需要手动分配它的内存并在你不需要它时立即释放它。虽然这样做仍有可能,但大多数 OpenCV 函数将自动分配其输出数据。如果你传递一个已经存在的Mat对象,它已经为矩阵分配了所需的空间,这是一个很好的奖励,这将被重用。换句话说,我们始终只使用执行任务所需的内存。
Mat基本上是一个具有两个数据部分的类:矩阵头(包含诸如矩阵大小、用于存储的方法、存储的矩阵的地址等信息)和指向包含像素值(根据选择的存储方法采用任何维度)。矩阵头大小是恒定的,但是矩阵本身的大小可能因图像而异,并且通常大几个数量级。
OpenCV 是一个图像处理库。它包含大量图像处理功能。为了解决计算难题,大多数时候您最终会使用库的多个功能。因此,将图像传递给函数是一种常见的做法。我们不应该忘记我们谈论的是图像处理算法,它往往计算量很大。我们要做的最后一件事是通过对可能较大的图像进行不必要的副本来进一步降低程序的速度。
一 、构造Mat
Mat重载了许多构造函数,常用的有:
1.构造一个单通道灰度值全零Mat
cv::Mat zereImage = cv::Mat::zeros(cv::Size(100,100),CV_8UC1);
2.构造一个单通道指定灰度值的Mat
cv::Mat spePixelImage = cv::Mat(cv::Size(100,100), CV_8UC1,cv::Scalar(128));
3.构造一个三通道灰度值全零Mat
cv::Mat zereImages = cv::Mat::zeros(cv::Size(100,100),CV_8UC3);
4.构造一个三通道指定灰度值的Mat
cv::Mat spePixelImages = cv::Mat(cv::Size(100,100), CV_8UC3,cv::Scalar(128,0,128));
二、 拷贝Mat
1.浅拷贝
即两个Mat的指针同时指向一个内存地址
cv::Mat spePixelImages = cv::Mat(cv::Size(100,100), CV_8UC3,cv::Scalar(128,0,128));
cv::Mat sCopy(spePixelImages);
//或者
cv::Mat sCopy1;
sCopy1 = spePixelImages;
2.深拷贝
即重新申请一块内存,Mat指针指向新的内存地址
cv::Mat spePixelImages = cv::Mat(cv::Size(100,100), CV_8UC3,cv::Scalar(128,0,128));
cv::Mat dCopy;
spePixelImages.copyTo(dCopy);
//或者
cv::Mat dCopy1 = spePixelImages.clone();
三、裁剪
1.使用cv::rect
cv::Mat spePixelImages = cv::Mat(cv::Size(100,100), CV_8UC3,cv::Scalar(128,0,128));
cv::Mat cropImage (spePixelImages, cv::Rect(10, 10, 50, 50)); // using a rectangle
2.使用Range
cv::Mat spePixelImages = cv::Mat(cv::Size(100,100), CV_8UC3,cv::Scalar(128,0,128));
cv::Mat cropImage1 = spePixelImages(cv::Range::all(), cv::Range(1,3));