OpenCV 图像基本操作

本教程(中文)专注于 OpenCV 图像基本操作,涵盖读取、显示、保存图像,访问和修改像素,颜色通道操作,图像属性获取,以及基本的 ROI(感兴趣区域)处理等内容。基于 Python 的 opencv-python 库,提供清晰的代码示例和解释,适合初学者快速上手。本教程假设你已安装 OpenCV,并使用 imgcodecshighgui 模块进行基础操作。


一、图像基本操作概述

  • 图像表示:OpenCV 中图像以 NumPy 数组表示,形状为 (height, width, channels),默认使用 BGR 颜色格式。
  • 基本操作
  • 读取和保存图像(imread, imwrite)。
  • 显示图像(imshow, waitKey)。
  • 访问和修改像素值。
  • 通道操作:拆分、合并、转换颜色空间。
  • 获取图像属性:尺寸、数据类型、像素总数。
  • ROI 裁剪:提取图像子区域。

二、核心操作与代码示例

以下逐一讲解每个基本操作,提供 Python 示例代码。

2.1 读取图像

使用 cv2.imread 读取图像,支持 JPG、PNG、BMP 等格式。

import cv2
import numpy as np

# 读取图像
img = cv2.imread('lena.jpg')  # 替换为你的图像路径

# 检查是否加载成功
if img is None:
    print("错误:无法加载图像,请检查文件路径")
else:
    print(f"图像加载成功,形状: {img.shape}")  # 输出 (高度, 宽度, 通道数)

输出示例

图像加载成功,形状: (512, 512, 3)

说明

  • imread 参数:
  • cv2.IMREAD_COLOR:默认,加载 BGR 彩色图像。
  • cv2.IMREAD_GRAYSCALE:加载灰度图像。
  • cv2.IMREAD_UNCHANGED:加载图像并保留 alpha 通道。
  • 始终检查返回值,防止路径错误。

2.2 显示图像

使用 cv2.imshow 显示图像,cv2.waitKey 等待用户输入。

import cv2

img = cv2.imread('lena.jpg')
if img is None:
    print("错误:无法加载图像")
    exit()

# 显示图像
cv2.imshow('图像', img)
key = cv2.waitKey(0)  # 等待按键,0 表示无限等待
if key == ord('q'):   # 按 'q' 退出
    print("退出显示")
cv2.destroyAllWindows()  # 关闭所有窗口

说明

  • imshow:创建窗口显示图像,窗口名称为第一个参数。
  • waitKey:控制窗口显示时间,0 表示等待用户按键。
  • destroyAllWindows:释放窗口资源。

2.3 保存图像

使用 cv2.imwrite 保存图像到文件。

import cv2

img = cv2.imread('lena.jpg')
if img is None:
    print("错误:无法加载图像")
    exit()

# 保存图像
success = cv2.imwrite('output.jpg', img)
if success:
    print("图像已保存为 output.jpg")
else:
    print("错误:无法保存图像")

说明

  • imwrite:支持多种格式,文件名扩展名决定编码(如 .jpg, .png)。
  • 可设置压缩参数,例如 JPG 质量:
  cv2.imwrite('output_high_quality.jpg', img, [cv2.IMWRITE_JPEG_QUALITY, 95])

2.4 访问和修改像素

图像是 NumPy 数组,可通过索引访问和修改像素值。

import cv2

img = cv2.imread('lena.jpg')
if img is None:
    print("错误:无法加载图像")
    exit()

# 访问像素 (y=100, x=100)
pixel = img[100, 100]  # 返回 [B, G, R]
print(f"像素(100,100): {pixel}")

# 修改像素为绿色
img[100, 100] = [0, 255, 0]

# 访问单个通道
blue = img[100, 100, 0]  # 蓝色通道
print(f"蓝色通道值: {blue}")

# 修改一块区域为红色
img[50:100, 50:100] = [0, 0, 255]  # 设置为红色

# 显示修改后的图像
cv2.imshow('修改后的图像', img)
cv2.waitKey(0)
cv2.destroyAllWindows()

输出示例

像素(100,100): [110 156 210]
蓝色通道值: 110

说明

  • 像素格式:img[y, x] 返回 [B, G, R](BGR 顺序)。
  • 通道索引:img[y, x, c],其中 c=0(蓝)、c=1(绿)、c=2(红)。

2.5 通道操作

拆分、合并通道或转换颜色空间。

示例:拆分和合并通道

import cv2

img = cv2.imread('lena.jpg')
if img is None:
    print("错误:无法加载图像")
    exit()

# 拆分通道
b, g, r = cv2.split(img)

# 显示各通道
cv2.imshow('蓝色通道', b)
cv2.imshow('绿色通道', g)
cv2.imshow('红色通道', r)

