主頁 > 後端開發 > 人臉識別IU(李知恩)

人臉識別IU(李知恩)

2021-04-15 10:32:32 後端開發

文章目錄

  • 前言
  • 一、專案結構
  • 二、資料集準備
  • 三、網路模型
  • 四、具體代碼
    • 1.get_face.py
    • 2.find_iu.py
    • 3.spider_iu.py
    • 4.file_deal.py
    • 5.network.py
    • 4.utils.py
  • 總結


前言

出于興趣和對IU的喜愛,筆者花了幾天嘗試用爬蟲從百度圖片獲取韓國藝人的人物圖片并下載,利用深度神經網路從其中識別出IU(李知恩),并將IU的人物圖片保存至檔案夾,但是限于GPU性能無法使用太復雜的網路,最后識別的效果不佳,若讀者有興趣,也可以去替換一下網路,改善一下資料集,嘗試提升識別性能,
專案環境:python3.6


一、專案結構

在這里插入圖片描述在這里插入圖片描述

二、資料集準備

資料集準備分為兩步:1、獲取圖片,2、提取人臉,
1、獲取圖片
首先可以利用爬蟲,從百度圖片上批量下載圖片,但注意下載資料集所用的關鍵詞不要和之后識別任務的關鍵詞太接近,否則若有圖片重合,就會產生“識別得很準”的錯覺,下面的程式為爬蟲部分,在name.txt檔案中寫好要搜索的關鍵詞,即可使用,

# 爬蟲部分,存放到 name + ‘檔案’
    #############################################################################################
    if GET_PIC == 1:

        headers = {
            'Accept-Language': 'zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2',
            'Connection': 'keep-alive',
            'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Firefox/60.0',
            'Upgrade-Insecure-Requests': '1'
        }

        A = requests.Session()
        A.headers = headers


        tm = int(input('請輸入每類圖片的下載數量 '))
        numPicture = tm
        line_list = []
        with open('./name.txt', encoding='utf-8') as file:
            line_list = [k.strip() for k in file.readlines()]  # 用 strip()移除末尾的空格

        for word in line_list:
            url = 'https://image.baidu.com/search/flip?tn=baiduimage&ie=utf-8&word=' + word + '&pn='
            tot = Find(url, A)
            Recommend = recommend(url)  # 記錄相關推薦
            print('經過檢測%s類圖片共有%d張' % (word, tot))
            file = word + '檔案'
            y = os.path.exists(file)
            if y == 1:
                print('該檔案已存在,無需創建')
            else:
                os.mkdir(file)
            t = 0
            tmp = url
            while t < numPicture:
                try:
                    url = tmp + str(t)
                    # result = requests.get(url, timeout=10)
                    # 這里搞了下
                    result = A.get(url, timeout=10, allow_redirects=False)
                    print(url)
                except error.HTTPError as e:
                    print('網路錯誤,請調整網路后重試')
                    t = t + 60
                else:
                    dowmloadPicture(result.text, word)
                    t = t + 60
            numPicture = numPicture + tm

        print('當前搜索結束,開始提取人臉')
    #############################################################################################

下載圖片時要注意區分,將IU的圖片放在一個檔案夾下,Other的放在另一檔案夾下,訓練集和測驗集都要如此,如下圖所示:
在這里插入圖片描述
每個檔案夾內都是下圖形式:
在這里插入圖片描述
在IU檔案夾內圖片如下所示:
在這里插入圖片描述
對于檔案夾內檔案的命名,可以利用以下這段程式,按順序重命名,

import os

raw_train_root_1 = 'E:/Table/學習資料集/find_iu/data/raw/train/IU/'
raw_train_root_2 = 'E:/Table/學習資料集/find_iu/data/raw/train/Other/'
raw_test_root_1 = 'E:/Table/學習資料集/find_iu/data/raw/test/IU/'
raw_test_root_2 = 'E:/Table/學習資料集/find_iu/data/raw/test/Other/'
raw_roots = [raw_train_root_1, raw_train_root_2, raw_test_root_1, raw_test_root_2]

for path in raw_roots:

    # 獲取該目錄下所有檔案,存入串列中
    fileList = os.listdir(path)

    n = 0
    for i in fileList:
        # 設定舊檔案名(就是路徑+檔案名)
        oldname = path + os.sep + fileList[n]  # os.sep添加系統分隔符

        # 設定新檔案名
        newname = path + os.sep + str(n) + '.JPG'

        os.rename(oldname, newname)  # 用os模塊中的rename方法對檔案改名
        print(oldname, '======>', newname)

        n += 1

2、提取人臉

提取人臉需要用到一個人臉識別庫face_recognition庫,face_recognition庫的下載步驟參考:https://blog.csdn.net/qq_34020487/article/details/101871752
主要有三步,可以直接在anaconda的命令列界面復制使用:

  1. pip install CMake -i https://pypi.douban.com/simple
  2. pip install dlib==19.7.0 -i https://pypi.douban.com/simple
  3. pip install face_recognition -i https://pypi.douban.com/simple

筆者已嘗試,確實可用,
使用下述的函式就可以獲得一張圖片對應的人臉,回傳值就是人臉圖片,

