f
(
x
,
y
)
f(x, y)
f(x,y),其中
(
x
,
y
)
(x, y)
(x,y) 是空间坐标,而
f
(
x
,
y
)
f(x, y)
f(x,y) 是图像在点
(
x
,
y
)
(x, y)
(x,y) 处的亮度或灰度或颜色值。另外,当f(x, y)和(x, y)值都是有限离散量时,该图像也被称为数字图像,此时:
- x
∈
[
0
,
h
−
1
]
x∈ [0, h-1]
x∈[0,h−1],其中
h
h
h 是图像的高度
2. y
∈
[
0
,
w
−
1
]
y∈ [0, w-1]
y∈[0,w−1],其中
w
w
w 是图像的宽度
3. f
(
x
,
y
)
∈
[
0
,
L
−
1
]
f(x, y)∈ [0,L-1]
f(x,y)∈[0,L−1],其中
L
=
256
L=256
L=256 (对于8位灰度图像)
彩色图像也可以用同样的方式表示,只是我们需要定义三个函数来分别表示红色、绿色和蓝色值。这三个单独的函数中的每一个都遵循与为灰度图像定义的
f
(
x
,
y
)
f(x, y)
f(x,y) 函数相同的公式。我们将这三个函数的子索引 R、G 和 B 分别表示为
f
R
(
x
,
y
)
f_R(x, y)
fR(x,y)、
f
G
(
x
,
y
)
f_G(x, y)
fG(x,y) 和
f
B
(
x
,
y
)
f_B(x, y)
fB(x,y)。
同样,黑白图像也可以表示为相同的形式,其仅需要一个函数来表示图像,且
f
(
x
,
y
)
f(x, y)
f(x,y) 只能取两个值。通常,0 表示黑色、1 表示白色。
下图显示了三种不同类型的图像(彩色图像、灰度图像和黑白图像):
数字图像可以看作是真实场景的近似,因为
f
(
x
,
y
)
f(x, y)
f(x,y) 值是有限的离散量。此外,灰度和黑白图像每个点只对应有一个值,彩色图像每个点需要三个函数对应于图像的红色、绿色和蓝色分量。
图像文件类型
尽管在 OpenCV 中处理的图像时,可以将图像看作 RGB 三元组的矩阵(在 RGB 图像模型情况下),但它们不一定是以这种格式创建、存储或传输的。有许多不同的文件格式,如GIF、PNG、位图或JPEG,使用不同形式的压缩(无损或有损)来更有效地表示图像。
下表列示了 OpenCV 支持的文件格式及其关联的文件扩展名:
文件格式 | 文件扩展名 |
---|---|
Windows bitmaps | *.bmp和*.dib |
JPEG files | *.JPEG、*.jpg 和 *.jpe |
JPEG 2000 files | *.jp2 |
Portable Network Graphics | *.png |
Portable image format | *.pbm、*.pgm 和 *.ppm |
TIFF files | *.TIFF 和 *.tif |
对图像应用无损或有损压缩算法,可以得到比未压缩图像占据存储空间小的图像。其中,在无损压缩算法中,得到的图像与原始图像等价,也就是说,经过反压缩过程后,得到的图像与原始图像完全等价(相同);而在有损压缩算法中,得到的图像并不等同于原始图像,这意味着图像中的某些细节会丢失,在许多有损压缩算法中,压缩级别是可以调整的。
OpenCV中的坐标系
为了更好的展示 OpenCV 中的坐标系以及如何访问各个像素,查看以下低分辨率图像为例:
这个图片的尺寸是 32×41 像素,也就是说,这个图像有 1312 个像素。为了进一步说明,我们可以在每个轴上添加像素计数,如下图所示:
现在,我们来看看
(
x
,
y
)
(x, y)
(x,y) 形式的像素索引。请注意,像素索引起始值为零,这意味着左上角位于
(
0
,
0
)
(0, 0)
(0,0),而不是
(
1
,
1
)
(1, 1)
(1,1)。下面的图像,索引了 4 个单独的像素,图像的左上角是原点的坐标:
单个像素的信息可以从图像中提取,方法与 Python 中引用数组的单个元素相同。
OpenCV中的通道顺序
在 OpenCV 使用中,使用的颜色通道顺序为 BGR 颜色格式而不是 RGB 格式。可以在下图中看到三个通道的顺序:
BGR 图像的像素结构如下图所示,作为演示,图示详细说明了如何访问pixel(y=n, x=1):
Tips:OpenCV 的最初开发人员选择了 BGR 颜色格式(而不是 RGB 格式),是因为当时 BGR 颜色格式在软件供应商和相机制造商中非常流行,因此选择 BGR 是出于历史原因。
此外,也有其他 Python 包使用的是 RGB 颜色格式(例如,Matplotlib 使用 RGB 颜色格式,Matplotlib 是最流行的 2D Python 绘图库,提供多种绘图方法,可以查看 Python-Matplotlib 可视化获取更多详细信息)。因此,我们需要知道如何将图像从一种格式转换为另一种格式。
当我们掌握了将图像从一种格式转换为另一种格式的方法后,就可以选择使用 OpenCV
进行图像处理,同时利用 Matplotlib
包提供的函数来显示图像,接下来,让我们看看如何处理两个库采用的不同颜色格式。
首先,我们使用 cv2.imread()
函数加载图像:
import cv2
img_OpenCV = cv2.imread('sigonghuiye.jpeg')
图像存储在 img_OpenCV
变量中,因为 cv2.imread()
函数以 BGR 顺序加载图像。然后,我们使用 cv2.split()
函数将加载的图像分成三个通道 (b, g, r) 。这个函数的参数就是我们要分割的图像:
b, g, r = cv2.split(img_OpenCV)
下一步是合并通道(以便根据通道提供的信息构建新图像),但合并时顺序与原图像不同。我们更改 b 和 r 通道的顺序以遵循 RGB 格式,即我们所需要的 Matplotlib 格式:
img_matplotlib = cv2.merge([r, g, b])
此时,我们有两个图像 (img_OpenCV 和 img_matplotlib),接下来,我们将分别使用 OpenCV 和 Matplotlib 绘制她们,以便我们可以对比结果。首先,我们将用 Matplotlib 显示这两个图像。
为了在同一个窗口中使用 Matplotlib 显示两个图像,我们将使用 subplot
,它将多个图像放置在同一个窗口中。可以在 subplot
中使用三个参数,例如 subplot(m,n,p)
,此时,子图处理
m
×
n
m \times n
m×n 网格中的图,其中
m
m
m 确定行数,
n
n
n 确定列数,而
p
p
p 确定要在网格中放置图的位置。要使用 Matplotlib
显示图像,需要使用 imshow
函数。
在这种情况下,当我们水平显示两个图像时,
m
=
1
m = 1
m=1、
n
=
2
n = 2
n=2 。我们将对第一个子图 (img_OpenCV) 使用
p
=
1
p = 1
p=1,对第二个子图(img_matplotlib) 使用
p
=
2
p = 2
p=2:
from matplotlib import pyplot as plt
plt.subplot(121)
plt.imshow(img_OpenCV)
plt.subplot(122)
plt.imshow(img_matplotlib)
plt.show()
程序输出如下图所示:
可以看出,第一个子图以错误的颜色( BGR 顺序)显示图像,而第二个子图以正确的颜色( RGB 顺序)显示图像。接下来,我们使用 cv2.imshow()
显示两个图像:
cv2.imshow('bgr image', img_OpenCV)
cv2.imshow('rgb image', img_matplotlib)
cv2.waitKey(0)
cv2.destroyAllWindows()
以下屏幕截图显示了执行上述代码获得的结果:
正如预期的那样,屏幕截图中,第一张图以正确的色彩显示图像,而第二张图以错误的颜色显示图像。
此外,如果我们想在同一个窗口中显示两个图像,可以构建一个包含这两个图像的拼接图像,将两张图片水平连接起来。为此,我们需要使用 NumPy
的 concatenate()
方法。该方法的参数是要连接的两个图像和要在哪个轴上进行堆叠,这里,我们令 axis = 1
(水平堆叠它们):
import numpy as np
img_concats = np.concatenate((img_OpenCV, img_matplotlib), axis=1)
cv2.imshow('bgr image and rgb image', img_concats)
cv2.waitKey(0)
cv2.destroyAllWindows()
下图显示了连接后的图像:
需要考虑的一个因素是 cv2.split()
是一项耗时的操作。如果确实需要划分不同通道,应当首先考虑使用 NumPy 索引。例如,如果想获取图像的一个通道,则可以使用 NumPy 索引获取通道:
B = img_OpenCV[:, :, 0]
G = img_OpenCV[:, :, 1]
R = img_OpenCV[:, :, 2]
另一个需要注意的是,可以使用 NumPy
在一条语句中将图像从 BGR 转换为 RGB:
img_matplotlib = img_OpenCV[:, :, ::-1]
在不同颜色空间中访问和操作OpenCV中的像素
本节将介绍如何使用 OpenCV 访问和读取像素值以及如何修改它们。此外,还将学习如何访问图像属性。如果想一次处理多个像素,则需要创建图像区域 (Region of Image, ROI)。
在 Python 中,图像表示为 NumPy 数组。因此,示例中包含的大多数操作都与 NumPy 相关,建议需要对 NumPy 包一些了解,才能更好明白示例代码的原理,但即使不了解也没关系,必要时会对所用函数进行讲解。
彩色图像访问和操作OpenCV中的像素
现在,我们来看看如何在 OpenCV 中处理BGR图像。如上所述,OpenCV 加载彩色图像时,蓝色通道是第一个,绿色通道是第二个,红色通道是第三个。
首先,使用 cv2.imread()
函数读取图像。图像应该在工作目录中,或者应该提供图片的完整路径。在本例中,读取 sigonghuiye.jpeg
图像并将其存储在img变量中:
收集整理了一份《2024年最新Python全套学习资料》免费送给大家,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上Python知识点,真正体系化!
加入社区:https://bbs.csdn.net/forums/4304bb5a486d4c3ab8389e65ecb71ac0
素
现在,我们来看看如何在 OpenCV 中处理BGR图像。如上所述,OpenCV 加载彩色图像时,蓝色通道是第一个,绿色通道是第二个,红色通道是第三个。
首先,使用 cv2.imread()
函数读取图像。图像应该在工作目录中,或者应该提供图片的完整路径。在本例中,读取 sigonghuiye.jpeg
图像并将其存储在img变量中:
收集整理了一份《2024年最新Python全套学习资料》免费送给大家,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。
[外链图片转存中…(img-SgH4VniS-1725721596356)]
[外链图片转存中…(img-yk9LmENy-1725721596357)]
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上Python知识点,真正体系化!
加入社区:https://bbs.csdn.net/forums/4304bb5a486d4c3ab8389e65ecb71ac0