(二)预训练图像模型预测(datawhale学习)

一、预训练模型的概念与目的

预训练模型是指在大规模数据上训练好的模型,通常采用无监督学习方法进行训练。

预训练模型的目的是:利用大规模数据训练得到的特征来初始化模型参数,从而加快模型的收敛速度和提高模型的泛化能力。预训练模型通常可以分为两类:

  1. 基于无监督学习的预训练模型,如自编码器、生成对抗网络等。这些模型在大规模无标注数据上进行训练,学习数据的高层次特征表示,如图像的纹理、形状等。
  2. 基于监督学习的预训练模型,如在ImageNet等大规模标注数据集上训练的模型。这些模型通常采用卷积神经网络(CNN)结构,在大规模数据上进行训练,学习到数据的高层次特征表示,如图像的纹理、形状等。

在图像分类等任务中,预训练模型可以用作特征提取器或者迁移学习的基础模型,通过微调等方式进行优化,从而得到更好的性能和泛化能力。

二、安装配置环境

1.下载工具包

!pip install numpy pandas matplotlib requests tqdm opencv-python pillow gc -i https://pypi.tuna.tsinghua.edu.cn/simple

库介绍:

  • pillow

    Pillow 是 Python 中一个流行的图像处理库,它基于 PIL (Python Imaging Library) 库的基础上进行了更新和优化。Pillow 提供了大量的图像处理函数和方法,可以方便地进行图像的加载、处理和保存。它支持的图像格式包括 JPEG、PNG、BMP、GIF、TIFF 等多种格式,并且可以对图像进行缩放、裁剪、旋转、滤镜等各种操作。

    Pillow 提供了 Image 类来表示图像,可以使用 Image.open() 方法来加载图像,使用 Image.save() 方法保存图像,还可以使用 Image.show() 方法来显示图像。除此之外,Pillow 还提供了丰富的图像处理方法,包括调整图像大小、调整图像颜色、应用图像滤镜等。

    总的来说,Pillow 是一个非常方便实用的图像处理库,特别适用于图像处理和数据预处理等任务,能够帮助用户更快速、更方便地进行图像处理任务。

  • gc

    gc(Garbage Collection)是 Python 内置的垃圾回收机制,负责回收不再使用的内存空间。

问题:

image-20230201153257916

不知道为什么gc这个包装不了,网上也没找到解决方案,后面将这个问题忽略了(因为没有这个包对程序并没什么影响)即:

!pip install numpy pandas matplotlib requests tqdm opencv-python pillow -i https://pypi.tuna.tsinghua.edu.cn/simple

2.下载安装Pytorch

!pip3 install torch torchvision torchaudio --extra-index-url https://download.pytorch.org/whl/cu113

PyTorch 是一个非常灵活、易用、高效和功能强大的机器学习框架,特别适合用于深度学习模型的开发和训练。同时,PyTorch 的社区也非常活跃,提供了大量的资源和支持,使得用户可以更快地掌握 PyTorch 并开发出更加优秀的深度学习模型。

3.下载安装 mmcv-full

# 安装mmcv -full
!pip install mmcv-full -f https://download.openmmlab.com/mmcv/dist/cu113/torch1.10.0/index.html

mmcv-full 是一个开源的计算机视觉工具箱,提供了丰富的图像和视频处理模块、模型和优化器等。它是基于 PyTorch 框架的高级计算机视觉库,可以用来开发和训练各种视觉模型,如目标检测、实例分割、姿态估计、图像分类、视频理解等。

mmcv-full 的主要特点包括:

  • 提供了丰富的图像和视频处理模块,如图像增强、数据集预处理、视频流处理等。
  • 提供了多个流行的目标检测、实例分割、姿态估计等算法的实现,如 Faster R-CNN、Mask R-CNN、YOLO、OpenPose 等。
  • 提供了各种优化器和学习率调度器,如 Adam、SGD、Cosine Annealing 等,方便用户进行模型优化。
  • 支持分布式训练,可以通过多个 GPU 或多个机器并行训练模型,提高训练速度和效率。
  • 提供了丰富的模型评估和可视化工具,可以帮助用户对模型的性能进行评估和分析。

使用 mmcv-full 库可以大大简化计算机视觉任务的开发和训练过程,提高开发效率和模型性能。

4.下载中文字体文件

!wget https://zihao-openmmlab.obs.cn-east-3.myhuaweicloud.com/20220716-mmclassification/dataset/SimHei.ttf

5.下载 ImageNet 1000类别信息

