智能识别猫猫

news2024/11/19 2:35:12

鸡蛋饼是什么猫

今天,有一位爱猫人士找到了我:“9月25日啦,炉石传说重新开服了!”

我:“哦!我知道这个,你是说,我现在该去领金卡了吗?”

爱猫人士:“不!是我看到他们又在讨论狗贼嘘嘘家的猫是什么品种的了!。”

狗贼叔叔是一位知名的老战士,在那样一个简单的下午,他组了一套平时最常用的卡牌,然后普普通通的登了一个顶,然后就再也没有回来。他有一只心爱的小猫叫做“鸡蛋饼”,大概是这样的:

在这里插入图片描述

我:“嗯,然后呢?”

爱猫人士:“我已经受够了有人管它叫做橘猫了!这些人对猫的种类太没有认知,张口就来!”

其实,鸡蛋饼是一只乳色的英短,或者也称为英短金渐层,这也是一个不常见的稀有品种了。英短就是人们常说的“蓝胖子”,这种猫一般都是蓝的或者蓝白的,因此,虽然很多人天天见“蓝胖子”,但是,遇到了鸡蛋饼,就认不出来了,这也不奇怪。

我:”那这不是显得你的水平高嘛?“

爱猫人士:”不,我觉得,你应该写一篇文章,给大家科普一下猫的种类的知识!“

啊这,科普猫的种类?我自己还认不全呢,不过,我想到了一个好办法,我应该训练一个ai,用来识别猫的种类。

资源下载

没有猫,我们也不能凭空变出猫来,因此,首先,我们需要得到一些猫的图片。

猫狗分类:https://www.kaggle.com/datasets/zippyz/cats-and-dogs-breeds-classification-oxford-dataset

比如说,这个数据集看起来不错,直接用这个好了。

我大致查阅了一下,感觉有些不太妙,关于英短的品种
在这里插入图片描述
这全是“蓝胖子”啊,一只英短金渐层也没有,如果就拿这个去给ai训练,到时候认不出鸡蛋饼的可能性非常高啊!

不过,这也正常,鸡蛋饼毕竟是稀有品种,而且这个数据集也有几年的历史了,那个时候,像鸡蛋饼这样的猫比现在还要更稀少,所以没有包括也正常。不过,我并不打算添加额外的图片进去,就先这样好了。

预处理

这个数据集原本叫做“cats and dogs“,肯定不只有猫,那还有狗呢!狗现在可不是我们需要的,首先,我们要想办法把狗删掉,但是,要怎么做呢!我怎么知道谁是猫,谁是狗啊?

还好,数据集的作者早就想到了,猫都是首字母大写的,狗都是首字母小写的,这样的话,我们只需要把首字母大写的图片提取出来就好了。

import os
import shutil
import pandas as pd
from sklearn.model_selection import train_test_split




dataset_path = "images"
cat_folder = os.path.join(dataset_path, "cats")
cat_data = []


os.makedirs(cat_folder, exist_ok=True)




for filename in os.listdir(dataset_path):
    if filename.endswith(".jpg"):
        if filename[0].isupper():
            shutil.move(os.path.join(dataset_path, filename), os.path.join(cat_folder, filename))
            
for filename in os.listdir(cat_folder):
    if filename.lower().endswith('.jpg'):
        filename_no_ext = os.path.splitext(filename)[0]
        try:
            cat_breed, number = filename_no_ext.rsplit('_', 1)
            cat_data.append({'filename': filename, 'breed': cat_breed})
        except ValueError:
            print(f"文件名格式不正确: {filename}")




cat_df = pd.DataFrame(cat_data)


breed_to_num = {breed: idx for idx, breed in enumerate(cat_df["breed"].unique())}
cat_df["breed_num"] = cat_df["breed"].map(breed_to_num)


train_df, test_df = train_test_split(df, test_size=0.2, stratify=cat_df["breed_num"], random_state=240925)


train_df.to_csv("train_dataset.csv", index=False)
test_df.to_csv("test_dataset.csv", index=False)


print("训练集样本数:", len(train_df))
print("测试集样本数:", len(test_df))

模型训练

import torch
import torch.nn as nn
import torchvision.models as models
import pandas as pd
import os
from PIL import Image
from torch.utils.data import Dataset, DataLoader
from torchvision import transforms




