学习笔记:Pytorch 搭建自己的Faster-RCNN目标检测平台

B站学习视频
up主的csdn博客

1、什么是Faster R-CNN

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2、pytorch-gpu环境配置(跳过)

3、Faster R-CNN整体结构介绍

在这里插入图片描述
Faster-RCNN可以采用多种的主干特征提取网络,常用的有VGG,Resnet,Xception等等。
Faster-RCNN对输入进来的图片尺寸没有固定,但一般会把输入进来的图片短边固定成600.

4、Resnet50-主干特征提取网络介绍

具体学习见:Resnet50

import math

import torch.nn as nn
from torch.hub import load_state_dict_from_url


class Bottleneck(nn.Module):
    expansion = 4 #最后一个卷积层输出通道数相对于输入通道数的倍数
    def __init__(self, inplanes, planes, stride=1, downsample=None):
        '''
        inplanes:输入通道数
        planes:卷积层输出的通道数
        stride:卷积的步长,默认为1
        downsample:是否对输入进行下采样
        '''
        super(Bottleneck, self).__init__()
        #使用1*1卷积核,压缩通道数
        self.conv1 = nn.Conv2d(inplanes, planes, kernel_size=1, stride=stride, bias=False)#二维卷积层
        self.bn1 = nn.BatchNorm2d(planes)#二维批归一化层
        #使用3*3卷积核,特征提取,padding=1,在输入的周围使用1个零填充,以保持特征图的尺寸
        self.conv2 = nn.Conv2d(planes, planes, kernel_size=3, stride=1, padding=1, bias=False)
        self.bn2 = nn.BatchNorm2d(planes)
        #使用1*1卷积核,扩张通道数
        self.conv3 = nn.Conv2d(planes, planes * 4, kernel_size=1, bias=False)
        self.bn3 = nn.BatchNorm2d(planes * 4)

        self.relu = nn.ReLU(inplace=True)
        self.downsample = downsample
        self.stride = stride

    def forward(self, x):
        residual = x#残差

        out = self.conv1(x)
        out = self.bn1(out)
        out = self.relu(out)

        out = self.conv2(out)
        out = self.bn2(out)
        out = self.relu(out)

        out = self.conv3(out)
        out = self.bn3(out)
        if self.downsample is not None:
            residual = self.downsample(x)

        out += residual
        out = self.relu(out)

        return out

class ResNet(nn.Module):
    def __init__(self, block, layers, num_classes=1000):
        #-----------------------------------#
        #   假设输入进来的图片是600,600,3
        #-----------------------------------#
        self.inplanes = 64 #初始化ResNet模型的通道数为64
        super(ResNet, self).__init__()

        # 600,600,3 -> 300,300,64
        self.conv1 = nn.Conv2d(3, 64, kernel_size=7, stride=2, padding=3, bias=False)
        self.bn1 = nn.BatchNorm2d(64)
        self.relu = nn.ReLU(inplace=True)

        # 300,300,64 -> 150,150,64 最大池化层,用于降低特征图的空间分辨率
        self.maxpool = nn.MaxPool2d(kernel_size=3, stride=2, padding=0, ceil_mode=True)

        #构建4个残差块组成的特征提取部分,每个部分的通道数和空间分辨率逐渐增加
        # 150,150,64 -> 150,150,256
        self.layer1 = self._make_layer(block, 64, layers[0])
        # 150,150,256 -> 75,75,512
        self.layer2 = self._make_layer(block, 128, layers[1], stride=2)
        # 75,75,512 -> 38,38,1024 到这里可以获得一个38,38,1024的共享特征层
        self.layer3 = self._make_layer(block, 256, layers[2], stride=2)
        # self.layer4被用在classifier模型中
        self.layer4 = self._make_layer(block, 512, layers[3], stride=2)
        
        self.avgpool = nn.AvgPool2d(7)#全局平均池化层 池化核7*7
        #将最终的特征映射到类别数量的空间
        self.fc = nn.Linear(512 * block.expansion, num_classes) #全连接层

        for m in self.modules():
            if isinstance(m, nn.Conv2d):
                n = m.kernel_size[0] * m.kernel_size[1] * m.out_channels
                m.weight.data.normal_(0, math.sqrt(2. / n))
            elif isinstance(m, nn.BatchNorm2d):
                m.weight.data.fill_(1)
                m.bias.data.zero_()

    def _make_layer(self, block, planes, blocks, stride=1):
        downsample = None
        #-------------------------------------------------------------------#
        #   当模型需要进行高和宽的压缩的时候,就需要用到残差边的downsample
        #-------------------------------------------------------------------#
        if stride != 1 or self.inplanes != planes * block.expansion:
            downsample = nn.Sequential(
                nn.Conv2d(self.inplanes, planes * block.expansion,kernel_size=1, stride=stride, bias=False),
                nn.BatchNorm2d(planes * block.expansion),
            )
        layers = []
        layers.append(block(self.inplanes, planes, stride, downsample))
        self.inplanes = planes * block.expansion
        for i in range(1, blocks):
            layers.append(block(self.inplanes, planes))
        return nn.Sequential(*layers)

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

        x = self.layer1(x)
        x = self.layer2(x)
        x = self.layer3(x)
        x = self.layer4(x)

        x = self.avgpool(x)
        x = x.view(x.size(0), -1)
        x = self.fc(x)
        return x

