深度学习视觉应用

1 数据集与评价指标

1.1算法评估的相关概念

TP: 被正确地划分为正例的个数,即实际为正例且被分类器划分为正例的实例数
FP: 被错误地划分为正例的个数,即实际为负例但被分类器划分为正例的实例数
FN:被错误地划分为负例的个数,即实际为正例但被分类器划分为负例的实例数
TN: 被正确地划分为负例的个数,即实际为负例且被分类器划分为负例的实例数

这些概念是混淆矩阵(Confusion Matrix)中的四个元素,用于描述二分类问题中模型预测结果和实际情况之间的对应关系。其中,TP、FP、FN、TN分别表示真正例(True Positive)、假正例(False Positive)、假负例(False Negative)和真负例(True Negative)。

TP表示模型正确地预测出了正例,FP表示模型将负例错误地预测为了正例,FN表示模型将正例错误地预测为了负例,TN表示模型正确地预测出了负例。这些指标可以用于计算准确率、精确率、召回率、F1-score等评价指标,从而对模型的性能进行评估。

P(精确率): TP/(TP+FP)
R(召回率): TP/(TP+FN)。召回率越高,准确度越低

 P-R曲线:P-R的关系曲线图,表示了召回率和准确率之间的关系。精度(准确率)越高,召回率越低

 1.2 算法评估案例

例子:80个男生,20个女生,做个女生识别器。结果测试了50个全部
输出女生,其中20个本来是女生,30个男生
TP: 20; FP:30 FN:0, TN: 0.
准确率:40%;
召回率:100%

以下是代码演示:

# 定义真阳性(True Positive)、假阳性(False Positive)、假阴性(False Negative)和真阴性(True Negative)的数量
TP = 20
FP = 30
FN = 0
TN = 0

# 计算准确率和召回率
accuracy = (TP + TN) / (TP + FP + FN + TN)
recall = TP / (TP + FN)

# 输出结果
print("准确率:", accuracy)
print("召回率:", recall)

1.3 置信度和准确率

调整阈值可改变准确率或召回值

可以通过改变阈值(也可以看作上下移动蓝色的虚线),来选择让系统识别能出多少个图片,当然阈值的变化会导致Precision与Recall值发生变化。比如,把蓝色虚线放到第一张图片下面,也就是说让系统只识别出最上面的那张飞机图片,那么Precision的值就是100%,而Recall的值则是20%。如果把蓝色虚线放到第二张图片下 面 , 也 就 是 说 让 系 统 只 识 别 出 最 上 面 的 前 两 张 图 片 , 那 么Precision的值还是100%,而Recall的值则增长到是40%。

 不同阈值条件下,Precision与Recall的变化情况

 2 目标检测问题

2.1 问题

目标检测是在给定的图片中精确找到物体所在位置,并标注出物体的类别物体的尺寸变化范围很大,摆放物体的角度,姿态不定,而且可以出现在图片的任何地方,并且物体还可以是多个类别。

2.2 目标检测基本原理

目标检测是计算机视觉中的一项重要任务,其目的是在图像或视频中识别和定位目标物体。基本原理可以概括为以下几个步骤:

  1. 图像预处理:对原始图像进行预处理,包括图像缩放、色彩空间转换、亮度均衡化、去噪等操作,以便更好地提取目标物体的特征。

  2. 特征提取:使用深度学习等方法提取图像中的特征。常用的方法包括卷积神经网络(CNN)、循环神经网络(RNN)等。

  3. 目标框生成:通过目标框生成算法,生成可能包含目标物体的候选框,如Selective Search等。

  4. 目标框分类:使用分类器对每个目标框进行分类,判断该框中是否包含目标物体。常用的分类器包括支持向量机(SVM)、卷积神经网络等。

  5. 目标框回归:对于包含目标物体的目标框,使用回归算法对框的位置进行微调,以更精确地定位目标物体。

  6. 后处理:通过非极大值抑制(NMS)等技术对检测结果进行过滤和优化,排除重复检测和误检测。

目标检测基本原理包含上述步骤,不同的算法会有所不同,但都是围绕这些基本步骤展开的。

在目标检测中,目标框通常是指用于表示目标物体位置和大小的矩形框。目标框也称为边界框(bounding box),其包围目标物体的位置和大小可以用坐标和尺寸来表示。

