## 智能貓狗識別任務,用攝像頭識別或者輸入圖片進行識別,軟件界面均通過pyqt完成
**
**代碼分析**
1. 數據准備我使用的是kaggle數據集。用來訓練的數據集包含600張的彩色圖片,2個類別,每個類包含300張。對貓和狗兩類進行預測。
2. 網絡配置定義了一個較簡單的卷積神經網絡。顯示了其結構:輸入的二維圖像,先經過三次卷積層、池化層和Batchnorm,再經過全連接層,最后使用softmax分類作為輸出層。
3. 模型訓練定義運算場所為 fluid.CUDAPlace(0)采用的二分類分類器,學習率為learning_rate=0.001把貓和狗的圖片分別放在兩個文件夾中,再分別讀取,將其保存為list格式,並保存一個json文件# 說明的json文件的class_detail數據
class_detail_list['class_name'] = class_dir
class_detail_list['class_label'] = class_label
class_detail_list['class_test_images'] = test_sum
class_detail_list['class_trainer_images'] = trainer_sum
class_detail.append(class_detail_list)
class_label += 1
每一個Pass訓練結束之后,再使用驗證集進行驗證,並打印出相應的損失值cost和准確率acc。
4. 模型測試在測試之前,要對圖像進行預處理。首先將圖片大小調整為32*32,接着將圖像轉換成一維向量,最后再對一維向量進行歸一化處理。通過fluid.io.load_inference_model,預測器會從params_dirname中讀取已經訓練好的模型,來對從未遇見過的數據進行預測。
**運行過程截圖主界面**

**訓練模型**

**打開圖片**


**打開攝像頭**

