AlexNet项目图片分类通用模型代码

news2024/9/19 23:03:52

目录

一:建立AlexNet模型(在model文件中写)

1.构造5层卷积层

2.构造3层神经网络层

3.forward函数

4.模型最终代码

二:训练数据(在train中写)

1.读出数据

2.训练

3. 测试模型更新参数

4.完整的训练代码:

三:预测和模型评分(在predict文件中写)

 四:代码使用:

点个赞呗!!!!!!


 

一:建立AlexNet模型(在model文件中写)

AlexNet网络结构相对简单,使用了8层卷积神经网络,前5层是卷积层,剩下的3层是全连接层

1.构造5层卷积层

Conv2d:构造卷积层,参数:(输入通道数,输出通道数等价于卷积核个数,卷积核大小,步长,加0)

ReLU:激活函数,inplace设置是否改变数据

MaxPool2d:池化操作,参数:(核大小,步长)

import torch
import torch.nn as nn

class AlexNet(nn.Module):
    def __init__(self,num_classes=1000):
        super().__init__()
        
        self.features = nn.Sequential(
                nn.Conv2d(3, 48, kernel_size=11, stride=4, padding=2),
                nn.ReLU(inplace=True),
                nn.MaxPool2d(kernel_size=3, stride=2),

                nn.Conv2d(48, 128, kernel_size=5, padding=2),
                nn.ReLU(inplace=True),
                nn.MaxPool2d(kernel_size=3, stride=2),

                nn.Conv2d(128, 192, kernel_size=3, padding=1),
                nn.ReLU(inplace=True),

                nn.Conv2d(192, 192, kernel_size=3, padding=1),
                nn.ReLU(inplace=True),

                nn.Conv2d(192, 128, kernel_size=3, padding=1),
                nn.ReLU(inplace=True),
                nn.MaxPool2d(kernel_size=3, stride=2) # output [128, 6, 6]
        )

2.构造3层神经网络层

Dropout:将比例数据置空,比如数据为(1,2,3,4,5,6),当参数p=0.5时,数据会变成:(1,0,3,0,5,0)。p代表置空的比例,当然这个置空是随机的

Linear:线性变换,参数:(输入数据的通道数,输出数据的通道数)

ReLu:和上面一样

self.classifier = nn.Sequential(
                nn.Dropout(p=0.5),
                nn.Linear(128 * 6 * 6, 2048),
                nn.ReLU(inplace=True),
                nn.Dropout(p=0.5),
                nn.Linear(2048, 2048),
                nn.ReLU(inplace=True),
                nn.Linear(2048, num_classes),
        )

3.forward函数

torch.nn.Flatten(start_dim=1, end_dim=-1)
start_dim与end_dim代表合并的维度,开始的默认值为1,结束的默认值为 - 1,因此常被使用在神经网络当中,将每个batch的数据拉伸成一维

forward的作用:先让数据经过5层卷积,在经过3层全连接层

    def forward(self, x):
        x = self.features(x)
        x = torch.flatten(x, start_dim=1)
        x = self.classifier(x)
        return x

4.模型最终代码

import torch
import torch.nn as nn


class AlexNet(nn.Module):
    def __init__(self, num_classes=1000):
        super().__init__()
        self.features = nn.Sequential(
                nn.Conv2d(3, 48, kernel_size=11, stride=4, padding=2),
                nn.ReLU(inplace=True),
                nn.MaxPool2d(kernel_size=3, stride=2),

                nn.Conv2d(48, 128, kernel_size=5, padding=2),
                nn.ReLU(inplace=True),
                nn.MaxPool2d(kernel_size=3, stride=2),

                nn.Conv2d(128, 192, kernel_size=3, padding=1),
                nn.ReLU(inplace=True),

                nn.Conv2d(192, 192, kernel_size=3, padding=1),
                nn.ReLU(inplace=True),

                nn.Conv2d(192, 128, kernel_size=3, padding=1),
                nn.ReLU(inplace=True),
                nn.MaxPool2d(kernel_size=3, stride=2) # output [128, 6, 6]
        )


        self.classifier = nn.Sequential(
                nn.Dropout(p=0.5),
                nn.Linear(128 * 6 * 6, 2048),
                nn.ReLU(inplace=True),
                nn.Dropout(p=0.5),
                nn.Linear(2048, 2048),
                nn.ReLU(inplace=True),
                nn.Linear(2048, num_classes),
        )

    def forward(self, x):
        torch.nn.Flatten(start_dim=1, end_dim=-1)
        x = self.features(x)
        x = torch.flatten(x, start_dim=1)
        x = self.classifier(x)
        return x