# 找到圖片中的人臉
#############################################################################################
def find_face(path):
    # Load the jpg file into a numpy array
    image = face_recognition.load_image_file(path)

    # Find all the faces in the image using the default HOG-based model.
    # This method is fairly accurate, but not as accurate as the CNN model and not GPU accelerated.
    # See also: find_faces_in_picture_cnn.py
    face_locations = face_recognition.face_locations(image) # 可以選擇 model="cnn"
    if len(face_locations) == 0:
        return None
    else:
        for face_location in face_locations:
            # Print the location of each face in this image
            top, right, bottom, left = face_location
            # You can access the actual face itself like this:
            face_image = image[top:bottom, left:right]
            pil_image = Image.fromarray(face_image)
            return pil_image
#############################################################################################

對資料集進行操作之后,就可以獲得處理后的人臉圖片,之所以不用人物圖訓練,而是提取出人臉后再進行訓練,是考慮到人物影像中干擾因素太多,且經過試驗后發現識別的效果非常差,于是加入這個提取人臉的環節,對資料集的操作代碼如下:

# 將訓練集和測驗集中的raw圖片處理,提取出人臉圖片
#############################################################################################
if __name__ == '__main__':  # 主函式入口

    raw_train_root_1 = 'E:/Table/學習資料集/find_iu/data/raw/train/IU/'
    raw_train_root_2 = 'E:/Table/學習資料集/find_iu/data/raw/train/Other/'
    raw_test_root_1 = 'E:/Table/學習資料集/find_iu/data/raw/test/IU/'
    raw_test_root_2 = 'E:/Table/學習資料集/find_iu/data/raw/test/Other/'
    raw_roots = [raw_train_root_1, raw_train_root_2, raw_test_root_1, raw_test_root_2]

    img_raw_train_1 = os.listdir(raw_train_root_1)
    img_raw_train_2 = os.listdir(raw_train_root_2)
    img_raw_test_1 = os.listdir(raw_test_root_1)
    img_raw_test_2 = os.listdir(raw_test_root_2)
    img_raws = [img_raw_train_1, img_raw_train_2, img_raw_test_1, img_raw_test_2]

    new_path_train_1 = 'E:/Table/學習資料集/find_iu/data/processed/train/IU/'
    new_path_train_2 = 'E:/Table/學習資料集/find_iu/data/processed/train/Other/'
    new_path_test_1 = 'E:/Table/學習資料集/find_iu/data/processed/test/IU/'
    new_path_test_2 = 'E:/Table/學習資料集/find_iu/data/processed/test/Other/'
    new_paths = [new_path_train_1, new_path_train_2, new_path_test_1, new_path_test_2]


    for raw_root, img_raw, new_path in zip(raw_roots, img_raws, new_paths):
        n = 0
        for i in range(len(img_raw)):
            try:
                img = Image.open(raw_root + img_raw[i])
            except:
                print('a file error, continue')
                continue
            else:
                img_train = find_face(raw_root + img_raw[i])
                if img_train == None:
                    continue
                else:
                    # img_train.save(new_path + '%d.JPG'%n)
                    # print(raw_root + img_raw[i])

                    n += 1
        print('在%d張圖片中,共找到%d張臉' % (len(img_raw), n))
#############################################################################################

處理前的圖片資料均存放在raw檔案夾中,處理后的存放在processed檔案夾中,如下圖:
在這里插入圖片描述
兩個檔案夾的內部結構完全一樣:
在這里插入圖片描述

在這里插入圖片描述
在這里插入圖片描述

三、網路模型

1、影像處理

將圖片裁剪為112×92大小,使用RGB影像,(這里試過用灰度影像,但好像效果不會更好,就放棄了),在對圖片進行歸一化處理,

data_transform = transforms.Compose([
        # transforms.Grayscale(num_output_channels=1),  # 彩色影像轉灰度影像num_output_channels默認1
        transforms.Resize(112),
        transforms.CenterCrop((112, 92)),  # 中心裁剪為112*92
        transforms.ToTensor(),
        transforms.Normalize(mean=[0.5, 0.5, 0.5], std=[0.5, 0.5, 0.5])
        # transforms.Normalize(mean=0.5, std=0.5)
    ])

使用孿生神經網路(Siamese Network)

class SiameNetwork(nn.Module):
    def __init__(self):
        super(SiameNetwork, self).__init__()

        # input: h=112, w=92

        self.conv1 = torch.nn.Sequential(
            torch.nn.Conv2d(in_channels=3,  # 輸入單通道
                            out_channels=16,  # 16個3*3卷積核
                            kernel_size=3,  # 卷積核尺寸
                            stride=2,  # 卷積核滑動步長, 1的話圖片大小不變,2的話會大小會變為(h/2)*(w/2)
                            padding=1),  # 邊緣填充大小,如果要保持原大小,kernel_size//2
            torch.nn.BatchNorm2d(16),  # 標準化,前面卷積后有16個圖層
            torch.nn.ReLU()  # 激活函式
        )  # output: h=56, w=46
        self.conv2 = torch.nn.Sequential(
            torch.nn.Conv2d(16, 32, 3, 2, 1),
            torch.nn.BatchNorm2d(32),
            torch.nn.ReLU()
        )  # output: h=28, w=23
        self.conv3 = torch.nn.Sequential(
            torch.nn.Conv2d(32, 64, 3, 2, 1),
            torch.nn.BatchNorm2d(64),
            torch.nn.ReLU()
        )  # output: h=14, w=12
        self.conv4 = torch.nn.Sequential(
            torch.nn.Conv2d(64, 64, 2, 2, 0),
            torch.nn.BatchNorm2d(64),
            torch.nn.ReLU()
        )  # output: h=7, w=6
        self.mlp1 = torch.nn.Linear(7 * 6 * 64, 100)  # 需要計算conv4的輸出尺寸,每次卷積的輸出尺寸(size - kernal + 2*padding)/stride + 1
        self.mlp2 = torch.nn.Linear(100, 10)

    def forward(self, x):
        x = self.conv1(x)
        x = self.conv2(x)
        x = self.conv3(x)
        x = self.conv4(x)
        x = self.mlp1(x.view(x.size(0), -1))  # view展平
        x = self.mlp2(x)
        return x

