计算机视觉:

  • 让计算机像人眼一样“看懂”图像/视频,自动完成识别、检测、分割、跟踪等任务,落地在刷脸、自动驾驶、医疗影像等领域。  

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)

Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