# 自製判斷好看醜陋演算法 並利用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"]) ``` ![](https://i.imgur.com/M0LC1jo.png) ## 判斷 ```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() ``` ![](https://i.imgur.com/phtkQ8j.png) 將模型存下來方便其他地使用 ```python= model.save('model_ok.h5') ``` ![](https://i.imgur.com/lkfLtCi.png) # 製作視窗判斷好看否 利用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同一個資料夾 ![](https://i.imgur.com/zGwlgnl.png) ![](https://i.imgur.com/ySoxOJm.png) ![](https://i.imgur.com/EnmslgW.png) 自動往下繼續判斷 ![](https://i.imgur.com/9oSFHWM.png) 跑完後跳回 ![](https://i.imgur.com/zGwlgnl.png)