OpenCV-Python 中的像素操作是图像处理的基础,包括像素值的读取、修改、算术运算、逻辑运算等。由于图像在 OpenCV 中以 NumPy 数组表示,像素操作本质上是对数组的操作,结合 NumPy 的高效运算可实现灵活的像素级处理。以下详细介绍常见的像素操作方法及示例:
一、像素值的读取与修改
1. 单个像素操作
通过数组索引访问像素值,注意 OpenCV 图像的索引顺序为[行, 列, 通道](行对应 y 轴,列对应 x 轴)。
python
import cv2
import numpy as np
# 读取彩色图像(BGR格式)
img = cv2.imread('image.jpg')
# 读取单个像素值(第100行,第200列)
b, g, r = img[100, 200] # BGR顺序
print(f"原始像素值(BGR): ({b}, {g}, {r})")
# 修改单个像素值(设为红色)
img[100, 200] = (0, 0, 255) # BGR: 蓝=0, 绿=0, 红=255
print(f"修改后像素值(BGR): {img[100, 200]}")
# 灰度图像的像素操作
gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
pixel = gray_img[100, 200]
print(f"灰度像素值: {pixel}")
gray_img[100, 200] = 255 # 设为白色
2. 区域像素操作
通过切片操作修改图像的特定区域,效率远高于逐个像素修改。
python
# 将图像中左上角100x100区域设为绿色
img[0:100, 0:100] = (0, 255, 0) # BGR: 绿色
# 将灰度图像中某区域设为黑色
gray_img[50:150, 50:150] = 0
# 提取图像的ROI(感兴趣区域)
roi = img[200:400, 300:500] # 行200-400,列300-500
img[0:200, 0:200] = roi # 将ROI复制到左上角
二、像素的算术运算
1. 加减运算(亮度调整)
对像素值进行加减可调整图像亮度,需注意像素值溢出(超过 0 或 255),可通过cv2.add()/cv2.subtract()自动截断,或手动处理。
python
# 方法1:直接算术运算(可能溢出)
img_bright = img + 50 # 增加亮度(值>255时会溢出,如250+50=44)
img_dark = img - 50 # 降低亮度(值<0时会溢出,如10-50=216)
# 方法2:使用OpenCV函数(自动截断)
img_bright_safe = cv2.add(img, np.ones_like(img) * 50)
img_dark_safe = cv2.subtract(img, np.ones_like(img) * 50)
2. 乘除运算(对比度调整)
乘法增强对比度,除法降低对比度,同样需注意溢出。
python
# 增强对比度(乘以1.5)
img_contrast = np.clip(img * 1.5, 0, 255).astype(np.uint8)
# 降低对比度(除以2)
img_contrast_low = (img / 2).astype(np.uint8)
3. 图像混合(加权和)
使用cv2.addWeighted()实现两幅图像的线性混合,公式:dst = α·img1 + β·img2 + γ。
python
img1 = cv2.imread('image1.jpg')
img2 = cv2.imread('image2.jpg')
img2 = cv2.resize(img2, (img1.shape[1], img1.shape[0])) # 统一尺寸
# 图像混合(α=0.7, β=0.3, γ=0)
blended = cv2.addWeighted(img1, 0.7, img2, 0.3, 0)
三、像素的逻辑运算
包括与(AND)、或(OR)、非(NOT)、异或(XOR),常用于图像掩码、区域提取等。
python
# 创建两幅测试图像
img_a = np.zeros((200, 200), dtype=np.uint8)
img_a[50:150, 50:150] = 255 # 白色正方形
img_b = np.zeros((200, 200), dtype=np.uint8)
img_b[100:200, 100:200] = 255 # 白色正方形
# 逻辑运算
and_img = cv2.bitwise_and(img_a, img_b)
or_img = cv2.bitwise_or(img_a, img_b)
not_img = cv2.bitwise_not(img_a)
xor_img = cv2.bitwise_xor(img_a, img_b)
四、像素值的统计分析
通过 NumPy 函数统计图像的像素特征,如均值、最值、方差等。
python
# 彩色图像的通道均值
mean_b = np.mean(img[:, :, 0]) # 蓝色通道均值
mean_g = np.mean(img[:, :, 1]) # 绿色通道均值
mean_r = np.mean(img[:, :, 2]) # 红色通道均值
print(f"通道均值(BGR): ({mean_b:.2f}, {mean_g:.2f}, {mean_r:.2f})")
# 灰度图像的最值与方差
min_val = np.min(gray_img)
max_val = np.max(gray_img)
std_val = np.std(gray_img)
print(f"灰度图像: 最小值={min_val}, 最大值={max_val}, 标准差={std_val:.2f}")
# 像素值直方图
hist = cv2.calcHist([gray_img], [0], None, [256], [0, 256])
五、像素阈值处理
将像素值与阈值比较,实现二值化或分段处理,常用cv2.threshold()。
OpenCV中cv2.threshold()函数用于图像阈值处理,将灰度图像转换为二值图像或其他形式。以下是核心信息:
函数定义:
cv2.threshold(src, thresh, maxval, type)
src:输入灰度图像thresh:设定的阈值(若使用Otsu方法,此值设为0)maxval:像素值高于/低于阈值时的设定值(如255)type:阈值类型,常用类型包括:cv2.THRESH_BINARY:大于阈值设为maxval,否则0cv2.THRESH_BINARY_INV:反转上述结果cv2.THRESH_TRUNC:大于阈值设为thresh,否则不变cv2.THRESH_TOZERO:大于阈值不变,否则0cv2.THRESH_TOZERO_INV:反转上述结果
- 返回值:
ret(实际使用的阈值,如Otsu方法自动计算)和处理后的图像
示例代码:
python
# 简单阈值处理
ret, binary = cv2.threshold(gray_img, 127, 255, cv2.THRESH_BINARY) # >127设为255,否则0
ret, binary_inv = cv2.threshold(gray_img, 127, 255, cv2.THRESH_BINARY_INV) # 反向
# 自适应阈值(局部阈值)
adaptive_binary = cv2.adaptiveThreshold(
gray_img, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 11, 2
)
注意事项:
- 阈值类型需与
maxval配合使用,例如THRESH_BINARY要求maxval为255。 - 若使用
cv2.THRESH_OTSU,需将thresh设为0,函数会自动计算最优阈值 。
六、像素的遍历与批量处理
1. 逐像素遍历(效率较低,适合简单操作)
python
# 遍历灰度图像并反转像素值
height, width = gray_img.shape
for i in range(height):
for j in range(width):
gray_img[i, j] = 255 - gray_img[i, j] # 反色
2. 批量处理(推荐,利用 NumPy 向量化运算)
python
# 批量反色(效率远高于逐像素遍历)
gray_img_inverted = 255 - gray_img
# 批量将像素值限制在[50, 200]
img_clipped = np.clip(img, 50, 200)
七、掩码操作(卷积核滤波)
通过自定义卷积核对像素进行邻域运算,实现模糊、锐化等效果。
python
# 均值模糊(3x3卷积核)
kernel = np.ones((3, 3), np.float32) / 9
blurred = cv2.filter2D(img, -1, kernel)
# 图像锐化
kernel_sharpen = np.array([[0, -1, 0], [-1, 5, -1], [0, -1, 0]])
sharpened = cv2.filter2D(img, -1, kernel_sharpen)
八、完整示例:像素操作综合应用
python
import cv2
import numpy as np
# 读取图像
img = cv2.imread('image.jpg')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 1. 修改区域像素(画红色矩形)
img[50:150, 200:300] = (0, 0, 255)
# 2. 调整亮度和对比度
img_bright = cv2.add(img, np.ones_like(img) * 30)
img_contrast = np.clip(img * 1.2, 0, 255).astype(np.uint8)
# 3. 灰度图像二值化
_, binary = cv2.threshold(gray, 150, 255, cv2.THRESH_BINARY)
# 4. 显示结果
cv2.imshow('Original', img)
cv2.imshow('Bright', img_bright)
cv2.imshow('Contrast', img_contrast)
cv2.imshow('Binary', binary)
cv2.waitKey(0)
cv2.destroyAllWindows()
总结
像素操作是 OpenCV 图像处理的核心,需结合 NumPy 的数组运算特性:
- 单个 / 区域像素操作通过索引或切片实现;
- 算术 / 逻辑运算可调整图像亮度、对比度或实现掩码;
- 批量处理优先使用 NumPy 向量化运算,避免低效的逐像素遍历;
- 阈值处理和掩码操作常用于图像分割、特征提取等场景。
通过这些操作,你可以读取、修改和保存图像中的像素数据,实现各种图像处理任务。**记得在进行大量或复杂的像素操作时优先使用NumPy的高效数组操作,以提高代码的执行效率。**掌握像素操作的底层逻辑,能更灵活地实现自定义图像处理算法。