class CatDataset(Dataset):
    def __init__(self, csv_file, img_dir, transform=None):
        self.data_frame = pd.read_csv(csv_file)
        self.img_dir = img_dir
        self.transform = transform


    def __len__(self):
        return len(self.data_frame)


    def __getitem__(self, idx):
        img_name = os.path.join(self.img_dir, self.data_frame.iloc[idx, 0])
        image = Image.open(img_name).convert("RGB")
        label = int(self.data_frame.iloc[idx, 2])


        if self.transform:
            image = self.transform(image)


        return image, label




transform = transforms.Compose([
    transforms.Resize(224, 224),
    transforms.ToTensor(),
    transforms.Normalize(mean=[0.485, 0.456, 0.406],
                         std=[0.229, 0.224, 0.225]),
])




train_dataset = CatDataset(csv_file="train_dataset.csv", img_dir="cats", transform=transform)
train_loader = DataLoader(train_dataset, batch_size=32, shuffle=True)


test_dataset = CatDataset(csv_file="test_dataset.csv", img_dir="cats", transform=transform)
test_loader = DataLoader(test_dataset, batch_size=32, shuffle=False)




class CatClassifier(nn.Module):
    def __init__(self, num_classes):
        super(CatClassifier, self).__init__()
        self.model = models.resnet18(weights=models.ResNet18_Weights.DEFAULT)
        self.model.fc = nn.Linear(self.model.fc.in_features, num_classes)


    def forward(self, x):
        return self.model(x)


num_classes = len(train_dataset.data_frame["breed_num"].unique())
model = CatClassifier(num_classes)


device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
model.to(device)


criterion = nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(model.parameters(), lr=0.001)




num_epochs = 10


for epoch in range(num_epochs):
    model.train()
    running_loss = 0.0
    correct = 0
    total = 0


    for images, labels in train_loader:
        images, labels = images.to(device), labels.to(device)


        optimizer.zero_grad()
        outputs = model(images)
        loss = criterion(outputs, labels)
        loss.backward()
        optimizer.step()


        running_loss += loss.item() * images.size(0)


        _, predicted = torch.max(outputs, 1)
        total += labels.size(0)
        correct += (predicted == labels).sum().item()


    epoch_loss = running_loss / len(train_loader.dataset)
    epoch_acc = correct / total


    print(f"Epoch [{epoch + 1}/{num_epochs}], Loss: {epoch_loss:.4f}, Accuracy: {epoch_acc:.4f}")

加载与使用

现在,我们已经得到了一个能够识别猫的种类的模型了,要怎么使用呢?

# 注意:你划分的数据集有可能不是这样的,要根据实际情况进行修改
breed_num_to_name = {11: 'British_Shorthair', 0: 'Maine_Coon', 3: 'Sphynx', 10: 'Egyptian_Mau', 2: 'Birman', 8: 'Bombay', 1: 'Siamese', 5: 'Ragdoll', 7: 'Abyssinian', 9: 'Russian_Blue', 4: 'Bengal', 6: 'Persian'}




def predict_image(image_path, threshold=0.8):
    transform = transforms.Compose([
        transforms.Resize(224, 224)
        transforms.ToTensor(),
        transforms.Normalize(mean=[0.485, 0.456, 0.406],
                             std=[0.229, 0.224, 0.225]),
    ])


    image = Image.open(image_path).convert("RGB")
    input_image = transform(image).unsqueeze(0).to(device)


    with torch.no_grad():
        outputs = model(input_image)
        probabilities = torch.nn.functional.softmax(outputs, dim=1)
        max_prob, predicted = torch.max(probabilities, 1)
        max_prob = max_prob.item()
        predicted_class = predicted.item()


        if max_prob >= threshold:
            predicted_breed = breed_num_to_name.get(predicted_class)
            print(f"这是一个: {predicted_breed}")
        else:
            print("这个我可能不认识~")




predict_image("cats/British_Shorthair_241.jpg", threshold=0.8)

最终结果

我们的ai确实已经可以认出测试集中猫的品种了,此时我们拿出来鸡蛋饼的照片:
在这里插入图片描述
我们的ai居然表示:“这个我可能不认识~”,怎么能这样,一定是打开的方式不对!再换一张!
在这里插入图片描述

