OpenCV-图像通道提取与处理

计算机视觉实验一:图像通道提取与处理

实验目标

学习 OpenCV 中图像通道的提取、处理和显示方法,理解 BGR 颜色空间和图像数组操作。

实验环境

  • Python 版本: 3.x
  • 主要库: OpenCV, NumPy, Matplotlib
  • 图像文件: leaf.jpg

核心知识点

1. OpenCV 颜色通道顺序

OpenCV 使用 BGR(蓝-绿-红)格式存储彩色图像:

  • 通道 0: 蓝色通道 (Blue)
  • 通道 1: 绿色通道 (Green)
  • 通道 2: 红色通道 (Red)

2. NumPy 数组切片语法

img[:,:,0]  # 选择所有行、所有列、第0个通道
  • 第一个 :: 选择所有行(高度)
  • 第二个 :: 选择所有列(宽度)
  • 第三个 0: 选择第0个通道(蓝色)

3. 图像数组维度

  • 3维数组: (height, width, channels) - 彩色图像
  • 2维数组: (height, width) - 灰度图像

实验代码详解

步骤1: 导入库和加载图像

import cv2
import numpy as np
import matplotlib.pyplot as plt

img = cv2.imread('leaf.jpg')

步骤2: 提取蓝色通道

# 提取蓝色通道(单通道)
img_blue = img[:,:,0]
cv2.imshow('img_blue', img_blue)

重要发现: 提取蓝色通道后显示的是灰度图像,而不是蓝色图像!

原因分析:

  • img_blue 是单通道的2维数组
  • OpenCV 显示单通道图像时自动转换为灰度显示
  • 要显示蓝色,需要保持3通道结构

步骤3: 创建只显示蓝色的彩色图像

# 创建与原始图像相同形状的零数组
img_blue_true = np.zeros_like(img)

# 只保留蓝色通道,其他通道设为0
img_blue_true[:,:,0] = img_blue

关键函数: np.zeros_like(img)

  • 创建与 img 形状和数据类型完全相同的数组
  • 所有元素填充为 0
  • 保持3通道结构

步骤4: 图像拼接显示

# 水平拼接两个图像进行对比
combined_img = np.hstack((img, img_blue_true))
cv2.imshow('combined_img', combined_img)

步骤5: 图像缩放处理

# 获取原始图像尺寸
height, width = img.shape[:2]  # 注意:返回的是(height, width)

# 设置缩放比例
scale_factor = 0.5  # 缩小到50%
new_width = int(width * scale_factor)
new_height = int(height * scale_factor)

# 缩放图像
img_blue = cv2.resize(img_blue, (new_width, new_height))
img_blue_true = cv2.resize(img_blue_true, (new_width, new_height))

步骤6: 通道转换和最终拼接

# 将单通道灰度图像转换为3通道BGR图像
img_blue = cv2.cvtColor(img_blue, cv2.COLOR_GRAY2BGR)

# 拼接缩放后的图像
combined_img_new = np.hstack((img_blue, img_blue_true))
cv2.imshow('combined_new', combined_img_new)

常见错误与解决方案

错误1: 数组维度不匹配

# 错误写法
img_blue_true[:,:,0] = img_blue[:,:,0]  # img_blue是2维数组,不能用3维索引

#  正确写法
img_blue_true[:,:,0] = img_blue

错误2: 宽高顺序错误

# 错误写法
width, height = img.shape[:2]  # 顺序错误

#  正确写法
height, width = img.shape[:2]  # img.shape返回(height, width, channels)

错误3: 通道数不匹配拼接

#  错误写法
combined = np.hstack((img_blue, img_blue_true))  # 2维和3维数组无法拼接

#  正确写法
img_blue_3channel = cv2.cvtColor(img_blue, cv2.COLOR_GRAY2BGR)
combined = np.hstack((img_blue_3channel, img_blue_true))

📊 实验结果