!wget https://zihao-openmmlab.obs.cn-east-3.myhuaweicloud.com/20220716-mmclassification/dataset/meta_data/imagenet_class_index.csv

下面为部分类别信息:

image-20230219114246413

6. 创建test_img和output目录

import os
# 存放测试图片
os.mkdir('test_img')

# 存放结果文件
os.mkdir('output')
# 下载测试图像文件至 test_img 文件夹
!wget https://zihao-openmmlab.obs.cn-east-3.myhuaweicloud.com/20220716-mmclassification/test/watermelon1.jpg -O test_img/watermelon1.jpg
!wget https://zihao-openmmlab.obs.cn-east-3.myhuaweicloud.com/20220716-mmclassification/test/banana1.jpg -O test_img/banana1.jpg
!wget https://zihao-openmmlab.obs.cn-east-3.myhuaweicloud.com/20220716-mmclassification/test/cat1.jpg -O test_img/cat1.jpg

# 哈士奇,来源:https://www.pexels.com/zh-cn/photo/2853130/
!wget https://zihao-openmmlab.obs.cn-east-3.myhuaweicloud.com/20220716-mmclassification/test/husky1.jpeg -O test_img/husky1.jpeg

# 猫狗,来源:https://unsplash.com/photos/ouo1hbizWwo
!wget https://zihao-openmmlab.obs.cn-east-3.myhuaweicloud.com/20220716-mmclassification/test/cat_dog.jpg -O test_img/cat_dog.jpg

!wget https://zihao-openmmlab.obs.cn-east-3.myhuaweicloud.com/20220716-mmclassification/test/video_2.mp4 -O test_img/video_2.mp4

三、预测单张图片

1. 导入基础工具包

import os # 操作系统库

import cv2 # 开源cv库

import pandas as pd # 数据分析库
import numpy as np # 科学计算库

import torch # pytorch

import matplotlib.pyplot as plt # 数据可视化库
%matplotlib inline

2. 获取计算设备

# 有 GPU 就用 GPU,没有就用 CPU
device = torch.device('cuda:0' if torch.cuda.is_available() else 'cpu')
print('device', device)

3. 载入预训练图像分类模型

from torchvision import models
# 载入预训练图像分类模型(resnet18为已经训练好的模型,我们直接调包用就好)
model = models.resnet18(pretrained=True) 
model = model.eval()
model = model.to(device)

4. 定义图像(模型输入)预处理方法

from torchvision import transforms

# 测试集图像预处理-RCTN:缩放、裁剪、转 Tensor、归一化
test_transform = transforms.Compose([transforms.Resize(256),
                                     transforms.CenterCrop(224),
                                     transforms.ToTensor(),
                                     transforms.Normalize(
                                         mean=[0.485, 0.456, 0.406], 
                                         std=[0.229, 0.224, 0.225])
                                    ])

PyTorch 中用于测试数据集预处理的 transforms.Compose 组合。具体解释如下:

  1. 缩放 transforms.Resize(256):将图像大小调整为 256x256 像素,保持原始图像的纵横比。

  2. 裁剪 transforms.CenterCrop(224):将图像中心区域裁剪为 224x224 像素,这是许多预训练模型接受的输入图像尺寸。

  3. 转tensor transforms.ToTensor():将 PIL 图像或 numpy 数组转换为 PyTorch 张量,并将像素值缩放到 0 到 1 之间。

    • 张量(tensor):是一种数学概念,它是一种多维数组,可以看作是标量、向量和矩阵的推广。在 PyTorch 中,张量是一种特殊的数据结构,它与 NumPy 数组类似,但是能够在 GPU 上运行,从而加速运算。与 NumPy 数组不同的是,PyTorch 张量可以自动求导,支持动态图,方便构建深度学习模型。

      import torch
      # 创建一个标量
      x = torch.tensor(3.14)
      # 创建一个向量
      y = torch.tensor([1, 2, 3])
      # 创建一个矩阵
      z = torch.tensor([[1, 2], [3, 4]])
      # 这些张量的形状可以通过 shape 属性获取,数据类型可以通过 dtype 属性获取。我们还可以使用张量进行数学运算。
      
  4. 归一化 transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]):对张量进行标准化处理,以便每个像素都以预定义的平均值和标准差为中心。这是为了减少数据之间的差异并帮助模型更好地进行训练。

