# 自製判斷好看醜陋演算法 並利用pygame做出視窗
###### tags: `tensorflow.keras`
```python=
from webdriver_manager.chrome import ChromeDriverManager
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
import time
from bs4 import BeautifulSoup
import pandas
import os
import face_recognition
import cv2
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
import requests
```
```python=
def search_picture(keyword):
options = Options()
options.add_argument("--disable-notifications")#進用通知
driver = webdriver.Chrome(ChromeDriverManager().install())#打開chrome瀏覽器
driver.get("https://www.google.com.tw/?hl=zh_TW")
q = driver.find_element(By.NAME,'q')
q.send_keys(keyword)
q.send_keys(Keys.ENTER)
soup = BeautifulSoup(driver.page_source)
a = soup.find_all("div", "hdtb-mitem")
c = a[1].find('a').get('href')
c = c.replace("_"," ")
driver.get("https://www.google.com"+c)
for x in range(1,20):#將網頁往下滑20次 載入更多數據
height = driver.execute_script("return document.documentElement.scrollHeight")
driver.execute_script("window.scrollTo(0, " + str(height) + ");")
time.sleep(0.1)
soup = BeautifulSoup(driver.page_source)
results = soup.find_all('img')
src = [result.get("src") for result in results]
return src
def download_picture(destination,good_or_bad_picture):
os.chdir(destination)
for i,url in enumerate(srcc):
if 'https:' in url:
response = requests.get(url)
print(i)
with open( good_or_bad_picture+ str(i) + ".jpg", "wb") as file: # 開啟資料夾及命名圖片檔
file.write(response.content)
def have_head_in_file(destination):
for i in os.listdir(destination):
path = destination+i
img = cv2.imread(path)
face_loc = face_recognition.face_locations(img)
if face_loc == []:
os.remove(path)
def clear_the_file(destination):
for i in os.listdir(destination):
os.remove(destination+i)
```
```python=
clear_the_file("C:/Users/bt/train/beautifulpeople/")
clear_the_file("C:/Users/bt/train/uglypeople/")
```
## 抓取好看的訓練集
```python=
a = search_picture("漂亮的人")
b = search_picture("明星")
c = search_picture("模特兒")
d = search_picture("handsome")
e = search_picture("beauty")
```
```python=
search = [a,b,c,d,e]
```
```python=
srcc = []
for i in range(len(search)):
for j in range(len(search[i])):
if search[i][j] != None and 'https:' in search[i][j] :
srcc.append(search[i][j])
```
```python=
download_picture("C:/Users/bt/train/beautifulpeople/",'good')
```
```python=
have_head_in_file('C:/Users/bt/train/beautifulpeople/')
```
## 抓取醜陋的訓練集
```python=
clear_the_file("C:/Users/bt/train/uglypeople/")
a = search_picture("醜人")
b = search_picture("醜男")
c = search_picture("醜女")
d = search_picture("ugly")
e = search_picture("ugly people")
f = search_picture("hideous")
```
```python=
search = [a,b,c,d,e,f]
```
```python=
srcc = []
for i in range(len(search)):
for j in range(len(search[i])):
if search[i][j] != None and 'https:' in search[i][j] :
srcc.append(search[i][j])
```
```python=
download_picture("C:/Users/bt/train/uglypeople/",'bad')
```
```python=
have_head_in_file('C:/Users/bt/train/uglypeople/')
```
## 分訓練集集測試集
```python=
import numpy as np
import os
import cv2
import tqdm
```
```python=
os.chdir('C:/Users/bt')
class_names = ['beautifulpeople','uglypeople']
class_names_label = {class_name:i for i, class_name in enumerate(class_names)}
nb_classes = len(class_names)
IMAGE_SIZE = (64,64)
```
```python=
def load_data():
datasets = ['train','test']#資料夾
output = []
for dataset in datasets:
images = []
labels = []
print("Loading {}".format(dataset))
for folder in os.listdir(dataset):
label = class_names_label[folder]
for file in os.listdir(os.path.join(dataset, folder)):
img_path = os.path.join(os.path.join(dataset, folder), file)
image = cv2.imread(img_path)
image = cv2.resize(image, IMAGE_SIZE)
images.append(image)
labels.append(label)
images = np.array(images, dtype = 'float32')
labels = np.array(labels, dtype = 'int32')
output.append((images, labels))
return output
```
```python=
(train_images, train_labels),(test_images , test_labels) = load_data()
```
```python=
train_images = train_images/255
```
## 建模
```python=
from keras.models import Sequential
from tensorflow.keras.layers import Conv2D, MaxPooling2D
from keras.layers import Dropout, Flatten
from keras.layers.core import Dense
input_shape = (64, 64, 3) #圖片格式
model = Sequential([
Conv2D(64, (3, 3), input_shape=input_shape, padding='same',#64神經元數目 3,3掃描器大小 padding:掃出來要跟原本一樣
activation='relu', strides=2),#激活函數, strides:每隔多少步掃描一次
MaxPooling2D(pool_size=(2, 2), strides=2),#池化曾:做特徵壓縮 (壓縮大小2*2,每隔多少步壓縮一次)
Dropout(0.2),#防止過度配適 把20%丟掉
#兩次卷基層 池畫曾
Conv2D(128, (3, 3), input_shape=input_shape, padding='same',
activation='relu', strides=2),
MaxPooling2D(pool_size=(2, 2), strides=2),
Dropout(0.2),
Flatten(),#把圖片攤平
Dropout(0.5),
Dense(2, activation='softmax') #輸出層,只有2個,分類用softmax
])
model.compile(optimizer = 'adam', #最佳化演算法 adam:動態 SGD(lr=0.1)
loss = 'sparse_categorical_crossentropy',#損失函數 :混淆矩陣
metrics=['accuracy'])#想看甚麼輸出 : 準確度
```
```python=
history = model.fit(train_images,train_labels,validation_split=0.2,batch_size=100,epochs=100,verbose=2)
```
```python=
from matplotlib import pyplot as plt
plt.title("train_accuracy")
plt.ylabel ('accuracy')
plt.xlabel('epoch')
plt.plot(history.history["accuracy"])
```