二:训练数据(在train中写)

1.读出数据

RandomResizedCrop:对图片的区域随机改变图片的大小

RandomHorizontalFlip:对图片进行随机翻转

ToTensor:将图片转为Tensor数据类型

Normalize:对数据进行标准化,参数:(标准化的平均值元组,方差元组)

datasets.ImageFolder:读数据类别返回一个字典{0:类别一,1:类别二}, 这行代码可以获取数据的类别数以及对应的类别标签。以字典的形式保存

        参数:(root:读取文件的路径(注意:路径文件中不能直接放图片,应该放各个图片类别的文件),transfrom:对图片进行预处理函数)

torch.utils.data.DataLoader:读取数据:参数(dataset:数据加载的数据集,batch_size:每次加载多少样本数,suffle:是否打乱数据,num_workers:最多并行加载数量)

import os
import sys
import json

from tqdm import tqdm
import torch
import torch.nn as nn
from torchvision import transforms,datasets

from model import AlexNet


def main():
    # 看看是否使用cpu
    device=torch.device('cuda:0' if torch.cuda.is_available() else 'cpu')
    print(f'using:',{device})
    # 要读入图片的目录路径,以下代码假设你这个路径下有文件(train训练集, val测试集)
    image_path=os.path.join('./','训练集和测试集的图片路径')
    # print(image_path)
    # 判断这个路径是否存在,若不存在则报错image path done nit exist
    assert os.path.exists(image_path),'image path done ont exist'
    # 创建读入数据后对数据处理的方法集合
    data_transform={
        # 将训练数据和测试数据的处理集使用对象的方法,以便后面使用
        'train':transforms.Compose([
            transforms.RandomResizedCrop(224),
            transforms.RandomHorizontalFlip(),
            transforms.ToTensor(),
            transforms.Normalize((0.485, 0.456, 0.406),(0.229, 0.224, 0.225))
        ]),
        'val':transforms.Compose([transforms.Resize((224, 224)),
                                       transforms.ToTensor(),
                                       transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))])
    }
    train_dataset=datasets.ImageFolder(root=os.path.join(image_path,'train'),
                                       transform=data_transform['train'])
    train_num=len(train_dataset)
    # print(train_num)
    flower_list=train_dataset.class_to_idx
    # print(flower_list)
    cla_dict=dict((val,key) for key,val in flower_list.items())
    # print(cla_dict)
    json_str=json.dumps(cla_dict,indent=4)
    with open('class_indices.json','w') as json_file:
        json_file.write(json_str)
    # print(json_str)
    batch_size=32
    # 这行代码可以得到你电脑的cpu最大进程数量,如果大于16那么就按照16来
    nw=min([os.cpu_count(),batch_size if batch_size>1 else 0,16])
    print(f'using {nw} dataloader workers every process')
    # 读取训练集数据
    train_loader=torch.utils.data.DataLoader(train_dataset,
                                             batch_size=batch_size,
                                             shuffle=True,
                                             num_workers=nw)
    validata_dataset=datasets.ImageFolder(root=os.path.join(image_path,'val'),
                                          transform=data_transform['val'])
    val_num = len(validata_dataset)
    # 读取测试集数据
    validata_loader=torch.utils.data.DataLoader(validata_dataset,
                                                batch_size=batch_size,
                                                shuffle=False,
                                                num_workers=nw)

2.训练