通过使用这些测试数据集预处理步骤,可以将测试数据集中的每个图像转换为张量,并进行与训练数据集相同的标准化处理,从而使测试数据集的预处理与训练数据集一致。这有助于确保测试数据集的输入具有相同的尺寸和像素值范围,从而更好地适应深度学习模型的要求。

5. 载入一张测试图像

img_path = 'test_img/cat_dog.jpg'

image-20230219164901950

# 用 pillow 载入
from PIL import Image
img_pil = Image.open(img_path)

使用Pillow的Image类来读取一张图片,实例化一个Image对象img_pil,并将图片读取到内存中。

np.array(img_pil).shape

PIL.Image 对象转换为 numpy.ndarray 数组,并查看该数组的形状。通常情况下,我们可以通过 np.array() 函数将 PIL.Image 对象转换为 numpy 数组,从而方便地对图像进行进一步的处理和分析。对于三通道的 RGB 彩色图像,其数组形状为 (height, width, 3),即高度、宽度和 3 个通道(红、绿、蓝)。

6. 执行图像分类预测

input_img = test_transform(img_pil) # 图像预处理(转换为张量)
input_img = input_img.unsqueeze(0).to(device)

input_img.unsqueeze(0) 是将 input_img 张量的维度从 [C, H, W] 变为 [1, C, H, W],即在第 0 个维度(即 batch 维度)增加一个维度,表示这是一个 batch 大小为 1 的数据。这是因为 PyTorch 中大多数模型都是设计为可以同时处理多个样本(即 batch),因此输入张量的第一个维度通常表示 batch 的大小。

.to(device) 表示将数据转移到指定设备上,其中 device 可以是 CPU 或 GPU。对于大规模的深度学习模型,通常需要使用 GPU 加速,因此需要将输入张量放到 GPU 上。

# 执行前向预测,得到所有类别的 logit 预测分数
pred_logits = model(input_img) 
import torch.nn.functional as F
pred_softmax = F.softmax(pred_logits, dim=1) # 对 logit 分数做 softmax 运算(因为我们要的是置信度)

7. 预测结果分析

  1. 各类别置信度柱状图
plt.figure(figsize=(8,4))

x = range(1000)
y = pred_softmax.cpu().detach().numpy()[0]

ax = plt.bar(x, y, alpha=0.5, width=0.3, color='yellow', edgecolor='red', lw=3)
plt.ylim([0, 1.0]) # y轴取值范围
# plt.bar_label(ax, fmt='%.2f', fontsize=15) # 置信度数值

plt.xlabel('Class', fontsize=20)
plt.ylabel('Confidence', fontsize=20)
plt.tick_params(labelsize=16) # 坐标文字大小
plt.title(img_path, fontsize=25)

plt.show()

image-20230219162421852

  1. 取置信度最大的 n 个结果
n = 10
top_n = torch.topk(pred_softmax, n)

image-20230219163333746

# 解析出类别
pred_ids = top_n[1].cpu().detach().numpy().squeeze()

image-20230219163432050

# 解析出置信度
confs = top_n[0].cpu().detach().numpy().squeeze()

