OpenCV的highgui模块

2023-05-16

Opencv把用于操作系统、文件系统以及摄像机等硬件设备交互的函数纳入到highgui(High-level Graphical User Interface)模块中,我们可以利用该模块方便地打开窗口、显示图像、读出或写入图像相关的文件(图像和视频)、处理简单的鼠标点击、鼠标移动和键盘事件等等众多功能。

图像的载入与保存

使用cv::imread()读取图片

cv::imread():
    cv::Mat cv::imread(
        const string &filename,            //Input filename
        int     flags=cv::IMREAD_COLOR     //Flags set how to interpret file
};

默认情况下,flags被设置为cv::IMREAD_COLOR,这个值表示图片将被以三通道8位的格式读取,在这种情况下,即使原始文件中的图像是灰度图像,读取到内存中的仍然有三通道,每个通道拥有相同数据的图像。

如果flags被设置为cv::IMREAD_GRAYSCALE,那么不管文件内部图像是几通道的,图片都以灰度图像的格式加载。 

flags的另外一个值是cv::IMREAD_ANYCOLOR,在此种情况下,图片的载入方式取决于其内部图像的具体情况,如果是彩色图像,就以三通道的形式载入,如果是灰度图像,则按单通道的形式载入。

CV::imread()的标志
cv::IMREAD_COLOR总是读取三通道图像
cv::IMREAD_GRAYSCALE总是读取单通道图像
cv::IMREAD_ANYCOLOR通道数由文件实际通道数决定(不超过3)
cv::IMREAD_ANYDEPTH允许加载超过8bit深度
cv::IMREAD_UNCHANGED读取图像时,将保留图像中的alpha通道
#include<iostream>
#include<opencv2/highgui/highgui.hpp>
using namespace std;
using namespace cv;
int main()
{
	Mat src= imread("C:\\Users\\32498\\Pictures\\17.png",IMREAD_COLOR);//IMREAD_COLOR 三通道读取
	imshow("src", src);

	Mat src_gray = imread("C:\\Users\\32498\\Pictures\\17.png", IMREAD_GRAYSCALE);//IMREAD_GRAYSCALE 单通道读取
	imshow("src_gray", src_gray);
    waitKey();
}

运行结果如下 

 以不同的方式读取同一幅图片,得到不同的结果。

使用cv::imwrite()保存图像

cv::imwrite()有三个输入参数

bool cv::imwrite(
    const string&    filename,                    //Input filename
    cv::InputArray    image,                    //image to write to file
    const vector<int>& params = vector<int>()    //optional for parameterized fmts
)

第一个参数给定了文件名,文件名的拓展部分用来决定以何种格式保存图像(比如常见的.jpg .png .tif .bmp等格式)

第二个参数是待存储的输入图像

第三个参数被用作特殊类型文件的写入操作时所需的数据

我们在前一个程序的基础上再增加一行语句,保存图片

imwrite("test.png", src); 
#include<iostream>
#include<opencv2/highgui/highgui.hpp>
using namespace std;
using namespace cv;
int main()
{
	Mat src= imread("C:\\Users\\32498\\Pictures\\17.png",IMREAD_COLOR);//IMREAD_COLOR 三通道读取
	imshow("src", src);

	Mat src_gray = imread("C:\\Users\\32498\\Pictures\\17.png", IMREAD_GRAYSCALE);//IMREAD_GRAYSCALE 单通道读取
	imshow("src_gray", src_gray);

	imwrite("test.png", src); 
	waitKey();
}

最终我们就把这张图片保存了下来,那么保存在哪里呢?

就在当前程序的文件夹里面 

当然也可以使用绝对路径设置图片要保存的地方,比如我们这里将路径设置为

imwrite("C:\\Users\\32498\\Pictures\\test.png", src); 

就可以将图片保存到这个路径下, 

 

视频的处理

使用cv::VideoCapture对象读取视频流

        首先我们需要一个cv::VideoCapture对象 ,它包含我们从摄像机或者视频文件读取每一帧所必需的信息,根据数据源的不同,我们需要以不同的调用方式来构建cv::VideoCapture对象:

cv::videoCapture::videoCapture(
    cosnt string& filename            //Input filename
);


cv::videoCapture::videoCapture(
    int device                        // video capture device id
);


cv::videoCapture::videoCapture();

在第一个构造函数中,只需要给出视频文件的文件名就可以了,opencv会自动打开对应的视频文件,并准备后续的读取操作 。如果打开成功,那么便可以从中获取图像帧,成员函数cv::VideoCapture::isOpened()会返回true。