**源代碼:**
model_save_dir="infer_catdog.model"
btn_3 = QPushButton(self)
btn_3.setText("退出")
btn_3.move(470, 460)
btn_3.setFixedSize(200, 50)
btn_3.clicked.connect(QCoreApplication.quit)
def readdata(self):
self.xunlian()
def xunlian(self):
def create_data_list(data_root_path):
with open(data_root_path + "test.list", 'w') as f:
pass
with open(data_root_path + "train.list", 'w') as f:
pass
# 所有類別的信息
class_detail = []
# 獲取所有類別
class_dirs = os.listdir(data_root_path)
# 類別標簽
class_label = 0
# 獲取總類別的名稱
father_paths = data_root_path.split('/')
while True:
if father_paths[len(father_paths) - 1] == '':
del father_paths[len(father_paths) - 1]
else:
break
father_path = father_paths[len(father_paths) - 1]
data_root_path = "train\\"
def shibie(self,fname):
global model_save_dir
# 創建執行器
place = fluid.CPUPlace()
exe = fluid.Executor(place)
exe.run(fluid.default_startup_program())
def readshexiangtou(self):
global fname
global num
if os.path.exists('infer_catdog.model'):
capture = cv2.VideoCapture(0)
while True:
ret, frame = capture.read()
frame = cv2.flip(frame, 1)
# cv2.imshow("video", frame)
cv2.imwrite("animal.png", frame) # 保存圖片
fname = "animal.png"
num = self.shibie(fname)
self.yuantu(fname)
self.huidu(fname)
self.erzhihua(fname)
self.bianyuan(fname)
self.jieguo(num)
c = cv2.waitKey(300)
# 如果在這個時間段內, 用戶按下ESC(ASCII碼為27),則跳出循環,否則,則繼續循環
if c == 27:
cv2.destroyAllWindows() # 銷毀所有窗口
break
def yuantu(self,fname):
image = cv2.imread(fname)
size = (int(self.label1.width()), int(self.label1.height()))
shrink = cv2.resize(image, size, interpolation=cv2.INTER_AREA)
shrink = cv2.cvtColor(shrink, cv2.COLOR_BGR2RGB)
self.QtImg = QtGui.QImage(shrink.data,
shrink.shape[1],
shrink.shape[0],
QtGui.QImage.Format_RGB888)
self.label1.setPixmap(QtGui.QPixmap.fromImage(self.QtImg))
def erzhihua(self,fname):
image = cv2.imread(fname)
if image is None:
print("未選擇圖片")
else:
image=cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)
ret,binary=cv2.threshold(image,0,255,cv2.THRESH_OTSU|cv2.THRESH_BINARY)
print("二值化的閾值為:",ret)
size = (int(self.label3.width()), int(self.label3.height()))
shrink = cv2.resize(binary, size, interpolation=cv2.INTER_AREA)
shrink = cv2.cvtColor(shrink, cv2.COLOR_BGR2RGB)
self.QtImg = QtGui.QImage(shrink.data,
shrink.shape[1],
shrink.shape[0],
QtGui.QImage.Format_RGB888)
self.label3.setPixmap(QtGui.QPixmap.fromImage(self.QtImg))
def jieguo(self,num):
if num!=None:
self.lable5.setText('該圖片識別為:{}'.format(num))
else:
self.lable5.setText(' 未進行圖片識別')
import cv2
import numpy as np
import paddle as paddle
import paddle.fluid as fluid
from PIL import Image
import matplotlib.pyplot as plt
import os
import json
import random
import shutil
from multiprocessing import cpu_count
import sys
from PyQt5 import QtWidgets, QtCore, QtGui
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
import numpy as np
import paddle as paddle
import paddle.fluid as fluid
from PIL import Image
import matplotlib.pyplot as plt
import os
import json
import random
import shutil
from multiprocessing import cpu_count
import sys
from PyQt5 import QtWidgets, QtCore, QtGui
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
model_save_dir="infer_catdog.model"
class animal(QWidget):
def __init__(self):
super(animal, self).__init__()
def __init__(self):
super(animal, self).__init__()
self.resize(1400,600)
self.center() #使窗口居中
self.setWindowTitle("貓狗分類")
self.setWindowIcon(QIcon('1.jpg'))
self.center() #使窗口居中
self.setWindowTitle("貓狗分類")
self.setWindowIcon(QIcon('1.jpg'))
self.label1 = QLabel(self)
self.label1.setText(" 原圖")
self.label1.setFixedSize(300, 400)
self.label1.move(10, 30)
self.label1.setStyleSheet("QLabel{background:white;}"
"QLabel{color:rgb(300,300,300,120);font-size:20px;font-weight:bold;font-family:宋體;}"
)
self.label1.setText(" 原圖")
self.label1.setFixedSize(300, 400)
self.label1.move(10, 30)
self.label1.setStyleSheet("QLabel{background:white;}"
"QLabel{color:rgb(300,300,300,120);font-size:20px;font-weight:bold;font-family:宋體;}"
)
self.label2 = QLabel(self)
self.label2.setText(" 原圖灰度")
self.label2.setFixedSize(300, 400)
self.label2.move(360, 30)
self.label2.setStyleSheet("QLabel{background:white;}"
"QLabel{color:rgb(300,300,300,120);font-size:20px;font-weight:bold;font-family:宋體;}"
)
self.label2.setText(" 原圖灰度")
self.label2.setFixedSize(300, 400)
self.label2.move(360, 30)
self.label2.setStyleSheet("QLabel{background:white;}"
"QLabel{color:rgb(300,300,300,120);font-size:20px;font-weight:bold;font-family:宋體;}"
)
self.label3 = QLabel(self)
self.label3.setText(" 原圖二值化")
self.label3.setFixedSize(300, 400)
self.label3.move(710, 30)
self.label3.setStyleSheet("QLabel{background:white;}"
"QLabel{color:rgb(300,300,300,120);font-size:20px;font-weight:bold;font-family:宋體;}"
)
self.label3.setText(" 原圖二值化")
self.label3.setFixedSize(300, 400)
self.label3.move(710, 30)
self.label3.setStyleSheet("QLabel{background:white;}"
"QLabel{color:rgb(300,300,300,120);font-size:20px;font-weight:bold;font-family:宋體;}"
)
self.label4 = QLabel(self)
self.label4.setText(" 原圖邊緣檢測")
self.label4.setFixedSize(300, 400)
self.label4.move(1060, 30)
self.label4.setStyleSheet("QLabel{background:white;}"
"QLabel{color:rgb(300,300,300,120);font-size:20px;font-weight:bold;font-family:宋體;}"
)
self.label4.setText(" 原圖邊緣檢測")
self.label4.setFixedSize(300, 400)
self.label4.move(1060, 30)
self.label4.setStyleSheet("QLabel{background:white;}"
"QLabel{color:rgb(300,300,300,120);font-size:20px;font-weight:bold;font-family:宋體;}"
)
self.lable5 = QLabel(self)
self.lable5.setText(" 顯示測試結果")
self.lable5.setFixedSize(300, 100)
self.lable5.move(1060, 450)
self.lable5.setStyleSheet("QLabel{background:white;}"
"QLabel{color:rgb(300,300,300,120);font-size:20px;font-weight:bold;font-family:宋體;}"
)
self.lable5.setText(" 顯示測試結果")
self.lable5.setFixedSize(300, 100)
self.lable5.move(1060, 450)
self.lable5.setStyleSheet("QLabel{background:white;}"
"QLabel{color:rgb(300,300,300,120);font-size:20px;font-weight:bold;font-family:宋體;}"
)
btn_1 = QPushButton(self)
btn_1.setText("訓練模型")
btn_1.move(30, 460)
btn_1.setFixedSize(200,50)
btn_1.clicked.connect(self.readdata)
btn_1.setText("訓練模型")
btn_1.move(30, 460)
btn_1.setFixedSize(200,50)
btn_1.clicked.connect(self.readdata)
btn_2 = QPushButton(self)
btn_2.setText("打開圖片")
btn_2.move(250, 460)
btn_2.setFixedSize(200, 50)
btn_2.clicked.connect(self.readphoto)
btn_2.setText("打開圖片")
btn_2.move(250, 460)
btn_2.setFixedSize(200, 50)
btn_2.clicked.connect(self.readphoto)
btn_4 = QPushButton(self)
btn_4.setText("打開攝像頭")
btn_4.move(250, 520)
btn_4.setFixedSize(200, 50)
btn_4.clicked.connect(self.readshexiangtou)
btn_4.setText("打開攝像頭")
btn_4.move(250, 520)
btn_4.setFixedSize(200, 50)
btn_4.clicked.connect(self.readshexiangtou)
btn_3 = QPushButton(self)
btn_3.setText("退出")
btn_3.move(470, 460)
btn_3.setFixedSize(200, 50)
btn_3.clicked.connect(QCoreApplication.quit)
def readdata(self):
self.xunlian()
def xunlian(self):
def create_data_list(data_root_path):
with open(data_root_path + "test.list", 'w') as f:
pass
with open(data_root_path + "train.list", 'w') as f:
pass
# 所有類別的信息
class_detail = []
# 獲取所有類別
class_dirs = os.listdir(data_root_path)
# 類別標簽
class_label = 0
# 獲取總類別的名稱
father_paths = data_root_path.split('/')
while True:
if father_paths[len(father_paths) - 1] == '':
del father_paths[len(father_paths) - 1]
else:
break
father_path = father_paths[len(father_paths) - 1]
all_class_images = 0
other_file = 0
for class_dir in class_dirs:
if class_dir == 'test.list' or class_dir == "train.list" or class_dir == 'readme.json':
other_file += 1
continue
class_detail_list = {}
test_sum = 0
trainer_sum = 0
# 統計每個類別有多少張圖片
class_sum = 0
# 獲取類別路徑
path = data_root_path + class_dir
# 獲取所有圖片
img_paths = os.listdir(path)
for img_path in img_paths:
# 每張圖片的路徑
name_path = class_dir + img_path
# 如果不存在這個文件夾,就創建
if not os.path.exists(data_root_path):
os.makedirs(data_root_path)
# 每10張圖片取一個做測試數據
if class_sum % 10 == 0:
test_sum += 1
with open(data_root_path + "test.list", 'a') as f:
f.write(name_path + "\t%d" % class_label + "\n")
else:
trainer_sum += 1
with open(data_root_path + "train.list", 'a') as f:
f.write(name_path + "\t%d" % class_label + "\n")
class_sum += 1
all_class_images += 1
# 說明的json文件的class_detail數據
class_detail_list['class_name'] = class_dir
class_detail_list['class_label'] = class_label
class_detail_list['class_test_images'] = test_sum
class_detail_list['class_trainer_images'] = trainer_sum
class_detail.append(class_detail_list)
class_label += 1
# 獲取類別數量
all_class_sum = len(class_dirs) - other_file
# 說明的json文件信息
readjson = {}
readjson['all_class_name'] = father_path
readjson['all_class_sum'] = all_class_sum
readjson['all_class_images'] = all_class_images
readjson['class_detail'] = class_detail
jsons = json.dumps(readjson, sort_keys=True, indent=4, separators=(',', ': '))
with open(data_root_path + "readme.json", 'w') as f:
f.write(jsons)
print('圖像列表已生成')
other_file = 0
for class_dir in class_dirs:
if class_dir == 'test.list' or class_dir == "train.list" or class_dir == 'readme.json':
other_file += 1
continue
class_detail_list = {}
test_sum = 0
trainer_sum = 0
# 統計每個類別有多少張圖片
class_sum = 0
# 獲取類別路徑
path = data_root_path + class_dir
# 獲取所有圖片
img_paths = os.listdir(path)
for img_path in img_paths:
# 每張圖片的路徑
name_path = class_dir + img_path
# 如果不存在這個文件夾,就創建
if not os.path.exists(data_root_path):
os.makedirs(data_root_path)
# 每10張圖片取一個做測試數據
if class_sum % 10 == 0:
test_sum += 1
with open(data_root_path + "test.list", 'a') as f:
f.write(name_path + "\t%d" % class_label + "\n")
else:
trainer_sum += 1
with open(data_root_path + "train.list", 'a') as f:
f.write(name_path + "\t%d" % class_label + "\n")
class_sum += 1
all_class_images += 1
# 說明的json文件的class_detail數據
class_detail_list['class_name'] = class_dir
class_detail_list['class_label'] = class_label
class_detail_list['class_test_images'] = test_sum
class_detail_list['class_trainer_images'] = trainer_sum
class_detail.append(class_detail_list)
class_label += 1
# 獲取類別數量
all_class_sum = len(class_dirs) - other_file
# 說明的json文件信息
readjson = {}
readjson['all_class_name'] = father_path
readjson['all_class_sum'] = all_class_sum
readjson['all_class_images'] = all_class_images
readjson['class_detail'] = class_detail
jsons = json.dumps(readjson, sort_keys=True, indent=4, separators=(',', ': '))
with open(data_root_path + "readme.json", 'w') as f:
f.write(jsons)
print('圖像列表已生成')
def net(input, class_dim, scale=1.0):
# conv1: 112x112
input = conv_bn_layer(input=input,
filter_size=3,
channels=3,
num_filters=int(32 * scale),
stride=2,
padding=1)
# conv1: 112x112
input = conv_bn_layer(input=input,
filter_size=3,
channels=3,
num_filters=int(32 * scale),
stride=2,
padding=1)
input = depthwise_separable(input=input,
num_filters1=32,
num_filters2=64,
num_groups=32,
stride=1,
scale=scale)
num_filters1=32,
num_filters2=64,
num_groups=32,
stride=1,
scale=scale)
input = depthwise_separable(input=input,
num_filters1=64,
num_filters2=128,
num_groups=64,
stride=2,
scale=scale)
num_filters1=64,
num_filters2=128,
num_groups=64,
stride=2,
scale=scale)
input = depthwise_separable(input=input,
num_filters1=256,
num_filters2=256,
num_groups=256,
stride=1,
scale=scale)
num_filters1=256,
num_filters2=256,
num_groups=256,
stride=1,
scale=scale)
input = depthwise_separable(input=input,
num_filters1=256,
num_filters2=512,
num_groups=256,
stride=2,
scale=scale)
num_filters1=256,
num_filters2=512,
num_groups=256,
stride=2,
scale=scale)
feature = fluid.layers.pool2d(input=input,
pool_size=0,
pool_stride=1,
pool_type='avg',
global_pooling=True)
pool_size=0,
pool_stride=1,
pool_type='avg',
global_pooling=True)
net = fluid.layers.fc(input=feature,
size=class_dim,
act='softmax')
return net
size=class_dim,
act='softmax')
return net
def conv_bn_layer(input, filter_size, num_filters, stride,
padding, channels=None, num_groups=1, act='relu', use_cudnn=True): # 9個參數
conv = fluid.layers.conv2d(input=input,
num_filters=num_filters,
filter_size=filter_size,
stride=stride,
padding=padding,
groups=num_groups,
act=None,
use_cudnn=use_cudnn,
bias_attr=False)
padding, channels=None, num_groups=1, act='relu', use_cudnn=True): # 9個參數
conv = fluid.layers.conv2d(input=input,
num_filters=num_filters,
filter_size=filter_size,
stride=stride,
padding=padding,
groups=num_groups,
act=None,
use_cudnn=use_cudnn,
bias_attr=False)
return fluid.layers.batch_norm(input=conv, act=act)
def depthwise_separable(input, num_filters1, num_filters2, num_groups, stride, scale): # 6個參數
depthwise_conv = conv_bn_layer(input=input,
filter_size=3,
num_filters=int(num_filters1 * scale),
stride=stride,
padding=1,
num_groups=int(num_groups * scale),
use_cudnn=False)
depthwise_conv = conv_bn_layer(input=input,
filter_size=3,
num_filters=int(num_filters1 * scale),
stride=stride,
padding=1,
num_groups=int(num_groups * scale),
use_cudnn=False)
pointwise_conv = conv_bn_layer(input=depthwise_conv,
filter_size=1,
num_filters=int(num_filters2 * scale),
stride=1,
padding=0)
return pointwise_conv
filter_size=1,
num_filters=int(num_filters2 * scale),
stride=1,
padding=0)
return pointwise_conv
# 訓練圖片的預處理
def train_mapper():
img_path, label, crop_size, resize_size = sample
try:
img = Image.open(img_path)
# 統一圖片大小
img = img.resize((resize_size, resize_size), Image.ANTIALIAS)
# 隨機水平翻轉
r1 = random.random()
if r1 > 0.5:
img = img.transpose(Image.FLIP_LEFT_RIGHT)
# 隨機垂直翻轉
r2 = random.random()
if r2 > 0.5:
img = img.transpose(Image.FLIP_TOP_BOTTOM)
# 隨機角度翻轉
r3 = random.randint(-3, 3)
img = img.rotate(r3, expand=False)
# 隨機裁剪
r4 = random.randint(0, int(resize_size - crop_size))
r5 = random.randint(0, int(resize_size - crop_size))
box = (r4, r5, r4 + crop_size, r5 + crop_size)
img = img.crop(box)
# 把圖片轉換成numpy值
img = np.array(img).astype(np.float32)
# 轉換成CHW
img = img.transpose((2, 0, 1))
# 轉換成BGR
img = img[(2, 1, 0), :, :] / 255.0
return img, int(label)
except:
print("%s 該圖片錯誤,請刪除該圖片並重新創建圖像數據列表" % img_path)
def train_mapper():
img_path, label, crop_size, resize_size = sample
try:
img = Image.open(img_path)
# 統一圖片大小
img = img.resize((resize_size, resize_size), Image.ANTIALIAS)
# 隨機水平翻轉
r1 = random.random()
if r1 > 0.5:
img = img.transpose(Image.FLIP_LEFT_RIGHT)
# 隨機垂直翻轉
r2 = random.random()
if r2 > 0.5:
img = img.transpose(Image.FLIP_TOP_BOTTOM)
# 隨機角度翻轉
r3 = random.randint(-3, 3)
img = img.rotate(r3, expand=False)
# 隨機裁剪
r4 = random.randint(0, int(resize_size - crop_size))
r5 = random.randint(0, int(resize_size - crop_size))
box = (r4, r5, r4 + crop_size, r5 + crop_size)
img = img.crop(box)
# 把圖片轉換成numpy值
img = np.array(img).astype(np.float32)
# 轉換成CHW
img = img.transpose((2, 0, 1))
# 轉換成BGR
img = img[(2, 1, 0), :, :] / 255.0
return img, int(label)
except:
print("%s 該圖片錯誤,請刪除該圖片並重新創建圖像數據列表" % img_path)
# 獲取訓練的reader
def train_reader(train_list_path, crop_size, resize_size):
father_path = os.path.dirname(train_list_path)
def train_reader(train_list_path, crop_size, resize_size):
father_path = os.path.dirname(train_list_path)
def reader():
with open(train_list_path, 'r') as f:
lines = f.readlines()
# 打亂圖像列表
np.random.shuffle(lines)
# 開始獲取每張圖像和標簽
for line in lines:
img, label = line.split('\t')
img = os.path.join(father_path, img)
yield img, label, crop_size, resize_size
with open(train_list_path, 'r') as f:
lines = f.readlines()
# 打亂圖像列表
np.random.shuffle(lines)
# 開始獲取每張圖像和標簽
for line in lines:
img, label = line.split('\t')
img = os.path.join(father_path, img)
yield img, label, crop_size, resize_size
return paddle.reader.xmap_readers(train_mapper, reader, cpu_count(), 102400)
# 測試圖片的預處理
def test_mapper(sample):
img, label, crop_size = sample
img = Image.open(img)
# 統一圖像大小
img = img.resize((crop_size, crop_size), Image.ANTIALIAS)
# 轉換成numpy值
img = np.array(img).astype(np.float32)
# 轉換成CHW
img = img.transpose((2, 0, 1))
# 轉換成BGR
img = img[(2, 1, 0), :, :] / 255.0
return img, int(label)
def test_mapper(sample):
img, label, crop_size = sample
img = Image.open(img)
# 統一圖像大小
img = img.resize((crop_size, crop_size), Image.ANTIALIAS)
# 轉換成numpy值
img = np.array(img).astype(np.float32)
# 轉換成CHW
img = img.transpose((2, 0, 1))
# 轉換成BGR
img = img[(2, 1, 0), :, :] / 255.0
return img, int(label)
# 測試的圖片reader
def test_reader(test_list_path, crop_size):
father_path = os.path.dirname(test_list_path)
def test_reader(test_list_path, crop_size):
father_path = os.path.dirname(test_list_path)
def reader():
with open(test_list_path, 'r') as f:
lines = f.readlines()
for line in lines:
img, label = line.split('\t')
img = os.path.join(father_path, img)
yield img, label, crop_size
with open(test_list_path, 'r') as f:
lines = f.readlines()
for line in lines:
img, label = line.split('\t')
img = os.path.join(father_path, img)
yield img, label, crop_size
return paddle.reader.xmap_readers(test_mapper, reader, cpu_count(), 1024)
data_root_path = "train\\"
crop_size = 100
resize_size = 100
resize_size = 100
# 定義輸入層
image = fluid.layers.data(name='image', shape=[3, crop_size, crop_size], dtype='float32')
label = fluid.layers.data(name='label', shape=[1], dtype='float64')
image = fluid.layers.data(name='image', shape=[3, crop_size, crop_size], dtype='float32')
label = fluid.layers.data(name='label', shape=[1], dtype='float64')
# 獲取分類器,因為這次只爬取了6個類別的圖片,所以分類器的類別大小為6
model = net(image, 2)
model = net(image, 2)
# 獲取損失函數和准確率函數
cost = fluid.layers.cross_entropy(input=model, label=label)
avg_cost = fluid.layers.mean(cost)
acc = fluid.layers.accuracy(input=model, label=label)
cost = fluid.layers.cross_entropy(input=model, label=label)
avg_cost = fluid.layers.mean(cost)
acc = fluid.layers.accuracy(input=model, label=label)
# 獲取訓練和測試程序
test_program = fluid.default_main_program().clone(for_test=True)
test_program = fluid.default_main_program().clone(for_test=True)
# 定義優化方法
optimizer = fluid.optimizer.Adam(learning_rate=0.001)
# optimizer = fluid.optimizer.AdamOptimizer(learning_rate=1e-3,
# regularization=fluid.regularizer.L2DecayRegularizer(1e-4))
opts = optimizer.minimize(avg_cost)
optimizer = fluid.optimizer.Adam(learning_rate=0.001)
# optimizer = fluid.optimizer.AdamOptimizer(learning_rate=1e-3,
# regularization=fluid.regularizer.L2DecayRegularizer(1e-4))
opts = optimizer.minimize(avg_cost)
# 獲取自定義數據
train_reader = paddle.batch(
reader=train_reader(r'train\train.list', crop_size, resize_size), batch_size=32)
test_reader = paddle.batch(reader=test_reader(r'train\test.list', crop_size),
batch_size=32)
train_reader = paddle.batch(
reader=train_reader(r'train\train.list', crop_size, resize_size), batch_size=32)
test_reader = paddle.batch(reader=test_reader(r'train\test.list', crop_size),
batch_size=32)
# 定義一個使用GPU的執行器
place = fluid.CUDAPlace(0)
# place = fluid.CPUPlace()
exe = fluid.Executor(place)
# 進行參數初始化
exe.run(fluid.default_startup_program())
place = fluid.CUDAPlace(0)
# place = fluid.CPUPlace()
exe = fluid.Executor(place)
# 進行參數初始化
exe.run(fluid.default_startup_program())
# 定義輸入數據維度
feeder = fluid.DataFeeder(place=place, feed_list=[image, label])
feeder = fluid.DataFeeder(place=place, feed_list=[image, label])
# 訓練100次
for pass_id in range(100):
# 進行訓練
for batch_id, data in enumerate(train_reader()):
train_cost, train_acc = exe.run(program=fluid.default_main_program(),
feed=feeder.feed(data),
fetch_list=[avg_cost, acc])
for pass_id in range(100):
# 進行訓練
for batch_id, data in enumerate(train_reader()):
train_cost, train_acc = exe.run(program=fluid.default_main_program(),
feed=feeder.feed(data),
fetch_list=[avg_cost, acc])
# 每100個batch打印一次信息
if batch_id % 10 == 0:
print('Pass:%d, Batch:%d, Cost:%0.5f, Accuracy:%0.5f' %
(pass_id, batch_id, train_cost[0], train_acc[0]))
if batch_id % 10 == 0:
print('Pass:%d, Batch:%d, Cost:%0.5f, Accuracy:%0.5f' %
(pass_id, batch_id, train_cost[0], train_acc[0]))
# 進行測試
test_accs = []
test_costs = []
for batch_id, data in enumerate(test_reader()):
test_cost, test_acc = exe.run(program=test_program,
feed=feeder.feed(data),
fetch_list=[avg_cost, acc])
test_accs.append(test_acc[0])
test_costs.append(test_cost[0])
# 求測試結果的平均值
test_cost = (sum(test_costs) / len(test_costs))
test_acc = (sum(test_accs) / len(test_accs))
print('Test:%d, Cost:%0.5f, Accuracy:%0.5f' % (pass_id, test_cost, test_acc))
test_accs = []
test_costs = []
for batch_id, data in enumerate(test_reader()):
test_cost, test_acc = exe.run(program=test_program,
feed=feeder.feed(data),
fetch_list=[avg_cost, acc])
test_accs.append(test_acc[0])
test_costs.append(test_cost[0])
# 求測試結果的平均值
test_cost = (sum(test_costs) / len(test_costs))
test_acc = (sum(test_accs) / len(test_accs))
print('Test:%d, Cost:%0.5f, Accuracy:%0.5f' % (pass_id, test_cost, test_acc))
# 保存預測模型
save_path = 'infer_catdog.model'
# 刪除舊的模型文件
shutil.rmtree(save_path, ignore_errors=True)
# 創建保持模型文件目錄
os.makedirs(save_path)
# 保存預測模型
fluid.io.save_inference_model(save_path, feeded_var_names=[image.name], target_vars=[model], executor=exe)
print('訓練模型保存完成!\n保存在%s'%(save_path))
QMessageBox.question(self, '提醒', '訓練模型保存完成!\n保存在%s'%(save_path),
QMessageBox.Ok)
save_path = 'infer_catdog.model'
# 刪除舊的模型文件
shutil.rmtree(save_path, ignore_errors=True)
# 創建保持模型文件目錄
os.makedirs(save_path)
# 保存預測模型
fluid.io.save_inference_model(save_path, feeded_var_names=[image.name], target_vars=[model], executor=exe)
print('訓練模型保存完成!\n保存在%s'%(save_path))
QMessageBox.question(self, '提醒', '訓練模型保存完成!\n保存在%s'%(save_path),
QMessageBox.Ok)
def shibie(self,fname):
global model_save_dir
# 創建執行器
place = fluid.CPUPlace()
exe = fluid.Executor(place)
exe.run(fluid.default_startup_program())
# 保存預測模型路徑
save_path = 'infer_catdog.model'
# 從模型中獲取預測程序、輸入數據名稱列表、分類器
[infer_program, feeded_var_names, target_var] = fluid.io.load_inference_model(dirname=save_path, executor=exe)
save_path = 'infer_catdog.model'
# 從模型中獲取預測程序、輸入數據名稱列表、分類器
[infer_program, feeded_var_names, target_var] = fluid.io.load_inference_model(dirname=save_path, executor=exe)
# 預處理圖片
def load_image(file):
img = Image.open(file)
# 統一圖像大小
img = img.resize((224, 224), Image.ANTIALIAS)
# 轉換成numpy值
img = np.array(img).astype(np.float32)
# 轉換成CHW
img = img.transpose((2, 0, 1))
# 轉換成BGR
img = img[(2, 1, 0), :, :] / 255.0
img = np.expand_dims(img, axis=0)
return img
# 獲取圖片數據
img = load_image(fname)
# 執行預測
result = exe.run(program=infer_program,
feed={feeded_var_names[0]: img},
fetch_list=target_var)
# 顯示圖片並輸出結果最大的label
lab = np.argsort(result)[0][0][-1]
names = ['貓', '狗']
print('預測結果標簽為:%d, 名稱為:%s, 概率為:%f' % (lab, names[lab], result[0][0][lab]))
return names[lab]
def load_image(file):
img = Image.open(file)
# 統一圖像大小
img = img.resize((224, 224), Image.ANTIALIAS)
# 轉換成numpy值
img = np.array(img).astype(np.float32)
# 轉換成CHW
img = img.transpose((2, 0, 1))
# 轉換成BGR
img = img[(2, 1, 0), :, :] / 255.0
img = np.expand_dims(img, axis=0)
return img
# 獲取圖片數據
img = load_image(fname)
# 執行預測
result = exe.run(program=infer_program,
feed={feeded_var_names[0]: img},
fetch_list=target_var)
# 顯示圖片並輸出結果最大的label
lab = np.argsort(result)[0][0][-1]
names = ['貓', '狗']
print('預測結果標簽為:%d, 名稱為:%s, 概率為:%f' % (lab, names[lab], result[0][0][lab]))
return names[lab]
def readphoto(self):
global fname
global num
if os.path.exists("infer_catdog.model"):
fname, imgType = QFileDialog.getOpenFileName(self, "打開圖片", "", "*;;*.png;;All Files(*)")
if fname:
self.yuantu(fname)
num = self.shibie(fname)
self.huidu(fname)
self.erzhihua(fname)
self.bianyuan(fname)
self.jieguo(num)
else:
QMessageBox.question(self, '提醒', '未選擇圖片',
QMessageBox.Ok)
else:
QMessageBox.question(self, '提醒', '未得到訓練模型',
QMessageBox.Ok)
global fname
global num
if os.path.exists("infer_catdog.model"):
fname, imgType = QFileDialog.getOpenFileName(self, "打開圖片", "", "*;;*.png;;All Files(*)")
if fname:
self.yuantu(fname)
num = self.shibie(fname)
self.huidu(fname)
self.erzhihua(fname)
self.bianyuan(fname)
self.jieguo(num)
else:
QMessageBox.question(self, '提醒', '未選擇圖片',
QMessageBox.Ok)
else:
QMessageBox.question(self, '提醒', '未得到訓練模型',
QMessageBox.Ok)
def readshexiangtou(self):
global fname
global num
if os.path.exists('infer_catdog.model'):
capture = cv2.VideoCapture(0)
while True:
ret, frame = capture.read()
frame = cv2.flip(frame, 1)
# cv2.imshow("video", frame)
cv2.imwrite("animal.png", frame) # 保存圖片
fname = "animal.png"
num = self.shibie(fname)
self.yuantu(fname)
self.huidu(fname)
self.erzhihua(fname)
self.bianyuan(fname)
self.jieguo(num)
c = cv2.waitKey(300)
# 如果在這個時間段內, 用戶按下ESC(ASCII碼為27),則跳出循環,否則,則繼續循環
if c == 27:
cv2.destroyAllWindows() # 銷毀所有窗口
break
cv2.waitKey(0) # 等待用戶操作,里面等待參數是毫秒,我們填寫0,代表是永遠,等待用戶操作
cv2.destroyAllWindows() # 銷毀所有窗口
else:
QMessageBox.question(self, '提醒', '未得到訓練模型',
QMessageBox.Ok)
cv2.destroyAllWindows() # 銷毀所有窗口
else:
QMessageBox.question(self, '提醒', '未得到訓練模型',
QMessageBox.Ok)
def yuantu(self,fname):
image = cv2.imread(fname)
size = (int(self.label1.width()), int(self.label1.height()))
shrink = cv2.resize(image, size, interpolation=cv2.INTER_AREA)
shrink = cv2.cvtColor(shrink, cv2.COLOR_BGR2RGB)
self.QtImg = QtGui.QImage(shrink.data,
shrink.shape[1],
shrink.shape[0],
QtGui.QImage.Format_RGB888)
self.label1.setPixmap(QtGui.QPixmap.fromImage(self.QtImg))
def erzhihua(self,fname):
image = cv2.imread(fname)
if image is None:
print("未選擇圖片")
else:
image=cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)
ret,binary=cv2.threshold(image,0,255,cv2.THRESH_OTSU|cv2.THRESH_BINARY)
print("二值化的閾值為:",ret)
size = (int(self.label3.width()), int(self.label3.height()))
shrink = cv2.resize(binary, size, interpolation=cv2.INTER_AREA)
shrink = cv2.cvtColor(shrink, cv2.COLOR_BGR2RGB)
self.QtImg = QtGui.QImage(shrink.data,
shrink.shape[1],
shrink.shape[0],
QtGui.QImage.Format_RGB888)
self.label3.setPixmap(QtGui.QPixmap.fromImage(self.QtImg))
def huidu(self,fname):
image = cv2.imread(fname)
if image is None:
print("未選擇圖片")
else:
image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
size = (int(self.label2.width()), int(self.label2.height()))
shrink = cv2.resize(image, size, interpolation=cv2.INTER_AREA)
shrink = cv2.cvtColor(shrink, cv2.COLOR_BGR2RGB)
self.QtImg = QtGui.QImage(shrink.data,
shrink.shape[1],
shrink.shape[0],
QtGui.QImage.Format_RGB888)
self.label2.setPixmap(QtGui.QPixmap.fromImage(self.QtImg))
image = cv2.imread(fname)
if image is None:
print("未選擇圖片")
else:
image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
size = (int(self.label2.width()), int(self.label2.height()))
shrink = cv2.resize(image, size, interpolation=cv2.INTER_AREA)
shrink = cv2.cvtColor(shrink, cv2.COLOR_BGR2RGB)
self.QtImg = QtGui.QImage(shrink.data,
shrink.shape[1],
shrink.shape[0],
QtGui.QImage.Format_RGB888)
self.label2.setPixmap(QtGui.QPixmap.fromImage(self.QtImg))
def bianyuan(self,fname):
image = cv2.imread(fname)
if image is None:
print("未選擇圖片")
else:
image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
image1=cv2.Canny(image,10,50)
size = (int(self.label4.width()), int(self.label4.height()))
shrink = cv2.resize(image1, size, interpolation=cv2.INTER_AREA)
shrink = cv2.cvtColor(shrink, cv2.COLOR_BGR2RGB)
self.QtImg = QtGui.QImage(shrink.data,
shrink.shape[1],
shrink.shape[0],
QtGui.QImage.Format_RGB888)
self.label4.setPixmap(QtGui.QPixmap.fromImage(self.QtImg))
image = cv2.imread(fname)
if image is None:
print("未選擇圖片")
else:
image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
image1=cv2.Canny(image,10,50)
size = (int(self.label4.width()), int(self.label4.height()))
shrink = cv2.resize(image1, size, interpolation=cv2.INTER_AREA)
shrink = cv2.cvtColor(shrink, cv2.COLOR_BGR2RGB)
self.QtImg = QtGui.QImage(shrink.data,
shrink.shape[1],
shrink.shape[0],
QtGui.QImage.Format_RGB888)
self.label4.setPixmap(QtGui.QPixmap.fromImage(self.QtImg))
def jieguo(self,num):
if num!=None:
self.lable5.setText('該圖片識別為:{}'.format(num))
else:
self.lable5.setText(' 未進行圖片識別')
def center(self): # 控制窗口顯示在屏幕中心的方法
# 獲得窗口
qr = self.frameGeometry()
# 獲得屏幕中心點
cp = QDesktopWidget().availableGeometry().center()
# 顯示到屏幕中心
qr.moveCenter(cp)
self.move(qr.topLeft())
qr = self.frameGeometry()
# 獲得屏幕中心點
cp = QDesktopWidget().availableGeometry().center()
# 顯示到屏幕中心
qr.moveCenter(cp)
self.move(qr.topLeft())
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
my = animal()
my.show()
sys.exit(app.exec_())
app = QtWidgets.QApplication(sys.argv)
my = animal()
my.show()
sys.exit(app.exec_())