在使用图像时,一些最基本且必须掌握的操作包括从磁盘读取图像、显示图像、访问图像的像素值以及将图像从一个颜色空间转换到另一个颜色空间。
本教程将解释这些基本操作,首先描述数字图像如何以其空间坐标和强度值的形式进行表示。
在本教程中,您将熟悉使用图像时必不可少的最基本的OpenCV操作。
完成本教程后,您将了解:
- 数字图像如何以其空间坐标和强度值的形式进行表示。
- 如何在OpenCV中读取和显示图像。
- 如何访问图像的像素值。
- 图像如何从一个颜色空间转换到另一个颜色空间。
通过我的书《OpenCV 机器学习》启动您的项目。它提供了带有可用代码的自学教程。
让我们开始吧。

使用OpenCV读取和显示图像,以及在颜色空间之间进行转换
图片由 Andrew Ridley 拍摄,保留部分权利。
教程概述
本教程分为三个部分;它们是:
- 图像的表示
- 在OpenCV中读取和显示图像
- 在颜色空间之间进行转换
图像的表示
数字图像由像素组成,每个像素的特征在于其在图像空间内的*空间坐标*及其*强度*或*灰度值*。
本质上,图像可以用一个二维函数 I(x, y) 来描述,其中 x 和 y 表示上述空间坐标,I 在任何图像位置 (x, y) 的值表示像素强度。在数字图像中,空间坐标和强度值都是有限的离散量。
我们刚刚描述的数字图像类型称为*灰度*图像,这是因为它包含一个单一通道,其中像素值仅携带强度信息。像素强度通常用 [0, 255] 范围内的整数值表示,这意味着每个像素可以取 256 个离散值中的任何一个。
另一方面,RGB图像由三个通道组成,即*红色*、*绿色*和*蓝色*。
RGB色彩模型并非唯一存在的模型,但它可能是许多计算机视觉应用中最常用的模型。它是一种加色模型,指的是通过混合(或添加)不同颜色光源的光谱来创建颜色的过程。
由于RGB图像由三个通道组成,因此我们需要三个函数来描述它:IR(x, y)、IG(x, y) 和 IB(x, y),分别对应于红色、绿色和蓝色通道。因此,在RGB图像中,每个像素值都由一个强度值三元组表示。
在OpenCV中读取和显示图像
让我们首先从Python的OpenCV库中导入`imread`方法。
1 |
from cv2 import imread |
然后继续读取一个RGB图像。为此,我下载了这张图片并将其以“Dog.jpg”的名称保存在名为“Images”的文件夹中。
1 |
img = imread('Images/Dog.jpg') |
imread
方法返回一个NumPy数组img
,其中包含图像像素值。我们可以如下检查数组的数据类型和维度:
1 |
print('Datatype:', img.dtype, '\nDimensions:', img.shape) |
1 2 |
数据类型:uint8 尺寸:(4000, 6000, 3) |
返回的信息告诉我们,数组的数据类型是uint8,这意味着我们正在处理8位无符号整数值。这意味着图像每个通道中的像素可以取28 = 256个值中的任何一个,范围从0到255。这与我们上面回顾的图像表示完全一致。我们还了解到数组的维度是4000 × 6000 × 3,分别对应于图像的行数、列数和通道数。
图像是一个三维NumPy数组。因此,您可以使用NumPy语法来操作该数组。
现在让我们尝试访问位于图像左上角的第一个像素的值。请记住,Python中的数组是零索引的,因此此像素的坐标是 (0, 0)。
1 |
print(img[0, 0]) |
1 |
[173 186 232] |
从输出中您可以看到,正如所料,每个像素带有三个值,分别对应组成图像的三个通道。在下一节中,我们将发现这三个值分别对应于哪个特定通道。
注意:需要记住的一个重要点是,如果`imread`方法未能加载输入图像(因为提供的图像名称不存在或其路径无效),它本身不会生成错误,而是返回一个`NoneType`对象。因此,在继续运行最终使用`img`值的进一步代码之前,可以包含以下检查:
1 2 |
if img is not None: ... |
接下来,我们将使用Matplotlib包以及OpenCV的`imshow`方法显示图像。`imshow`方法将其第一个参数作为将包含图像的窗口的名称,第二个参数作为要显示的图像。我们还将在图像显示后调用OpenCV的`waitkey`函数,该函数等待键盘事件指定毫秒数。如果输入值为0,则`waitkey`函数将无限期等待,允许我们看到显示的窗口,直到生成键盘事件。
- 使用 Matplotlib
1 2 3 4 5 |
import matplotlib.pyplot as plt plt.imshow(img) plt.title('使用Matplotlib显示图像') plt.show() |
- 使用OpenCV
1 2 3 4 |
from cv2 import imshow, waitKey imshow('使用OpenCV显示图像', img) waitKey(0) |
如果您对Matplotlib生成的输出感到惊讶,并想知道这是如何发生的,其原因是OpenCV读取并显示图像是按BGR而不是RGB顺序。
OpenCV的早期开发者之所以选择BGR颜色格式(而非RGB),是因为当时BGR颜色格式在软件提供商和相机制造商中非常流行。
使用Python掌握OpenCV 4,2019年。
另一方面,Matplotlib 使用 RGB 颜色格式,因此,在正确显示 BGR 图像之前,需要先将其转换为 RGB 格式。
想开始学习 OpenCV 机器学习吗?
立即参加我的免费电子邮件速成课程(附示例代码)。
点击注册,同时获得该课程的免费PDF电子书版本。
使用 OpenCV,您还可以将 NumPy 数组作为图像写入文件,如下所示:
1 2 |
from cv2 import imwrite imwrite("output.jpg", img) |
当您使用OpenCV的`imwrite()`函数写入图像时,您必须确保NumPy数组的格式符合OpenCV的预期,即它是一个uint8类型的3维数组,按行×列×通道,并采用BGR通道顺序。
在颜色空间之间进行转换
图像从一个颜色空间到另一个颜色空间的转换可以通过OpenCV的cvtColor
方法实现,该方法将源图像作为输入参数,并带有一个颜色空间转换代码。
为了在 BGR 和 RGB 颜色空间之间进行转换,我们可以使用以下代码:
1 2 3 |
from cv2 import cvtColor, COLOR_BGR2RGB img_rgb = cvtColor(img, COLOR_BGR2RGB) |
如果我们尝试用 Matplotlib 再次显示图像,现在可能会看到它显示正确。
1 2 |
plt.imshow(img_rgb) plt.show() |
如果我们还要访问新转换的RGB图像的第一个像素值:
1 |
print(img_rgb[0, 0]) |
1 |
[232 186 173] |
并将其与我们之前打印的BGR图像的值 [173 186 232] 进行比较,我们可能会注意到第一个和第三个值现在已经交换。这告诉我们,值的顺序因此对应于图像通道的顺序。
BGR到RGB并非此方法可实现的唯一颜色转换。实际上,有许多颜色空间转换代码可供选择,例如`COLOR_RGB2HSV`,它在RGB和HSV(色相、饱和度、值)颜色空间之间进行转换。
另一个流行的转换是从RGB到灰度,如前所述,预期结果是一个单通道图像。让我们来试一下:
1 2 3 4 5 6 |
from cv2 import COLOR_RGB2GRAY img_gray = cvtColor(img_rgb, COLOR_RGB2GRAY) imshow(‘灰度 图像', img_gray) waitKey(0) |
转换似乎进行得很顺利,但我们也要尝试访问坐标 (0, 0) 处的第一个像素值。
1 |
print(img_gray[0, 0]) |
1 |
198 |
正如预期,只打印出一个数字,对应于像素的强度值。
值得注意的是,这并不是将图像转换为灰度的唯一方法。实际上,如果我们正在处理一个只需要使用灰度图像(而非RGB图像)的应用程序,那么我们也可以选择直接以灰度模式读取图像。
1 2 3 4 5 6 |
from cv2 import IMREAD_GRAYSCALE img_gray = imread('Images/Dog.jpg', IMREAD_GRAYSCALE) imshow(‘灰度 图像', img_gray) waitKey(0) |
注意:这里的OpenCV文档警告说,使用`IMREAD_GRAYSCALE`会在可用时利用编解码器的内部灰度转换,这可能导致与`cvtColor()`不同的输出。
imread
方法还支持其他几个标志值,其中两个是IMREAD_COLOR
和IMREAD_UNCHANGED
。IMREAD_COLOR
标志是默认选项,它将图像转换为BGR颜色,忽略任何透明度。而IMREAD_UNCHANGED
则读取可能还包含alpha通道的图像。
进一步阅读
如果您想深入了解,本节提供了更多关于该主题的资源。
书籍
- 使用 Python 精通 OpenCV 4, 2019.
网站
- OpenCV,https://opencv.ac.cn/
- OpenCV颜色转换代码,https://docs.opencv.ac.cn/4.x/d8/d01/group__imgproc__color__conversions.html#func-members
总结
在本教程中,您熟悉了在图像处理时必不可少的最基本的 OpenCV 操作。
具体来说,你学到了:
- 数字图像如何以其空间坐标和强度值的形式进行表示。
- 如何在OpenCV中读取和显示图像。
- 如何访问图像的像素值。
- 图像如何从一个颜色空间转换到另一个颜色空间。
你有什么问题吗?
在下面的评论中提出您的问题,我将尽力回答。
谢谢您
亲爱的 Stefania 博士,
在文章中您提到了各种颜色空间,如 RGB、BGR、HSV 和 CMYK。
在进行图像处理时,是否有任何颜色空间比其他颜色空间在计算上更高效?
谢谢你
安东尼,悉尼