四、具體代碼

1.get_face.py

from PIL import Image
import face_recognition
import os

# 找到圖片中的人臉
#############################################################################################
def find_face(path):
    # Load the jpg file into a numpy array
    image = face_recognition.load_image_file(path)

    # Find all the faces in the image using the default HOG-based model.
    # This method is fairly accurate, but not as accurate as the CNN model and not GPU accelerated.
    # See also: find_faces_in_picture_cnn.py
    face_locations = face_recognition.face_locations(image) # 可以選擇 model="cnn"
    if len(face_locations) == 0:
        return None
    else:
        for face_location in face_locations:
            # Print the location of each face in this image
            top, right, bottom, left = face_location
            # You can access the actual face itself like this:
            face_image = image[top:bottom, left:right]
            pil_image = Image.fromarray(face_image)
            return pil_image
#############################################################################################

# 將訓練集和測驗集中的raw圖片處理,提取出人臉圖片
#############################################################################################
if __name__ == '__main__':  # 主函式入口

    raw_train_root_1 = 'E:/Table/學習資料集/find_iu/data/raw/train/IU/'
    raw_train_root_2 = 'E:/Table/學習資料集/find_iu/data/raw/train/Other/'
    raw_test_root_1 = 'E:/Table/學習資料集/find_iu/data/raw/test/IU/'
    raw_test_root_2 = 'E:/Table/學習資料集/find_iu/data/raw/test/Other/'
    raw_roots = [raw_train_root_1, raw_train_root_2, raw_test_root_1, raw_test_root_2]

    img_raw_train_1 = os.listdir(raw_train_root_1)
    img_raw_train_2 = os.listdir(raw_train_root_2)
    img_raw_test_1 = os.listdir(raw_test_root_1)
    img_raw_test_2 = os.listdir(raw_test_root_2)
    img_raws = [img_raw_train_1, img_raw_train_2, img_raw_test_1, img_raw_test_2]

    new_path_train_1 = 'E:/Table/學習資料集/find_iu/data/processed/train/IU/'
    new_path_train_2 = 'E:/Table/學習資料集/find_iu/data/processed/train/Other/'
    new_path_test_1 = 'E:/Table/學習資料集/find_iu/data/processed/test/IU/'
    new_path_test_2 = 'E:/Table/學習資料集/find_iu/data/processed/test/Other/'
    new_paths = [new_path_train_1, new_path_train_2, new_path_test_1, new_path_test_2]


    for raw_root, img_raw, new_path in zip(raw_roots, img_raws, new_paths):
        n = 0
        for i in range(len(img_raw)):
            try:
                img = Image.open(raw_root + img_raw[i])
            except:
                print('a file error, continue')
                continue
            else:
                img_train = find_face(raw_root + img_raw[i])
                if img_train == None:
                    continue
                else:
                    # img_train.save(new_path + '%d.JPG'%n)
                    # print(raw_root + img_raw[i])

                    n += 1
        print('在%d張圖片中,共找到%d張臉' % (len(img_raw), n))
#############################################################################################

2.find_iu.py

import torch
import torchvision
import torch.nn as nn
from torch.autograd import Variable
from torchvision import datasets, transforms
from torch.utils.data import DataLoader
import cv2   #opencv庫,用于圖片可視化
import numpy as np
import os
from utils import draw_result
from network import SiameNetwork
from get_face import find_face


