《计算机视觉实战营:30 个代码案例带你从入门到落地》
本文介绍了计算机视觉基础及OpenCV库的使用方法。主要内容包括:1.计算机视觉概念及其应用场景;2.OpenCV库的安装与基本功能;3.图像处理基本操作:读取、显示、保存图片,获取图片属性(shape,dtype,size);4.视频处理:逐帧读取、灰度转换;5.ROI区域提取;6.颜色通道分离与合并;7.图像修改操作(打码、组合、缩放)。代码示例展示了如何通过OpenCV实现这些功能,强调了矩
·
计算机视觉:
- 让计算机像人眼一样“看懂”图像/视频,自动完成识别、检测、分割、跟踪等任务,落地在刷脸、自动驾驶、医疗影像等领域。
OpenCV:
- 一个免费、跨平台的 计算机视觉工具箱,提供上千个现成算法(滤波、特征提取、目标检测、相机标定等),几行代码就能调相机、读视频、跑模型。
我们接下来的代码案例,安装的OpenCV指定了版本,分别是:opencv-python==3.4.18.65和opencv-contrib-python==3.4.18.65(包含了其他一些图像处理算法函数的OpenCV扩展库)
pip install opencv-python==3.4.18.65 -i https://pypi.tuna.tsinghua.edu.cn/simple
pip install opencv-contrib-python==3.4.18.65 -i https://pypi.tuna.tsinghua.edu.cn/simple
彩色图片包含RGB三个通道,亮度值在0~255,我们通过代码对图片的处理,本质上是对RGB对应通道的数字进行处理

接下来的代码案例都导入OpenCV库和numpy库
import cv2 # 读取的格式是BGR numpy
import numpy as np
代码案例一:读取图片
'''-------------------读取图片----------------------------'''
a = cv2.imread('timg98.jpg')#读取图片
# print(a) # NumPy数组,其中存储了读取的图像文件的像素值。
cv2.imshow('tu',a) #显示图片。显示图片的名称,显示的图片数据。
b = cv2.waitKey(0)#是在一个给定的时间内(单位ms)触发;如果用户没有按下键,到时自动结束。设置waitKey(0),代表按任意键继续。
print(b)#当前按下按键 ASCII码值
cv2.destroyAllWindows() #关闭所有打开的窗口并释放所有相关内存。
# # # 对于简单的程序不需要调用这些函数,应用程序的所有资源和窗口在退出时都会由操作系统自动关闭 。
# # '''调试模型观察shape,dtype、size属性'''
print("图像形状 (shape):", a.shape) #高、宽、通道数
print("图像数据类型 (dtype):", a.dtype) #无符号 8 位整数,用于表示像素值的范围在 0 到 255 之间。
print("图像大小 (size):", a.size) #表示图像的大小,通常是一个整数,表示图像的总像素数,即图像的高度乘以宽度乘以通道数
- 这段代码所在的.py脚本文件与图片在同一文件夹下,直接给图片的文件名,也可以直接读取图片
- .py脚本与图片在同一目录,可以把文件名直接写进去
a = cv2.imread('timg98.jpg')#读取图片
- 直接输出的是数组,本质上图片对应的是一片数组
print(a) # NumPy数组,其中存储了读取的图像文件的像素值。

- 用来展示图片
cv2.imshow('tu',a) #显示图片。显示图片的名称,显示的图片数据。
- 控制图片展示时长,按下任意按键,可直接关闭图片
b = cv2.waitKey(0)#是在一个给定的时间内(单位ms)触发;如果用户没有按下键,到时自动结束。设置waitKey(0),代表按任意键继续。
- 可以输出你按下“任意按键”对应的ASCII码值
print(b)#当前按下按键 ASCII码值
- 关闭所有窗口
cv2.destroyAllWindows() #关闭所有打开的窗口并释放所有相关内存。
- 读取的a有很多属性,a为ndarray数组
- min和max表示图片的像素值在0~255之间所对应的最大值和最小值是多少,该图片min=0,max=255
- shape:形状(546,618,3)546:高度,618:宽度,3:通道数
- dtype:数据类型,该图片的dtype('uint8')

- size:图片大小1012284=546*618*3,表示高度*宽度*通道数
# # # 对于简单的程序不需要调用这些函数,应用程序的所有资源和窗口在退出时都会由操作系统自动关闭 。
# # '''调试模型观察shape,dtype、size属性'''
print("图像形状 (shape):", a.shape) #高、宽、通道数
print("图像数据类型 (dtype):", a.dtype) #无符号 8 位整数,用于表示像素值的范围在 0 到 255 之间。
print("图像大小 (size):", a.size) #表示图像的大小,通常是一个整数,表示图像的总像素数,即图像的高度乘以宽度乘以通道数