输入参数为整型变量的cv::VideoCapture::VideoCapture()函数,即就是第二种构造函数,我们给出一个标识符来表明我们希望使用哪个摄像机以及我们希望操作系统以何种方式与该摄像机通信。对于摄像机来说,它只是一个标识码,如果当前系统下只有以恶搞摄像机时参数为0,当有多个摄像机同时处于当前系统中时,参数递增即可。在某些平台上,你可以给cv::VideoCapture::VideoCapture()函数传入-1,这会使OpenCV弹出一个选择窗口,让你能够手动选择希望使用的相机。

创建VideoCapture()对象的最后一种方式是直接创建一个VideoCapture对象而不提供关于即将打开的硬件设备的任何信息。

cv::VideoCapture cap;
cap.open("test.avi");

这种情况下,虽然会创建一个VideoCapture对象,但无法直接使用,直到显式打开你想要读取数据的视频源。

使用cv::VideoCapture::read()从视频流中读取图像

bool cv::VideoCapture::read(
    cv::OutputArray image
);

一旦有了一个cv::VideoCapture对象,便可以从中读取图像了,最简单的一种方式是调用cv::VideoCapture::read()函数,该函数从cv::VideoCapture表示的文件中读取下一帧数据,并将数据插入到你提供的变量中。

使用cv::VideoCapture::operator>>()从视频流读取图像数据

cv::VideoCapture& cv::VideoCapture::operator>>(
    cv::Mat &image
);

也可以使用重载函数 cv::VideoCapture& cv::VideoCapture::operator>>()(输入流操作符)从VideoCapture对象中读取下一帧数据。

使用cv::VideoCapture::grab()和cv::VideoCapture::retrieve()从视频流中读取图像数据

为了取代上述的一次从相机或者视频源只读取一张图像并完成解码的操作,你可以将其拆分为一个捕获操作(类似于内存的拷贝)和恢复操作(用于实际完成对已抓取的数据进行解码)

bool cv::VideoCapture::grab(void);
bool cv::VideoCapture::retrieve(
    cv::OutputArray image,
    int  channel=0
);

grab()函数将当前可以使用的图像数据拷贝至用户看不到的一个内部缓冲区。先完成数据的抓取(grab),将数据安全放入缓存区之后再进行解码恢复(retrieve),这样做十分有意义。因为在多相机读取时,需要尽可能缩短多个相机获取的图像帧之间的时间差。

相机属性cv::VideoCapture::get()和cv::VideoCapture::set()

视频文件通常不仅仅包含一帧一帧的图像,还包括许多重要的元数据,当打开一个视频文件时,相关信息就会被拷贝到cv::VideoCapture对象内部数据区,如果能够实现对该数据区参数的读取或者写入将会非常有用,这两个函数就帮我们实现了。

 HighGui图形用户接口

HighGUI的图形用户输入工具只支持三个基本的交互、即按键、鼠标在图像区域点击、鼠标滚轮

使用cv::namedWindow()创建一个窗口

首先我们想用HighGUI在屏幕上创建一个窗口并显示图像。cv::namedWindow()可以完成这一功能,它需要一个窗口的名称和一个标识符flag作为参数输入,标识符flag用于表示窗口是否需要自动调整大小来适应我们输入的图像的大小,完整的函数定义如下

int cv::namedWindow(
    const string& name,           //handle used to identify window
    int flags = 0                //tell window to autosize
);

flag可以设置为0(默认值)WINDOW_NORMAL,表示用户可以调整窗口的大小。

#include<iostream>
#include<opencv2/highgui/highgui.hpp>
using namespace std;
using namespace cv;
int main()
{
	Mat src= imread("C:\\Users\\32498\\Pictures\\17.png");
	namedWindow("src", WINDOW_NORMAL);//用户可以改变窗口大小
	imshow("src", src);

	Mat src1 = imread("C:\\Users\\32498\\Pictures\\R-C(3).jpg");
	namedWindow("src1", 0);//用户可以改变窗口大小
	imshow("src1", src1);

	waitKey();


}

 

图中左上角出现红框内的双向箭头表示我们可以通过鼠标来控制图片的大小,对图片进行伸缩。 

或设置为cv::WINDOW_AUTOSIZE,此时加载不同的图像时,HighGUI会自动对窗口大小进行自适应调整,但是用户不能调整窗口。例如这样一段代码

#include<iostream>
#include<opencv2/highgui/highgui.hpp>
using namespace std;
using namespace cv;
int main()
{
	Mat src= imread("C:\\Users\\32498\\Pictures\\17.png");
	namedWindow("src", WINDOW_AUTOSIZE);//用户不可以改变窗口大小
	imshow("src", src);

	Mat src1 = imread("C:\\Users\\32498\\Pictures\\R-C(3).jpg");
	namedWindow("src1", WINDOW_AUTOSIZE);//用户不可以改变窗口大小
	imshow("src1", src1);

	waitKey();

}