每行代码都要注释哦!!!

    
    net.to(device)
    # 使用交叉熵损失函数
    loss_fn=nn.CrossEntropyLoss()
    # 使用优化器类,这里使用Adam优化器
    optimizer=torch.optim.Adam(net.parameters(),lr=0.0002)
    # 迭代数量
    epochs=10
    # 训练后的参数保存地址
    save_path='./AlexNet.pth'
    best_acc=0.0
    # 训练样本数
    train_step=len(train_loader)

    for epoch in range(epochs):
        # 开启训练模式
        net.train()
        # 初始化每次迭代的总损失
        running_loss=0.0
        
        # tqdm是一个进度条,将要迭代的数据放入,可以查看迭代的进度
        # stdout :它使用其参数直接显示在控制台窗口上。
        train_bar=tqdm(train_loader,file=sys.stdout)

        for step,data in enumerate(train_bar):
            # images是要训练的图片,labels是这张图片的类别
            images,labels=data
            # 将优化器的梯度置零
            optimizer.zero_grad()
            # 将图片加入到cpu中训练后返回outputs
            outputs=net(images.to(device))
            # 计算损失
            loss=loss_fn(outputs,labels.to(device))
            # 反向传播计算参数
            loss.backward()
            # 跟新优化器中的参数
            optimizer.step()
            # 累加损失
            running_loss+=loss.item()
            # 输出语句
            train_bar.desc = f'train epoch {epoch + 1}/ {epochs} loss: {loss:.3f}'

3. 测试模型更新参数

       # 开启预测模型
        net.eval()
        acc=0.0
        # 关闭torch中的梯度记录
        with torch.no_grad():
            # 开启进度条
            val_bar=tqdm(validata_loader,file=sys.stdout)
            # 开始迭代
            for val_data in val_bar:
                # 测试集图片,测试集目标值
                val_images,val_labels=val_data
                # 开始预测
                outputs=net(val_images.to(device))
                # 获取预测的结果集,因为用的是softmax,所以取没张图片的结果集的最大值就是这张图片的预测结果
                predict_y=torch.max(outputs,dim=1)[1]
                # 计算总损失
                acc+=torch.eq(predict_y,val_labels.to(device)).sum().item()
        # 计算平均损失
        val_accuracy=acc/val_num
        # 打印结果
        print(f'[epoch {epoch + 1}] train_loss: {running_loss / train_step:.3f},         val_accuracy:{val_accuracy:.3f}')
        # 如果这次的结果比上次的好,就更新参数,否则不变
        if val_accuracy>best_acc:
            best_acc=val_accuracy
            torch.save(net.state_dict(),save_path)

4.完整的训练代码:

import os
import sys
import json

from tqdm import tqdm
import torch
import torch.nn as nn
from torchvision import transforms,datasets

from model import AlexNet


