lol英雄联盟角色识别

import torch
import random
from torch import nn, optim
from torch.nn import functional as F
from torch.utils.data import DataLoader
import torchvision.transforms as transforms
from torchvision.datasets import ImageFolder
import matplotlib.pyplot as plt
from PIL import Image
import os

# 检查是否有可用的CUDA设备
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
print(f"Using device: {device}")

# 数据集根目录路径
dataset_path = r'D:\pytorch_code\LOL峡谷识别'

# 定义图像变换
transform = transforms.Compose([
    transforms.Resize((980, 500)),  # 调整图像大小
    transforms.ToTensor(),         # 将图像转换为张量
    transforms.Normalize((0.5,), (0.5,))  # 归一化到[-1, 1]
])

# 加载训练集
train_dataset = ImageFolder(root=dataset_path, transform=transform)

# 使用DataLoader创建数据加载器
batch_size = 16  # 定义批量大小
train_loader = DataLoader(train_dataset, batch_size=batch_size, shuffle=True)

# 加载测试集
test_dataset = ImageFolder(root=dataset_path, transform=transform)

# 创建测试集 DataLoader
test_loader = DataLoader(test_dataset, batch_size=batch_size, shuffle=False)

# 打印类别名称和数量
print(f"Classes: {train_dataset.classes}")
print(f"Number of training samples: {len(train_dataset)}")

class SimpleCNN(nn.Module):
    def __init__(self):
        super(SimpleCNN, self).__init__()
        self.conv1 = nn.Conv2d(3, 16, 3, 1)  # 输入3通道,输出16通道
        self.conv2 = nn.Conv2d(16, 32, 3, 1)  # 输入16通道,输出32通道

        # 使用AdaptiveAvgPool2d来自适应调整特征图的大小
        self.pool = nn.AdaptiveAvgPool2d((7, 15))

        # 定义全连接层的输入大小
        self.fc_input_size = 32 * 7 * 15
        
        self.fc1 = nn.Linear(self.fc_input_size, 128)
        self.fc2 = nn.Linear(128, len(train_dataset.classes))

    def forward(self, x):
        x = F.relu(self.conv1(x))
        x = F.max_pool2d(x, 2, 2)
        x = F.relu(self.conv2(x))
        x = F.max_pool2d(x, 2, 2)

        # 使用AdaptiveAvgPool2d来动态调整特征图的大小
        x = self.pool(x)

        x = x.view(-1, self.fc_input_size)  # 展平张量
        x = F.relu(self.fc1(x))
        x = self.fc2(x)
        return F.log_softmax(x, dim=1)

# 创建模型实例并移动到设备
model = SimpleCNN().to(device)

# 定义损失函数和优化器
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=0.001)

# 记录每个epoch的损失和准确率
train_losses = []
train_accuracies = []

# 训练模型
def train(model, train_loader, criterion, optimizer, epoch, device):
    model.train()
    correct = 0
    total_loss = 0
    for batch_idx, (data, target) in enumerate(train_loader):
        data, target = data.to(device), target.to(device)  # 将数据移动到设备
        optimizer.zero_grad()
        output = model(data)
        loss = criterion(output, target)
        loss.backward()
        optimizer.step()
        
        total_loss += loss.item()
        pred = output.argmax(dim=1, keepdim=True)
        correct += pred.eq(target.view_as(pred)).sum().item()

        if batch_idx % 10 == 0:
            print(f'Train Epoch: {epoch} [{batch_idx * len(data)}/{len(train_loader.dataset)} '
                  f'({100. * batch_idx / len(train_loader):.0f}%)]\tLoss: {loss.item():.6f}')
    
    avg_loss = total_loss / len(train_loader)
    accuracy = 100. * correct / len(train_loader.dataset)
    train_losses.append(avg_loss)
    train_accuracies.append(accuracy)

# 测试模型
def test(model, test_loader, criterion, device):
    model.eval()
    test_loss = 0
    correct = 0
    with torch.no_grad():
        for data, target in test_loader:
            data, target = data.to(device), target.to(device)  # 将数据移动到设备
            output = model(data)
            test_loss += criterion(output, target).item()  # 累加batch的损失
            pred = output.argmax(dim=1, keepdim=True)  # 获取最大概率的类别
            correct += pred.eq(target.view_as(pred)).sum().item()

    test_loss /= len(test_loader.dataset)
    accuracy = 100. * correct / len(test_loader.dataset)
    print(f'\nTest set: Average loss: {test_loss:.4f}, Accuracy: {correct}/{len(test_loader.dataset)} '
          f'({accuracy:.0f}%)\n')