image-20230219163518356

  1. 载入ImageNet 1000图像分类标签

    df = pd.read_csv('imagenet_class_index.csv')
    

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-u7bysEB4-1676878703009)(https://gitee.com/i-dont-have-him/cloudimage/raw/master/img/202302191632909.png)]

    # 将数据转换成键值对形式,键是id,值是[wordnet编号,英文名称]
    idx_to_labels = {}
    for idx, row in df.iterrows():
        idx_to_labels[row['ID']] = [row['wordnet'], row['class']]
    

    下面是部分数据:

    image-20230219163305716

  2. 图像分类结果写在原图上

# 用 opencv 载入原图
img_bgr = cv2.imread(img_path)
for i in range(n):
    class_name = idx_to_labels[pred_ids[i]][1] # 获取类别名称
    confidence = confs[i] * 100 # 获取置信度
    text = '{:<15} {:>.4f}'.format(class_name, confidence)
    print(text)
    
    # !图片,添加的文字,左上角坐标,字体,字号,bgr颜色,线宽
    img_bgr = cv2.putText(img_bgr, text, (25, 50 + 40 * i), cv2.FONT_HERSHEY_SIMPLEX, 1.25, (0, 0, 255), 3)

image-20230219163951848

# 保存图像
cv2.imwrite('output/img_pred.jpg', img_bgr)
# 载入预测结果图像
img_pred = Image.open('output/img_pred.jpg')
img_pred

image-20230219165252817

  1. 图像和柱状图一起显示
fig = plt.figure(figsize=(18,6))

# 绘制左图-预测图
ax1 = plt.subplot(1,2,1)
ax1.imshow(img_pred)
ax1.axis('off')

# 绘制右图-柱状图
ax2 = plt.subplot(1,2,2)
x = df['ID']
y = pred_softmax.cpu().detach().numpy()[0]
ax2.bar(x, y, alpha=0.5, width=0.3, color='yellow', edgecolor='red', lw=3)

plt.ylim([0, 1.0]) # y轴取值范围
plt.title('{} Classification'.format(img_path), fontsize=30)
plt.xlabel('Class', fontsize=20)
plt.ylabel('Confidence', fontsize=20)
ax2.tick_params(labelsize=16) # 坐标文字大小

plt.tight_layout()
fig.savefig('output/预测图+柱状图.jpg')

image-20230219165324522

  1. 预测结果表格输出

    pred_df = pd.DataFrame() # 预测结果表格
    for i in range(n):
        class_name = idx_to_labels[pred_ids[i]][1] # 获取类别名称
        label_idx = int(pred_ids[i]) # 获取类别号
        wordnet = idx_to_labels[pred_ids[i]][0] # 获取 WordNet
        confidence = confs[i] * 100 # 获取置信度
        pred_df = pred_df.append({'Class':class_name, 'Class_ID':label_idx, 'Confidence(%)':confidence, 'WordNet':wordnet}, ignore_index=True) # 预测结果表格添加一行
    display(pred_df) # 展示预测结果表格
    

image-20230219165344592

标签的中文显示

整体流程基本上与上面一致,只是改成了中文标签。

设置matplotlib中文字体

import matplotlib.pyplot as plt
# windows操作系统
plt.rcParams['font.sans-serif']=['SimHei']  # 用来正常显示中文标签 
plt.rcParams['axes.unicode_minus']=False  # 用来正常显示负号

导入pillow中文字体

from PIL import ImageFont, ImageDraw
# 导入中文字体,指定字号
font = ImageFont.truetype('SimHei.ttf', 32)

四、预测视频文件

处理逻辑:

  1. 载入预训练图像分类模型(resnet18)

  2. 载入ImageNet 1000图像分类标签

  3. 编写测试集图像预处理规则(缩放、剪裁、转tensor、归一化)

  4. 图像分类预测函数(输入摄像头画面bgr-array,输出前n个图像分类预测结果的图像bgr-array)

    跟之前预测单张图片逻辑大致是一样的:

    • BGR 转 RGB:

      在计算机视觉领域中,常用的图像颜色空间有 RGB 和 BGR 两种。RGB 颜色空间指的是红绿蓝三原色,而 BGR 颜色空间则是指蓝绿红三原色,通常在使用 OpenCV 库进行图像处理时,图像数据存储的是 BGR 格式。而在 PyTorch 中,使用 PIL 库读入的图像数据格式为 RGB 格式,所以需要在读入图像后通过 cv2.cvtColor 函数进行颜色空间转换,将 BGR 格式转换为 RGB 格式,才能与使用 PIL 库处理的图像数据保持一致。

    • array 转 pil

    • 对图片进行预处理;执行前向预测,得到所有类别的 logit 预测分数;对 logit 分数做 softmax 运算;取置信度最大的 n 个结果;解析出类别、置信度;在图像上写字。

    • RGB转BGR

    • 返回前n个图像分类预测结果的图像bgr-array和所有类别的 logit 预测分数做softmax运算后的结果

  5. 视频预测:

    • 输入待预测视频路径
    • 创建一个临时文件夹存放每帧(用存入时间命名)的结果
    • 通过路径读入待预测视频
    • 对视频进行逐帧处理(每一帧都进行图像分类预测,即调用上一步编写的分类预测函数),将处理后的当前帧图像保存至临时文件夹
    • 将处理后的每一帧图像串成视频文件

五、预测摄像头实时画面

处理逻辑:

  1. 载入预训练图像分类模型

  2. 载入ImageNet 1000图像分类标签

  3. 编写测试集图像预处理规则(缩放、剪裁、转tensor、归一化)

  4. 获取摄像头的一帧画面

  5. 对该帧画面进行图像分类预测(与前面预测单张图片是一样的)

  6. 编写处理单帧画面的函数(同上)

  7. 调用摄像头获取每帧,设置一个死循环,不断重复做以下操作(直至break触发:按q或者esc):

    • 获取画面

    • 调用处理帧函数处理画面

    • 展示处理后的三通道图像

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值