[PYTHON] Une histoire que j'ai eu du mal en essayant de créer une "application qui convertit des images comme des peintures" avec la première application Web

introduction

Il s'agit d'une histoire dans laquelle l'auteur, qui a peu de connaissances sur les réseaux, a tenté de créer une application Web de traitement d'images comme première application Web et a eu du mal à gérer les images. Même si j'ai cherché sur le net, il y avait étonnamment peu d'articles sur ** application Web de traitement d'image utilisant Python, GCP, Flask **, donc ** j'ai eu du mal avec la procédure de création d'une application Web de traitement d'image ** qui fonctionne pour le moment. Je vais le présenter.

Produit fini

** 1. Ouvrez le site Web, sélectionnez l'image que vous souhaitez traiter et envoyez-la, ** image.png ** Image originale sélectionnée ** 処理前.jpg

** 2. Une image convertie comme une peinture sera renvoyée. ** ** 処理後.PNG

Application Web qui convertit des images telles que des peintures

Présentation de l'application Web

J'ai essayé de résumer le contour de l'application Web créée dans la figure. Cette fois, j'ai utilisé le cloud ** GCP ** de Google comme serveur Web dans le cadre du service gratuit. La partie de traitement d'image réelle a été créée en utilisant ** Python ** et l'apparence du site Web a été facilement créée en utilisant uniquement ** HTML **. Ensuite, j'ai créé le lien entre Python et HTML en utilisant ** Flask **, qui est une sorte d'API Python.

image.png

1. Construction de l'environnement GCE (Google Cloud Engine)

Tout d'abord, nous allons créer un environnement pour publier des applications Web à l'aide d'un service appelé GCE dans GCP. ** Un compte Google et une carte de crédit sont nécessaires pour utiliser GCP **, alors préparez-les. De plus, dans cet article, la ** connexion SSH de Google Chrome à GCE ** est utilisée pour contrôler à distance l'environnement virtuel dans le cloud. Pour utiliser le service GCE, vous devez effectuer les trois tâches suivantes, mais veuillez vous référer à l'article qui l'explique de manière facile à comprendre. Je me connecte à partir de la console Google Cloud Platform (le navigateur est Google Chrome), j'ai donc ignoré la partie clé d'authentification SSH de l'article. Des paramètres sont nécessaires si vous souhaitez établir une connexion SSH à partir du terminal Mac. [Article de référence] GCP (GCE) pour commencer à partir de maintenant, utilisez le cadre gratuit en toute sécurité

[Travail demandé] ・ Inscrivez-vous pour un essai gratuit de GCP ・ Création d'un projet -Création d'une instance de machine virtuelle

2. Comment démarrer Cloud Shell

Après avoir créé l'environnement GCE, ouvrez la page Instances (https://console.cloud.google.com/compute/instances) et cliquez sur Activer cloud shell en haut à droite pour lancer le terminal. .. ** Une fois le terminal démarré, vous pouvez utiliser l'instance GCE construite à l'aide des commandes Linux. ** À propos, selon le site officiel, Compute Engine se connecte automatiquement à l'instance de VM pour la première fois. Il semble qu'une paire de clés d'authentification SSH a été générée.

image.png

3. Comment transférer des données vers et depuis l'environnement local

Pour que GCE exécute les sites Web et le traitement d'images créés dans l'environnement local, il est nécessaire de partager les données dans l'environnement local avec GCE. Il y a un moyen de le dire de manière cool avec une commande, mais comme c'est difficile à configurer, j'ai choisi ** la méthode d'utilisation de Cloud Storage, qui est la plus simple à comprendre **. Dans l'onglet GCP, sélectionnez Strage → Navigateur. Après avoir créé un bucket avec un nom approprié dans le navigateur de stockage, téléchargez le fichier que vous souhaitez partager avec GCE localement. image.png

Et vous pouvez enregistrer les données enregistrées dans le stockage vers n'importe quel emplacement de GCE en exécutant le code suivant avec Cloud Shell. gsutil est une application fournie pour accéder à Cloud Storage depuis la ligne de commande.

gsutil cp -r gs://{Nom du bucket}/ ./{Nom du dossier GCE, etc.}

[Article de référence] [Gratuit] L'histoire du Temple de la renommée de Qiita [Facile]

4. Structure des fichiers de l'application Web (lors de l'utilisation de GCE / Python / Flask)

