【卷积神经网络作业实现人脸的关键点定位功能】

下面是完成这道题目的代码:

python 复制代码
import os
import cv2
import numpy as np
import pandas as pd
import torch
import torch.nn as nn
from torch.utils.data import Dataset,DataLoader
from torchvision import transforms
import matplotlib.pyplot as plt
复制代码
1. 数据集定义(匹配你的目录结构)
python 复制代码
class FaceKeypointDataset(Dataset):
    def __init__(self,txt_path,img_dir,transform=None):
        self.df = pd.read_csv(txt_path,sep=r'\s+',header=None,on_bad_lines='skip')
        self.img_dir = img_dir
        self.transform = transform

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


    def __getitem__(self,idx):
        #读取图片名和路径
        img_name=self.df.iloc[idx,0]
        img_path=os.path.join(self.img_dir,img_name)

        img = cv2.imread(img_path)
        img = cv2.cvtColor(img,cv2,COLOR_BGR2RGB)
        img = cv2.resize(img,(64,64))



        #读取10个关键点坐标

        kpts=self.df.iloc[idx,1:11].values.astype(np.float32)

        #坐标归一化
        kpts[0::2]/=64.0#x坐标
        kpts[1::2]/=64.0#y坐标

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

        return img,torch.tensor(kpts,dtype=torch.float32)
复制代码
2. 卷积神经网络模型 
python 复制代码
class KeypointNet(nn.Module):
    def __init__(self):
        super().__init__()
        #卷积层提取特征
        self.conv_layers =nn.Sequential(
            nn.Conv2d(3,16,kernel_size=3,padding=1),
            nn.RELU(),
            nn.MaxPool2d(2,2),

            nn.Conv2d(16,32,kernel_size = 3,padding=1),
            nn.ReLU(),
            nn.MaxPool2d(2,2),
            
            nn.Conv2d(32,64,kernel_size=3,padding=1),
            nn.ReLU(),
            nn.MaxPool2d(2,2),
        )
    #全连接层:输出10个关键点坐标
     self.fc_layers=nn.Sequential(
        nn.Linear(64*8*8,256),
        nn.ReLU(),
        nn.Linear(256,10)#输出层:10个神经元
       )
    def forward(self,x):
        x=self.conv_layers(x)
        x=x.view(x.size(0),-1)
        x=self.fc_layers(x)
        retrun x
复制代码
3. 训练主程序 
python 复制代码
def main():
    #配置设备
    device=torch.device("cuda" if torch.cuda.is_available() else "cpu")

    print(f"使用设备:{device}")


    #数据预处理

    transform = transforms.Compose([
        transfroms.ToTensor(),
        transforms.Normalize(mean=[0.5,0.5,0.5],std=[0.5,0.5,0.5])
    ])

    train_dataset = FaceKeypointDataset(txt_path="train.txt", img_dir="imgdata", transform=transform)
    test_dataset = FaceKeypointDataset(txt_path="test.txt", img_dir="imgdata", transform=transform)



    train_loader = DataLoader(train_dataset,batch_size=8,shuffle=True)
    test_loader = DataLoader(test_dataset,batch_size=8,shuffle=False)


    #初始化模型,损失函数,优化器

    model = KeypointNet().to(device)

    criterion = nn.L1loss()
    optimizer = torch.optim.Adam(model.parameters(),lr=1e-3)


    #训练参数
    num_ephchs=30
    train_loss_history =[]
    test_loss_history=[]

    print("\n=====开始训练=====")
    for epoch in range(num_epochs):
        model.train()
        train_loss=0.0
        for imgs,kpts in train_loader:

            imgs,kpts=imgs.to(device),kpts.to(device)


            #前向传播
            outputs = model(imgs)

            loss = criterion(outputs,kpts)

            #反向传播
            optimizer.zero_grad()
            loss.backward()
            optimizer.step()
            train_loss+=loss.item() * imgs.size(0)
          #计算平均训练损失
          train_loss/ = len(train_dataset)
          train_loss_history.append(train_loss)

          #测试阶段
          model.eval()
          test_loss=0.0

          with torch.no_grad():
              for imgs,kpts in test_loader:
                  imgs,kpts = imgs.to(device),kpts.to(device)
                  outputs = model(imgs)

                  test_loss +=criterion(outputs,kpts).item()*imgs.size(0)

          test_loss / =len(test_dataset)
          test_loss_history.append(test_loss)

          print(f"Epoch [{epoch+1}/{num_epochs}} | Train Loss:{train_loss:.6f} | Test Loss:{test_loss:.6f}")
    print("======训练完成======")

    plt.figure(figsize=(10,5))
    plt.plot(train_loss_history,label = "Train Loss")
    plt.plot(test_loss_history,label="Test Loss")

    plt.xlabel("Epoch")
    plt.ylabel("L1 Loss")
    plt.title("Training and Testing Loss Curve")
    plt.lengend()
    plt.grid(True)
    plt.savefig("loss_curve.png")
    plt.show()
    torch.save(model.state_dict(), "face_keypoint_model.pth")
    print("模型已保存为 face_keypoint_model.pth")

if __name__ == "__main__":
    main()




       

运行结果:

相关推荐
张张123y2 小时前
后端第一课:输入 URL 后发生了什么?我用手写 Socket 把全链路跑通了
python·websocket·ai·socket·url·后端开发
白帽攻防录4 小时前
SRC 挖洞:PostScript 打印机驱动双 RCE,打印服务器怎么变成内网跳板
开发语言·网络安全·php·内网安全
十年Java程序媛4 小时前
Java枚举Enum完整教程|替代静态常量,开发与面试要点
java·开发语言·spring boot·后端·面试
全栈弄潮儿4 小时前
Python实战第7期:字典与集合
后端·python·编程语言
2603_965148114 小时前
电商选品调研:通过关键词搜索API获取市场热销商品,结合商品详情API分析竞品卖点与定价
开发语言·数据库·人工智能·python·信息可视化
xixiaoyunya5 小时前
Python 异步编程入门:用 asyncio 轻松实现并发任务
开发语言·python·php
把我格子衫拿来5 小时前
Dice 很高就够了吗?分割评价中的 IoU、表面距离与 HD95
python·图像分割·模型评估·医学影像·dice
学逆向的5 小时前
C 循环结构的执行效率分析
c语言·开发语言·数据结构·网络安全
曲径海盗5 小时前
【Python 学习第 31 天】复习:变量与数据类型 等 3 题
python·学习笔记·编程入门
Data_Journal5 小时前
如何绕过 Cloudflare:网页抓取的最佳方法
网络·python