【从零入门 OpenCV】Python 实现图像 / 视频处理全解析
一、前言:为什么 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 环境比较特殊,可以用手动配置法,步骤如下:
-
打开 CMD,执行
where python找到你的 Python 安装路径,比如D:\py\python.exe -
进入
D:\py\Lib\site-packages\cv2目录,找到cv2.pyd文件 -
将该文件复制到你的项目虚拟环境的
site-packages目录下 -
重启 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 代码逐行解析
cv2.imread()读取图像:- 第一个参数是图像路径,推荐用
r'路径'避免转义字符问题 - 第二个参数
cv2.IMREAD_GRAYSCALE(或 0)表示以灰度模式读取,图像会被转为单通道 8 位数据
- 第一个参数是图像路径,推荐用
cv2.imshow()显示图像:- 第一个参数是窗口名称,第二个参数是要显示的图像数组
cv2.waitKey()等待按键:- 参数为等待时间(单位 ms),0 表示无限等待,直到用户按下任意键
- 按下的键值会被返回,比如 ESC 键的 ASCII 码是 27
cv2.destroyAllWindows()释放资源:- 关闭所有 OpenCV 创建的窗口,避免内存泄漏
- 图像属性解读:
shape:灰度图返回(高, 宽),彩色图返回(高, 宽, 通道数)dtype:默认是uint8,表示每个像素值的范围是 0(黑)~255(白)size:图像的总像素数,等于高 × 宽(灰度图)或高 × 宽 ×3(彩色图)
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_end和x_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 代码逐行解析
- 两种通道提取方法:
- 方法一:直接数组切片
a[:, :, 0],第三个维度表示通道索引(0=B,1=G,2=R) - 方法二:
cv2.split(a),直接返回 B、G、R 三个通道的数组,更直观
- 方法一:直接数组切片
- 单个通道显示为灰度图的原因:
- 单个通道的数组是二维的(高 × 宽),OpenCV 会自动将其显示为灰度图,像素值越大(越接近 255),表示该通道的颜色越亮
- 只保留单个通道的彩色图像:
- 将其他两个通道的值设为 0,只保留目标通道的值,这样图像就会只显示该通道的颜色,比如只保留蓝色通道,图像会整体偏蓝
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 核心原理详解
cv2.VideoCapture()创建视频捕获对象:- 参数可以是视频文件路径,也可以是摄像头索引(0 表示默认摄像头,1 表示外接摄像头)
- 用
isOpened()方法检查视频是否成功打开,避免文件路径错误或摄像头被占用导致的异常
video_capture.read()读取帧:- 返回两个值:
ret(是否成功读取,布尔值)和frame(读取到的帧图像数组) - 当视频读取结束时,
ret会变为False,此时退出循环
- 返回两个值:
- 帧处理与显示:
- 对每一帧图像进行处理,比如灰度转换、滤波、边缘检测等
cv2.imshow()实时显示处理后的帧
- 退出控制:
cv2.waitKey(60)表示每帧等待 60ms,控制帧率约为 1000/60≈16fps- 按下 ESC 键(ASCII 码 27)时退出循环,也可以用其他键值,比如
ord('q')表示按下 q 键退出
- 资源释放:
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()
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐

所有评论(0)