def resnet50(pretrained = False):
    model = ResNet(Bottleneck, [3, 4, 6, 3])
    if pretrained:
        state_dict = load_state_dict_from_url("https://download.pytorch.org/models/resnet50-19c8e357.pth", model_dir="./model_data")
        model.load_state_dict(state_dict)
    #----------------------------------------------------------------------------#
    #   获取特征提取部分,从conv1到model.layer3,最终获得一个38,38,1024的特征层
    #----------------------------------------------------------------------------#
    features    = list([model.conv1, model.bn1, model.relu, model.maxpool, model.layer1, model.layer2, model.layer3])
    #----------------------------------------------------------------------------#
    #   获取分类部分,从model.layer4到model.avgpool
    #----------------------------------------------------------------------------#
    classifier  = list([model.layer4, model.avgpool])
    
    features    = nn.Sequential(*features)
    classifier  = nn.Sequential(*classifier)
    return features, classifier

5、RPN-建议框网络构建

在这里插入图片描述
在这里插入图片描述

6、Anchors-先验框详解

import numpy as np

#--------------------------------------------#
#   生成基础的先验框
#--------------------------------------------#
def generate_anchor_base(base_size=16, ratios=[0.5, 1, 2], anchor_scales=[8, 16, 32]):
    '''
    base_size:基础框的大小,默认为16
    ratios:生成锚框的宽高比,默认为[0.5,1,2]
    anchor_scales:生成锚框的尺度,默认为[8,16,32]
    '''
    #创建一个形状为((len(ratios) * len(anchor_scales), 4)的全零数组,用于存储生成的基础先验框的坐标信息
    #每个先验框由4个坐标值表示
    anchor_base = np.zeros((len(ratios) * len(anchor_scales), 4), dtype=np.float32)
    for i in range(len(ratios)):
        for j in range(len(anchor_scales)):
            #使用两个嵌套的循环遍历宽高比和尺度的所有组合,宽高比定义+面积不变性
            h = base_size * anchor_scales[j] * np.sqrt(ratios[i])
            w = base_size * anchor_scales[j] * np.sqrt(1. / ratios[i])

            index = i * len(anchor_scales) + j
            anchor_base[index, 0] = - h / 2.
            anchor_base[index, 1] = - w / 2.
            anchor_base[index, 2] = h / 2.
            anchor_base[index, 3] = w / 2.
    return anchor_base

#--------------------------------------------#
#   对基础先验框进行拓展对应到所有特征点上
#--------------------------------------------#
def _enumerate_shifted_anchor(anchor_base, feat_stride, height, width):
    #---------------------------------#
    #   计算网格中心点
    #---------------------------------#
    '''
    anchor_base 表示基础先验框的坐标信息;
    feat_stride 特征点间距步长
    height 和 width 表示特征图的高度和宽度。
    '''
    shift_x             = np.arange(0, width * feat_stride, feat_stride)
    shift_y             = np.arange(0, height * feat_stride, feat_stride)
    shift_x, shift_y    = np.meshgrid(shift_x, shift_y)
    shift               = np.stack((shift_x.ravel(), shift_y.ravel(), shift_x.ravel(), shift_y.ravel(),), axis=1)

    #---------------------------------#
    #   每个网格点上的9个先验框
    #---------------------------------#
    A       = anchor_base.shape[0]
    K       = shift.shape[0]
    anchor  = anchor_base.reshape((1, A, 4)) + shift.reshape((K, 1, 4))
    #---------------------------------#
    #   所有的先验框
    #---------------------------------#
    anchor  = anchor.reshape((K * A, 4)).astype(np.float32)
    return anchor
    
