[PYTHON] J'ai essayé de laisser AI juger la bonne épouse de la mariée qui est divisée en cinq parts égales

introduction

download.jpg

Il n'est pas exagéré de dire que la qualité du riz d'amour est déterminée par la fin. Et il y a beaucoup de fins différentes pour le riz d'amour. Harlem fin qui ne choisit pas une personne en particulier. Multi-end qui prépare la fin de chaque héroïne. Une fin individuelle qui ne se réalise qu'avec une personne spécifique. C'est une comédie d'amour où les fans se disputent toujours avec chaque fin, mais je pense que c'est la fin individuelle qui est la plus déroutante.

Parmi eux, le riz d'amour récent le plus confus à propos de la fin est, oui, "Bride of Five Equals" </ b>.

On dit que la fin de ce travail est la fin Yotsuba. Cependant, l'illusion de se terminer avec d'autres héroïnes doit être une sorte de plaisir du riz d'amour.

Dans cet article, après avoir appris les images de la première période d'animation, l'IA est faite pour juger la bonne épouse, et je réfléchis un peu à la possibilité de se terminer qui aurait pu être avec d'autres héroïnes.

Ce que tu as fait

La femme qui est apparue à la cérémonie de mariage de la première période de l'animation était considérée comme une épouse régulière et la femme régulière était jugée par la classification multi-classes des quintuplés et autres images. Keras est utilisé comme cadre d'apprentissage automatique. De plus, toutes les images d'apprentissage seront celles de la première période d'animation et les images à juger seront les suivantes.

0_5.png

Au fait, je pousse Sanku, alors j'espère que je vais faire de mon mieux et choisir Sanku.

environnement

Python : 3.9.0 conda version : 4.9.1 CPU : Intel(R) Core(TM)i5-6500 GPU : Intel(R) HD Graphics 530 keras : 2.3.1