在目标检测中,生成目标框的过程通常是通过候选框生成算法完成的,如Selective Search等。这些算法会在图像中生成一组候选框,其中可能包含目标物体。对于每个候选框,目标检测算法会使用分类器来判断该框中是否包含目标物体,并进行回归调整,以更精确地定位目标物体。

在检测结果中,每个目标框通常会包含目标物体的位置和大小信息,例如左上角和右下角的坐标、宽度和高度等。这些信息可以用于定位目标物体,并计算目标物体的其他属性,例如目标物体的运动、速度等。

需要注意的是,在实际应用中,目标框的大小和位置可能会受到多种因素的影响,例如目标物体的尺寸、姿态、遮挡等,因此需要结合具体应用场景和需求,选择合适的目标框生成算法和参数进行调整和优化。

除了目标框,还有其他的框在目标检测中也经常使用。以下是一些常见的框:

  1. 建议框(proposals):建议框是在目标检测中用于生成目标框的一种框。与候选框不同,建议框通常是在较小的尺度下生成的,因此需要进行缩放和变换来适应目标物体的不同大小和姿态。目标检测算法通常会在建议框上使用分类器来判断是否包含目标物体,并进行回归调整。

  2. 锚点框(anchor boxes):锚点框是一种用于处理多尺度目标的方法。在锚点框算法中,图像会被分成多个区域,并在每个区域中生成一组锚点框。这些锚点框的大小、形状和位置都是预先定义好的,目标检测算法会在每个锚点框上使用分类器来判断是否包含目标物体,并进行回归调整。

  3. 蒙版框(mask boxes):蒙版框是一种用于处理物体分割的框。与目标框不同,蒙版框包围的是目标物体的轮廓,通常用于生成物体的分割掩模,以便将目标物体与背景进行分离。

需要注意的是,在目标检测中,不同的框类型和参数选择可能会对检测结果产生不同的影响,因此需要根据具体应用场景和需求选择合适的框类型和参数进行调整和优化。

2.2.1 边界框

在目标检测里,我们通常使用边界框(bounding box)来描述目标位置。边界框是一个矩形框,可以由矩形左上角的x和y轴坐标与右下角的x和y轴坐标确定。我们根据下面的图的坐标信息来定义图中狗和猫的边界框。图中的坐标原点在图像的左上角,原点往右和往下分别为x轴和y轴的正方向。

dog_bbox, cat_bbox = [60, 45, 378, 516], [400, 112, 655, 493]

我们将边界框加载在图像上输出:
fig = d2l.plt.imshow(img)
fig.axes.add_patch(bbox_to_rect(dog_bbox,'blue'))
fig.axes.add_patch(bbox_to_rect(cat_bbox,'red'));

可以看到目标的主要轮廓在框内

 2.2.2 锚框

目标检测算法通常会在输入图像中采样大量的区域,然后判断这些区域中是否包含我们感兴趣的目标,并调整区域边缘从而更准确地预测目标的真实边界框(ground-truth bounding box)。
不同的模型使用的区域采样方法可能不同。这里我们介绍其中的一种方法:它以每个像素为中心生成多个大小和宽高比(aspect ratio)不同的边界框。这些边界框被称为锚框(anchor box)。我们将在后面基于锚框实践目标检测。

先导相关包。

%matplotlib inline
from PIL import Image
import numpy as np
import math
import torch
import sys
sys.path.append("..")
import d2lzh_pytorch as
d2l
print(torch.__version__)
# 1.6.0

生成多个锚框