# 合并通道
img_merged = cv2.merge([b, g, r])
cv2.imshow('合并后的图像', img_merged)
cv2.waitKey(0)
cv2.destroyAllWindows()

# 修改蓝色通道并合并
b[:] = 0  # 将蓝色通道置零
img_no_blue = cv2.merge([b, g, r])
cv2.imwrite('no_blue.jpg', img_no_blue)

说明

  • split:将图像拆分为三个通道(B、G、R),返回单通道图像。
  • merge:合并通道,需保持通道顺序。

示例:颜色空间转换

import cv2

img = cv2.imread('lena.jpg')
if img is None:
    print("错误:无法加载图像")
    exit()

# BGR -> 灰度
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# BGR -> HSV
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)

# 显示结果
cv2.imshow('灰度图像', gray)
cv2.imshow('HSV图像', hsv)
cv2.waitKey(0)
cv2.destroyAllWindows()

说明

  • cvtColor:转换颜色空间,常见选项包括 COLOR_BGR2GRAYCOLOR_BGR2HSV

2.6 获取图像属性

获取图像的形状、数据类型和像素总数等信息。

import cv2

img = cv2.imread('lena.jpg')
if img is None:
    print("错误:无法加载图像")
    exit()

# 图像属性
print(f"形状: {img.shape}")  # (高度, 宽度, 通道数)
print(f"数据类型: {img.dtype}")  # 通常 uint8
print(f"像素总数: {img.size}")  # 高度 * 宽度 * 通道数
print(f"维度: {img.ndim}")  # 2(灰度)或 3(彩色)

输出示例

形状: (512, 512, 3)
数据类型: uint8
像素总数: 786432
维度: 3

2.7 ROI(感兴趣区域)裁剪

提取图像的子区域。

import cv2

img = cv2.imread('lena.jpg')
if img is None:
    print("错误:无法加载图像")
    exit()

# 裁剪 ROI (y=100:200, x=100:200)
roi = img[100:200, 100:200]

# 显示和保存 ROI
cv2.imshow('ROI', roi)
cv2.imwrite('roi.jpg', roi)
cv2.waitKey(0)
cv2.destroyAllWindows()

说明

  • ROI 通过 NumPy 数组切片实现:img[y_start:y_end, x_start:x_end]

三、综合示例:图像操作流水线

结合读取、显示、修改像素、通道操作和 ROI:

import cv2
import numpy as np

def process_image(image_path):
    """图像处理流水线"""
    # 读取图像
    img = cv2.imread(image_path)
    if img is None:
        print("错误:无法加载图像")
        return

    # 获取属性
    print(f"形状: {img.shape}, 数据类型: {img.dtype}")

    # 修改像素(将 (100,100) 设为绿色)
    img[100, 100] = [0, 255, 0]

    # 拆分和合并通道
    b, g, r = cv2.split(img)
    b[:] = 0  # 移除蓝色通道
    img_no_blue = cv2.merge([b, g, r])

    # 裁剪 ROI
    roi = img[100:300, 100:300]

    # 转换为灰度
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

    # 显示结果
    cv2.imshow('原始图像', img)
    cv2.imshow('无蓝色通道', img_no_blue)
    cv2.imshow('ROI', roi)
    cv2.imshow('灰度图像', gray)
    cv2.waitKey(0)
    cv2.destroyAllWindows()

    # 保存结果
    cv2.imwrite('no_blue.jpg', img_no_blue)
    cv2.imwrite('roi.jpg', roi)
    cv2.imwrite('gray.jpg', gray)

# 使用示例
process_image('lena.jpg')  # 替换为你的图像路径

输出示例

形状: (512, 512, 3), 数据类型: uint8

四、注意事项

  1. 颜色格式
  • OpenCV 使用 BGR 格式,与 Matplotlib 的 RGB 不同,需转换(如 COLOR_BGR2RGB)。
  1. 错误处理
  • 始终检查 imread 返回值,防止路径错误。
  • 确保图像格式受支持(如 JPG、PNG)。
  1. 内存管理
  • 使用 destroyAllWindows() 关闭窗口,释放资源。
  • 处理大图像时,考虑内存使用量。
  1. 性能优化
  • 像素操作(如循环)较慢,尽量使用 NumPy 矢量化操作。
  • ROI 操作可减少计算量。
  1. 文件路径
  • 使用绝对路径或确保相对路径正确。
  • Windows 用户注意路径分隔符(\\/)。

五、资源

  • 官方文档:https://docs.opencv.org/master/d4/df6/tutorial_py_basic_ops.html
  • Python 教程:https://opencv-python-tutroals.readthedocs.io/
  • 社区:在 X 平台搜索 #opencv 获取最新讨论。

如果你需要更深入的操作(如批量处理图像、复杂像素操作)或 C++ 实现代码,请告诉我,我可以提供针对性的示例或进一步优化!

类似文章

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注