一、前言:为什么 OpenCV 是计算机视觉入门首选?

在人工智能和计算机视觉飞速发展的今天,OpenCV 作为开源跨平台的计算机视觉库,早已成为开发者入门的必备工具。它支持 Python、C++ 等多种语言,内置了数百种优化算法,涵盖图像读取、灰度转换、ROI 区域提取、颜色通道处理、视频读取等核心功能,无论是做图像处理、目标检测还是视频分析,都能提供高效便捷的解决方案。

本文将从环境搭建开始,带你一步步实现灰度图读取与保存、ROI 区域截取、BGR 颜色通道分离与合并、视频读取与实时处理四大核心功能,每一个环节都附带完整代码、详细注释和避坑指南,零基础也能轻松上手。


二、环境搭建:解决 OpenCV 导入失败问题

很多新手入门 OpenCV 的第一个坑就是import cv2报错,下面给大家提供两种稳定的安装方案,从根源解决问题。

2.1 pip 一键安装(推荐)

这是最省事的安装方式,直接在终端执行以下命令,自动安装预编译版本:

# 安装主库(基础功能)
pip install opencv-python -i https://pypi.tuna.tsinghua.edu.cn/simple
# 安装扩展库(含特征检测、人脸算法等高级功能,可选)
pip install opencv-contrib-python -i https://pypi.tuna.tsinghua.edu.cn/simple

提示:使用清华镜像源可以大幅提升下载速度,避免超时失败。

2.2手动配置 cv2.pyd 文件

如果你的 Python 环境比较特殊,可以用手动配置法,步骤如下:

  1. 打开 CMD,执行where python找到你的 Python 安装路径,比如D:\py\python.exe

  2. 进入D:\py\Lib\site-packages\cv2目录,找到cv2.pyd文件

  3. 将该文件复制到你的项目虚拟环境的site-packages目录下

  4. 重启 Python 环境,执行import cv2验证是否成功

2.3 环境验证

安装完成后,执行以下代码,不报错则说明环境配置成功:

python

import cv2
print(cv2.__version__)  # 打印版本号

三、灰度图读取、显示与保存

灰度图是图像处理的基础,相比彩色图,它只有一个通道,计算量更小,常用于图像预处理、边缘检测等场景。

3.1 完整代码实现

python

# -------------------------- 读取图片的灰度图 --------------------------
import cv2

# 1. 读取灰度图:cv2.IMREAD_GRAYSCALE参数表示以灰度模式读取图像
b = cv2.imread(r'./text.jpg', cv2.IMREAD_GRAYSCALE)  # 也可以直接写0,效果相同

# 2. 显示图像
cv2.imshow('xx', b)

# 3. 等待用户按键触发,0表示按任意键继续
a = cv2.waitKey(0)

# 4. 关闭所有窗口并释放内存
cv2.destroyAllWindows()

# 5. 查看图像属性
print("图像形状(shape):", b.shape)  # (高, 宽),灰度图无通道数
print("图像数据类型(dtype):", b.dtype)  # uint8(0-255)
print("图像大小(size):", b.size)  # 像素总数 = 高 × 宽

# 6. 保存灰度图
cv2.imwrite('text_GRAY.jpg', b)

3.2 代码逐行解析

  1. cv2.imread()读取图像
    • 第一个参数是图像路径,推荐用r'路径'避免转义字符问题
    • 第二个参数cv2.IMREAD_GRAYSCALE(或 0)表示以灰度模式读取,图像会被转为单通道 8 位数据
  2. cv2.imshow()显示图像
    • 第一个参数是窗口名称,第二个参数是要显示的图像数组
  3. cv2.waitKey()等待按键
    • 参数为等待时间(单位 ms),0 表示无限等待,直到用户按下任意键
    • 按下的键值会被返回,比如 ESC 键的 ASCII 码是 27
  4. cv2.destroyAllWindows()释放资源
    • 关闭所有 OpenCV 创建的窗口,避免内存泄漏
  5. 图像属性解读
    • shape:灰度图返回(高, 宽),彩色图返回(高, 宽, 通道数)
    • dtype:默认是uint8,表示每个像素值的范围是 0(黑)~255(白)
    • size:图像的总像素数,等于高 × 宽(灰度图)或高 × 宽 ×3(彩色图)
  6. cv2.imwrite()保存图像
    • 第一个参数是保存路径,第二个参数是要保存的图像数组
    • 会根据文件后缀自动选择保存格式(如 jpg、png)

3.3 运行效果与避坑指南

  • 运行后会弹出一个窗口显示灰度图,按下任意键窗口关闭,同时项目目录下会生成timg98_GRAY.jpg文件
  • 避坑点 1:图像路径必须正确,否则读取的图像数组为None,后续操作会报错
  • 避坑点 2:cv2.imread()默认读取彩色图为 BGR 格式,而不是常见的 RGB 格式,灰度图不受影响
  • 避坑点 3:cv2.waitKey()必须和cv2.imshow()搭配使用,否则窗口会一闪而过