结果还是一样的,“这个我可能不认识~”。唉,枉费我花费了这么多心血,不过其实也是很正常的事情啦,毕竟我们的训练集中,一张英短金渐层也没,这个时候,想把鸡蛋饼归类为蓝胖子一类,还是太不容易了!

相关链接

普通的一个下午:https://www.bilibili.com/video/BV16w411N7FT/

历史直播回放(up主饕餮):https://space.bilibili.com/10579668/

ai狗贼唱心会很痛:https://www.bilibili.com/video/BV11m411S7rf/

看看鸡蛋饼,突然又有一些伤感,“国服炉石今又在,不见当年叠甲人。”,再排队>15分钟我就要进去了,那位战士说他的补偿不要了,可以给我吗?在这里插入图片描述

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

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

相关文章

VMware下Ubuntu找不到共享文件夹

在VMware的设置中已经设置了共享文件夹,在Ubuntu系统中找不到,参考了网上其他的文章,发现还是不能解决问题,无意中尝试了一小步,没想到成功解决了,在这里记录一下。 1)首先查询本机的gid 2&…

聚焦Llama新场景和AR眼镜,扎克伯格用AI赋能元宇宙,Meta Connect 2024开发者大会直播约起...

作者:十九 编辑:十九,李宝珠 北京时间 9 月 26 日凌晨 1 点,Meta Connect 2024 开发者大会即将举行,马克扎克伯格将聚焦 AI 和元宇宙,向大家分享 Llama 模型的更多潜在应用,并介绍 Meta 最新产品…

2024年汉字小达人区级自由报名备考冲刺:最新问题和官模题练一练

今天是2024年第十一届汉字小达人的区级自由报名活动的第二天。 我们继续回答几个关于汉字小达人的最新问题,做几道2024年官方模拟题,帮助孩子们少走弯路,再冲刺一般,更精准地备考2024年汉字小达人。 【温馨提示】本专题在比赛期…

芯科科技2024年Works With开发者大会登陆上海,物联网和人工智能的变革性融合带来无限精彩

谷歌、三星等生态大厂将带来重磅演讲和圆桌讨论,亦可切身体验多样化无线技术实作 中国,北京 – 2024年9月25日 – 安全、智能无线连接技术领域的全球领导厂商Silicon Labs(亦称“芯科科技”,NASDAQ:SLAB)&a…

MySQL InnoDB MVCC读写逻辑分析与调测

目标 1、构建MVCC读写场景 2、gdb调试MVCC过程,输出流程图(函数级别调用过程) 前提 准备1 打开服务端 查询mysqld进程号 线程树 打开客户端,想创建几个事务号就打开几个客户端 准备2 数据库mvcc,两个表test和stu…

JVM(HotSpot):虚拟机栈(JVM Stacks)之线程问题排查方法

文章目录 前言一、CPU占用过大二、程序运行很长时间没有结果三、总结 前言 本篇讲的排查都是基于Linux环境的。 一、CPU占用过大 这个一般是出现了死循环导致的。 1、先用top命令查看占用CPU的进程ID top2、再用ps命令查看对应的线程 就看一查看到对应的线程id ps H -eo …

王道考研视频——操作系统笔记

操作系统第一章!入门 王道考研视频——操作系统笔记,第一部分,操作系统的概念和体系结构 0.0 课程白嫖指南_哔哩哔哩_bilibili0.0 课程白嫖指南是王道计算机考研 操作系统的第1集视频,该合集共计84集,视频收藏或关注UP…

openkylin介绍及其特点和优势

openKylin(开放麒麟)openKylin(开放麒麟) 社区是在开源、自愿、平等和协作的基础上,由基础软硬件企业、非营利性组织、社团组织、高等院校、科研机构和个人开发者共同创立的一个开源社区,致力于通过开源、开…

51单片机应用开发---keil 创建一个新工程并用Protues 8仿真(以点亮LED为例)

实现目标 1、掌握keil V5软件 创建一个新工程; 2、具体目标:1.会新建一个工程;2.编程实现点亮开发板的LED1. 一、新建工程步骤 1.1 在桌面上新建一个名字为 LED的文件夹 1.2 双击打开Keil uVision5 软件,点击 Project —>…

HTML和CSS中的浮动以及边框塌陷解决方案(内置练习及答案)