d2l.set_figsize()
img = Image.open('img/catdog.jpg')
w, h = img.size
print("w = %d, h = %d" % (w, h)) # w = 728, h = 561
def MultiBoxPrior(feature_map, sizes=[0.75, 0.5, 0.25],
ratios=[1, 2, 0.5])
pairs = [] # pair of (size, sqrt(ration))
for r in ratios:
pairs.append([sizes[0], math.sqrt(r)])
for s in sizes[1:]:
pairs.append([s, math.sqrt(ratios[0])])
pairs = np.array(pairs)
ss1 = pairs[:, 0] * pairs[:, 1] # size * sqrt(ration)
ss2 = pairs[:, 0] / pairs[:, 1] # size / sqrt(ration)
base_anchors = np.stack([-ss1, -ss2, ss1, ss2], axis=1) / 2
h, w = feature_map.shape[-2:]
shifts_x = np.arange(0, w) / w
shifts_y = np.arange(0, h) / h
shift_x, shift_y = np.meshgrid(shifts_x, shifts_y)
shift_x = shift_x.reshape(-1)
shift_y = shift_y.reshape(-1)
shifts = np.stack((shift_x, shift_y, shift_x, shift_y), axis=1)
anchors = shifts.reshape((-1, 1, 4)) + base_anchors.reshape((1, -1, 4))
return torch.tensor(anchors, dtype=torch.float32).view(1, -1, 4)
X = torch.Tensor(1, 3, h, w) # 构造输入数据
Y = MultiBoxPrior(X, sizes=[0.75, 0.5, 0.25], ratios=[1, 2, 0.5])
Y.shape # torch.Size([1, 2042040, 4])

标注训练集的锚框

在训练集中,我们将每个锚框视为一个训练样本。为了训练目标检测模型,我们需要为每个锚框标注两类标签:一是锚框所含目标的类别,简称类别;二是真实边界框相对锚框的偏移量,简称偏移量(offset)。在目标检测时,我们首先生成多个锚框,然后为每个锚框预测类别以及偏
移量。接着根据预测的偏移量调整锚框位置从而得到预测边界框。最后筛选需要输出的预测边界框。

输出预测边界框

锚框数量较多时,同一个目标上可能会输出较多相似的预测边界框。为了使结果更加简洁,我们可以移除相似的预测边界框。常用的方法叫作非极大值抑制。假设有ABCDEF6个预测边界框(已经按照得分从小到大排序)
1、从最大概率矩形框F开始,分别判断A~E与F的重叠度IOU是否大于某个设定的阈值;
2、假设B、D与F的重叠度超过阈值,那么就扔掉B、D;并标记第一个矩形框F,是我们保留下来的。
3、从剩下的矩形框A、C、E中,选择概率最大的E,然后判断E与A、C的重叠度,重叠度大于一定的阈值,那么就扔掉;并标记E是我们保留下来的第二个矩形框。
4、一直重复这个过程,找到所有曾经被保留下来的矩形框。

2.2.3 案例

面来看一个具体的例子。先构造4个锚框。简单起见,我们假设预测偏移量全是0:预测边界框即锚框。最后,我们构造每个类别的预测概率

anchors = torch.tensor([[0.1, 0.08, 0.52, 0.92], [0.08, 0.2, 0.56, 0.95],
[0.15, 0.3, 0.62, 0.91], [0.55, 0.2, 0.9, 0.88]])
offset_preds = torch.tensor([0.0] * (4 * len(anchors)))
cls_probs = torch.tensor([[0., 0., 0., 0.,], # 背景的预测概率
[0.9, 0.8, 0.7, 0.1], # 狗的预测概率
[0.1, 0.2, 0.3, 0.9]]) # 猫的预测概率

在图像上打印预测边界框和它们的置信度。
fig = d2l.plt.imshow(img)
show_bboxes(fig.axes, anchors * bbox_scale,
['dog=0.9', 'dog=0.8', 'dog=0.7','cat=0.9'])

3  语义分割

 语义分割关注如何将图像分割成属于不同语义类别的区域。值得一提的是,这些语义区域的标注和预测都是像素级的。下图展示了语义分割中图像有关狗、猫和背景的标签。可以看到,与目标检测相比,语义分割标注的像素级的边框显然更加精细。

 3.1 语义分割

计算机视觉领域还有2个与语义分割相似的重要问题,即图像分割和实例分割。我们在这里将它们与语义分割简单区分一下。
• 图像分割将图像分割成若干组成区域。这类问题的方法通常利用图像中像素之间的相关性。它在训练时不需要有关图像像素的标签信息,在预测时也无法保证分割出的区域具有我们希望得到的语义。
• 实例分割又叫同时检测并分割。它研究如何识别图像中各个目标实例的像素级区域。与语义分割有所不同。
• 以上一张ppt中的两只狗为例,图像分割可能将狗分割成两个区域:一个覆盖以黑色为主的嘴巴和眼睛,而另一个覆盖以黄色为主的其余部分身体
。而实例分割不仅需要区分语义,还要区分不同的目标实例。如果图像中有两只狗,实例分割需要区分像素属于这两只狗中的哪一只。