if __name__ == '__main__':  # 主函式入口
    # 設定引數
    #############################################################################################
    path = 'E:/Table/學習資料集/find_iu/result/'    # 存放和生成結果的路徑標志
    epochs = 20       #訓練周期
    BATCH_SIZE = 16    #批量樣本大小
    NUM_WORKERS = 0
    #############################################################################################




    # 資料處理
    #############################################################################################
    data_transform = transforms.Compose([
        # transforms.Grayscale(num_output_channels=1),  # 彩色影像轉灰度影像num_output_channels默認1
        transforms.Resize(112),
        transforms.CenterCrop((112, 92)),  # 中心裁剪為112*92
        transforms.ToTensor(),
        transforms.Normalize(mean=[0.5, 0.5, 0.5], std=[0.5, 0.5, 0.5])
        # transforms.Normalize(mean=0.5, std=0.5)
    ])

    train_dataset = datasets.ImageFolder(root = r'E:/Table/學習資料集/find_iu/data/processed/train',
                                         transform = data_transform)
    test_dataset = datasets.ImageFolder(root = r'E:/Table/學習資料集/find_iu/data/processed/test',
                                         transform = data_transform)

    train_loader = DataLoader(train_dataset, batch_size=BATCH_SIZE, shuffle=True, num_workers=NUM_WORKERS)
    test_loader = DataLoader(test_dataset, batch_size=BATCH_SIZE, shuffle=True, num_workers=NUM_WORKERS)

    image, labels = next(iter(train_loader))       #資料可視化

    img = torchvision.utils.make_grid(image, nrow = 10)
    img = img.numpy().transpose(1, 2, 0)
    cv2.imshow('img', img)    #展示影像
    cv2.waitKey(0)  #按下任一按鍵后開始作業

    print("data ready!")
    #############################################################################################

    #配置設備、損失函式和優化器
    #############################################################################################
    device = torch.device('cuda')
    model = SiameNetwork().to(device)
    cost = torch.nn.CrossEntropyLoss()        #定義損失函式,使用交叉熵
    optimizer = torch.optim.Adam(model.parameters(), lr=0.0008, weight_decay=0.001)            #Adam優化器
    print("device ready!")
    #############################################################################################

    #訓練程序,訓練周期由epochs決定
    #############################################################################################

    draw_epoch = []   #記錄訓練階段
    draw_loss = []    #記錄訓練損失,用于繪制
    draw_train_acc = []   #記錄訓練準確度,用于繪制
    draw_val_loss = []   #記錄測驗損失,用于繪制
    draw_val_acc = []  # 記錄測驗準確度,用于繪制
    for epoch in range(epochs):
        #訓練程序
        sum_loss = 0.0
        sum_val_loss = 0.0
        train_correct = 0
        test_correct = 0
        for data in train_loader:
            inputs,labels = data
            inputs,labels = Variable(inputs).cuda(),Variable(labels).cuda()
            optimizer.zero_grad()        #將上一batch梯度清零
            outputs = model(inputs)
            loss = cost(outputs, labels)
            loss.backward()             #反向傳播
            optimizer.step()

            _, id = torch.max(outputs.data, 1)
            sum_loss += loss.data
            train_correct += torch.sum(id == labels.data)

        for data in test_loader:              # 模型測驗
            inputs,labels = data
            inputs,labels = Variable(inputs).cuda(),Variable(labels).cuda()
            outputs = model(inputs)
            val_loss = cost(outputs, labels)
            _,id = torch.max(outputs.data, 1)
            sum_val_loss += val_loss.data
            test_correct += torch.sum(id == labels.data)


        print('[%d,%d] train loss:%.03f      train acc:%.03f%%'
              %(epoch + 1, epochs, sum_loss / len(train_loader), (100 * train_correct / len(train_dataset))))
        print('        val loss:%.03f        val acc:%.03f%%'
              %(sum_val_loss / len(test_loader), (100 * test_correct / len(test_dataset))))


        draw_epoch.append(epoch+1)       # 用于后續畫圖的資料
        draw_loss.append(sum_loss / len(train_loader))
        draw_train_acc.append(100 * train_correct / len(train_dataset))
        draw_val_loss.append(sum_val_loss / len(test_loader))
        draw_val_acc.append(100 * test_correct / len(test_dataset))

        np.savetxt('%s/train_loss.txt'%(path), draw_loss, fmt="%.3f")        # 保存損失資料
        np.savetxt('%s/train_acc.txt'%(path), draw_train_acc, fmt="%.3f")  # 保存準確率資料
        np.savetxt('%s/val_loss.txt'%(path), draw_val_loss, fmt="%.3f")     # 保存損失資料
        np.savetxt('%s/val_acc.txt'%(path), draw_val_acc, fmt="%.3f")  # 保存準確率資料

    print("train ready!")
    #############################################################################################

    #資料可視化
    #############################################################################################
    draw_result(draw_epoch, path)   # 繪圖函式

    print("draw ready!")
    #############################################################################################

    #模型的存盤和載入
    #############################################################################################
    torch.save(model.state_dict(), "parameter.pkl") #save

    print("save ready!")
    #############################################################################################

3.spider_iu.py

import re
import requests
from urllib import error
from bs4 import BeautifulSoup
import os
import torch
from torch.autograd import Variable
from torchvision import datasets, transforms
from torch.utils.data import DataLoader
from network import SiameNetwork
from utils import cv_imread
import cv2
from PIL import Image
import shutil
from get_face import find_face

# 設定引數
#############################################################################################
GET_PIC = 0    # 1 執行這步,0 不執行
GET_FACE = 0
GET_IU = 1
#############################################################################################
num = 0
numPicture = 0
file = ''
List = []

# 爬蟲所用函式
#############################################################################################
def Find(url, A):
    global List
    print('正在檢測圖片總數,請稍等.....')
    t = 0
    i = 1
    s = 0
    while t < 1000:
        Url = url + str(t)
        try:
            # 這里搞了下
            Result = A.get(Url, timeout=7, allow_redirects=False)
        except BaseException:
            t = t + 60
            continue
        else:
            result = Result.text
            pic_url = re.findall('"objURL":"(.*?)",', result, re.S)  # 先利用正則運算式找到圖片url
            s += len(pic_url)
            if len(pic_url) == 0:
                break
            else:
                List.append(pic_url)
                t = t + 60
    return s


def recommend(url):
    Re = []
    try:
        html = requests.get(url, allow_redirects=False)
    except error.HTTPError as e:
        return
    else:
        html.encoding = 'utf-8'
        bsObj = BeautifulSoup(html.text, 'html.parser')
        div = bsObj.find('div', id='topRS')
        if div is not None:
            listA = div.findAll('a')
            for i in listA:
                if i is not None:
                    Re.append(i.get_text())
        return Re