代码案例二:读取图片的灰度图
'''---------------------读取图片的灰度图------------------------'''
b = cv2.imread(r'./timg98.jpg',cv2.IMREAD_GRAYSCALE) # 0
# print(b)
cv2.imshow('xx',b)
a=cv2.waitKey(0) #是在一个给定的时间内(单位ms)等待用户按键触发;如果用户没有按下键,到时自动运行下一行。设置waitKey(0),代表按任意键继续。
cv2.destroyAllWindows() #关闭所有打开的窗口并释放所有相关内存。
print("图像形状 (shape):", b.shape)
print("图像数据类型 (dtype):", b.dtype)
print("图像大小 (size):", b.size)
'''图片保存'''
cv2.imwrite('timg98_GRAY.jpg',b)
- 灰度图只是将色彩改变,但是图片中的特征没有改变,cv2.IMREAD_GRAYSCALE也可以直接替换成数字0,效果是一样的
b = cv2.imread(r'./timg98.jpg',cv2.IMREAD_GRAYSCALE) # 0
- 输出为(546,618),没有通道数,表明为单通道
print("图像形状 (shape):", b.shape)
- size值为546*618,数据量比之前更小,计算机处理会更快
print("图像数据类型 (dtype):", b.dtype)
- imwrite将图片保存到本地文件
'''图片保存'''
cv2.imwrite('timg98_GRAY.jpg',b)#timg98_GRAY.jpg为图片名字,b为图片数据