if __name__ == "__main__":
    import matplotlib.pyplot as plt
    nine_anchors = generate_anchor_base()
    print(nine_anchors)

    height, width, feat_stride  = 38,38,16
    anchors_all                 = _enumerate_shifted_anchor(nine_anchors, feat_stride, height, width)
    print(np.shape(anchors_all))
    
    fig     = plt.figure()
    ax      = fig.add_subplot(111)
    plt.ylim(-300,900)
    plt.xlim(-300,900)
    shift_x = np.arange(0, width * feat_stride, feat_stride)
    shift_y = np.arange(0, height * feat_stride, feat_stride)
    shift_x, shift_y = np.meshgrid(shift_x, shift_y)
    plt.scatter(shift_x,shift_y)
    box_widths  = anchors_all[:,2]-anchors_all[:,0]
    box_heights = anchors_all[:,3]-anchors_all[:,1]
    
    for i in [108, 109, 110, 111, 112, 113, 114, 115, 116]:
        rect = plt.Rectangle([anchors_all[i, 0],anchors_all[i, 1]],box_widths[i],box_heights[i],color="r",fill=False)
        ax.add_patch(rect)
    plt.show()

在这里插入图片描述

在这里插入图片描述

7、模型训练及测试结果

结合博客及视频,完成VOC2007数据集的训练及预测,对faster rcnn原理及如何使用有了初步的认识。train.py frcnn.py predict.py get_map.py 相关结果如下:
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/205776.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Re8 Generative Modeling by Estimating Gradients of the Data Distribution

宋扬博士的作品,和DDPM同属扩散模型开创工作,但二者的技术路线不同 Introduction 当前生成模型主要分成两类 基于似然模型 通过近似最大似然直接学习分布的概率密度,如VAE 隐式生成模型 概率分布由其抽样过程的模型隐式表示&#xff0c…

Verilog 入门(三)(表达式)

文章目录 操作数操作符算术操作符关系操作符相等关系操作符逻辑操作符按位操作符条件操作符 操作数 操作数可以是以下类型中的一种: 常数参数线网寄存器位选择部分选择存储器单元函数调用 操作符 Verilog HDL中的操作符可以分为下述类型: 算术操作符…

WPF窗口样式的比较

WPF窗口样式的比较 1.WPF默认Window窗口 带有图标 标题栏 最小最大化推出按钮 <Window x:Class"GlowWindowDemo.MainWindow"xmlns"http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x"http://schemas.microsoft.com/winfx/2006…

在Spring Boot中使用JavaMailSender发送邮件

用了这么久的Spring Boot&#xff0c;我们对Spring Boot的了解应该也逐步进入正轨了&#xff0c;这篇文章讲的案例也在我们的实际开发中算是比较实用的了&#xff0c;毕竟我们完成注册功能和对用户群发消息&#xff0c;都可以采用到邮箱发送功能&#xff0c;往下看&#xff0c;…

焕发图片生机,批量升级gif图片像素,打造高质量图片盛宴!

你是否曾经遇到过需要提高gif图片质量&#xff0c;但手动处理每一张图片又非常耗时且繁琐的情况&#xff1f;如果你觉得处理大量图片会让你感到压力&#xff0c;那么你一定需要我们的批量提高像素工具&#xff01; 第一步&#xff0c;首先我们要进入首助剪辑高手主页面&#x…

ELFK集群部署(Filebeat+ELK) 本地收集nginx日志 远程收集多个日志

filebeat是一款轻量级的日志收集工具&#xff0c;可以在非JAVA环境下运行。 因此&#xff0c;filebeat常被用在非JAVAf的服务器上用于替代Logstash&#xff0c;收集日志信息。 实际上&#xff0c;Filebeat几乎可以起到与Logstash相同的作用&#xff0c; 可以将数据转发到Logst…

正式版PS 2024 25新增功能 刚刚发布的虎标正式版

Adobe Photoshop 2024是一款业界领先的图像编辑软件&#xff0c;被广泛应用于设计、摄影、插图等领域。以下是这款软件的一些主要功能和特点&#xff1a; 丰富的工具和功能。Adobe Photoshop 2024提供了丰富的工具和功能&#xff0c;可以帮助用户对图像进行编辑、修饰和优化。…

虚拟数据生成_以Python为工具

生成虚拟数据_以Python为工具 生成虚拟数据技术在现实生活中具有多个重要的应用领域。它为数据隐私保护、机器学习算法开发、数据处理和可视化等方面提供了实用且有价值的解决方案。尤其是能满足定制化需求的虚拟数据&#xff0c;在预期的方向上让数据定向随机。 &#x1f339…

编程之外,生活的美好航程