def dowmloadPicture(html, keyword):
    global num
    # t =0
    pic_url = re.findall('"objURL":"(.*?)",', html, re.S)  # 先利用正則運算式找到圖片url
    print('找到關鍵詞:' + keyword + '的圖片,即將開始下載圖片...')
    for each in pic_url:
        print('正在下載第' + str(num + 1) + '張圖片,圖片地址:' + str(each))
        try:
            if each is not None:
                pic = requests.get(each, timeout=7)
            else:
                continue
        except BaseException:
            print('錯誤,當前圖片無法下載')
            continue
        else:
            string = file + r'\\' + keyword + '_' + str(num) + '.jpg'
            fp = open(string, 'wb')
            fp.write(pic.content)
            fp.close()
            num += 1
        if num >= numPicture:
            return
#############################################################################################



if __name__ == '__main__':  # 主函式入口

    # 爬蟲部分,存放到 name + ‘檔案’
    #############################################################################################
    if GET_PIC == 1:

        headers = {
            'Accept-Language': 'zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2',
            'Connection': 'keep-alive',
            'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Firefox/60.0',
            'Upgrade-Insecure-Requests': '1'
        }

        A = requests.Session()
        A.headers = headers


        tm = int(input('請輸入每類圖片的下載數量 '))
        numPicture = tm
        line_list = []
        with open('./name.txt', encoding='utf-8') as file:
            line_list = [k.strip() for k in file.readlines()]  # 用 strip()移除末尾的空格

        for word in line_list:
            url = 'https://image.baidu.com/search/flip?tn=baiduimage&ie=utf-8&word=' + word + '&pn='
            tot = Find(url, A)
            Recommend = recommend(url)  # 記錄相關推薦
            print('經過檢測%s類圖片共有%d張' % (word, tot))
            file = word + '檔案'
            y = os.path.exists(file)
            if y == 1:
                print('該檔案已存在,無需創建')
            else:
                os.mkdir(file)
            t = 0
            tmp = url
            while t < numPicture:
                try:
                    url = tmp + str(t)
                    # result = requests.get(url, timeout=10)
                    # 這里搞了下
                    result = A.get(url, timeout=10, allow_redirects=False)
                    print(url)
                except error.HTTPError as e:
                    print('網路錯誤,請調整網路后重試')
                    t = t + 60
                else:
                    dowmloadPicture(result.text, word)
                    t = t + 60
            numPicture = numPicture + tm

        print('當前搜索結束,開始提取人臉')
    #############################################################################################

    # 將訓練集和測驗集中的raw圖片處理,提取出人臉圖片,從file+'檔案'到‘待分辨人臉’
    ############################################################################################
    if GET_FACE == 1:
        if GET_PIC == 0:
            file = '韓國女藝人檔案'
        raw_root = 'E:/Table/學習資料集/find_iu/'+ file + '/'
        img_raw = os.listdir(raw_root)
        new_path = 'E:/Table/學習資料集/find_iu/待分辨人臉/'

        n = 0
        for i in range(len(img_raw)):
            try:
                img = Image.open(raw_root + img_raw[i])
            except:
                print('a file error, continue')
                continue
            else:
                img_train = find_face(raw_root + img_raw[i])
                if img_train == None:
                    continue
                else:
                    img_train.save(new_path + '%d.JPG' % n)
                    print(raw_root + img_raw[i])
                    n += 1
        print('在%d張圖片中,共找到%d張臉' % (len(img_raw), n))
        print('提取人臉結束,開始尋找IU')
    #############################################################################################

    # 開始判別,從’待分辨人臉‘中找出IU存放到’IU_pic‘
    #############################################################################################
    if GET_IU == 1:

        data_transform = transforms.Compose([
            # transforms.Grayscale(num_output_channels=1),  # 彩色影像轉灰度影像num_output_channels默認1
            transforms.Resize(112),
            transforms.CenterCrop((112, 92)),  # 中心裁剪為112*92
            transforms.ToTensor(),
            transforms.Normalize(mean=[0.5, 0.5, 0.5],std=[0.5, 0.5, 0.5])
            # transforms.Normalize(mean=0.5, std=0.5)
        ])

        device = torch.device('cuda')
        model = SiameNetwork().to(device)
        model.load_state_dict(torch.load('parameter.pkl'))  # load
        model.eval()

        judge_root = 'E:/Table/學習資料集/find_iu/待分辨人臉/'
        img_judge = os.listdir(judge_root)
        new_path = 'E:/Table/學習資料集/find_iu/IU_pic/'

        result = []
        n = 0
        for i in range(len(img_judge)):
            try:
                img = Image.open(judge_root + img_judge[i])
            except:
                print('a file error, continue')
                continue
            else:
                img = img.convert('RGB')
                print(judge_root + img_judge[i])
                input = data_transform(img)
                input = input.unsqueeze(0)  # 這里經過轉換后輸出的input格式是[C,H,W],網路輸入還需要增加一維批量大小B
                # 增加一維,輸出的img格式為[1,C,H,W]
                input = Variable(input.cuda())
                output = model(input)  # 將圖片輸入網路得到輸出
                _, id = torch.max(output.data, 1)   # 0是IU,1是其他
                if id.item() == 0:
                    shutil.copy(judge_root + img_judge[i], new_path)
                    n += 1

        print('/n在%d張圖片中,共找到%d張IU的圖片'%(len(img_judge), n))
    #############################################################################################

