OpenCV计算机视觉入门之图像色彩空间转换
1. 引言
本文通过导入函数库、读取图像、转换图像色彩空间、缩放图像和保存图像五个步骤详细讲解了使用opencv-python库和Numpy库操作并保存图像的基本过程。
运行本文所讲解程序需要如下环境准备:
- 已有Python虚拟环境,并安装了opencv-python库、numpy库和matplotlib库;
- 已有Python虚拟环境可支持Jupyter Notebook运行。
2. 概念
2.1 数字图像
计算机视觉技术的作用对象是数字图像,数字图像由有限数量的元素组成,每个元素都有一个特定的位置和数值,这些元素也被称之为像素。在计算机中,图像数据是由数值矩阵的方式保存的,矩阵中的位置和数值与图像的像素点一一对应。
2.2 色彩空间
计算机中有多种色彩模型,以一维、二维至多维空间坐标来表示某一色彩,空间坐标系统所能定义的色彩范围即是色彩空间。常用的色彩空间主要有 RGB、HSL以及HSV等,不同的工业环境或视觉应用所使用的色彩空间不尽相同,因此,色彩空间转换经常在计算机视觉任务中的预处理环节出现。
3. 实践-图像读取
(1)导入函数库
首先要导入opencv-python库、numpy库和matplotlib库。“%matplotlib inline”表示要将图像在Jupyter Notebook的行内显示。
# 导入函数库
import cv2
import numpy as np
%matplotlib inline
import matplotlib.pyplot as plt
(2)指定读取图像路径
图像文件通常是保存在本地的,在读取图像时要明确图像的路径。最简单的指定图像路径的方式是直接赋值。示例中,将数据类型为字符串的图像相对路径赋值给imagePath变量。
# 指定图像路径
imagePath = './test.png'
[!notice] 提示-相对路径于绝对路径的辨析:
绝对路径就是文件的真正存在的路径,是从系统根目录开始的文件的完整路径。
相对路径是以某个目录为起点,相对于这个起点的路径,比如:
a) …/ 表示当前文件所在的目录的上一级目录
b) ./ 表示当前文件所在的目录(可以省略)
(3)使用imread()函数读取图像并保存到image变量中
imread()函数的格式为“cv2.imread(图片路径,读取方式)”,该方法方法从指定的文件加载图像。如果无法读取图像(由于缺少文件, 权限不正确, 格式不受支持或格式无效), 则此方法将返回一个空矩阵。imread()函数有“图片路径”和“读取方式”两个参数。其中,“图片路径”为要读取的图片在计算机中的保存位置,“读取方式”如下三种:
- cv2.IMREAD_COLOR:以彩色图片模式读取图像,此选项为默认参数。
- cv2.IMREAD_GRAYSCALE:以灰度模式读取图像。
- cv2.IMREAD_UNCHANGED:包括alpha的模式读取图像。
本任务示例中没有指定读取方式,程序会以默认的彩色图片模式读取。读取后的图像显示如图1所示。
image = cv2.imread(imagePath)
plt.imshow(image)
在OpenCV中,图像不是默认按通常的 RGB颜色通道读取的,而是按BGR的通道顺序存储的。因此,直接使用matplotlib的imshow()函数显示图像会发现显示的颜色是不正确的。
(4)转换通道排列
要显示正确的图像色彩,还需要进行色彩空间转换操作。Opencv库提供了cvtColor()函数来实现图像的色彩空间转换。在读取了原始图像之后,使用cvtColor()函数可以实现将按照BGR通道排列的图像转换为按RGB排列。代码中的“cv2.COLOR_BGR2RGB”指定了转换方式,“BGR2RGB”可以简单理解为“BGR to RGB”,也就是将图像从BGR色彩空间转换为RGB色彩空间的意思。常见的转换方式还有“cv2.COLOR_BGR2GRAY”、 “cv2.COLOR_GRAY2BGR”等,通过其命名方式即可以知道其指定的转换方式。转换后的图像颜色通道数与转换方式是一致的,比如,灰度图像是单通道的,所以使用“cv2.COLOR_BGR2GRAY”转换的图像就应该是单通道的。进行通道转换后的图像显示如图2所示,变换了通道顺序后的图像显示是正确的了。
image = cv2.cvtColor(image,cv2.COLOR_BGR2RGB)
plt.imshow(image)
(5)缩放图像
cv2.resize()函数用于图像的缩放操作,其模版如下:
cv.resize(图像地址, 缩放后的图像大小, 目标图像, X轴缩放比例, Y轴缩放比例, 插值方法)
以下程序示例中,目标图像参数设置为None,X轴缩放比例和Y轴缩放比例均设置为0.005,插值方法未指定,程序会使用默认的插值方法cv2.INTER_LINEAR。缩放后的图像如图3所示。
image = cv2.resize(image, None, fx=0.005, fy=0.005)
plt.imshow(image)
(6)保存图像
为了更好的理解图像的像素,本任务最后要将图片保存到CSV文件中。保存的CSV文件可以用Excel或Numbers软件打开,图像的每个像素值会被写入到相应的方格中。使用np.savetxt()方法可以实现将图像保存为CSV文件,np.savetxt()方法的模版如下所示:
numpy.savetxt(文件名, 要保存的数据)
如下示例代码中,指定了要保存的CSV文件名为“new.csv”,要保存的矩阵数据对象为“image”,delimiter = ‘,’表示使用逗号分隔字符,fmt = “%d”表示数值以整数形式保存。保存后的CSV文件部分表格如表1所示。
# 将图像矩阵保存为csv文件
np.savetxt("new.csv", image, delimiter=",", fmt="%d")
下表展示了所保存的图像像素点矩阵,矩阵大小为47 x 18,每一个方格都对应着图像的1个像素点。通过对照观察csv文件和示例图片找到像素点的对应关系,读者对于图像像素的概念以及数字图像在计算机中的保存方式的理解应该更深入了。
255 | 255 | 255 | … | … | 255 | 255 |
255 | 255 | 255 | … | … | 255 | 255 |
255 | 255 | 255 | … | … | 255 | 255 |
255 | 255 | 255 | … | … | 255 | 255 |
255 | 255 | 255 | … | … | 255 | 255 |
255 | 255 | 255 | … | … | 143 | 255 |
255 | 255 | 255 | … | … | 143 | 255 |
255 | 255 | 255 | … | … | 143 | 255 |
255 | 255 | 255 | … | … | 255 | 255 |
255 | 255 | 255 | … | … | 255 | 255 |
255 | 255 | 255 | … | … | 147 | 147 |
255 | 255 | 255 | … | … | 255 | 255 |
255 | 255 | 255 | … | … | 255 | 255 |
255 | 255 | 255 | … | … | 255 | 255 |
255 | 255 | 255 | … | … | 255 | 255 |
255 | 255 | 255 | … | … | 255 | 255 |
255 | 255 | 255 | … | … | 255 | 255 |
255 | 255 | 255 | … | … | 255 | 255 |
[!notice] 提示:image的变量类型
使用type( )函数可以输出image的变量类型,通过如下代码的运行结果可以看出,image的变量类型为一个numpy的ndarry对象。NumPy 的 ndarray 是一个(通常是固定大小)由相同类型和大小的数据组成的多维容器。由此可知,使用imread()函数是将图像读取为多位数组,并且可以通过索引访问和修改其中的数值实现图像的变换效果。
image = cv2.imread(imagePath)
print(type(image))
输出:<class ‘numpy.ndarray’>
5. 完整代码
本文所讲解内容的完整代码如下所示。
# 导入函数库
import cv2
import numpy as np
# 指定图像路径
imagePath = './test.png'
# 读取为灰度图像
image = cv2.imread(imagePath, cv2.IMREAD_GRAYSCALE)
# 缩放图像
image = cv2.resize(image, None, fx=0.005, fy=0.005)
# 将图像矩阵保存为csv文件
np.savetxt("new.csv", image, delimiter=",", fmt="%d")
6. 总结
本文讲解了使用opencv-python库和Numpy库实现图像的读取、变换和保存操作过程。