Python OpenCV 图像细节操作:像素读写与属性解析
本文详解OpenCV中图像像素的读写技巧,涵盖BGR通道拆分、特定像素点修改及numpy高效操作法。同时解析图像shape、size、dtype等关键属性,通过实例演示彩色与灰度图差异,并解决常见读取错误,助力掌握图像底层处理。
本系列采用创新问答模式,助你快速掌握OpenCV从基础到进阶的核心知识。
6. Python OpenCV 图像细节处理技巧
本文旨在解析图像拆解技术,包括像素值说明、属性信息的获取与修改、感兴趣区域(ROI)处理,以及图像通道的拆分与合并知识。
这些内容与 numpy 库紧密相关,建议从学习角度储备 numpy 相关知识。
读取与修改图像像素值
此前博客已介绍使用 cv2.imread 函数读取图像,并掌握了其两个关键参数。
读取图片后,可直接通过数组操作获取任意位置颜色,默认顺序为 BGR。
测试代码如下:
import cv2
import matplotlib.pyplot as plt
src = cv2.imread("./6_test.jpg")
# 获取 100 x 100 位置的像素值
print(src[100, 100])
cv2.imshow("src", src)
cv2.waitKey()
首先获取坐标 (100, 100) 处的像素值。src[100,100] 将返回三个值,分别对应 B、G、R 通道。我们在图片上标记像素点 rows=250, cols=470,修改上述代码以查看获取到的 BGR 值。
import cv2
import matplotlib.pyplot as plt
src = cv2.imread("./6_test.jpg")
# 注意获取像素值的格式为 [cols,rows]
print(src[250, 470])
cv2.imshow("src", src)
cv2.waitKey()

需注意像素值获取格式为 [cols,rows],即列坐标在前,行坐标在后。
上述获取的是 BGR 总值,也可单独获取单个通道值,对应代码为 [cols,rows,channel],具体代码段如下:
# 获取蓝色通道值
print(src[250, 470, 0])
蓝色通道索引为 0,绿色通道为 1,红色通道为 2。若索引超出此范围,将出现如下错误:
IndexError: index 3 is out of bounds for axis 2 with size 3
若直接读取灰度图(如下述代码),三个通道值将相同。
import cv2
import matplotlib.pyplot as plt
src = cv2.imread("./6_test.jpg", 0)
# 注意获取像素值的格式为 [cols,rows]
print(src[250, 470])
cv2.imshow("src", src)
cv2.waitKey()
此处存在一个编码潜在问题:若读取四通道图片(含透明度),数组索引可读取到 3,即下述代码正确。
import cv2
import matplotlib.pyplot as plt
src = cv2.imread("./test.jpg", -1)
# 注意获取像素值的格式为 [cols,rows]
print(src[250, 470, 3])
cv2.imshow("src", src)
cv2.waitKey()
src[250, 470, 3] 成功读取透明通道值。
我们可以针对特定像素点修改值,如下述代码:
import cv2
import matplotlib.pyplot as plt
src = cv2.imread("./6_test.jpg")
# 注意获取像素值的格式为 [cols,rows]
src[250, 470] = [255, 255, 255]
cv2.imshow("src", src)
cv2.waitKey()
注意图中红色箭头指向位置出现白色亮点,利用此法可制造【椒盐噪声】效果。

此处需注意一个潜在 BUG:读取图片的通道数决定了复制时数组元素个数,如下述代码将报错。
import cv2
import matplotlib.pyplot as plt
src = cv2.imread("./6_test.jpg")
# 注意获取像素值的格式为 [cols,rows]
src[250, 470] = [255, 255, 255, 255]
cv2.imshow("src", src)
cv2.waitKey()
错误信息类似,提示数组维度不匹配。
ValueError: cannot copy sequence with size 4 to array axis with dimension 3
最后,直接操作像素点非常耗时,因图片像素数据庞大。一般建议使用 numpy 集成方法,避免使用这种低效方式。
使用 numpy 获取通道值时,注意该方式返回标量。若想获取所有 BGR 值,需使用 array.item() 依次获取。
import cv2
import numpy as np
src = cv2.imread("./6_test.jpg")
print(src[100, 100])
b = src.item(100, 100, 0)
g = src.item(100, 100, 1)
r = src.item(100, 100, 2)
print(b, g, r)
cv2.imshow("src", src)
cv2.waitKey()
若需设置该值,直接使用 itemset 函数即可。
src.itemset((100, 100, 0), 200)
print(src[100, 100])
可任选图片测试,运行效果如下:
[ 31 68 118] 31 68 118 [200 68 118]
OpenCV 图像属性常见问题解析
除像素矩阵外,图像属性至关重要,包括行、列、通道数、数据类型、像素总数及图像形状等。
例如,常使用 img.shape 获取图像形状。需注意,返回内容为行数(rows)、列数(cols)及通道数(channels),且返回类型为元组。
若读取图像时指定仅读取灰度图,则只返回行数和列数。通过此值可轻松判断加载的图像类型。
如下述代码,通过不同方式读取同一张图片,输出图像的不同形状。
import cv2
import numpy as np
# 选择一个 jpg 图片,可以读取到不同的通道
src1 = cv2.imread("./test.jpg", -1)
src2 = cv2.imread("./test.jpg", 0)
src3 = cv2.imread("./test.jpg")
# 四通道,包含透明通道
print(src1.shape)
# 灰度图
print(src2.shape)
# 三通道
print(src3.shape)
输出结果可快速判断图像是彩色还是灰度。
(397, 595, 4)
(397, 595)
(397, 595, 3)
使用 img.size 可快速返回图像像素总数,测试代码如下:
# 选择一个 jpg 图片,可以读取到不同的通道
src1 = cv2.imread("./test.jpg", -1)
src2 = cv2.imread("./test.jpg", 0)
src3 = cv2.imread("./test.jpg")
# 四通道,包含透明通道
print(src1.shape)
print(src1.size)
# 灰度图
print(src2.shape)
print(src2.size)
# 三通道
print(src3.shape)
print(src3.size)
依旧以三种不同读取方式为例,得到的像素数分别如下:
(397, 595, 4)
944860
(397, 595)
236215
(397, 595, 3)
708645
注意,灰度图像与彩色图像的像素数不同,它们之间存在如下关系。
灰度图像像素数 = 行数 x 列数 = 397 x 595 = 236215
彩色图像像素数 = 行数 x 列数 x 通道数 = 944860(四通道)/ 708645(三通道)
使用 img.dtype 属性可获取图像类型,具体如下:
print(src1.dtype)
此处读取到的值均为相同的 uint8,表示 8 位图像。需记住,只要是 uint8 格式,对应的 BGR 值范围在 [0,255] 之间。
操作上述属性值时,可能出现如下 BUG。该 BUG 的通用解决方案是排查图片是否正常读取,需特别注意:
AttributeError: 'NoneType' object has no attribute 'shape'
print(src1.dtype)
此处读取到的值均为相同的 uint8,表示 8 位图像。需记住,只要是 uint8 格式,对应的 BGR 值范围在 [0,255] 之间。
操作上述属性值时,可能出现如下 BUG。该 BUG 的通用解决方案是排查图片是否正常读取,需特别注意:
AttributeError: 'NoneType' object has no attribute 'shape'
至此,关于 Python OpenCV 图像细节操作的文章介绍完毕。更多相关 Python OpenCV 图像内容请搜索本站以前的文章或继续浏览下面的相关文章,希望大家以后多多支持本站!
本站声明
本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。