2.2 语义分割实例

import torch.nn as nn

class UNet(nn.Module):
    def __init__(self, in_channels, out_channels):
        super(UNet, self).__init__()

        self.down1 = DoubleConv(in_channels, 64)
        self.down2 = DoubleConv(64, 128)
        self.down3 = DoubleConv(128, 256)
        self.down4 = DoubleConv(256, 512)

        self.up1 = Up(512, 256)
        self.up2 = Up(256, 128)
        self.up3 = Up(128, 64)

        self.out = nn.Conv2d(64, out_channels, kernel_size=1)

    def forward(self, x):
        x1 = self.down1(x)
        x2 = self.down2(x1)
        x3 = self.down3(x2)
        x4 = self.down4(x3)

        x = self.up1(x4, x3)
        x = self.up2(x, x2)
        x = self.up3(x, x1)

        x = self.out(x)

        return x

class DoubleConv(nn.Module):
    def __init__(self, in_channels, out_channels):
        super(DoubleConv, self).__init__()

        self.conv1 = nn.Conv2d(in_channels, out_channels, kernel_size=3, padding=1)
        self.bn1 = nn.BatchNorm2d(out_channels)
        self.relu1 = nn.ReLU(inplace=True)

        self.conv2 = nn.Conv2d(out_channels, out_channels, kernel_size=3, padding=1)
        self.bn2 = nn.BatchNorm2d(out_channels)
        self.relu2 = nn.ReLU(inplace=True)

    def forward(self, x):
        x = self.conv1(x)
        x = self.bn1(x)
        x = self.relu1(x)

        x = self.conv2(x)
        x = self.bn2(x)
        x = self.relu2(x)

        return x