代码案例三:视频文件读取
'''----------------------视频文件读取--------------------------'''
import cv2
# 打开视频文件
video_capture = cv2.VideoCapture('转场.mp4') # 摄像头:0
# 检查视频是否成功打开
if not video_capture.isOpened():
print("无法打开视频文件")
exit()
# 循环读取视频帧
while True:
# 逐帧读取视频
ret, frame = video_capture.read() #ret是布尔值,表示是否成功读取了帧,frame 是读取到的帧
# 检查是否成功读取帧
if not ret:
break
# 将图像从一种颜色空间转换为另一种颜色空间。
frame=cv2.cvtColor(frame,cv2.COLOR_BGR2GRAY)
# 显示当前帧
cv2.imshow('Video', frame)
# 检查用户是否按下 'esc' 键,如果是则退出循环
if cv2.waitKey(100) == 27:
break
# 释放资源
video_capture.release()
cv2.destroyAllWindows()
- imread读取图片,图片对应的路径和名字尽量不要包含中文(本地加载),而VideoCapture读取的视频的路径和名字可以包含中文,加载本地摄像头可以把转场,mp4直接替换成0即可
# 打开视频文件
video_capture = cv2.VideoCapture('转场.mp4') # 摄像头:0
- 正常情况下,该判断语句的代码不会被执行,当 video_capture.isOpened() 返回 False 时,执行 exit() 会直接退出脚本,后面的代码不再运行,防止后续对未打开的视频流做无效操作
# 检查视频是否成功打开
if not video_capture.isOpened():
print("无法打开视频文件")
exit()
- 判断每次是否成功读取视频中的每一帧画面
- 每次读取该视频中一帧画面,就将读取到的该帧画面返回给frame
- 视频是由一帧帧画面组成的,对视频中的每一帧画面都进行处理,就需要video_capture.read()
- video_capture.read() 每将一帧画面成功返回给frame的同时,也会给ret返回True,当把整个视频都读取完后,ret返回False
# 逐帧读取视频
ret, frame = video_capture.read() #ret是布尔值,表示是否成功读取了帧,frame 是读取到的帧
- 当 ret 返回 False(读取失败或已到视频末尾)时,if not ret: 成立,执行 break 立即跳出循环,防止后续对空帧做无效处理
# 检查是否成功读取帧
if not ret:
break
- 对收集到的帧帧画面的frame进行处理,就可以达到对视频处理的效果
- 对frame每一帧画面都转化为灰度图,就可以达到对视频转化为灰度视频的效果
# 将图像从一种颜色空间转换为另一种颜色空间。
frame=cv2.cvtColor(frame,cv2.COLOR_BGR2GRAY)
- 60表示控制单帧画面显示时长为60ms,27表示ASCII值,对应为ESC键的ASCII值,如果按下ESC键,则break跳出循环
# 检查用户是否按下 'esc' 键,如果是则退出循环
if cv2.waitKey(100) == 27:
break
- video_capture.release() 告诉 OpenCV「我已经不用摄像头 / 视频文件了」,立即释放硬件资源并关闭视频流,防止占用或内存泄漏
# 释放资源
video_capture.release()
代码案例四:ROI
'''ROI:区域感兴趣(Region of Interest)的缩写。它指的是图像或视频中感兴趣的特定区域,需要进行分析或处理。
ROI可以由用户手动选择,也可以使用计算机视觉算法自动检测。'''
a = cv2.imread(r'./timg98.jpg')
b = a[30:230,100:300] #直接对numpy数组进行切片
cv2.imshow('yuantu',a)
cv2.imshow('qiepian',b)
cv2.waitKey(0)
cv2.destroyAllWindows()
- 对图片进行处理可能并不涉及到整张图片,ROI只是对图片中部分或者指定区域进行处理
- [30:230,100:300] 分别对应行和列,对numpy数组进行切片处理,达到对图片进行处理的一个效果
b = a[30:230,100:300] #直接对numpy数组进行切片
代码案例五:提取RGB颜色通道
'''--------------提取RGB颜色通道---------------------'''
import cv2
# 1. 读取图像
a = cv2.imread(r'./timg98.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 包含红色通道
cv2.imshow('result', r)
# 4. 设置窗口显示时间,单位为毫秒(这里设置为100秒,可以根据需要调整)
cv2.waitKey(100000)
# 5. 关闭所有窗口
cv2.destroyAllWindows()
'''
注意:我们这里是显示蓝色通道的图像,但是所显示的图片确实灰色的,那是因为只显示蓝色通道时,
实际上是将蓝色通道作为亮度值,而将绿色和红色通道设置为默认的最大值,也就是255。这会导致图像呈现为灰色。
想要展示只包含蓝色通道信息的彩色图像,可以将图像中的绿色通道和红色通道设为0,即移除绿色和红色,只保留蓝色。
'''
import cv2
a = cv2.imread(r'./timg98.jpg')
# 复制原始图像以避免更改原始图像
a_new = a.copy()
a_new[:, :, 0] = 0 # 绿色通道设为0
a_new[:, :, 1] = 0 # 红色通道设为0
# 创建一个窗口来显示修改后的图像,并将其命名为'result'
cv2.imshow('result', a_new)
cv2.waitKey(100000)
cv2.destroyAllWindows()
'''合并颜色通道'''
import cv2
# 1. 读取图像
a = cv2.imread(r'./timg98.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 包含红色通道
# 使用cv2.merge()函数将三个通道重新合并成一个图像
# img = cv2.merge((b, g, r))
img = cv2.merge((a1,a2,a3)) #或者使用这行代码
cv2.imshow('result', img)
cv2.waitKey(100000)
cv2.destroyAllWindows()
- 提取RGB颜色通道,可以通过ROI切片处理得到
# 2. 提取颜色通道
a1 = a[:, :, 0] # 蓝色通道(B通道)
a2 = a[:, :, 1] # 绿色通道(G通道)
a3 = a[:, :, 2] # 红色通道(R通道)
- split()也可以用来分离颜色通道,三个返回值b,g,r
# 或者使用 cv2.split() 来分离颜色通道
b, g, r = cv2.split(a)
- 想要展示只包含蓝色通道信息的彩色图像,可以将图像中的绿色通道和红色通道设为0,即移除绿色和红色,只保留蓝色
import cv2
a = cv2.imread(r'./timg98.jpg')
# 复制原始图像以避免更改原始图像
a_new = a.copy()
a_new[:, :, 0] = 0 # 绿色通道设为0
a_new[:, :, 1] = 0 # 红色通道设为0
# 创建一个窗口来显示修改后的图像,并将其命名为'result'
cv2.imshow('result', a_new)
cv2.waitKey(100000)
cv2.destroyAllWindows()
- 将3个通道重新合并成一个图像
img = cv2.merge((b, g, r))
代码案例六:图片修改
'''----------------图片修改--------------------------'''
import numpy as np
# 图片打码
a = cv2.imread(r'./timg98.jpg')
a[100:200,200:300] = np.random.randint(0,256,(100,100,3))#矩阵赋值必须是相同大小
cv2.imshow('masaike',a)
cv2.waitKey(1000000)
cv2.destroyAllWindows()
# 图片组合
a = cv2.imread('timg98.jpg')
b = cv2.imread('zl.png')
b[200:350,200:350] = a[50:200,100:250]#注意:矩阵的大小必须要统一。
cv2.imshow('b',b)
cv2.imshow('a',a)
cv2.waitKey(100000)
cv2.destroyAllWindows()
# 图片缩放cv2.resize
# 用于调整图像的大小。它有以下几个参数:
# src:要调整大小的输入图像,可以是numpy数组、PIL图像或其他类型。
# dsize:输出图像的大小,可以是一个元组,例如(宽,高),或者使用整数标量来缩放原始图像。如果dsize为None,则根据scalefx和scalefy缩放原始图像。
# fx:沿x轴的缩放系数。
# fy:沿y轴的缩放系数。
a = cv2.imread('timg98.jpg')
# a_new = cv2.resize(a,(200,600)) # 宽、高
a_new = cv2.resize(a,dsize=None,fx=1.5,fy=0.5)
# print(a.shape) # 高、宽、通道数
cv2.imshow('a',a)
cv2.imshow('a_new',a_new)
cv2.waitKey(100000)
cv2.destroyAllWindows()
- [100:200,200:300]:选定区域
- np.random:随机库
- np.random.randint:随机生成整数
- (0,256,(100,100,3)):数据类型范围0~255之间,填充到指定区域(100,100,3)
a[100:200,200:300] = np.random.randint(0,256,(100,100,3))#矩阵赋值必须是相同大小
- 矩阵大小统一,将a指定区域放到b指定区域
b[200:350,200:350] = a[50:200,100:250]#注意:矩阵的大小必须要统一。
- resize:调整指定图片的大小
- a:指定图片
- (200,600):200表示宽,600表示高
a_new = cv2.resize(a,(200,600)) # 宽、高
a_new = cv2.resize(a,dsize=None,fx=1.5,fy=0.5)
DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐

所有评论(0)