## 判斷
```python=
predictions = model.predict(test_images)
pred_labels = np.argmax(predictions, axis = 1)
```
```python=
from sklearn.metrics import confusion_matrix
CM = confusion_matrix( test_labels,pred_labels)#混淆矩陣 因為適分類的預測
def accuracy(confusion_matrix):
diagonal_sum = confusion_matrix.trace()#預測正確的
sum_of_all_elements = confusion_matrix.sum()#總預測數
return diagonal_sum/sum_of_all_elements
print(accuracy(CM))#預測效果
```
```
0.8865979381443299
```
```python=
from matplotlib import pyplot as plt
import seaborn as sn
ax =plt.axes()
sn.heatmap(CM,annot = True,#裡面數字是否呈現
annot_kws={"size":20},#裡面的數字
xticklabels = class_names,
yticklabels = class_names, ax =ax,
)
ax.set_title("confusion_matrix")
plt.show()
```

將模型存下來方便其他地使用
```python=
model.save('model_ok.h5')
```

# 製作視窗判斷好看否
利用pygame將視窗做出
```python=
import pygame
import random
import os
import re
from keras.models import load_model
import os
import cv2
import numpy as np
import time
model = load_model('model_ok.h5')
pygame.init()#遊戲初始化
WIDTH = 550
HIGHT = 600
screen = pygame.display.set_mode((WIDTH,HIGHT))#視窗大小 寬度500高度600
pygame.display.set_caption("MaJuGoDioaLaAhMaow")#更改視窗名字
clock = pygame.time.Clock()#可管理時間
input_adress = "beautyorugly"
things_in_file = os.listdir(input_adress)
background_img = pygame.image.load(os.path.join("beautyorugly",'白文章.jpg')).convert() #os.path 是檔案位置 一堆圖為資料夾名稱, 套套2.png為照片名稱 convert為將圖轉為pygame比較好讀的格式
background_img = pygame.transform.scale(background_img , (550, 600))
bg_color = (255,102,178)
font_name = pygame.font.match_font('DFKai-SB')
def draw_text(surf, text, size ,x,y,z,a,b):#畫東西的函示 (哪個平面, 內容,大小,x,y)
font = pygame.font.Font(font_name, size)
text_surface = font.render(text, True, (z,a,b))
text_rect = text_surface.get_rect()
text_rect.centerx = x
text_rect.top = y
surf.blit(text_surface, text_rect)
def draw_init():
screen.blit(background_img ,(0,0))
draw_text(screen, "MaJuGoDioaLaAhMaow",55,WIDTH/2,HIGHT/3,255,0,0)
draw_text(screen ,"一次最多只能判斷25張圖片",25,WIDTH/2,HIGHT/2,255,204,255)
draw_text(screen, "連按2次空白鍵開始執行...",25,WIDTH/2,HIGHT/2+60,255,204,255)
pygame.display.update()
watting = True
while watting:
clock.tick(FPS)#1秒鐘之內最多只能執行 FPS 次
for event in pygame.event.get():#全部事件列出來
if event.type == pygame.QUIT:#如果按x讓視窗關閉
pygame.quit()
return True
elif event.type == pygame.KEYUP:#按下鍵盤建 (KEYUP 是按下再拿起案件才開始)
watting = False
return False
def scan_files_picture():
c = []
for i in range(len(things_in_file)-1):
img_path = os.path.join("beautyorugly",things_in_file[i])
image = cv2.imread(img_path)
image = cv2.resize(image,(64,64) )
a = np.array(image,dtype = 'float32')
c.append(a)
c = np.array(c)
return c
def predictions_labels():
predictions = model.predict(scan_files_picture())
pred_labels = np.argmax(predictions, axis = 1)
return pred_labels
FPS = 60
show_init = True
running = True
while running:
if show_init:
draw_init()
show_init = False
clock.tick(FPS)#1秒鐘之內最多只能執行 FPS 次
for event in pygame.event.get():#全部事件列出來
if event.type == pygame.QUIT:#如果按x讓視窗關閉
running = False
elif event.type == pygame.KEYUP:
if event.key == pygame.K_SPACE:
screen.fill(bg_color)
pygame.display.update()
draw_text(screen,"你要判斷的圖片有:",55,WIDTH/2,10,0,0,0)
if len(things_in_file) < 10:
if len(things_in_file) % 2== 0:
for i in range(int(len(things_in_file))-1):
draw_text(screen,things_in_file[i],40,WIDTH/2, 40*i+40+HIGHT/len(things_in_file),0,0,0)
pygame.display.update()
if len(things_in_file) % 2!= 0:
for i in range(int(len(things_in_file))-1):
draw_text(screen,things_in_file[i],40,WIDTH/2, 40*i+40+HIGHT/len(things_in_file),0,0,0)
pygame.display.update()
draw_text(screen,"連按2次 '1' 繼續判斷",40,WIDTH/2, 40*(i+1)+40+HIGHT/len(things_in_file),255,204,250)
pygame.display.update()
if len(things_in_file) >= 10:
if len(things_in_file)%2 == 0 :
for i in range(int(len(things_in_file)/2)):
draw_text(screen,things_in_file[i],30,90, 40*i+40+HIGHT/len(things_in_file),0,0,0)
for j in range(int(len(things_in_file)/2)-1):
draw_text(screen,things_in_file[i+j+1],30,WIDTH/2+90, 40*(j)+40+HIGHT/len(things_in_file),0,0,0)
if len(things_in_file)%2 != 0 :
for i in range(int(len(things_in_file)/2)):
draw_text(screen,things_in_file[i],30,90, 40*i+40+HIGHT/len(things_in_file),0,0,0)
for j in range(int(len(things_in_file)/2)):
draw_text(screen,things_in_file[i+j+1],30,WIDTH/2+90, 40*(j)+40+HIGHT/len(things_in_file),0,0,0)
draw_text(screen,things_in_file[i+j+1],30,WIDTH/2+90, 40*(j+1)+40+HIGHT/len(things_in_file),0,0,0)
pygame.display.update()
draw_text(screen,"連按2次 '1' 繼續判斷",30,WIDTH/2, 40*(j+2)+40+HIGHT/len(things_in_file),255,204,250)
pygame.display.update()
if event.key == pygame.K_1:
pre_labels = predictions_labels()
for i in range(int(len(things_in_file))-1):
back_img = pygame.image.load(os.path.join("beautyorugly",things_in_file[i])).convert() #os.path 是檔案位置 一堆圖為資料夾名稱, 套套2.png為照片名稱 convert為將圖轉為pygame比較好讀的格式
back_img = pygame.transform.scale(back_img , (550, 600))
screen.blit(back_img,(0,0))
pygame.display.update()
time.sleep(0.5)
if pre_labels [i] ==0:
draw_text(screen,"這張圖...",50,WIDTH/2, HIGHT/2,255,128,0)
pygame.display.update()
time.sleep(1.5)
draw_text(screen,"很好看喔",50,WIDTH/2, HIGHT/2+50,255,128,0)
pygame.display.update()
if pre_labels [i] ==1:
draw_text(screen,"這張圖...",50,WIDTH/2,HIGHT/2,255,128,0)
pygame.display.update()
time.sleep(1.5)
draw_text(screen,"好醜喔",50,WIDTH/2,HIGHT/2+50,255,128,0)
pygame.display.update()
time.sleep(1.5)
draw_init()
pygame.QUIT
```
利用auto-py-to-exe將檔案打包後,將model_ok.h5以及資料夾"beautyorugly"(可以將想要判斷的圖片放進此資料夾)放入與exe同一個資料夾



自動往下繼續判斷

跑完後跳回