我们使用了WINDOW_AUTOSIZE作为flag, 加载不同的图像时,HighGUI会自动对窗口大小进行自适应调整

 

可以看到它会根据图片大小自动调整窗口(但是我们不能通过鼠标改变图片的大小)。

当然flag还有其他的值,有需要的话大家可以自己去尝试用一下

 

 通过创建窗口,我们可以放置一些东西在里面。加入我们现在不需要一个窗口,如何销毁一个窗口,也很简单使用函数cv::destoryWindow(),它只有一个参数,就是创建窗口时给窗口指定的名称。

int cv::destoryWindow(
    const string& name,
)

通过cv::imshow()显示函数 

通过imshow()函数可以加载一张图片到窗口,方便我们在窗口中查看和欣赏图像

void cv::imshow(
    const string &name,
    cv::InputArray image
);

第一个参数是我们将要用来展示窗口的名称,第二个参数是将要展示的图像。

注意如果我们只是写了如下代码想用来欣赏一幅图像的话,那很不幸地你会看到这幅图像在屏幕上一闪而过,并不会停留,

#include<iostream>
#include<opencv2/highgui/highgui.hpp>
using namespace std;
using namespace cv;
int main()
{
	Mat src= imread("C:\\Users\\32498\\Pictures\\17.png");
	imshow("src", src);
}

为什么呢?在这段代码后面还需要加上一句代码,这样我们才能愉快的观察图片,需要加的代码就是我们下面即将学习的waitKey()函数

更新窗口和cv::waitKey()函数

cv::waitKey()函数是用于对键盘事件进行特定时长的等待。

int cv::waitKey(
    int delay=0
);

这个函数接受一个参数delay,这是在自动返回之前等待按键的时间量(以毫秒为单位),如果延迟设为0,cv::waitKey()将无限期地等待按键。这样我们要显示的图片就会一直停留在屏幕上供我们欣赏。

#include<iostream>
#include<opencv2/highgui/highgui.hpp>
using namespace std;
using namespace cv;
int main()
{
	Mat src= imread("C:\\Users\\32498\\Pictures\\17.png");
	imshow("src", src);
	waitKey(0);

}

 

如果设置为waitKey(300),这张图片就会在屏幕上停留300毫秒然后程序会结束,图片也会消失。 

如果在延迟毫秒时间之前没有按键输入,cv::waitKey()将返回-1。 

通过上面的学习,我们已经能在图片上显示一幅图像了,现在我们再介绍一个函数

void cv::moveWindow(const char*name,int x,int y);

这个函数是用于对窗口在屏幕上进行简单移动,使得窗口的左上角坐标位于(x,y)点,比如

#include<iostream>
#include<opencv2/highgui/highgui.hpp>
using namespace std;
using namespace cv;
int main()
{
	Mat src= imread("C:\\Users\\32498\\Pictures\\17.png");
	namedWindow("src1", 0);
	moveWindow("src", 1200, 1200);
	imshow("src1", src);
	

	namedWindow("src2", 0);
	imshow("src2", src);
	moveWindow("src", 800, 800);
	waitKey(0);

}

 

我们可以看到通过设置moveWindow()函数设置坐标(x,y),同一幅图被显示在屏幕的不同位置 。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

