700字范文,内容丰富有趣,生活中的好帮手!
700字范文 > OpenCV 笔记(02)— 图像显示 保存 腐蚀 模糊 canny 边缘检测(imread imshow namedWindow imwrite)

OpenCV 笔记(02)— 图像显示 保存 腐蚀 模糊 canny 边缘检测(imread imshow namedWindow imwrite)

时间:2023-03-12 15:44:02

相关推荐

OpenCV 笔记(02)— 图像显示 保存 腐蚀 模糊 canny 边缘检测(imread imshow namedWindow imwrite)

OpenCV提供两种用户界面选项:

基于原生用户界面的基本界面,适用于Mac OS Xcocoacarbon,以及适用于LinuxWindows用户界面的GTK,这些界面在编译OpenCV时被默认选择。基于Qt库的略微更高级的界面,这是跨平台的界面。必须在编译OpenCV之前,在CMake中手动启用Qt选项。

1. 图像显示

OpenCV中,图像显示过程非常简单,只需用imread函数载入到新版本的图像存储数据结构Mat类中,然后用imshow函数显示即可。

#include <iostream>#include "opencv2/opencv.hpp"using namespace cv;// 使用 cv 命名空间,否则后面需要使用 cv::Mat, cv::imread 等带cv前缀int main(){Mat image;image = imread("./image/dog.jpg");// 载入图像if (image.empty())// 或者 if(!image.data) 判断图片是否加载成功{std::cout << "image not exist";return -1;}namedWindow("demo 图片");imshow("demo 图片", image);// 显示图像imwrite("save.jpg", image);waitKey(0);// 等待任意按键按下,退出图片显示return 0;}

显示结果

代码分析:

1.1 Mat 类

Mat类是用于保存图像以及其他矩阵数据的数据结构, 默认情况下其尺寸为 0。我们也可以指定其初始尺寸, 比如定义一个Mat类对象, 就要写cv::Mat pic( 320, 640, cv::Scalar(100))

1.2 imread 载入图像函数

首先来看imread函数, 其用于读取文件中的图片到OpenCV中。可以在OpenCV官方文档中查到它的原型, 如下。

Mat imread( const String& filename, int flags = IMREAD_COLOR )

第一个参数,const string&类型的filename, 填我们需要载入的图片路径名。第二个参数,int类型的flags, 为载入标识,它指定一个加载图像的颜色类型。默认值为 1 这个参数可以在OpenCV中标识图像格式的枚举体中取值,详情如下:

enum ImreadModes {IMREAD_UNCHANGED = -1, //!< If set, return the loaded image as is (with alpha channel, otherwise it gets cropped).IMREAD_GRAYSCALE = 0, //!< If set, always convert image to the single channel grayscale image (codec internal conversion).IMREAD_COLOR= 1, //!< If set, always convert image to the 3 channel BGR color image.IMREAD_ANYDEPTH = 2, //!< If set, return 16-bit/32-bit image when the input has the corresponding depth, otherwise convert it to 8-bit.IMREAD_ANYCOLOR = 4, //!< If set, the image is read in any possible color format.IMREAD_LOAD_GDAL = 8, //!< If set, use the gdal driver for loading the image.IMREAD_REDUCED_GRAYSCALE_2 = 16, //!< If set, always convert image to the single channel grayscale image and the image size reduced 1/2.IMREAD_REDUCED_COLOR_2= 17, //!< If set, always convert image to the 3 channel BGR color image and the image size reduced 1/2.IMREAD_REDUCED_GRAYSCALE_4 = 32, //!< If set, always convert image to the single channel grayscale image and the image size reduced 1/4.IMREAD_REDUCED_COLOR_4= 33, //!< If set, always convert image to the 3 channel BGR color image and the image size reduced 1/4.IMREAD_REDUCED_GRAYSCALE_8 = 64, //!< If set, always convert image to the single channel grayscale image and the image size reduced 1/8.IMREAD_REDUCED_COLOR_8= 65, //!< If set, always convert image to the 3 channel BGR color image and the image size reduced 1/8.IMREAD_IGNORE_ORIENTATION = 128 //!< If set, do not rotate the image according to EXIF's orientation flag.};

所以有时候这个参数在调用时可以忽略,就表示载入三通道的彩色图像。

因为flagsint型的变量,若我们不在这个枚举体中取固定的值, 可以这样进行:

flags>0返回一个3 通道的彩色图像;flags=0返回灰度图像;flags<0返回包含 Alpha 通道的加载图像;

注意:若以彩色模式载入图像,解码后的图像会以BGR的通道顺序进行存储,即蓝、绿、红的顺序,而不是通常的RGB的顺序。

1.3 imshow 显示图像函数

imshow()函数用于在指定的窗口中显示一幅图像, 函数原型如下。

void imshow(const String& winname, InputArray mat);

第一个参数:const string&类型的winname,填需要显示的窗口标识名称。第二个参数:InputArray类型的mat, 填需要显示的图像。

imshow函数用于在指定的窗口中显示图像。如果窗口是用CV_WINDOW_AUTOSIZE(默认值)标志创建的,那么显示图像原始大小。否则,将图像进行缩放以适合窗口。

imshow函数缩放图像,取决于图像的深度,具体如下。

如果载入的图像是 8 位无符号类型(8-bit unsigned),就显示图像本来的样子。如果图像是 16 位无符号类型(16-bit unsigned)或 32 位整型( 32-bit integer),便用像素值除以 256。也就是说,值的范围是[0,255 x 256]映射到[0,255]。如果图像是 32 位浮点型(32-bit floating-point), 像素值便要乘以 255。也就是说, 该值的范围是[0,1]映射到[0,255]。

1.4 namedWindow 创建窗口函数

namedWindow函数用于创建一个窗口。若是简单地进行图片显示,可以略去namedWindow函数的调用,即先调用imread读入图片,然后用imshow直接指定出窗口名进行显示即可。

但需要在显示窗口之前就用到窗口名时, 比如我们后面会马上讲到滑动条的使用, 要指定滑动条依附到某个窗口上, 就需要namedWindow函数先创建出窗口, 显式地规定窗口名称了。

namedWindow的函数原型如下:

void namedWindow(const String& winname, int flags = WINDOW_AUTOSIZE);

第一个参数,const string&型的name, 填写被用作窗口的标识符的窗口名称;第二个参数,int类型的flags, 窗口的标识, 可以填如下几种值;

enum WindowFlags {WINDOW_NORMAL= 0x00000000, //!< the user can resize the window (no constraint) / also use to switch a fullscreen window to a normal size.WINDOW_AUTOSIZE = 0x00000001, //!< the user cannot resize the window, the size is constrainted by the image displayed.WINDOW_OPENGL= 0x00001000, //!< window with opengl support.WINDOW_FULLSCREEN = 1,//!< change the window to fullscreen.WINDOW_FREERATIO = 0x00000100, //!< the image expends as much as it can (no ratio constraint).WINDOW_KEEPRATIO = 0x00000000, //!< the ratio of the image is respected.WINDOW_GUI_EXPANDED=0x00000000, //!< status bar and tool barWINDOW_GUI_NORMAL = 0x00000010, //!< old fashious way};

namedWindow函数的作用是通过指定的名字, 创建一个可以作为图像和进度条的容器窗口。如果具有相同名称的窗口已经存在, 则函数不做任何事情。

我们可以调用destroyWindow()或者destroyAllWindows()函数来关闭窗口, 并取消之前分配的与窗口相关的所有内存空间。

但是事实上, 对于代码量不大的简单程序来说, 我们完全没有必要手动调用上述的destroyWindow()或者destroyAllWindows()函数, 因为在退出时, 所有的资源和应用程序的窗口会被操作系统自动关闭。

1.5 imwrite 保存图像函数

OpenCV中, 输出图像到文件一般采用imwrite函数, 它的声明如下。

bool imwrite( const String& filename, InputArray img,const std::vector<int>& params = std::vector<int>());

第一个参数,const string&类型的filename,填需要写入的文件名。注意要带上后缀,如“save.jpg ”。第二个参数,InputArray类型的img, 一般填一个Mat类型的图像数据。第三个参数,const vector<int>&类型的params, 表示为特定格式保存的参数编码。它有默认值vector<int>(), 所以一般情况下不需要填写。而如果要填写的话,有下面这些需要了解的地方: 对于JPEG格式的图片, 这个参数表示从 0 到100 的图片质量 (CV _IMWRITE_JPEG_ QUALITY), 默认值是 95。对于PNG格式的图片, 这个参数表示压缩级别(CV_IMWRITE_PNG_COMPRESSION) 从 0 到 9。较高的值意味着更小的尺寸和更长的压缩时间,默认值是 3。对于PPMPGM、或PBM格式的图片, 这个参数表示一个二进制格式标志(CV _IMWRITE_PXM_ BINARY),取值为 0 或1 , 默认值是 1 。

注意:imwrite函数用于将图像保存到指定的文件。图像格式是基于文件扩展名的,可保存的扩展名和imread中可以读取的图像扩展名一致。

2. 图像腐蚀

再来看如何用OpenCV实现最基本的形态学运算之腐蚀, 即用图像中的暗色部分“腐蚀”掉图像中的高亮部分。

#include <iostream>#include "opencv2/highgui.hpp" // OpenCV highgui 模块头文件#include "opencv2/imgproc.hpp" // OpenCV 图像处理头文件using namespace cv;int main(){Mat src = imread("./image/dog.jpg");// 载入图像if (src.empty())// 或者 if(!image.data) 判断图片是否加载成功{std::cout << "image not exist";return -1;}imshow("原始图片", src);// 显示图像// 进行腐蚀操作Mat element = getStructuringElement(MORPH_RECT, Size(15, 15));Mat dst;erode(src, dst, element);imshow("腐蚀图片", dst);// waitKey(30)等待30毫秒,以此检查用户是否使用任何键停止应用程序的执行。waitKey(0);// 等待任意按键按下,退出图片显示,return 0;}

程序首先依然是载入和显示一幅图像,然后定义一个Mat类型的变量来获得getStructuringElement函数的返回值,而getStructuringElement函数的返回值为指定形状和尺寸的结构元素(内核矩阵)。参数准备完毕,接着便可以调用erode函数进行图像腐蚀操作,最后调用imshow函数进行显示,用waitKey函数等待按键按下,以便能让窗口一直显示。

显示结果:

3. 图像模糊

接着让我们看看用OpenCV对图像进行均值滤波操作,模糊一幅图像的代码如何书写。主要使用进行均值滤波操作的blur函数,代码如下:

#include <iostream>#include "opencv2/highgui.hpp"#include "opencv2/imgproc.hpp"using namespace cv;int main(){Mat src = imread("./image/dog.jpg");// 载入图像if (src.empty())// 或者 if(!image.data) 判断图片是否加载成功{std::cout << "image not exist";return -1;}imshow("原始图片", src);// 显示图像// 进行均值滤波模糊操作Mat dst;blur(src, dst, Size(15, 15));imshow("模糊图片", dst);waitKey(0);// 等待任意按键按下,退出图片显示return 0;}

显示结果

4. 边缘检测

接着我们来看看如何用OpenCV进行canny边缘检测。载入图像,并将其转成灰度图,再用blur函数进行图像模糊以降噪,然后用canny函数进行边缘检测,最后进行显示。

#include <iostream>#include "opencv2/highgui.hpp"#include "opencv2/imgproc.hpp"using namespace cv;int main(){Mat src = imread("./image/dog.jpg");// 载入图像if (src.empty())// 或者 if(!image.data) 判断图片是否加载成功{std::cout << "image not exist";return -1;}imshow("原始图片", src);// 显示图像Mat dst, edge, gray;// 创建与原图片同类型和大小的矩阵( dst )dst.create(src.size(), src.type());// 将原图像转换为灰度图像 OpenCV2 版本// cvtColor(src, gray, CV_BGR2GRAY)// OpenCV3 或者 OpenCV4 版本cvtColor(src, gray, COLOR_BGR2GRAY);// 先使用5 x 5 内核来降噪blur(gray, edge, Size(5, 5));// 运行Canny 算子Canny(edge, edge, 1, 3, 3);imshow("Canny 边缘检测", edge);waitKey(0);// 等待任意按键按下,退出图片显示return 0;}

显示结果:

5. 其它示例

#include <iostream>#include <string>#include <sstream>using namespace std;// OpenCV includes#include "opencv2/core.hpp"#include "opencv2/highgui.hpp"using namespace cv;const int CV_GUI_NORMAL= 0x10;int main( int argc, const char** argv ){// Read imagesMat lena= imread("../lena.jpg");Mat photo= imread("../photo.jpg");// Create windowsnamedWindow("Lena", WINDOW_NORMAL);// Checking if Lena image has been loadedif (!lena.data) {cout << "Lena image missing!" << endl;return -1;}namedWindow("Photo", WINDOW_AUTOSIZE);if (!photo.data) {cout << "Lena image missing!" << endl;return -1;}// Move window// moveWindow函数将窗口移动到桌面的任何区域moveWindow("Lena", 10, 10);moveWindow("Photo", 520, 10);// show imagesimshow("Lena", lena);imshow("Photo", photo); // Resize window, only non autosize// resizeWindow函数将Lena窗口的大小调整为512像素,该函数有三个参// 数:window name、width和height。resizeWindow("Lena", 512, 512); // wait for any key presswaitKey(0);// Destroy the windowsdestroyWindow("Lena");destroyWindow("Photo");// Create 10 windowsfor(int i =0; i< 10; i++){ostringstream ss;ss << "Photo " << i;namedWindow(ss.str());moveWindow(ss.str(), 20*i, 20*i);imshow(ss.str(), photo);}waitKey(0);// Destroy all windowsdestroyAllWindows();return 0;}

以上都是原生OpenCV的一些基本图像处理过滤器,但也有新的开源替代品,它们能够添加更多功能,比如cvui(https://dovyski.github.io/cvui/) 或OpenCVGUI(https://damiles.github.io/OpenCVGUI/)。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。