一、浮动概述 在HTML和CSS中,“浮动”(Float)是一种布局技术,它允许元素脱离其正常的文档流,向左或向右移动,直到它的外边缘碰到包含框或另一个浮动元素的边缘。浮动元素仍然保持块级盒模型的特性&#xff…

【GUI设计】基于图像分割的GUI系统(6),matlab实现

博主简介: 如需获取设计的完整源代码或者有matlab图像代码项目需求/合作,可联系主页个人简介提供的联系方式或者文末的二维码。博客内容有疑问可联系沟通(博主邮箱:3249726188qq.com)。 ~~~~~~~~~~~~~~~~~~~~~~~…

【ComfyUI】减少连线的节点——cg-use-everywhere

源码:https://github.com/chrisgoringe/cg-use-everywhere 介绍:一组节点,允许数据“广播”到一些或所有未连接的输入端。大大减少了链接混乱。 【秋葉aaaki】comfyui一键运行包 夸克网盘:https://pan.quark.cn/s/64b808baa960 …

PMP--二模--解题--131-140

文章目录 反例14.敏捷–角色–教练/项目经理–仆人式领导–职责–核心工作–消除障碍;–作用–促进合作(关键字:合作,一起解决问题)--不是出现“合作”就一定选131、 [单选] 一个项目经理被分配到一个针对客户的分析项…

【网络安全】网络基础第一阶段——第三节:网络协议基础---- VLAN、Trunk与三层交换技术

目录 一、交换机 1.1 交换机定义 1.1.1 交换机 1.2 工作原理 1.2.1 数据帧的转发 1.2.2 交换机处理数据帧的三种行为 1.2.3 交换机通信 二、虚拟局域网(VLAN) 2.1 虚拟局域网简介 2.1.1 为什么需要VLAN 2.1.2 广播域的分割与VLAN的必要性 2.…

【Linux】权限管理——专治不会设置权限而头疼

🚀个人主页:小羊 🚀所属专栏:Linux 很荣幸您能阅读我的文章,诚请评论指点,欢迎欢迎 ~ 目录 前言一、Linux权限管理1.1 Linux用户类型1.2 文件类型和访问权限1.3 文件访问权限的相关设置方法1.3.1 更改文…

vue2加载本地html文件

实现方法&#xff1a; 1、在public文件夹下创建static文件夹&#xff0c;static文件夹下放置需要展示的html文件&#xff0c;有没有static都没问题&#xff0c;需要在public文件夹下 <div style"width: 100%"><!--静态html资源--><div class"t…

C语言⾃定义类型:结构体

目录 前言 1. 结构体类型的声明 1.1 结构的声明 1.2 结构体变量的创建和初始化 1.3 结构的特殊声明 1.4 结构的⾃引⽤ 2.结构体内存对齐 2.1 对⻬规则 实例讲解 2.2 为什么存在内存对⻬&#xff1f; 2.3 修改默认对⻬数 3. 结构体传参 4. 结构体实现位段 4.1 什么…

H7-TOOL脱机烧录增加国产3PEAK混合信号单片机TPS32和富芮坤FR8008,FR8003和FR2012支持

支持单路&#xff0c;1拖4和1拖16脱机烧录 3PEAKS思瑞浦混合信号单片机TPS32M支持 1、在线烧录&#xff0c;脱机烧录均正常。 2、注意事项&#xff1a;推荐使用整片擦除。 在线烧录&#xff1a; 脱机烧录&#xff1a; 接线效果&#xff1a; 富芮坤FR8008x支持&#xff0c;支…

3-2 RTE对Runnable的作用

返回总目录->返回总目录<- 一、前言 通过RTE给runnable提供触发事件。 runnable是可以被触发的,但是需要通过RTE来实现这个触发和调用runnable通过RTE给runnable提供所需资源。 RTE将runnable需要的一些资源通过接口传输给它(Port的实现)将BSW和SWC做隔绝。 因此OS和r…

基于标签相关性的多标签学习

本文所涉及所有资源均在 传知代码平台可获取。 目录 论文概述 什么是多标签学习 论文贡献 算法流程 挖掘“主题“——提取标签相关性 训练 &#x1d440; &#x1d447; M T 模型——拟合{特征集, 主题集合} 用标记相关性扩增数据集 再次训练拟合 &#x1d440; M模型——对真…