4.file_deal.py

import os

raw_train_root_1 = 'E:/Table/學習資料集/find_iu/data/raw/train/IU/'
raw_train_root_2 = 'E:/Table/學習資料集/find_iu/data/raw/train/Other/'
raw_test_root_1 = 'E:/Table/學習資料集/find_iu/data/raw/test/IU/'
raw_test_root_2 = 'E:/Table/學習資料集/find_iu/data/raw/test/Other/'
raw_roots = [raw_train_root_1, raw_train_root_2, raw_test_root_1, raw_test_root_2]

for path in raw_roots:

    # 獲取該目錄下所有檔案,存入串列中
    fileList = os.listdir(path)

    n = 0
    for i in fileList:
        # 設定舊檔案名(就是路徑+檔案名)
        oldname = path + os.sep + fileList[n]  # os.sep添加系統分隔符

        # 設定新檔案名
        newname = path + os.sep + str(n) + '.JPG'

        os.rename(oldname, newname)  # 用os模塊中的rename方法對檔案改名
        print(oldname, '======>', newname)

        n += 1

5.network.py

import torch
import torch.nn as nn

class SiameNetwork(nn.Module):
    def __init__(self):
        super(SiameNetwork, self).__init__()

        # input: h=112, w=92

        self.conv1 = torch.nn.Sequential(
            torch.nn.Conv2d(in_channels=3,  # 輸入單通道
                            out_channels=16,  # 16個3*3卷積核
                            kernel_size=3,  # 卷積核尺寸
                            stride=2,  # 卷積核滑動步長, 1的話圖片大小不變,2的話會大小會變為(h/2)*(w/2)
                            padding=1),  # 邊緣填充大小,如果要保持原大小,kernel_size//2
            torch.nn.BatchNorm2d(16),  # 標準化,前面卷積后有16個圖層
            torch.nn.ReLU()  # 激活函式
        )  # output: h=56, w=46
        self.conv2 = torch.nn.Sequential(
            torch.nn.Conv2d(16, 32, 3, 2, 1),
            torch.nn.BatchNorm2d(32),
            torch.nn.ReLU()
        )  # output: h=28, w=23
        self.conv3 = torch.nn.Sequential(
            torch.nn.Conv2d(32, 64, 3, 2, 1),
            torch.nn.BatchNorm2d(64),
            torch.nn.ReLU()
        )  # output: h=14, w=12
        self.conv4 = torch.nn.Sequential(
            torch.nn.Conv2d(64, 64, 2, 2, 0),
            torch.nn.BatchNorm2d(64),
            torch.nn.ReLU()
        )  # output: h=7, w=6
        self.mlp1 = torch.nn.Linear(7 * 6 * 64, 100)  # 需要計算conv4的輸出尺寸,每次卷積的輸出尺寸(size - kernal + 2*padding)/stride + 1
        self.mlp2 = torch.nn.Linear(100, 10)

    def forward(self, x):
        x = self.conv1(x)
        x = self.conv2(x)
        x = self.conv3(x)
        x = self.conv4(x)
        x = self.mlp1(x.view(x.size(0), -1))  # view展平
        x = self.mlp2(x)
        return x

4.utils.py

import matplotlib as mpl
import matplotlib.pyplot as plt
import numpy as np
import cv2

# 繪制訓練、測驗的損失、準確度
#############################################################################################
def draw_result(draw_epoch, path):

    show_loss = np.loadtxt('%s/train_loss.txt' % (path))   # 讀取txt檔案,不同優化器的損失
    show_train_acc = np.loadtxt('%s/train_acc.txt' % (path))  # 讀取不同模型的準確度
    show_val_loss = np.loadtxt('%s/val_loss.txt' % (path))  # 讀取txt檔案,不同優化器的損失
    show_val_acc = np.loadtxt('%s/val_acc.txt' % (path))  # 讀取不同模型的準確度

    mpl.rc('font',family='Times New Roman', weight='semibold', size=9)  # 設定matplotlib中所有繪圖風格的設定
    font1 = {'weight' : 'semibold', 'size' : 11}  #設定文字風格

    fig = plt.figure(figsize = (7,5))    #figsize是圖片的大小`

    ax1 = fig.add_subplot(2, 2, 1)       # ax1是子圖的名字
    ax1.plot(draw_epoch, show_loss,color = 'red', label = u'AdaPID', linewidth =1.0)
    ax1.legend()   #顯示圖例
    ax1.set_title('Training Loss', font1)
    ax1.set_xlabel(u'Epoch', font1)

    ax2 = fig.add_subplot(2, 2, 2)
    ax2.plot(draw_epoch, show_val_loss,color = 'red', label = u'Adam', linewidth =1.0)
    ax2.legend()   #顯示圖例
    ax2.set_title('Validation Loss', font1)
    ax2.set_xlabel(u'Epoch', font1)

    ax3 = fig.add_subplot(2, 2, 3)
    ax3.plot(draw_epoch, show_train_acc,color = 'red', label = u'Adam', linewidth =1.0)
    ax3.legend()   #顯示圖例
    ax3.set_title('Training Accuracy', font1)
    ax3.set_xlabel(u'Epoch', font1)

    ax4 = fig.add_subplot(2, 2, 4)
    ax4.plot(draw_epoch, show_val_acc,color = 'red', label = u'Adam', linewidth =1.0)
    ax4.legend()   #顯示圖例
    ax4.set_title('Validation Accuracy', font1)
    ax4.set_xlabel(u'Epoch', font1)

    plt.subplots_adjust(left=None, bottom=None, right=None, top=None, wspace=None, hspace=0.45) # hspace為子圖上下間距
    plt.savefig('%s/show_curve.jpg' % (path), dpi=300)