显示效果对比

  1. 原始图像: 完整的彩色图像
  2. 蓝色通道(灰度): 单通道提取,显示为灰度图像
  3. 蓝色通道(彩色): 只显示蓝色分量,其他通道为0
  4. 拼接对比: 并排显示,便于观察差异

关键观察

  • 蓝色通道提取后,图像中蓝色分量强的区域在灰度图中显示较亮
  • 通过设置其他通道为0,可以创建只显示特定颜色分量的图像
  • 图像缩放和拼接是图像处理中的常用技术

🔧 实用技巧

1. 图像尺寸获取

height, width, channels = img.shape  # 获取完整形状信息
height, width = img.shape[:2]        # 只获取高度和宽度

2. 图像缩放

# 等比例缩放
scale_factor = 0.5
new_width = int(width * scale_factor)
new_height = int(height * scale_factor)
resized_img = cv2.resize(img, (new_width, new_height))

3. 通道转换

# 灰度转BGR
gray_3channel = cv2.cvtColor(gray_img, cv2.COLOR_GRAY2BGR)

# BGR转灰度
gray_img = cv2.cvtColor(bgr_img, cv2.COLOR_BGR2GRAY)

4. 图像拼接

# 水平拼接
combined_h = np.hstack((img1, img2))

# 垂直拼接
combined_v = np.vstack((img1, img2))

总结

本次实验学习了:

  1. OpenCV 图像读取和显示
  2. BGR 颜色空间和通道提取
  3. NumPy 数组操作和切片语法
  4. 图像缩放和拼接技术
  5. 通道转换和图像处理技巧

通过对比不同处理方法的显示效果,深入理解了图像在计算机中的存储和表示方式。


实验日期: 2025.9.23
实验者: Atta

补充:来自 test00.py 的要点(笔记未覆盖)

  • 像素总数 np.size: 获取单通道图像的像素数量,可用于快速统计。

    x, y = img_channel.shape  # x=height, y=width
    num = img_channel.size    # 等于 x * y
    
  • np.zeros_like(img) 构造三通道并仅填充某一通道: 便于恢复为 BGR 三通道用于彩色显示/拼接。

    img_zeros_like = np.zeros_like(img)  # 形状与 dtype 与 img 一致 (H, W, 3)
    img_zeros_like[:, :, 0] = img_channel  # 仅赋值蓝色通道
    
  • 灰度/单通道转三通道 BGR: 单通道在拼接或彩色窗口显示前可先扩展为三通道。

    img_channel_bgr = cv2.cvtColor(img_channel, cv2.COLOR_GRAY2BGR)
    img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    img_gray_bgr = cv2.cvtColor(img_gray, cv2.COLOR_GRAY2BGR)
    
  • 严禁用 ndarray.resize 做图像缩放,改用 cv2.resize:

    • ndarray.resize(new_h, new_w) 会原地重排数据、可能改变维度,且返回 None,容易导致图像内容错乱。
    • 正确做法:
    new_height = x // 2
    new_width = y // 2           # 注意:cv2.resize 的参数顺序是 (width, height)
    img_bgr_small = cv2.resize(img_bgr, (new_width, new_height))
    
  • 宽高命名与顺序对齐:

    • x, y = img_channel.shape 中,x 表示高度(height),y 表示宽度(width)。
    • cv2.resize(src, (width, height)) 传参顺序是 (W, H)
  • 横向拼接前的检查清单:

    • 三者应为同尺寸、同通道数(通常 (H, W, 3))、同 dtype=uint8
    • 例:
    print(img_a.shape, img_b.shape, img_c.shape)
    print(img_a.dtype, img_b.dtype, img_c.dtype)
    num_m = np.hstack([img_a, img_b, img_c])
    
  • 窗口资源释放: 显示后关闭窗口,避免占用。

    cv2.imshow('img', num_m)
    cv2.waitKey(0)
    cv2.destroyAllWindows()
    
posted @ 2025-09-20 17:34  AttaSayyid  阅读(74)  评论(0)    收藏  举报