四、ROI 区域提取

ROI(Region of Interest)指的是图像中你需要重点处理的特定区域,比如人脸检测中只截取人脸部分、车牌识别中只截取车牌区域,是图像处理中非常常用的操作。

4.1 完整代码实现

python

'''
ROI:区域感兴趣(Region of Interest)的缩写。它指的是图像或视频中感兴趣的特定区域,需要进行分析或处理。
ROI可以由用户手动选择,也可以使用计算机视觉算法自动检测。
'''
import cv2

# 1. 读取彩色图像
a = cv2.imread(r'./text.jpg')

# 2. 提取ROI区域:直接对numpy数组进行切片
# 语法:img[y_start:y_end, x_start:x_end],注意OpenCV坐标系原点在左上角,y轴向下为正
b = a[30:230, 100:300]  # 截取行30~230,列100~300的区域

# 3. 显示原图和ROI区域
cv2.imshow('yuantu', a)
cv2.imshow('qiepian', b)

# 4. 等待按键并释放资源
cv2.waitKey(0)
cv2.destroyAllWindows()

4.2 核心原理详解

OpenCV 读取的图像本质上是一个 NumPy 数组,因此我们可以直接用 NumPy 的切片语法来截取 ROI 区域,核心语法是:

python

roi = img[y_start:y_end, x_start:x_end]
  • y_start:y_end:表示截取的行范围(图像的高度方向,从上到下)
  • x_start:x_end:表示截取的列范围(图像的宽度方向,从左到右)
  • 注意:切片是左闭右开区间,即y_endx_end的像素不包含在内

4.3 运行效果与避坑指南

  • 运行后会弹出两个窗口,一个显示原图,一个显示截取的 ROI 区域
  • 避坑点 1:切片顺序不能搞反![行, 列],也就是[y, x],很多新手会写成[x, y]导致区域错误
  • 避坑点 2:切片范围不能超出图像尺寸,比如原图高度只有 400,就不能写y_end=500,否则会报错
  • 拓展:你还可以将截取的 ROI 区域复制到原图的其他位置,比如:

    python

    a[0:200, 0:200] = b  # 将ROI区域复制到原图左上角
    cv2.imshow('copy_roi', a)
    

五、BGR 颜色通道的分离与合并

彩色图像在 OpenCV 中默认以 BGR(蓝、绿、红)格式存储,每个像素由三个通道的值组成,分别表示蓝、绿、红三种颜色的亮度(0~255)。我们可以单独提取某个通道,或者修改通道值来实现各种色彩效果。

5.1 完整代码实现

python

'''
提取BGR颜色通道
'''
import cv2

# 1. 读取图像
a = cv2.imread(r'./text.jpg')

# -------------------------- 方法一:直接数组切片提取 --------------------------
# 2. 提取颜色通道
a1 = a[:, :, 0]  # 蓝色通道(B通道)
a2 = a[:, :, 1]  # 绿色通道(G通道)
a3 = a[:, :, 2]  # 红色通道(R通道)

# -------------------------- 方法二:cv2.split()分离通道 --------------------------
b, g, r = cv2.split(a)
# b 包含蓝色通道
# g 包含绿色通道
# r 包含红色通道

# 3. 显示单个通道(注意:单个通道显示为灰度图)
cv2.imshow('b', a1)
cv2.imshow('g', a2)
cv2.imshow('r', a3)

# 4. 设置窗口显示时间,单位为毫秒(这里设置为0,表示一直显示直到按键)
cv2.waitKey(0)
cv2.destroyAllWindows()

'''
注意:我们这里是显示蓝色通道的图像,但是所显示的图片却是灰色的,那是因为只显示蓝色通道时,
实际上是将蓝色通道作为亮度值,是单个通道,这会导致图像呈现为灰色。
想要展示只包含蓝色通道信息的彩色图像,可以将图像中的绿色通道和红色通道设为0,即移除绿色和红色,只保留蓝色。
'''
import cv2

a = cv2.imread(r'./text.jpg')

# 复制原始图像以避免更改原始图像
a_new = a.copy()
a_new[:, :, 1] = 0  # 绿色通道设为0
a_new[:, :, 2] = 0  # 红色通道设为0

# 创建一个窗口来显示修改后的图像,并将其命名为'result2'
cv2.imshow('result2', a_new)
cv2.waitKey(0)
cv2.destroyAllWindows()

# -------------------------- 合并颜色通道 --------------------------
img = cv2.merge((b, g, r))
# img = cv2.merge((a1,a2,a3)) # 或者使用这行代码
cv2.imshow('result3', img)
cv2.waitKey(0)
cv2.destroyAllWindows()