def main():
    # 看看是否使用cpu
    device=torch.device('cuda:0' if torch.cuda.is_available() else 'cpu')
    print(f'using:',{device})
    # 要读入图片的目录路径,以下代码假设你这个路径下有文件(train训练集, val测试集)
    image_path=os.path.join('./','训练集和测试集的图片路径')
    # print(image_path)
    # 判断这个路径是否存在,若不存在则报错image path done nit exist
    assert os.path.exists(image_path),'image path done ont exist'
    # 创建读入数据后对数据处理的方法集合
    data_transform={
        # 将训练数据和测试数据的处理集使用对象的方法,以便后面使用
        'train':transforms.Compose([
            transforms.RandomResizedCrop(224),
            transforms.RandomHorizontalFlip(),
            transforms.ToTensor(),
            transforms.Normalize((0.485, 0.456, 0.406),(0.229, 0.224, 0.225))
        ]),
        'val':transforms.Compose([transforms.Resize((224, 224)),
                                       transforms.ToTensor(),
                                       transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))])
    }
    train_dataset=datasets.ImageFolder(root=os.path.join(image_path,'train'),
                                       transform=data_transform['train'])
    train_num=len(train_dataset)
    # print(train_num)
    flower_list=train_dataset.class_to_idx
    # print(flower_list)
    cla_dict=dict((val,key) for key,val in flower_list.items())
    # print(cla_dict)
    json_str=json.dumps(cla_dict,indent=4)
    with open('class_indices.json','w') as json_file:
        json_file.write(json_str)
    # print(json_str)
    batch_size=32
    nw=min([os.cpu_count(),batch_size if batch_size>1 else 0,16])
    print(f'using {nw} dataloader workers every process')
    train_loader=torch.utils.data.DataLoader(train_dataset,
                                             batch_size=batch_size,
                                             shuffle=True,
                                             num_workers=nw)
    validata_dataset=datasets.ImageFolder(root=os.path.join(image_path,'val'),
                                          transform=data_transform['val'])
    val_num = len(validata_dataset)
    validata_loader=torch.utils.data.DataLoader(validata_dataset,
                                                batch_size=batch_size,
                                                shuffle=False,
                                                num_workers=nw)
    net=AlexNet(num_classes=5)
    net.to(device)
    # 使用交叉熵损失函数
    loss_fn = nn.CrossEntropyLoss()
    # 使用优化器类,这里使用Adam优化器
    optimizer = torch.optim.Adam(net.parameters(), lr=0.0002)
    # 迭代数量
    epochs = 10
    #  训练后的参数保存地址
    save_path = './AlexNet.pth'
    best_acc = 0.0
    # 训练样本数
    train_step = len(train_loader)

    for epoch in range(epochs):
        # 开启训练模式
        net.train()
        # 初始化每次迭代的总损失
        running_loss = 0.0

        # tqdm是一个进度条,将要迭代的数据放入,可以查看迭代的进度
        # stdout :它使用其参数直接显示在控制台窗口上。
        train_bar = tqdm(train_loader, file=sys.stdout)

        for step, data in enumerate(train_bar):
            # images是要训练的图片,labels是这张图片的类别
            images, labels = data
            # 将优化器的梯度置零
            optimizer.zero_grad()
            # 将图片加入到cpu中训练后返回outputs
            outputs = net(images.to(device))
            # 计算损失
            loss = loss_fn(outputs, labels.to(device))
            # 反向传播计算参数
            loss.backward()
            # 跟新优化器中的参数
            optimizer.step()
            # 累加损失
            running_loss += loss.item()
            # 输出语句
            train_bar.desc = f'train epoch {epoch + 1}/ {epochs} loss: {loss:.3f}'
        # 开启预测模型
        net.eval()
        acc = 0.0
        # 关闭torch中的梯度记录
        with torch.no_grad():
            # 开启进度条
            val_bar = tqdm(validata_loader, file=sys.stdout)
            # 开始迭代
            for val_data in val_bar:
                # 测试集图片,测试集目标值
                val_images, val_labels = val_data
                # 开始预测
                outputs = net(val_images.to(device))
                # 获取预测的结果集,因为用的是softmax,所以取没张图片的结果集的最大值就是这张图片的预测结果
                predict_y = torch.max(outputs, dim=1)[1]
                # 计算总损失
                acc += torch.eq(predict_y, val_labels.to(device)).sum().item()
        # 计算平均损失
        val_accuracy = acc / val_num
        # 打印结果
        print(
            f'[epoch {epoch + 1}] train_loss: {running_loss / train_step:.3f},         val_accuracy:{val_accuracy:.3f}')
        # 如果这次的结果比上次的好,就更新参数,否则不变
        if val_accuracy > best_acc:
            best_acc = val_accuracy
            torch.save(net.state_dict(), save_path)

三:预测和模型评分(在predict文件中写)

import os
import json

import torch
from PIL import Image
from torchvision import transforms
import matplotlib.pyplot as plt

from model import AlexNet


def main():
    device=torch.device('cuda:0' if torch.cuda.is_available() else 'cpu')
    # 处理图片函数
    data_transform=transforms.Compose([
        transforms.Resize((224,224)),
        transforms.ToTensor(),
        transforms.Normalize((0.5,0.5,0.5),(0.5,0.5,0.5))
    ])
    # 测试图片的路径
    img_path='./1.jpeg'
    # 判断这张图片是否存在
    assert os.path.exists(img_path),f'{img_path} does not exist'
    # 读取图片
    img=Image.open(img_path)
    # 将图片展示出来
    plt.imshow(img)
    # 使用上面的函数处理图片
    img=data_transform(img)
    # print(img.shape)
    # 对图片维度进行扩充
    img=torch.unsqueeze(img,dim=0)
    print(img.shape)
    # 训练的时候生成的图片类别文件
    json_path='./class_indices.json'
    # 判断类别文件是否存在
    assert os.path.exists(json_path),f'{json_path} done not exist'
    # 读取文件
    with open(json_path,'r') as f:
        class_dict=json.load(f)
    print(class_dict)
    # 建立模型
    model=AlexNet(num_classes=5).to(device)
    # 训练后的参数文件
    weights_path='./AlexNet.pth'
    # 判断参数文件是否存在
    assert os.path.exists(weights_path),f'file {weights_path} does not exist'
    # 模型加载参数
    model.load_state_dict(torch.load(weights_path))
    # 开启预测模式
    model.eval()
    # 关闭梯度
    with torch.no_grad():
        # 预测
        output=model(img.to(device))
        print(output)
        # 对图片维度压缩回来
        output=torch.squeeze(output).cpu()
        # 使用softmax函数分类
        predict=torch.softmax(output,dim=0)
        # 获得图片的预测概率最大的那个就是这张图片的类别
        predict_class=torch.argmax(predict).numpy()
    # 完成打印
    print_res = f"class: {class_dict[str(predict_class)]}, prob: {predict[predict_class].numpy():.3f}"
    # 将图片类别写在图片上
    plt.title(print_res)
    # 展示图片
    plt.show()