OpenCV的highgui模块 的相关文章

  • Matlab 中 interp2 的类似 OpenCV Api

    有没有类似的功能 其工作原理与 interp2 x y frame z xd yd linear 0 在 OpenCV 中 功能cv remap 几乎可以满足您的要求 请参阅文档here http docs opencv org modul
  • Python 函数前的星号[重复]

    这个问题在这里已经有答案了 我正在关注这个教程 http www pyimagesearch com 2015 04 20 sorting contours using python and opencv comment 405768 ht
  • 相机姿态估计(OpenCV PnP)

    我正在尝试使用网络摄像头从具有已知全球位置的四个基准点的图像中获取全局姿态估计 我检查了许多 stackexchange 问题和一些论文 但似乎无法得到正确的解决方案 我得到的位置数字是可重复的 但与相机移动绝不成线性比例 仅供参考 我正在
  • 将四边形(四边形)拟合到斑点

    应用不同的过滤和分割技术后 我最终得到如下图像 我可以访问一些轮廓检测函数 这些函数返回该对象边缘上的点列表 或者返回一个拟合的多边形 尽管有很多边 远多于 4 个 我想要一种将四边形适合该形状的方法 因为我知道它是应该是四边形的鞋盒的正面
  • 屏幕截图中低分辨率文本的 OCR

    我正在编写一个 OCR 应用程序来从屏幕截图图像中读取字符 目前 我只关注数字 我的方法部分基于这篇博文 http blog damiles com 2008 11 basic ocr in opencv http blog damiles
  • 编译使用Basler相机的程序

    我正在尝试使用 Basler 相机捕获图像的 C 程序来工作 我拿到 来自制造商的代码 它应该 非常容易使用 但是 链接它有 成为一场噩梦 我的 C 时代已经过去了 最近只使用 Matlab 所以我可能会犯一些愚蠢的错误 但请赐教 代码如下
  • 如何使图像呈现出陈旧、布满灰尘、颜色褪色的外观?

    我有旧画的图像 这些画很旧 布满灰尘 颜色褪色 如图所示here https i stack imgur com xuoEF jpg 如何赋予任何图像这种 旧 外观 我找不到任何过滤器或 openCV 函数来实现这种类型的外观 EDIT 我
  • 使用相位相关和对数极坐标变换获得旋转位移

    我一直在编写一个脚本 它使用 cv2 计算两个图像之间的旋转位移phaseCorrelate method 我有两张图像 第二张是第一张图像的 90 度旋转版本 加载图像后 我将它们转换为对数极坐标 然后将它们传递到phaseCorrela
  • OpenCV findContours 破坏源图像

    我编写了一个在单通道空白图像中绘制圆形 直线和矩形的代码 之后 我只需找出图像中的轮廓 就可以正确获取所有轮廓 但找到轮廓后 我的源图像变得扭曲 为什么会出现这种情况 任何人都可以帮我解决这个问题 我的代码如下所示 using namesp
  • 在 Python 3.5 64 位上通过 pip 安装 OpenCV

    我尝试安装 OpenCV 但找不到任何合适的 pip 软件包 我决定上网查找有关如何安装它的官方文档 并发现this https opencv python tutroals readthedocs io en latest py tuto
  • 使用 openCV 和 python 检测物体

    我正在尝试使用 OpenCV 和 Python 检测下图中的白点 我尝试使用函数 cv2 HoughCircles 但没有成功 我需要使用不同的方法吗 这是我的代码 import cv2 cv import numpy as np impo
  • Opencv matchTemplate 和 np.where():仅保留唯一值

    继带有马里奥硬币的 opencv 教程 https opencv python tutroals readthedocs io en latest py tutorials py imgproc py template matching p
  • 如何在给定目标大小的情况下在 python 中调整图像大小,同时保留纵横比?

    首先 我觉得这是一个愚蠢的问题 对此感到抱歉 目前 我发现计算最佳缩放因子 目标像素数的最佳宽度和高度 同时保留纵横比 的最准确方法是迭代并选择最佳缩放因子 但是必须有更好的方法来做到这一点 一个例子 import cv2 numpy as
  • 提高 pytesseract 从图像中正确识别文本的能力

    我正在尝试使用读取验证码pytesseract模块 大多数时候它都能提供准确的文本 但并非总是如此 这是读取图像 操作图像以及从图像中提取文本的代码 import cv2 import numpy as np import pytesser
  • 如何计算图像中的 RGB 或 HSV 通道组合?

    我使用 python opencv 加载形状为 30 100 3 的图像 现在想要按颜色计算所有颜色的频率 我不是指单个通道 而是指通道组合 含义 3 个频道列表 例如 255 0 0 表示红色 255 255 0 表示黄色 100 100
  • OpenCV 错误:使用 COLOR_BGR2GRAY 函数时断言失败

    我在使用 opencv 时遇到了一个奇怪的问题 我在 jupyter 笔记本中工作时没有任何问题 但在尝试运行此 Sublime 时却出现问题 错误是 OpenCV错误 cvtColor中断言失败 深度 CV 8U 深度 CV 16U 深度
  • 如何将 mat 转换为 array2d

    我为dlib http dlib net face landmark detection ex cpp html那里的面部地标代码使用 array2d 来获取图像 但我喜欢使用 Mat 读取图像并转换为 array2d 因为 dlib 仅支
  • 如何在 OpenCV 中从 YUV 文件读取帧?

    如何在 OpenCV 中从 YUV 文件读取帧 我编写了一个非常简单的 python 代码来从二进制文件读取 YUV NV21 流 import cv2 import numpy as np class VideoCaptureYUV de
  • 创建 OpenCV 的 mouseCallback 函数的基于类的实现时遇到问题

    正如标题所示 我在基于类的 C 结构中实现 OpenCV 的 mouseCallback 函数时遇到了一些麻烦 请允许我解释一下 我定义了一个名为 BriskMatching 的类 在其中创建了一个名为 mouseCallback 的成员函
  • ffmpeg AVFrame 到 opencv Mat 转换

    我目前正在开发一个使用 ffmpeg 解码接收到的帧的项目 解码后 我想将 AVFrame 转换为 opencv Mat 帧 以便我可以在 imShow 函数上播放它 我拥有的是字节流 我将其读入缓冲区 解码为 AVFrame f fope

随机推荐