# 运行训练和测试
num_epochs = 100
for epoch in range(1, num_epochs + 1):
    train(model, train_loader, criterion, optimizer, epoch, device)
    test(model, test_loader, criterion, device)

# 示例函数,用于展示预测结果
def show_predictions(images, actual_classes, predicted_classes, num_images_per_row=3):
    num_images = len(images)
    num_rows = (num_images + num_images_per_row - 1) // num_images_per_row  # 计算行数

    plt.figure(figsize=(15, 5 * num_rows))  # 根据行数调整图像大小
    for idx in range(num_images):
        plt.subplot(num_rows, num_images_per_row, idx + 1)
        plt.imshow(images[idx])
        plt.title(f'Predicted: {predicted_classes[idx]}\nActual: {actual_classes[idx]}')
        plt.axis('off')

    plt.tight_layout()
    plt.show()

# 设置设备
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')

# 自定义测试数据集的路径(使用原始字符串或双反斜杠来避免转义问题)
custom_data_dir = r'D:\pytorch_code\LOL峡谷测试数据'

# 定义图像预处理和转换
transform = transforms.Compose([
    transforms.Resize((224, 224)),  # 调整大小为模型输入尺寸
    transforms.ToTensor(),  # 转换为Tensor
    transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]),  # 归一化
])

# 加载自定义测试数据集
images_list = []
actual_classes_list = []
predicted_classes_list = []

# 遍历每个类别文件夹
for class_name in os.listdir(custom_data_dir):
    class_folder = os.path.join(custom_data_dir, class_name)
    if os.path.isdir(class_folder):
        for filename in os.listdir(class_folder):
            if filename.endswith('.jpg') or filename.endswith('.png'):  # 假设你的数据集是jpg或png格式的图像
                image_path = os.path.join(class_folder, filename)
                image = Image.open(image_path).convert('RGB')  # 加载图像并转换为RGB格式
                image_tensor = transform(image).unsqueeze(0).to(device)  # 进行预处理和转换,并添加批次维度

                # 使用模型进行预测
                with torch.no_grad():
                    outputs = model(image_tensor)
                    _, predicted = torch.max(outputs, 1)

                # 存储图像、实际类别和预测类别
                images_list.append(image)
                actual_classes_list.append(class_name)  # 使用文件夹名称作为实际类别
                predicted_classes_list.append(train_dataset.classes[predicted.item()])

# 显示预测结果
show_predictions(images_list, actual_classes_list, predicted_classes_list)

# 计算预测准确率
correct = sum([1 for actual, predicted in zip(actual_classes_list, predicted_classes_list) if actual == predicted])
total = len(actual_classes_list)
accuracy = 100. * correct / total
print(f'Accuracy: {accuracy:.2f}% ({correct}/{total})')
 

# 绘制训练损失和准确率曲线
plt.figure(figsize=(12, 5))

plt.subplot(1, 2, 1)
plt.plot(range(1, num_epochs + 1), train_losses, marker='o', label='Train Loss')
plt.xlabel('Epoch')
plt.ylabel('Loss')
plt.title('Training Loss')
plt.legend()

plt.subplot(1, 2, 2)
plt.plot(range(1, num_epochs + 1), train_accuracies, marker='o', label='Train Accuracy')
plt.xlabel('Epoch')
plt.ylabel('Accuracy (%)')
plt.title('Training Accuracy')
plt.legend()

plt.tight_layout()
plt.show()

# 添加用户输入图像路径并进行预测的功能
def predict_image(image_path, model, transform, device, classes):
    image = Image.open(image_path).convert('RGB')  # 加载图像并转换为RGB格式
    image_tensor = transform(image).unsqueeze(0).to(device)  # 进行预处理和转换,并添加批次维度

    # 使用模型进行预测
    model.eval()
    with torch.no_grad():
        outputs = model(image_tensor)
        _, predicted = torch.max(outputs, 1)

    return classes[predicted.item()]

#r"C:\Users\29847\Desktop\测试\Mundo\蒙多 (3).png"
# 输入图像路径并进行预测
while True:
    image_path = input("请输入图像路径 (或输入'退出'结束程序): ")
    if image_path.lower() == '退出':
        break
    predicted_class = predict_image(image_path, model, transform, device, train_dataset.classes)
    print(f'图像的预测类别是: {predicted_class}')

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一只唐小木

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值