if __name__ == '__main__':
    main()

 四:代码使用:

准备好需要训练和预测的数据集比如:

 文件中有训练集和测试集

 

将flower_data这个路径写到image_path这个变量中就可以

点个赞呗!!!!!!

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Datawhile 组队学习Tiny-universe Task01

Task01:LLama3模型讲解 仓库链接:GitHub - datawhalechina/tiny-universe: 《大模型白盒子构建指南》:一个全手搓的Tiny-Universe 参考博客:LLaMA的解读与其微调(含LLaMA 2):Alpaca-LoRA/Vicuna/BELLE/中文LLaMA/姜子…

新的突破,如何让AI与人类对话变得“顺滑”:Moshi背后的黑科技

你有没有想过,当我们跟智能音箱、客服机器人或者语音助手对话时,它们是怎么“听懂”我们说的话,又是怎么迅速给出回应的?就好像你对着Siri、Alexa说一句:“给我订个披萨”,它立刻明白你想要干嘛,然后帮你下单。背后的技术其实比我们想象的要复杂得多,但现在,有了Moshi…

Qt_布局管理器

目录 1、QVBoxLayout垂直布局 1.1 QVBoxLayout的使用 1.2 多个布局管理器 2、QHBoxLayout水平布局 2.1 QHBoxLayout的使用 2.2 嵌套的Layout 3、QGridLayout网格布局 3.1 QGridLayout的使用 3.2 设置控件大小比例 4、QFormLayout 4.1 QFormLayout的使用 5、…

【2024】前端学习笔记8-内外边距-边框-背景

