新闻  |   论坛  |   博客  |   在线研讨会
独家|OpenCV 1.4 对图像的操作
数据派THU | 2021-08-07 21:25:28    阅读:199   发布文章

图像的输入/输出

从文件中加载图像:

1.png

如果读入的是一个JPG文件,默认状态下会创建一个3通道图像。如果你需要将其制成灰度图像,则使用以下代码:

2.png

文件格式由其内容(前几个字节)确定。将图像保存为一个文件:

3.png

文件的格式由其扩展名确定。

用CV :: imdecode和CV :: imencode从内存中读取和写入图像。

基本的图像操作

访问像素亮度值

为了获取像素亮度值,首先必须知道图像的类型和通道数。下面是一个单通道灰度图像的示例(数据类型8UC1)和像素坐标x和y:

4.png

C ++版本:intensity.val [0]包含从0到255的值,需要注意的是x和y的排序。OpenCV图像采用了结构化的矩阵来表示,使用以下两种情形使用同样的协议 - 基于0的行索引(或y坐标)在先,后面跟随基于0的列索引(或x坐标)。此外,也可以使用下面的符号(仅适用于C ++ ):

5.png

下面,来看一个BGR色彩排序的3通道图像(由imread返回默认格式):

C ++代码

6.png

Python

7.png

对于数据类型为浮点值的图像,可以使用相同的方法(例如,可以通过运行Sobel算子获取一个通道的图像)(仅适用于C ++):

8.png

利用相同的方法可以修改像素亮度值:

9.png

OpenCV中有一些函数,尤其是在calib3d模块中,如CV :: projectPoints函数,可以将 2D或3D像素点值转换成Mat形式的矩阵。该矩阵包含一列,每一行对应于一个点,矩阵类型为32FC2或32FC3。利用std::vector可以很容易地构建出这样的矩阵(仅适用于C ++):

10.png

利用相同的方法Mat::at可以访问矩阵中的点(仅适用于C ++):

11.png

内存管理和引用计数

Mat是保持矩阵/图像特性的一种结构(包括行数和列数,数据类型等)和一个指向数据的指针。对应一个相同的图像数据,可以构建出多个Mat实例,此外, Mat还包含一个引用计数器,当Mat对象被释放时,利用引用计数器指针来决定是否重新分配数据。下面的这个例子是在不进行数据复制的情况下,创建两个MAT矩阵: (仅适用于C ++)

12.png

结果得到了一个3列的32FC1矩阵,而不是一个1列的32FC3矩阵。pointsMat使用像素点的数据,释放时无需重新分配内存。在这种特殊情况下,开发人员必须确保 points的生命周期要比比pointsMat的生命周期更长。如果需要复制数据的话,则使用cv::Mat::copyTo或者 cv::Mat::clone两个函数:

13.png

应为上述每个函数提供一个空的Mat输出,每一次实现均是对目标矩阵调用一次Mat::create。如果矩阵为空,则利用该方法为矩阵分配数据。如果矩阵不为空,并且大小和数据类型均无误,则该方法不起作用。然而,如果大小或数据类型与输入参数不同,则重新分配(和丢失)原有数据,重新分配一个新的数据:

14.png

基本操作

每一个像素矩阵均定义有一些快捷的操作符。例如,下面是如何从现有的灰度图像中提取出黑色图像IMG

15.png

选择感兴趣的区域:

16.png

将彩色图像转换成灰度图像:

17.png

将图像类型从8UC1变为 32FC1:

18.png

可视化图像

在算法开发过程中,如果能看到运行的中间结果是非常有用的。OpenCV提供了一种可视化图像的便捷方式。采用以下代码可以显示一副8U图像:

19.png

调用waitKey()函数启动消息传递周期,等待“图像”窗口的一次键盘键入。此时,需要将32F图像转换为8U类型的图像。例如:

20.png

这里没有必要使用CV :: namedWindow函数,因为它后面紧跟着CV :: imshow。然而,可以用cv::createTrackbar来改变窗口属性。

本文以C++语言代码为例,获取Java和python版本可在原文中查看:

https://docs.opencv.org/4.5.2/d5/d98/tutorial_mat_operations.html

*博客内容为网友个人发布,仅代表博主个人观点,如有侵权请联系工作人员删除。

参与讨论
登录后参与讨论
推荐文章
最近访客