class Up(nn.Module):
    def __init__(self, in_channels, out_channels):
        super(Up, self).__init__()

        self.up = nn.ConvTranspose2d(in_channels, in_channels // 2, kernel_size=2, stride=2)
        self.conv = DoubleConv(in_channels, out_channels)

    def forward(self, x1, x2):
        x1 = self.up(x1)

        diffY = x2.size()[2] - x1.size()[2]
        diffX = x2.size()[3] - x1.size()[3]

        x1 = F.pad(x1, (diffX // 2, diffX - diffX // 2, diffY // 2, diff

首先,我们需要准备语义分割的数据集。这里我们选择使用Pascal VOC 2012数据集作为示例数据集。该数据集包含20个不同的物体类别,例如人、车辆、飞机等,并提供了标注信息,包括每个像素的类别标签。

接下来,我们使用PyTorch框架搭建一个基于U-Net的语义分割模型。U-Net是一种常用的语义分割网络结构,具有编码器和解码器两部分,其中编码器用于提取特征,解码器用于将特征图恢复到原始尺寸并生成分割结果。

4 人脸识别

4.1 人脸识别含义

人脸识别是一种通过计算机技术对人脸图像进行分析、处理、识别的技术。其主要应用包括安全监控、身份识别、辅助刑侦等领域。

人脸识别的基本原理是通过采集人脸图像,并对图像进行特征提取和匹配,最终确定人脸的身份。常用的人脸识别技术包括以下几种:

  1. 基于特征的人脸识别:通过计算人脸图像中的特征点,如眼睛、鼻子、嘴巴等位置的距离、角度等信息,提取人脸的特征向量,再通过比对特征向量来实现人脸识别。

  2. 基于模板的人脸识别:事先将多张人脸图像的模板保存在数据库中,当需要识别时,将待识别的人脸图像与模板进行匹配,找到最匹配的模板即可确定身份。

  3. 基于深度学习的人脸识别:使用深度神经网络对人脸图像进行特征提取和匹配,深度学习模型可以自动学习人脸图像中的特征,因此相对于传统的基于特征或模板的方法更为准确。

在实际应用中,人脸识别技术还需要考虑诸如光照、角度、遮挡等因素对识别效果的影响,因此需要对图像进行预处理和优化。此外,对于大规模的人脸识别系统,还需要考虑如何高效地存储和管理人脸数据。

4.2 人脸识别步骤

  1. 数据准备:首先需要准备一些带有标签的人脸图像,可以使用公开的人脸数据集,例如LFW(Labeled Faces in the Wild)。

  2. 数据预处理:对人脸图像进行预处理,如缩放、灰度化、归一化等,以便神经网络可以更好地处理。

  3. 构建神经网络:使用深度学习框架,如TensorFlow、PyTorch等,搭建一个神经网络模型,输入为预处理后的人脸图像,输出为人脸的身份标签。常用的神经网络结构包括卷积神经网络(Convolutional Neural Network,CNN)和残差网络(Residual Neural Network,ResNet)等。

  4. 训练神经网络:使用训练集进行神经网络的训练,通过反向传播算法不断调整神经网络的权重和偏置,以达到最优的识别效果。训练过程中需要注意避免过拟合的问题,可以使用数据增强、正则化等方法。

  5. 测试神经网络:使用测试集对已训练好的神经网络进行测试,评估模型的识别准确率、召回率、F1值等指标,以及ROC曲线、PR曲线等评价指标。

  6. 预测新样本:使用训练好的神经网络对新的人脸图像进行预测,输出其对应的身份标签,从而实现人脸识别。

需要注意的是,人脸识别技术涉及个人隐私等敏感问题,需要遵守相关法律法规,并对数据进行保护处理,确保个人信息不被滥用。

4.3 人脸识别案例

以下是一个基于Keras深度学习框架的人脸识别代码演示:

  1. 数据准备:使用LFW数据集中的人脸图像作为训练集和测试集,并将标签信息保存在CSV文件中。
    import numpy as np
    import pandas as pd
    from sklearn.model_selection import train_test_split
    from sklearn.preprocessing import LabelEncoder
    from keras.utils import to_categorical
    
    # 读取CSV文件中的标签信息
    df = pd.read_csv('lfw_labels.csv')
    
    # 将标签编码为整数
    le = LabelEncoder()
    labels = le.fit_transform(df['person'])
    
    # 将标签进行one-hot编码
    labels = to_categorical(labels)
    
    # 划分训练集和测试集
    X_train, X_test, y_train, y_test = train_test_split(df['file'], labels, test_size=0.2, random_state=42)
    

  2. 数据预处理:使用OpenCV库将人脸图像进行灰度化和归一化处理
    import cv2
    
    # 将人脸图像进行灰度化和归一化处理
    def preprocess_image(image_path):
        img = cv2.imread(image_path, cv2.IMREAD_GRAYSCALE)
        img = cv2.resize(img, (64, 64))
        img = img.astype('float32') / 255.
        return np.expand_dims(img, axis=-1)
    
    # 对训练集和测试集的图像进行预处理
    X_train = np.array([preprocess_image(x) for x in X_train])
    X_test = np.array([preprocess_image(x) for x in X_test])
    

  3. 构建神经网络:使用Keras库搭建一个简单的卷积神经网络模型。
    from keras.models import Sequential
    from keras.layers import Conv2D, MaxPooling2D, Flatten, Dense
    
    # 构建卷积神经网络模型
    model = Sequential()
    model.add(Conv2D(32, (3, 3), activation='relu', input_shape=(64, 64, 1)))
    model.add(MaxPooling2D((2, 2)))
    model.add(Conv2D(64, (3, 3), activation='relu'))
    model.add(MaxPooling2D((2, 2)))
    model.add(Conv2D(128, (3, 3), activation='relu'))
    model.add(MaxPooling2D((2, 2)))
    model.add(Conv2D(128, (3, 3), activation='relu'))
    model.add(MaxPooling2D((2, 2)))
    model.add(Flatten())
    model.add(Dense(512, activation='relu'))
    model.add(Dense(128, activation='relu'))
    model.add(Dense(7, activation='softmax'))
    
    # 编译模型
    model.compile(optimizer='rmsprop', loss='categorical_crossentropy', metrics=['accuracy'])
    
  4. 训练神经网络:使用训练集对神经网络进行训练。
    # 训练模型
    model.fit(X_train, y_train, epochs=10, batch_size=32, validation_data=(X_test, y_test))
    

  5. 测试神经网络:使用测试集对已训练好的神经网络进行测试,输出模型的准确率。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值