在本节中,我将向您展示如何使用 OpenCV 库函数从文件加载图像并在窗口中显示图像。
首先,打开C IDE并创建一个新项目。然后,您必须为 OpenCV 配置新项目。
代码语言:javascript复制#include <iostream>
#include <opencv2opencv.hpp>
using namespace cv;
using namespace std;
int main()
{
// 读取一个图像文件并赋给image变量
Mat image = imread("lena.png");
// 判断读取图像是否为空
if (image.empty())
{
cout << "没有发现读取图像文件";
// 输入人员字符
cin.get();
return -1;
}
// 定义一个窗体的名称
String winName = "lena 图像";
// 创建一个窗体用于显示图像
namedWindow(winName);
// 把图像显示到创建窗体上面
imshow(winName, image);
// 等待输入字符并关闭窗口
waitKey(0);
destroyWindow(winName);
}
将上述代码片段复制并粘贴到 IDE 中并运行它。请注意,您必须将代码中的“*C:UsersGerryDesktoplena.png*”替换为计算机中图像的有效位置。然后,您应该会看到如下图所示的输出。
解释
让我们逐行浏览上面的OpenCV程序。
代码语言:javascript复制//#include "stdafx.h"
这是由Visual Studio IDE生成的预编译头文件。如果您使用的是Visual Studio,请取消注释此行以避免编译错误。
opencv2/opencv.hpp 头文件本身将包含 OpenCV 库中所有其他必要的头文件。您必须仅包含此头文件才能编译 OpenCV 代码。
还应包含 iostream 头文件,因为我们在程序中使用 COUT 和 CIN 将错误消息打印到控制台。
所有 OpenCV 函数、类和数据结构都在 cv 命名空间内声明。因此,我们必须在程序顶部添加“**使用命名空间 cv”**行。否则,我们必须在每个 OpenCV 函数、类和数据结构之前附加 ’cv::“说明符。(例如 - cv::Mat, cv::imread() 等)。
我们还必须使用 std 命名空间,因为 cout、endl 和 cin 函数位于 std 命名空间内。
该函数从文件“*C:UsersGerryDesktoplena.png*”加载图像,并将其作为 Mat 对象返回。 在你的代码中,你必须将“*C:UsersGerryDesktoplena.png*”替换为计算机中图像文件的有效位置。
代码语言:javascript复制#include <opencv2/opencv.hpp>
#include <iostream>
using namespace cv;
using namespace std;
Mat image = imread("C:UsersGerryDesktoplena.png");
Mat imread(const String&filename, int flags = IMREAD_COLOR)
此函数从指定文件加载图像,并作为 Mat 对象返回。如果函数无法读取文件,它将返回一个空的 Mat 对象。
- 文件名 - 您必须提供图像文件的相对或绝对路径。如果要提供相对路径,则它应该是相对于cpp文件的。始终支持 JPEG、JPG、BMP、PNG、TIFF 和 TIF 图像文件类型。支持其他映像文件类型,具体取决于您的平台和安装的编解码器。
- flags - 标志参数有几个可能的值。在上面的程序中,我没有向此参数传递任何值,以便使用默认的IMREAD_COLOR参数。
- IMREAD_UNCHANGED - 图像将按原样加载。如果要在输入图像中获取 alpha 通道(如果可用),则必须使用此标志。
- IMREAD_GRAYSCALE - 图像将作为灰度图像加载(即 - 单通道图像,黑白图像)
- IMREAD_COLOR - 图像将作为BGR图像加载(即 - 3通道图像,彩色图像)
// Check for failure
if (image.empty())
{
cout << "Could not open or find the image" << endl;
cin.get(); //wait for any key press
return -1;
}
如果imread()函数无法加载图像,则返回的 Mat 对象将为空。如果 Mat 对象为空,**则 image.empty()** 函数将返回 true。在这种情况下,我们的程序会将错误消息打印到控制台并等待任何按键。当用户按键盘中的任意键时,程序将退出,返回 -1。最好检查图像是否为空并退出程序。否则,您的程序将在尝试执行imshow()函数时崩溃。
此函数创建一个名为“*lena*”的窗口。窗口的名称稍后将在此代码中用于标识窗口。
代码语言:javascript复制namedWindow(windowName); // Create a window
void namedWindow(const String&winname, int flags = WINDOW_AUTOSIZE) 此函数创建一个可用于放置图像和跟踪栏的窗口。如果已存在具有给定名称的窗口,则此函数不执行任何操作。
- winname - 窗口的名称。该名称将显示在新创建的窗口的标题栏中。此名称也是此窗口的标识符,它将在以后的 OpenCV 函数调用中用于标识窗口。
- 标志 - 确定窗口的大小。在上面的程序中,我没有向此参数传递任何值,因此将使用默认WINDOW_AUTOSIZE参数。
- WINDOW_AUTOSIZE - 用户无法调整窗口大小。图像将以其原始大小显示。
- WINDOW_NORMAL-用户可以调整窗口大小。
imshow(windowName, image); // Show our image inside the created window.
此函数在上一步中创建的窗口中显示图像。
void imshow(const String&winname, InputArray mat) 此函数在 winname 指定的窗口中显示图像。如果使用WINDOW_AUTOSIZE标志创建窗口,则图像将以其原始大小显示。否则,图像可能会缩放到窗口的大小。如果尚未通过调用 namedWindow() 函数创建窗口,则此函数将创建一个带有 WINDOW_AUTOSIZE 标志的窗口。 此函数调用后应遵循 waitKey(int) 函数调用,以便提供足够的时间在指定的持续时间(以毫秒为单位)内在窗口中绘制和显示图像。如果不调用waitKey(int)函数,图像将不会显示在窗口中。
- winname - 由 namedWindow() 函数创建的窗口的名称。
- mat - 保存图像的垫子对象waitKey(0); // Wait for any keystroke in the window
waitKey(0); // Wait for any keystroke in the window
waitKey(0) 函数永远等待按键。当按下任何键时,此函数返回键的 ASCII 值,您的程序将继续。
如果将正值传递给 waitKey() 函数,则它仅等待按键的持续时间,由传递的值(以毫秒为单位)指定。如果在此期间按下任何键,此函数将返回该键的 ASCII 值,您的程序将继续。如果在此期间没有按下任何键,它将返回 -1,程序将继续。
仅当程序至少打开了一个活动的 HIGHGUI 窗口时,此功能才有效。
此函数关闭以名称 windowName 标识的打开窗口,并取消分配任何关联的内存使用量。此功能对于上述程序不是必需的,因为当程序退出时,操作系统通常会关闭所有打开的窗口并取消分配任何关联的内存使用量。
代码语言:javascript复制destroyWindow(windowName); //destroy the created window
总结
在上面的部分中,您已经了解到, - 如何从文件加载图像 - 如何处理图像加载失败时的错误情况 - 如何创建窗口并显示图像 - 如何在不退出程序的情况下等待,直到用户按下某个键 - 如何销毁已创建的窗口