Lors de la création d'une application Web à l'aide de Python et Flask sur GCE, il est nécessaire de disposer de la structure de fichiers et de répertoires suivante. ** À l'inverse, vous pouvez enregistrer le programme créé avec la configuration suivante et exécuter certaines commandes sur GCP pour créer une application immédiatement. ** Si vous nommez chaque fichier et dossier autre que mon nom de dossier différemment de ce qui suit, une erreur se produira, vous devez donc faire attention.

le nom de mon dossier (tout nom est OK) /  ├ static/  ├ templates/  │  └ index.html  ├ app.yaml  ├ main.py  └ requirements.txt

Je décrirai brièvement chaque rôle.

5. Créez une application Web

Une fois la structure de fichiers ci-dessus créée sur GCE, il est facile de créer une application Web. Exécutez la commande suivante.

Pour déployer une application, vous devez d'abord créer l'application dans une région.

gcloud app create

Déployez l'application.

gcloud app deploy app.yaml --project {my project name}

Entrez le nom de votre projet dans la partie {mon nom de projet}. Je pense que c'est écrit dans Cloud Shell. Si vous copiez et collez le code source au chapitre 9 de cet article pour créer un fichier programme et que la structure des répertoires est identique au chapitre 4, cela fonctionnera. Si vous obtenez une erreur, vous pouvez vérifier le contenu du Tableau de bord App Engine.

6. Méthode de traitement d'image

J'ai adopté le ** filtre Kuwahara ** introduit dans l'article ci-dessous et utilisé le code tel quel. ** Il est étonnant que vous puissiez obtenir une image semblable à une peinture qui ressemble à un traitement d'image approfondi élaboré, même si elle peut être exprimée par une formule simple **. Je pense que c'est assez intéressant. Voir l'article ci-dessous pour plus de détails. Je suis tombé sur un filtre d'image avec un nom clairement japonais appelé filtre Kuwahara, et quand je l'ai essayé, c'était incroyable, alors je vais le présenter.

** L'image d'origine ** a.jpeg

** Après avoir appliqué le filtre ** b.jpe

7. Difficulté à passer des images de Python à HTML

J'ai eu du mal à passer l'image après traitement d'image en Python en HTML. Au début, j'enregistrais généralement l'image une fois dans un fichier statique, passais le chemin vers HTML et lisais l'image à partir de HTML. ** Cependant, lorsque l'application s'exécute dans l'environnement GCE, l'écriture à partir de Python dans le dossier semble être limitée, ce qui entraîne une erreur. ** Selon le site officiel, les quatre options suivantes sont recommandées pour enregistrer des données dans l'environnement d'exécution. Était là. · Cloud Firestore en mode Datastore ・ Cloud SQL pour MySQL ・ Cloud SQL pour PostgreSQL · Stockage en ligne

J'ai essayé Cloud Storage, qui semble pouvoir enregistrer des images, mais je n'ai pas pu le faire fonctionner correctement avec mes connaissances actuelles des réseaux. En outre, j'ai trouvé un article selon lequel les données peuvent être enregistrées avec tempfile, qui est une API Python, et je l'ai essayé, et j'ai pu enregistrer des données depuis Python, mais au contraire, je ne pouvais pas accéder à partir de HTML et il est resté bloqué. C'était.

Quand j'y pense, je n'ai pas besoin d'enregistrer l'image quelque part en premier lieu, j'ai donc cherché un moyen de transmettre les données d'image directement de Python vers HTML **. ** Il y avait une méthode d'encodage des données d'image avec base64 du côté Python, en le passant au HTML sous forme de chaîne de caractères, et en décodant la chaîne de caractères du côté HTML pour créer une image! ** Quand je l'ai essayé en référence à l'article ci-dessous, cela a fonctionné. Afficher le html des images générées à l'aide de l'oreiller sans enregistrer dans un fichier [Django]

8. Problèmes dus au manque de mémoire