5.2 代码逐行解析

  1. 两种通道提取方法
    • 方法一:直接数组切片a[:, :, 0],第三个维度表示通道索引(0=B,1=G,2=R)
    • 方法二:cv2.split(a),直接返回 B、G、R 三个通道的数组,更直观
  2. 单个通道显示为灰度图的原因
    • 单个通道的数组是二维的(高 × 宽),OpenCV 会自动将其显示为灰度图,像素值越大(越接近 255),表示该通道的颜色越亮
  3. 只保留单个通道的彩色图像
    • 将其他两个通道的值设为 0,只保留目标通道的值,这样图像就会只显示该通道的颜色,比如只保留蓝色通道,图像会整体偏蓝
  4. cv2.merge()合并通道
    • 将分离的 B、G、R 通道重新合并为彩色图像,参数是一个包含三个通道的元组
    • 注意:通道顺序必须是 BGR,否则合并后的图像颜色会错乱

5.3 运行效果与拓展

  • 运行后会依次显示蓝色、绿色、红色通道的灰度图,以及只保留蓝色通道的彩色图像,最后合并后的图像和原图一致
  • 拓展 1:通道交换,比如将 B 和 R 通道交换,实现图像的颜色反转:

    python

    img = cv2.merge((r, g, b))  # 将R通道放在第一个位置,B通道放在第三个位置
    cv2.imshow('swap_br', img)
    
  • 拓展 2:通道增强,比如将红色通道的值整体加 50,让图像偏红:

    python

    a_new = a.copy()
    a_new[:, :, 2] = cv2.add(a_new[:, :, 2], 50)  # 避免溢出,用cv2.add()代替直接+50
    cv2.imshow('red_enhance', a_new)
    

六、视频读取与实时处理

视频本质上是由一帧帧连续的图像组成的,OpenCV 的视频处理就是对每一帧图像进行处理,然后连续显示。下面我们实现读取视频文件,将视频转为灰度并实时显示。

6.1 完整代码实现

python

import cv2

# 1. 打开视频文件(参数为视频路径,也可以传入0表示打开默认摄像头)
video_capture = cv2.VideoCapture('转场.mp4')  # 摄像头:0

# 2. 检查视频是否成功打开(异常处理,新手必加)
if not video_capture.isOpened():
    print("无法打开视频文件")
    exit()

# 3. 循环读取视频帧
while True:
    # 逐帧读取视频
    ret, frame = video_capture.read()
    # ret是布尔值,表示是否成功读取了帧,frame 是读取到的帧图像数组

    # 检查是否成功读取帧(视频结束时ret会为False)
    if not ret:
        break

    # 4. 将图像从BGR颜色空间转换为灰度空间(也可以添加其他处理步骤,如边缘检测、滤波等)
    frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

    # 5. 显示当前帧
    cv2.imshow('Video', frame)

    # 6. 检查用户是否按下 'esc' 键(ASCII码27),如果是则退出循环
    if cv2.waitKey(60) == 27:  # waitKey(60)表示每帧等待60ms,控制帧率约16fps
        break

# 7. 释放资源(非常重要,否则会导致资源泄漏)
video_capture.release()
cv2.destroyAllWindows()

6.2 核心原理详解

  1. cv2.VideoCapture()创建视频捕获对象
    • 参数可以是视频文件路径,也可以是摄像头索引(0 表示默认摄像头,1 表示外接摄像头)
    • isOpened()方法检查视频是否成功打开,避免文件路径错误或摄像头被占用导致的异常
  2. video_capture.read()读取帧
    • 返回两个值:ret(是否成功读取,布尔值)和frame(读取到的帧图像数组)
    • 当视频读取结束时,ret会变为False,此时退出循环
  3. 帧处理与显示
    • 对每一帧图像进行处理,比如灰度转换、滤波、边缘检测等
    • cv2.imshow()实时显示处理后的帧
  4. 退出控制
    • cv2.waitKey(60)表示每帧等待 60ms,控制帧率约为 1000/60≈16fps
    • 按下 ESC 键(ASCII 码 27)时退出循环,也可以用其他键值,比如ord('q')表示按下 q 键退出
  5. 资源释放
    • video_capture.release()释放视频捕获对象
    • cv2.destroyAllWindows()关闭所有窗口,避免资源泄漏

6.3 运行效果与拓展

  • 运行后会弹出一个窗口,显示灰度化的视频画面,按下 ESC 键即可退出
  • 拓展 1:添加边缘检测,将视频转为黑白边缘效果:

    python

    frame = cv2.Canny(frame, 50, 150)  # 边缘检测
    
  • 拓展 2:读取摄像头画面并实时处理,只需要将cv2.VideoCapture('转场.mp4')改为cv2.VideoCapture(0)即可
  • 拓展 3:保存处理后的视频,需要创建cv2.VideoWriter对象:

    python

    # 定义视频编码器和输出对象
    fourcc = cv2.VideoWriter_fourcc(*'XVID')
    out = cv2.VideoWriter('output.avi', fourcc, 20.0, (640, 480), isColor=False)  # 灰度图设为False
    # 在循环中写入帧
    out.write(frame)
    # 最后释放
    out.release()

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