#############################################################################################

# 用于解決cv.imread不能讀取中文路徑的問題
#############################################################################################
def cv_imread(filePath):
    # 核心就是下面這句,一般直接用這句就行,直接把圖片轉為mat資料
    cv_img = cv2.imdecode(np.fromfile(filePath, dtype=np.uint8), -1)
    # imdecode讀取的是rgb,如果后續需要opencv處理的話,需要轉換成bgr,轉換后圖片顏色會變化
    # cv_img=cv2.cvtColor(cv_img,cv2.COLOR_RGB2BGR)
    return cv_img
#############################################################################################

總結

總體而言,這是一個新人的興趣之作,雖然失敗了但是做的程序還蠻有趣的,主要是程序中可以看到iu,哈哈,

轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/276192.html

標籤:python

上一篇:Java陣列詳解

下一篇:十進制、二進制、十六進制轉換(面試題)原碼 補碼 python

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 【C++】Microsoft C++、C 和匯編程式檔案

    ......

    uj5u.com 2020-09-10 00:57:23 more
  • 例外宣告

    相比于斷言適用于排除邏輯上不可能存在的狀態,例外通常是用于邏輯上可能發生的錯誤。 例外宣告 Item 1:當函式不可能拋出例外或不能接受拋出例外時,使用noexcept 理由 如果不打算拋出例外的話,程式就會認為無法處理這種錯誤,并且應當盡早終止,如此可以有效地阻止例外的傳播與擴散。 示例 //不可 ......

    uj5u.com 2020-09-10 00:57:27 more
  • Codeforces 1400E Clear the Multiset(貪心 + 分治)

    鏈接:https://codeforces.com/problemset/problem/1400/E 來源:Codeforces 思路:給你一個陣列,現在你可以進行兩種操作,操作1:將一段沒有 0 的區間進行減一的操作,操作2:將 i 位置上的元素歸零。最終問:將這個陣列的全部元素歸零后操作的最少 ......

    uj5u.com 2020-09-10 00:57:30 more
  • UVA11610 【Reverse Prime】

    本人看到此題沒有翻譯,就附帶了一個自己的翻譯版本 思考 這一題,它的第一個要求是找出所有 $7$ 位反向質數及其質因數的個數。 我們應該需要質數篩篩選1~$10^{7}$的所有數,這里就不慢慢介紹了。但是,重讀題,我們突然發現反向質數都是 $7$ 位,而將它反過來后的數字卻是 $6$ 位數,這就說明 ......

    uj5u.com 2020-09-10 00:57:36 more
  • 統計區間素數數量

    1 #pragma GCC optimize(2) 2 #include <bits/stdc++.h> 3 using namespace std; 4 bool isprime[1000000010]; 5 vector<int> prime; 6 inline int getlist(int ......

    uj5u.com 2020-09-10 00:57:47 more
  • C/C++編程筆記:C++中的 const 變數詳解,教你正確認識const用法

    1、C中的const 1、區域const變數存放在堆疊區中,會分配記憶體(也就是說可以通過地址間接修改變數的值)。測驗代碼如下: 運行結果: 2、全域const變數存放在只讀資料段(不能通過地址修改,會發生寫入錯誤), 默認為外部聯編,可以給其他源檔案使用(需要用extern關鍵字修飾) 運行結果: ......

    uj5u.com 2020-09-10 00:58:04 more
  • 【C++犯錯記錄】VS2019 MFC添加資源不懂如何修改資源宏ID

    1. 首先在資源視圖中,添加資源 2. 點擊新添加的資源,復制自動生成的ID 3. 在解決方案資源管理器中找到Resource.h檔案,編輯,使用整個專案搜索和替換的方式快速替換 宏宣告 4. Ctrl+Shift+F 全域搜索,點擊查找全部,然后逐個替換 5. 為什么使用搜索替換而不使用屬性視窗直 ......

    uj5u.com 2020-09-10 00:59:11 more
  • 【C++犯錯記錄】VS2019 MFC不懂的批量添加資源

    1. 打開資源頭檔案Resource.h,在其中預先定義好宏 ID(不清楚其實ID值應該設定多少,可以先新建一個相同的資源項,再在這個資源的ID值的基礎上遞增即可) 2. 在資源視圖中選中專案資源,按F7編輯資源檔案,按 ID 型別 相對路徑的形式添加 資源。(別忘了先把檔案拷貝到專案中的res檔案 ......

    uj5u.com 2020-09-10 01:00:19 more
  • C/C++編程筆記:關于C++的參考型別,專供新手入門使用

    今天要講的是C++中我最喜歡的一個用法——參考,也叫別名。 參考就是給一個變數名取一個變數名,方便我們間接地使用這個變數。我們可以給一個變數創建N個參考,這N + 1個變數共享了同一塊記憶體區域。(參考型別的變數會占用記憶體空間,占用的記憶體空間的大小和指標型別的大小是相同的。雖然參考是一個物件的別名,但 ......

    uj5u.com 2020-09-10 01:00:22 more
  • 【C/C++編程筆記】從頭開始學習C ++:初學者完整指南

    眾所周知,C ++的學習曲線陡峭,但是花時間學習這種語言將為您的職業帶來奇跡,并使您與其他開發人員區分開。您會更輕松地學習新語言,形成真正的解決問題的技能,并在編程的基礎上打下堅實的基礎。 C ++將幫助您養成良好的編程習慣(即清晰一致的編碼風格,在撰寫代碼時注釋代碼,并限制類內部的可見性),并且由 ......

    uj5u.com 2020-09-10 01:00:41 more
最新发布
  • Rust中的智能指標:Box<T> Rc<T> Arc<T> Cell<T> RefCell<T> Weak

    Rust中的智能指標是什么 智能指標(smart pointers)是一類資料結構,是擁有資料所有權和額外功能的指標。是指標的進一步發展 指標(pointer)是一個包含記憶體地址的變數的通用概念。這個地址參考,或 ” 指向”(points at)一些其 他資料 。參考以 & 符號為標志并借用了他們所 ......

    uj5u.com 2023-04-20 07:24:10 more
  • Java的值傳遞和參考傳遞

    值傳遞不會改變本身,參考傳遞(如果傳遞的值需要實體化到堆里)如果發生修改了會改變本身。 1.基本資料型別都是值傳遞 package com.example.basic; public class Test { public static void main(String[] args) { int ......

    uj5u.com 2023-04-20 07:24:04 more
  • [2]SpinalHDL教程——Scala簡單入門

    第一個 Scala 程式 shell里面輸入 $ scala scala> 1 + 1 res0: Int = 2 scala> println("Hello World!") Hello World! 檔案形式 object HelloWorld { /* 這是我的第一個 Scala 程式 * 以 ......

    uj5u.com 2023-04-20 07:23:58 more
  • 理解函式指標和回呼函式

    理解 函式指標 指向函式的指標。比如: 理解函式指標的偽代碼 void (*p)(int type, char *data); // 定義一個函式指標p void func(int type, char *data); // 宣告一個函式func p = func; // 將指標p指向函式func ......

    uj5u.com 2023-04-20 07:23:52 more
  • Django筆記二十五之資料庫函式之日期函式

    本文首發于公眾號:Hunter后端 原文鏈接:Django筆記二十五之資料庫函式之日期函式 日期函式主要介紹兩個大類,Extract() 和 Trunc() Extract() 函式作用是提取日期,比如我們可以提取一個日期欄位的年份,月份,日等資料 Trunc() 的作用則是截取,比如 2022-0 ......

    uj5u.com 2023-04-20 07:23:45 more
  • 一天吃透JVM面試八股文

    什么是JVM? JVM,全稱Java Virtual Machine(Java虛擬機),是通過在實際的計算機上仿真模擬各種計算機功能來實作的。由一套位元組碼指令集、一組暫存器、一個堆疊、一個垃圾回收堆和一個存盤方法域等組成。JVM屏蔽了與作業系統平臺相關的資訊,使得Java程式只需要生成在Java虛擬機 ......

    uj5u.com 2023-04-20 07:23:31 more
  • 使用Java接入小程式訂閱訊息!

    更新完微信服務號的模板訊息之后,我又趕緊把微信小程式的訂閱訊息給實作了!之前我一直以為微信小程式也是要企業才能申請,沒想到小程式個人就能申請。 訊息推送平臺🔥推送下發【郵件】【短信】【微信服務號】【微信小程式】【企業微信】【釘釘】等訊息型別。 https://gitee.com/zhongfuch ......

    uj5u.com 2023-04-20 07:22:59 more
  • java -- 緩沖流、轉換流、序列化流

    緩沖流 緩沖流, 也叫高效流, 按照資料型別分類: 位元組緩沖流:BufferedInputStream,BufferedOutputStream 字符緩沖流:BufferedReader,BufferedWriter 緩沖流的基本原理,是在創建流物件時,會創建一個內置的默認大小的緩沖區陣列,通過緩沖 ......

    uj5u.com 2023-04-20 07:22:49 more
  • Java-SpringBoot-Range請求頭設定實作視頻分段傳輸

    老實說,人太懶了,現在基本都不喜歡寫筆記了,但是網上有關Range請求頭的文章都太水了 下面是抄的一段StackOverflow的代碼...自己大修改過的,寫的注釋挺全的,應該直接看得懂,就不解釋了 寫的不好...只是希望能給視頻網站開發的新手一點點幫助吧. 業務場景:視頻分段傳輸、視頻多段傳輸(理 ......

    uj5u.com 2023-04-20 07:22:42 more
  • Windows 10開發教程_編程入門自學教程_菜鳥教程-免費教程分享

    教程簡介 Windows 10開發入門教程 - 從簡單的步驟了解Windows 10開發,從基本到高級概念,包括簡介,UWP,第一個應用程式,商店,XAML控制元件,資料系結,XAML性能,自適應設計,自適應UI,自適應代碼,檔案管理,SQLite資料庫,應用程式到應用程式通信,應用程式本地化,應用程式 ......

    uj5u.com 2023-04-20 07:22:35 more