** En essayant différentes images, il semble qu'une erreur se produise car la mémoire maximale (256 Mo) de la version gratuite GCE est dépassée en fonction de la taille de l'image (c'était inutile si elle était supérieure à 1000 x 600). ** Peut-être que je peux améliorer le programme et la structure des données sans mettre à niveau la machine, mais je ne l'ai pas encore fait. ** GCP offre un crédit gratuit de 300 USD pour la première année **, vous pouvez donc procéder à une mise à niveau et essayer. En passant, vous pouvez vérifier les détails de l'erreur à partir du tableau de bord App Engine dans l'onglet GCP. メモリ不足エラー.PNG

9. Code source

app.yaml


runtime: python37

main.py


#Chargez le module requis
#Flacon lié
from flask import Flask, render_template, request, redirect, url_for, abort
import base64
import tempfile
from PIL import Image
import io
import numpy as np
import cv2

app = Flask(__name__)

def kuwahara(pic,r=5,resize=False,rate=0.5): #Image originale, un côté d'une zone carrée, rapport lors du redimensionnement ou du redimensionnement
    h,w,_=pic.shape
    if resize:pic=cv2.resize(pic,(int(w*rate),int(h*rate)));h,w,_=pic.shape
    pic=np.pad(pic,((r,r),(r,r),(0,0)),"edge")
    ave,var=cv2.integral2(pic)
    ave=(ave[:-r-1,:-r-1]+ave[r+1:,r+1:]-ave[r+1:,:-r-1]-ave[:-r-1,r+1:])/(r+1)**2 #Calcul par lots de la valeur moyenne
    var=((var[:-r-1,:-r-1]+var[r+1:,r+1:]-var[r+1:,:-r-1]-var[:-r-1,r+1:])/(r+1)**2-ave**2).sum(axis=2) #Calcul global de la distribution
    
    def filt(i,j):
        return np.array([ave[i,j],ave[i+r,j],ave[i,j+r],ave[i+r,j+r]])[(np.array([var[i,j],var[i+r,j],var[i,j+r],var[i+r,j+r]]).argmin(axis=0).flatten(),j.flatten(),i.flatten())].reshape(w,h,_).transpose(1,0,2)
    filtered_pic = filt(*np.meshgrid(np.arange(h),np.arange(w))).astype(pic.dtype) #Détermination de la couleur
    return filtered_pic
    
@app.route("/", methods=["GET", "POST"])
def upload_file():
    if request.method == "GET":
        return render_template("index.html")
    if request.method == "POST":
        #Enregistrez le fichier téléchargé une fois
        f = request.files["file"]
        filepath = tempfile.mkdtemp()+"/a.png "
        #filepath = "{}/".format(tempfile.gettempdir()) + datetime.now().strftime("%Y%m%d%H%M%S") + ".png "
        
        f.save(filepath)
        image = Image.open(filepath)
        
        #Partie de traitement d'image
        image = np.asarray(image)
        filtered = kuwahara(image, r=7)        
        filtered = Image.fromarray(filtered)
        
        #Encodé avec base64
        buffer = io.BytesIO()
        filtered.save(buffer, format="PNG")
        img_string = base64.b64encode(buffer.getvalue()).decode().replace("'", "")
        
        result = "image size {}×{}".format(len(image[0]), len(image))
        return render_template("index.html", filepath=filepath, result=result, img_data=img_string)
    
    
if __name__ == "__main__":
     app.run(host="127.0.0.1", port=8080, debug=True)

L'article suivant a été utilisé comme référence lors de l'écriture du code Flask. Python x Flask x PyTorch Easy Construction of Number Recognition Web App

requirements.txt


Flask==1.1.2
Pillow==7.2.0
Numpy==1.16.4
opencv-python==4.2.0.34

index.html


<html>
    <body>
        {% if result %}
	<IMG SRC="data:image/png;base64,{{img_data}}" alt="img_data"  id="imgslot"/>
        <div>{{result}}</div>
	<HR>
        {% endif %}
Veuillez sélectionner un fichier et envoyer<BR>
        <form action = "./" method = "POST" 
           enctype = "multipart/form-data">
           <input type = "file" name = "file" />
           <input type = "submit"/>
        </form>
     </body>
</html>

10. Enfin

Merci d'avoir lu l'article jusqu'à la fin. Créer une application Web n'a pas été simple, mais j'ai réussi à créer quelque chose qui fonctionne. ** LGTM sera l'une des motivations pour écrire des articles, alors merci. ** **

Recommended Posts

Une histoire que j'ai eu du mal en essayant de créer une "application qui convertit des images comme des peintures" avec la première application Web
L'histoire qui n'avait rien à voir avec la partition lorsque j'ai fait une sauvegarde de disque avec dd pour la première fois
Notez que j'étais accro à accéder à la base de données avec mysql.connector de Python en utilisant une application Web
Une histoire que j'ai eu du mal à afficher des graphiques les uns sur les autres avec matplotlib
J'ai créé une application Web en Python qui convertit Markdown en HTML
Avec LINEBot, j'ai fait une application qui m'informe de "l'heure du bus"
L'histoire de la création d'une application Web qui enregistre des lectures approfondies avec Django
Je souhaite créer une application WEB en utilisant les données de League of Legends ①
Créez une application Web qui convertit le PDF en texte à l'aide de Flask et PyPDF2
Je souhaite créer une API qui retourne un modèle avec une relation récursive dans Django REST Framework
(Remarque) Une application Web qui utilise TensorFlow pour déduire les noms de morceaux recommandés [Créer un environnement d'exécution avec docker-compose]
Une histoire qui a échoué lors de la tentative de suppression du suffixe d'une chaîne avec rstrip
Je voulais créer une dll pour utiliser une fonction écrite en C à partir de Python dans ctypes, mais j'ai eu du mal
J'ai eu du mal à essayer d'accéder à Hadoop3.0.0 depuis un navigateur (et ArchLinux)
J'ai joué avec des GAN simples (SinGAN) (+ j'ai également résumé les points que j'ai eu du mal à mettre en œuvre (via le chemin, la commande Linux, l'utilisation de googlecolab, etc.))
Je souhaite créer une base de données de déjeuners [EP1] Django pour la première fois
Je souhaite créer une base de données de déjeuner [EP1-4] Django pour la première fois
Une histoire dont je voulais afficher le résultat de la division (%) sur HTML avec une application utilisant django [Débutant apprend python avec un livre de référence dans une main]
Une histoire à laquelle j'ai pensé en essayant d'identifier les informations de plénitude du parking en utilisant l'image obtenue par la caméra Web et Razpai et le deep learning.
Créez une application Web qui reconnaît les nombres avec un réseau neuronal
La première étape de la création d'une application sans serveur avec Zappa
Créez une API Web capable de fournir des images avec Django
Je veux créer un Dockerfile pour le moment.
J'ai essayé de créer un traitement par lots sans serveur pour la première fois avec DynamoDB et Step Functions
Une histoire qui n'a pas fonctionné lorsque j'ai essayé de me connecter avec le module de requêtes Python
J'ai créé une application Web qui trace le journal de vie enregistré sur Google Home comme un diagramme de Gantt.
Créez un BOT qui peut appeler des images enregistrées avec Discord comme des pictogrammes
J'ai eu du mal avec l'erreur d'importation: le chargement de la DLL a échoué dans tensorflow 2.0
Créez une application Web qui peut être facilement visualisée avec Plotly Dash
Une histoire à laquelle j'étais accro à essayer d'obtenir une URL de vidéo avec tweepy
L'histoire du développement d'une application WEB qui génère automatiquement des copies de capture [MeCab]
Jouez comme une application Web avec ipywidgets
Créez une application Web simple avec Flask
J'ai fait une application WEB avec Django
Créons une application Web de conversion A vers B avec Flask! De zéro ...
L'histoire de l'adresse IPv6 que je souhaite conserver au minimum
[kotlin] Créez une application qui reconnaît les photos prises avec un appareil photo sur Android
J'ai créé une commande appdo pour exécuter des commandes dans le contexte de l'application
Créez une application qui fonctionne bien avec les rapports des utilisateurs à l'aide de l'API COTOHA
Une histoire à laquelle j'étais accro après la communication SFTP avec python
J'ai essayé de créer un modèle avec l'exemple d'Amazon SageMaker Autopilot
Créez une application qui devine les étudiants avec Python
Procédure de création d'application multi-plateforme avec kivy
J'ai créé une application Twitter qui décrypte les caractères de pré-connexion avec heroku (échec)
Une histoire qui nécessitait des préparatifs pour essayer de faire un tutoriel Django avec des centos simples
J'ai essayé de faire quelque chose comme un chatbot avec le modèle Seq2Seq de TensorFlow
Une histoire bloquée lors de la tentative de mise à niveau de la version Python avec GCE
Je ne trouve pas l'horloge tsc! ?? L'histoire d'essayer d'écrire un patch de noyau
Création d'une application Web qui mappe les informations sur les événements informatiques avec Vue et Flask
Essayez de créer une forme d'onde (spectre audio) qui se déplace en fonction du son avec python
Utilisez l'API Twitter pour réduire le temps nécessaire à Twitter (créer une chronologie de mise en évidence (comme))
Lors de l'écriture dans un fichier csv avec python, une histoire que j'ai fait une légère erreur et n'a pas respecté la date de livraison
J'ai créé un programme en Python qui change les données de 1 minute de FX en une heure arbitraire (1 heure, etc.)
Une histoire que je voulais faire une fonction comme before_action utilisée dans les rails avec django [Débutant apprend python avec un livre de référence]
Une histoire que je ne savais pas charger de mixin lors de la création d'une façade avec l'application django [Débutant apprend python avec un livre de référence]