Procédure de mise en œuvre

  1. Collection d'images
  2. Extraction d'images de visage
  3. Etiquetage
  4. Classification des données
  5. Remplissage des données li>
  6. Apprentissage du modèle
  7. Jugement positif de la femme

    1. Collection d'images

    Le premier est la collection d'images. Il semble que vous puissiez utiliser opencv pour capturer automatiquement une image en spécifiant une image d'une vidéo, mais comme il n'y avait pas de vidéo enregistrée, j'ai décidé de capturer l'animation cette fois. En guise de méthode, j'ai créé un programme qui capture toutes les 5 secondes tout en dégoulinant d'une période d'animation. Sélectionnez pyautogui comme module. Ce module est très utile car il automatise diverses autres opérations de l'interface graphique.

    capture.py

    
    
    import os
    import pyautogui
    import time
    
    start = time.time()
    
    for l in range(1,13):
        for i in range(275):
            im = pyautogui.screenshot('./capture_data/' + str(l) +'_'+ str(i) + '.png', region=(1050,50,800,450))
            time.sleep(5)
    
    end = time.time()
    print('result time is :', end - start)
    
    

    Dans mon cas, l'animation coulait sur l'écran supérieur droit du bureau divisé en quatre, il s'agit donc d'un programme qui capture region = (1050,50,800,450) et le coin supérieur droit du bureau. Un total de 3300 </ b> images ont été capturées sur une période d'environ 5 heures. L'image capturée ressemble à ceci.

    capture01.png

    Je ne peux toujours pas oublier l'ordre des plats de viande grillée sans viande grillée. À propos, lors de la capture à partir d'une vidéo en spécifiant une image, ce qui suit sera utile.

    Lors de la capture à partir d'une vidéo

    2. Extraction de l'image du visage

    Ensuite, l'image du visage est extraite de l'image capturée par opencv. En tant que classificateur en cascade pour les images de visage, nous avons utilisé ici, qui est célèbre pour les images d'anime. Copiez ce fichier xml dans votre répertoire de travail, détectez le visage de l'image capturée précédente, puis extrayez-le. De plus, pour faciliter l'utilisation de VGG16 comme modèle d'apprentissage en profondeur, le nombre de pixels est défini sur 64 x 64 pixels.

    face_cut.py

    
    
    import cv2
    
    def face_cut(img_path, save_path):
        img = cv2.imread(img_path)
        cascade = cv2.CascadeClassifier('lbpcascade_animeface.xml')![face_cut01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/208060/e1ce4d3c-113c-f329-ee3a-71a47e7a462c.png)
    
        facerect = cascade.detectMultiScale(img)
        for i, (x,y,w,h) in enumerate(facerect):
            face_img = img[y:y+h, x:x+w]
            face_img = cv2.resize(face_img, (64, 64))
            cv2.imwrite(save_path, face_img)
    
    for l in range(1,13):
        for i in range(275):
            face_cut('capture_data/'+str(l)+'_'+str(i)+'.png', 'cut_data/'+str(l)+'_'+str(i)+'.png')
    
    
    

    Les images extraites sont les suivantes. Il semble que même la tante du repas scolaire soit extraite pour le moment. Sur les 3300 images capturées, 1365 </ b> étaient des visages détectés. En d'autres termes, il était possible d'extraire le visage avec un peu plus de 1/3 du total.

    face_cut01.png

    3. Étiquetage

    Ici, 1365 feuilles sont triées manuellement dans les répertoires de chaque héroïne. Cela n'a pas pris beaucoup de temps s'il s'agissait d'environ 1365, mais lorsque le nombre d'images est de l'ordre de 10 000, cela semble peu probable.

    tesagyou.py

    
    
    #Fais de ton mieux! !! !!
    
    

    Les résultats du tri sont présentés dans le tableau ci-dessous.

    Classification Nombre de feuilles
    Ichihana 206
    Nino 168
    Sanku 152
    Yotsuba 172
    Mai 204
    Autre 463

    Ichihana a pris la tête avec 206 feuilles et May courait après une marge serrée. Il y a une différence de 54 entre le nombre maximum d'Ichihana et le nombre minimum de Sanku, et il peut être nécessaire de rendre le nombre de feuilles d'apprentissage le même si l'on doit s'attendre à la rigueur, mais cette fois cela n'a pas d'importance aussi rigueur, alors continuez comme il est Je le ferai.

    4. Classification des données

    Ici, l'image du visage précédente est convertie en pandas et étiquetée de 0 à 5. Le rapport entre le nombre de trains et les essais était de 8: 2.

    split.py

    
    
    # split.py
    
    import numpy as np
    import glob
    import cv2
    from keras.utils.np_utils import to_categorical
    import pandas as pd
    import matplotlib.pyplot as plt
    
    names = ['other', 'ichika', 'nino', 'miku', 'yotsuba', 'itsuki']
    img_list = []
    label_list = []
    
    # append index
    for index, name in enumerate(names):
        face_img = glob.glob('data/'+name+'/*.png')
        for face in face_img:
            # imread RGB
            a = cv2.imread(face, 1)
            b = np.expand_dims(a, axis=0)
            img_list.append(b)
            label_list.append(index)
    
    # convert pandas
    X_pd = pd.Series(img_list)
    y_pd = pd.Series(label_list)
    
    # merge
    Xy_pd = pd.concat([X_pd, y_pd], axis=1)
    # shuffle
    sf_Xy = Xy_pd.sample(frac=1)
    #Réacquérir en tant que liste après la lecture aléatoire
    img_list = sf_Xy[0].values
    label_list = sf_Xy[1].values
    #Tuple et combiner
    X = np.r_[tuple(img_list)]
    # convert binary
    Y = to_categorical(label_list)
    
    train_rate = 0.8
    
    train_n = int(len(X) * train_rate)
    train_X = X[:train_n]
    test_X = X[train_n:]
    train_y = Y[:train_n][:]
    test_y = Y[train_n:][:]
    
    

    5. Données gonflées

    Ensuite, je n'avais pas envie d'apprendre plus de 1000 feuilles, alors je n'ai rembourré que les images du train. En tant qu'éléments gonflés, une inversion gauche-droite, un flou et une conversion y ont été effectués, et l'image du train a été gonflée 2 ** 3 fois. Avec cela, le nombre total est d'environ 10 000.

    • Pour plus de commodité, les codes sont séparés, mais les codes 4 et 5 sont en fait un seul fichier.

    split.py

    
    
    ## define scratch_functions
    
    #Retourner horizontalement
    def flip(img):
        flip_img = cv2.flip(img, 1)
        return flip_img
    
    #Brouiller
    def blur(img):
        blur_img = cv2.GaussianBlur(img, (5,5), 0)
        return blur_img
    
    #conversion γ
    def gamma(img):
        gamma = 0.75
        LUT_G = np.arange(256, dtype = 'uint8')
        for i in range(256):
            LUT_G[i] = 255 * pow(float(i) / 255, 1.0 / gamma)
        gamma_img = cv2.LUT(img, LUT_G)
        return gamma_img
    
    total_img = []
    for x in train_X:
        imgs = [x]
        # concat list
        imgs.extend(list(map(flip, imgs)))
        imgs.extend(list(map(blur, imgs)))
        imgs.extend(list(map(gamma, imgs)))
        total_img.extend(imgs)
    
    # add dims to total_img
    img_expand = list(map(lambda x:np.expand_dims(x, axis=0), total_img))
    #Tuple et combiner
    train_X_scratch = np.r_[tuple(img_expand)]
    
    labels = []
    for label in range(len(train_y)):
        lbl = []
        for i in range(2**3):
            lbl.append(train_y[label, :])
        labels.extend(lbl)
    
    label_expand = list(map(lambda x:np.expand_dims(x, axis=0), labels))
    train_y_scratch = np.r_[tuple(label_expand)]
    
    

    6. Formation sur modèle

    Enfin, le modèle est entraîné à l'aide de l'image préparée. VGG16 a été choisi comme modèle pour l'apprentissage en profondeur, bien qu'il n'ait pas de signification particulière. Pour être honnête, il était surprenant qu'il ait fallu environ une demi-journée pour apprendre car le nombre d'époques était fixé à 100 et le GPU était tellement confus.

    model.py

    
    
    from keras.applications import VGG16
    from keras.models import Model, Sequential
    from keras.layers import Dense, Activation, Flatten, Input, Dropout
    from keras import optimizers
    import matplotlib.pyplot as plt
    from split import *
    
    # define input_tensor
    input_tensor = Input(shape=(64,64,3))
    vgg16 = VGG16(include_top=False, weights='imagenet', input_tensor=input_tensor)
    
    top_model = Sequential()
    top_model.add(Flatten(input_shape=vgg16.output_shape[1:]))
    top_model.add(Dense(64, activation='sigmoid'))
    top_model.add(Dropout(0.5))
    top_model.add(Dense(32, activation='sigmoid'))
    top_model.add(Dropout(0.5))
    top_model.add(Dense(6, activation='softmax'))
    
    model = Model(inputs=vgg16.input, outputs=top_model(vgg16.output))
    
    # vgg_model apply to 15layers
    for layer in model.layers[:15]:
        layer.trainable = False
    
    # compile
    model.compile(loss='categorical_crossentropy', optimizer=optimizers.SGD(lr=1e-4, momentum=0.9), metrics=['accuracy'])
    history = model.fit(train_X_scratch, train_y_scratch, epochs=100, batch_size=32, validation_data=(test_X, test_y))
    score = model.evaluate(test_X, test_y, verbose=0)
    print(score)
    
    # save model
    model.save('my_model.h5')
    
    # plot acc, val_acc
    plt.plot(history.history['acc'], label='acc', ls='-')
    plt.plot(history.history['val_acc'], label='val_acc', ls='-')
    plt.ylabel('accuracy')
    plt.xlabel('epoch')
    plt.legend(loc='best')
    plt.show()
    
    

    La précision n'est pas très bonne, mais un modèle de classification des cinq héroïnes a été élaboré.

    pic20.jpg

    7. Jugement de l'épouse positive

    Maintenant, c'est enfin le jugement tant attendu de la bonne épouse! (Il a fallu environ un jour pour arriver ici)

    Quelle était la femme positive jugée par AI? !! !!












    pic8.png

    «Celui qui a été choisi était Ichihana </ b>.

    Non, n'était-ce pas la longueur des cheveux? En termes de couleur, je pensais qu'il y aurait aussi un chan en mai. Pour Sanku, j'aurais dû synthétiser Sanku Hana ~, même des écouteurs qui ressemblent à Audio Tenika.

    Eh bien, dans la première période d'animation, il n'y avait presque pas de scènes où des héroïnes autres qu'Ichihana levaient les cheveux, il peut donc être raisonnable qu'Ichihana ait été choisie. Les yeux sont plus importants que les cheveux en tant que caractéristique qui détermine le visage humain, mais dans le cas des quintuplés, ce sont toutes des couleurs bleuâtres, donc elles étaient indiscernables. En conséquence, je sens qu'Ichihana a été choisie à cause de ses cheveux courts. La couleur des cheveux est comme celle de mai.

    prime

    Comme c'est un gros problème, j'ai également essayé de classer d'autres images.

    pic11.png C'est une scène du serment de la scène précédente. Cela a également été classé comme une fleur. Après tout, cela ressemble à un raccourci.

    pic26.jpg

    Eh bien, c'est aussi une fleur ~~

    Et enfin, la dernière scène de 8 épisodes. C'est une photo d'une fille dont Kazetaro est tombé amoureux il y a longtemps.

    pic27.png

    e! C'est aussi une fleur! ?? ?? Je pense que ma couleur de cheveux était comme une fleur cette fois, mais je pense qu'Ichihana est un peu trop forte ...

    Conclusion

    Donc, en termes d'IA, l'héroïne qui est sortie en tant que mariée au mariage et la fille qui l'aimait généralement sont généralement Ichihana-san </ b>. C'est ça. Quelque chose de désagréable sœur aînée attribut l'héroïne </ del> Une personne qui pousse Ichihana dit: "Non, vous voyez, c'est parce qu'Ichihana est une épouse positive en termes d'IA ..." Vous pourriez dire ça. Peut être.

    référence

    J'ai essayé de reconnaître l'animation "Keion!" Avec Keras Collectons des images de personnages d'anime à partir de vidéos avec opencv! Lbpcascade_animeface.xml pour la détection de visage d'anime par OpenCV

    Recommended Posts