学习笔记 外边距:Margin内边距:Padding边框:Border背景:Background 外边距:Margin 用于控制元素周围的空间,它在元素边框之外创建空白区域,可用于调整元素与相邻元素(包括父元素和兄…

AI预测福彩3D采取888=3策略+和值012路或胆码测试9月19日新模型预测第92弹

经过90多期的测试,当然有很多彩友也一直在观察我每天发的预测结果,得到了一个非常有价值的信息,那就是9码定位的命中率非常高,90多期一共只错了10次,这给喜欢打私房菜的朋友提供了极高价值的预测结果~当然了&#xff0…

教育政策与智能技术:构建新时代教师队伍

据最新统计,我国目前拥有各级各类教师共计1891.8万人,这一庞大的教师群体不仅支撑起了全球规模最大的教育体系,更成为了推动教育创新与变革的主力军。面对教育数字化的不断发展,育人内容、目标要求、方式方法的全面升级&#xff0…

【测向定位】差频MUSIC算法DOA估计【附MATLAB代码】

​微信公众号:EW Frontier QQ交流群:554073254 摘要 利用多频处理方法,在不产生空间混叠的情况下,估计出高频区域平面波的波达方向。该方法利用了差频(DF),即两个高频之间的差。这使得能够在可…

鹏鼎控股社招校招入职SHL综合能力测评:高分攻略及真题题库解析答疑

鹏鼎控股(深圳)股份有限公司,成立于1999年4月29日,是一家专注于印制电路板(PCB)的设计、研发、制造与销售的高新技术企业。公司总部位于中国广东省深圳市,并在全球多个地区设有生产基地和服务中…

【软考】数据字典(DD)

目录 1. 说明2. 数据字典的内容2.1 说明2.2 数据流条目2.3 数据存储条目2.4 数据项条目2.5 基本加工条目 3. 数据词典管理4. 加工逻辑的描述4.1 说明4.2 结构化语言4.3 判定表4.3 判定树 5. 例题5.1 例题1 1. 说明 1.数据流图描述了系统的分解,但没有对图中各成分进…

软件自动定时启动器-添加可执行文件软件,设置启动的时间,也可以设置关闭的时间-供大家学习研究参考

点击添加软件,可以添加可执行文件软件,设置启动的时间,也可以设置关闭的时间 注意,时间为00:00:00 等于没设置,这个时间不在设置范围,其他任何时间都可以。 下载地址: h…

【C++ Primer Plus习题】16.9

大家好,这里是国中之林! ❥前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站。有兴趣的可以点点进去看看← 问题: 解答: #include <iostream> #include <ctime> #include <v…

驱动---动态模块编译

动态模块编译 ctags 用法 创建文件 ------- ctags -R 一定要在顶层目录下 1&#xff0e; ctags –R * 2. vi –t tag (请把tag替换为您欲查找的变量或函数名) 3&#xff0e; Ctrl ] (跳转到要找的目标) 4&#xff0e; Ctrl T (回跳) 5&#xff0e; set tag/p…

解决使用nvm管理node版本时提示npm下载失败的问题

目录 一、引言 二、解决步骤 1. 访问该网站下载对应版本的npm Release v6.14.18 npm/cli GitHubthe package manager for JavaScript. Contribute to npm/cli development by creating an account on GitHub.https://github.com/npm/cli/releases/tag/v6.14.18 2. 解压到n…

mac使用技巧

mac使用技巧 快捷键 Command-X&#xff1a;剪切所选项并拷贝到剪贴板。Command-C&#xff1a;将所选项拷贝到剪贴板。这同样适用于“访达”中的文件。Command-V&#xff1a;将剪贴板的内容粘贴到当前文稿或应用中。这同样适用于“访达”中的文件。Command-Z&#xff1a;撤销上…

高级算法设计与分析 学习笔记6 B树

B树定义 一个块里面存了1000个数和1001个指针&#xff0c;指针指向的那个块里面的数据大小介于指针旁边的两个数之间 标准定义&#xff1a; B树上的操作 查找B树 创建B树 分割节点 都是选择正中间的那个&#xff0c;以免一直分裂。 插入数字 在插入的路上就会检查节点需不需要…

Ansible——Playbook基本功能???

文章目录 一、Ansible Playbook介绍1、Playbook的简单组成1&#xff09;“play”2&#xff09;“task”3&#xff09;“playbook” 2、Playbook与ad-hoc简单对比区别联系 3、YAML文件语法&#xff1a;---以及多个---&#xff1f;&#xff1f;使用 include 指令 1. 基本结构2. 数…

搜维尔科技:Haption力反馈遥操作解决方案

硬件设备 多种力反馈设备型号&#xff1a; 1.Haption Virtuose 6D&#xff1a;能在 6 个自由度&#xff08;x、y、z 轴 3 个平移和 3 个旋转&#xff09;上提供精确的力反馈&#xff0c;工作空间相当于一条人体手臂的活动范围&#xff0c;最大力度和旋转扭矩分别高达 35N 和 …

干货:分享6款ai论文写作助手,一键生成原创论文(步骤+工具)

写一篇论文是一个复杂的过程&#xff0c;涉及多个步骤&#xff0c;包括选题、研究、撰写、编辑和校对。AI可以在其中的一些步骤中提供帮助&#xff0c;但最终的论文还是需要人类作者的深入思考和创造性输入。以下是六款值得推荐的AI论文写作助手&#xff0c;其中特别推荐千笔-A…

秃姐学AI系列之:目标检测(物体检测) + 边缘框代码实现 | 锚框 + 代码实现

目录 目标检测 边缘框 目标检测数据集 总结 代码实现 定义在两种表示之间进行转换的函数 定义图像中狗和猫的边界框 将边框在图中画出 锚框 Anchor Box IoU——交并比 赋予锚框标号 使用非极大值抑制&#xff08;NMS&#xff09;输出 总结 代码实现 锚框 IoU——交…

高并发内存池(三):CentralCache与PageCache的实现

目录 CentralCache的实现 主体框架 ​Span 页与页号 WIN32、_WIN32、_W64的区别 条件编译 SpanList 为ThreadCache分配内存结点 补充内容1 补充内容2 具体实现 从PageCache申请非空span 补充内容 具体实现 PageCache的实现 主体框架 关于整体加锁的解释 桶锁…