&#x1f680; 作者主页&#xff1a; 有来技术 &#x1f525; 开源项目&#xff1a; youlai-mall &#x1f343; vue3-element-admin &#x1f343; youlai-boot &#x1f33a; 仓库主页&#xff1a; Gitee &#x1f4ab; Github &#x1f4ab; GitCode &#x1f496; 欢迎点赞…

volatile-之小总结

凭什么我们Java写了一个volatile关键字&#xff0c;系统底层加入内存屏障&#xff1f;两者的关系如何勾搭&#xff1f; 内存屏障是什么&#xff1f; 是一种屏障指令&#xff0c;它使得CPU或编译器对屏障指令的前和后所发出的内存操作执行一个排序的约 束。也称为内存栅栏或栅…

概念理论类-k8s :架构篇

转载&#xff1a;新手通俗易懂 k8s &#xff1a;架构篇 Kubernetes&#xff0c;读音是[kubə’netis]&#xff0c;翻译成中文就是“库伯奈踢死”。当然了&#xff0c;也可以直接读它的简称&#xff1a;k8s。为什么把Kubernetes读作k8s&#xff0c;因为Kubernetes中间有8个字母…

centos7配置tomcat

简介 Tomcat是一个使用Java编写的开源Web应用服务器,是由Apache Software Foundation管理的一个项目。它是一个轻量级的应用服务器,可以下载、安装和使用,而且还提供了许多高级功能,例如支持Java Servlet、JavaServer Pages (JSP)和JavaServer Faces (JSF) 等JavaEE技术,…

mysql中字符串截取与拆分

按分隔符把字符串拆成多行 引言截取字符串一、left(str,length)二、right(str,length)三、截取特定长度的字符串四、按分隔符截取 分割字符串一、分割成多列二、分割成多行 总结 引言 截取和拆分字符串在编程生涯中是普遍存在的&#xff0c;在sql中也不例外&#xff0c;下面就…

Panalog 日志审计系统 前台RCE漏洞复现

0x01 产品简介 Panalog是一款日志审计系统&#xff0c;方便用户统一集中监控、管理在网的海量设备。 0x02 漏洞概述 Panalog日志审计系统 sy_query.php接口处存在远程命令执行漏洞&#xff0c;攻击者可执行任意命令&#xff0c;接管服务器权限。 0x03 复现环境 FOFA&#xf…

Elasticsearch:使用 ILM 示例运行降采样 (downsampling)

如果你对降采样还不是很熟的话&#xff0c;请阅读之前的文章 “Elasticsearch&#xff1a;对时间序列数据流进行降采样&#xff08;downsampling)”。这是一个简化的示例&#xff0c;可让你快速了解降采样如何作为 ILM 策略的一部分来减少一组采样指标的存储大小。 该示例使用典…

如何充分了解客户需求

如何充分了解客户需求 如何充分了解客户需求&#xff0c;以提供贴心服务&#xff1f; 想要提供超出客户期望的优质服务&#xff0c;首先需要了解他们的需求。通过多种方式收集客户反馈、深入挖掘数据、建立紧密的客户关系&#xff0c;我们可以更好地理解客户需求&#xff0c;…

Flutter使用flutter_gen管理资源文件

pub地址&#xff1a; https://pub.dev/packages/flutter_gen 1.添加依赖 在你的pubspec.yaml文件中添加flutter_gen作为开发依赖 dependencies:build_runner:flutter_gen_runner: 2.配置pubspec.yaml 在pubspec.yaml文件中&#xff0c;配置flutter_gen的参数。指定输出路…

6.1 Windows驱动开发:内核枚举SSDT表基址

SSDT表&#xff08;System Service Descriptor Table&#xff09;是Windows操作系统内核中的关键组成部分&#xff0c;负责存储系统服务调用的相关信息。具体而言&#xff0c;SSDT表包含了系统调用的函数地址以及其他与系统服务相关的信息。每个系统调用对应SSDT表中的一个表项…

Netty Review - 探索Channel和Pipeline的内部机制

文章目录 概念Channel Pipeline实现原理分析详解 Inbound事件和Outbound事件演示Code 概念 Netty中的Channel和Pipeline是其核心概念&#xff0c;它们在构建高性能网络应用程序时起着重要作用。 Channel&#xff1a; 在Netty中&#xff0c;Channel表示一个开放的连接&#xff…

Spring整合web环境

目录 Javaweb三大组件及环境特点 Spring整合web环境的思路及实现 Spring的web开发组件spring-web MVC框架思想及其设计思路 Javaweb三大组件及环境特点 Spring整合web环境的思路及实现 package com.xfy.listener;import com.xfy.config.SpringConfig; import org.springfra…