Table des matières:

Planétarium alimenté par un réseau de neurones utilisant Python, Electron et Keras : 8 étapes
Planétarium alimenté par un réseau de neurones utilisant Python, Electron et Keras : 8 étapes

Vidéo: Planétarium alimenté par un réseau de neurones utilisant Python, Electron et Keras : 8 étapes

Vidéo: Planétarium alimenté par un réseau de neurones utilisant Python, Electron et Keras : 8 étapes
Vidéo: Intelligence Artificielle [12.13] : Apprentissage automatique - exemple de réseau de neurones 2024, Juillet
Anonim
Planétarium alimenté par un réseau de neurones utilisant Python, Electron et Keras
Planétarium alimenté par un réseau de neurones utilisant Python, Electron et Keras

Dans ce instructable, je vais vous montrer comment j'ai écrit un générateur de planétarium 3D automatique, à l'aide de Python et Electron

La vidéo ci-dessus montre l'un des planétariums aléatoires générés par le programme.

**Remarque: ce programme n'est en aucun cas parfait, et à certains endroits pas très pythonique. Le discriminateur de réseau neuronal n'est précis qu'à environ 89 %, donc certaines images étranges seront intégrées au planétarium**

Détails

Le planétarium interroge une API de la NASA pour les images liées à l'espace et utilise un réseau de neurones convolutifs pour déterminer si l'image est adaptée au traitement. Le programme utilise ensuite OpenCV pour supprimer l'arrière-plan de l'image, et enfin les images sont assemblées en une grande image équirectangulaire. Cette image est ensuite enregistrée et une application Electron Node.js ouvre l'image et utilise le package PhotoSphere.js pour afficher l'image dans un format 3D de style planétarium.

Dépendances

Python:

  • Keras
  • Oreiller
  • cv2
  • Numpy
  • Demandes
  • urllib
  • Aléatoire
  • temps
  • io

Électron:

Photosphère

Étape 1: Configuration de votre environnement

Installer Electron et Python

Tout d'abord, assurez-vous que node.js et npm sont installés (sinon, vous pouvez télécharger ici)

Ensuite, vous devez installer Electron. Ouvrez une invite de commande et entrez la commande suivante:

npm installer l'électron -g

Ensuite, vous avez besoin de python, qui peut être téléchargé ici

Configuration d'un environnement virtuel

Ouvrez une invite de commande, puis saisissez les commandes suivantes pour configurer votre environnement virtuel:

pip installer virtualenv

espace virtuel

espace disque

scripts\activer

Installation des dépendances Python

Exécutez ces commandes dans l'invite de commande pour installer vos dépendances python:

pip installer keras

pip installer oreiller

pip installer numpy

demandes d'installation de pip

pip installer opencv-pythonSi vous souhaitez former le réseau vous-même, assurez-vous de configurer l'accélération GPU pour Keras

Étape 2: Interroger l'API de recherche de la NASA

Aperçu

La NASA a beaucoup d'API vraiment utiles que vous pouvez utiliser avec vos projets. Pour ce projet, nous utiliserons l'API de recherche, qui nous permet de rechercher dans la base de données d'images de la NASA des images liées à l'espace.

Le code

Tout d'abord, nous devons définir une fonction python pour accepter un argument qui servira de terme de recherche:

def get_image_search(phrase):

passe

Ensuite, nous allons convertir le terme de recherche au format URL, puis utiliser la bibliothèque de requêtes pour interroger l'API:

def get_image_search(phrase):

params = {"q": urllib.parse.quote(arg), "media_type": "image"} résultats = request.get("https://images-api.nasa.gov/search", params=params)

Enfin, nous allons décoder la chaîne collection+JSON que l'API nous a renvoyée, et extraire une liste de liens vers des images liées au terme de recherche:

def get_image_search(phrase):

params = {"q": urllib.parse.quote(arg), "media_type": "image"} resultats = request.get("https://images-api.nasa.gov/search", params=params) data = [result['href'] pour le résultat dans results.json()["collection"]["items"]

C'est parti ! Nous avons maintenant un extrait de code qui peut interroger l'API de recherche d'images de la NASA et renvoyer une liste de liens vers des images liées à notre terme de recherche.

Étape 3: Le réseau de neurones convolutifs

Aperçu

Le travail du réseau de neurones est de classer si une image est de quelque chose dans l'espace, ou si ce n'est pas le cas. Pour ce faire, nous utiliserons un réseau de neurones convolutifs, ou CNN, pour effectuer une série d'opérations matricielles sur l'image et déterminer son espace-y. Je ne vais pas tout expliquer, car il y a beaucoup de théorie derrière, mais si vous voulez en savoir plus sur les réseaux de neurones, je suggère "Machine Learning Mastery"

Le code

Tout d'abord, nous devons importer nos dépendances:

importer le système d'exploitation

#Correction du problème pendant le train stepn on GPU os.environ['CUDA_VISIBLE_DEVICES'] = '' import tensorflow as tf if tf.test.gpu_device_name(): print('GPU found') else: print("No GPU found") de keras.preprocessing.image importer ImageDataGenerator de keras.preprocessing importer l'image de keras.models importer Sequential de keras.layers importer Conv2D, MaxPooling2D de keras.layers importer Activation, Dropout, Flatten, Dense de keras importer le backend en tant que K de PIL importer l'image importer numpy en tant que np

Ensuite, nous devons définir notre modèle:

largeur_img, hauteur_img = 1000, 500

train_data_dir = 'v_data/train' validation_data_dir = 'v_data/test' nb_train_samples = 203 nb_validation_samples = 203 epochs = 10 batch_size = 8 if K.image_data_format() == 'channels_first': input_shape = (3, img_height, else) = (img_width, img_height, 3) model = Sequential() model.add(Conv2D(32, (2, 2), input_shape=input_shape)) model.add(Activation('relu')) model.add(MaxPooling2D(pool_size =(2, 2))) model.add(Conv2D(32, (2, 2))) model.add(Activation('relu')) model.add(MaxPooling2D(pool_size=(2, 2))) modèle.add(Conv2D(64, (2, 2))) model.add(Activation('relu')) model.add(MaxPooling2D(pool_size=(2, 2))) model.add(Flatten()) modèle. add(Dense(64)) model.add(Activation('relu')) model.add(Dropout(0.5)) model.add(Dense(1)) model.add(Activation('sigmoid')) model.compile (loss='binary_crossentropy', optimiseur='rmsprop', metrics=['accuracy'])

J'ai entraîné le modèle pour vous, mais si vous souhaitez entraîner le modèle vous-même, sur votre propre ensemble de données, j'ai joint le code d'entraînement. Sinon, vous pouvez télécharger le fichier HDF5 du modèle entraîné. En raison des restrictions de fichier Instructables, j'ai dû le renommer avec une extension ".txt". Pour l'utiliser, renommez le fichier en une extension ".h5", et chargez-le avec ce code:

model.load_weights("model_saved.h5")

Pour utiliser le réseau pour prédire l'espace-y d'une image, nous allons définir cette fonction:

def prédire (image_path):

img = image.load_img(image_path, target_size=(1000, 500)) img = np.expand_dims(img, axis=0) result=model.predict_classes(img) return result[0][0]

Étape 4: traitement de l'image

Aperçu

Pour le traitement d'image, j'utilise la bibliothèque OpenCV (cv2). Tout d'abord, nous allons brouiller les bords de l'image, puis nous supprimerons l'arrière-plan en créant un masque et en modifiant les valeurs alpha des couleurs les plus sombres

Le code

C'est la partie de la fonction qui brouille les contours:

def processImage(img):

RADIUS = 20 # Ouvrir une image im = Image.open("pilbuffer.png") # Coller l'image sur fond blanc diam = 2 * RADIUS back = Image.new('RGB', (im.size[0] + diam, im.size[1] + diam), (0, 0, 0)) back.paste(im, (RADIUS, RADIUS)) # Créer un masque de flou mask = Image.new('L', (im.size[0] + diam, im.size[1] + diam), 255) blck = Image.new('L', (im.size[0] - diam, im.size[1] - diam), 0) masque. paste(blck, (diam, diam)) # Flou l'image et colle le bord flou selon le masque blur = back.filter(ImageFilter. GaussianBlur(RADIUS / 2)) back.paste(blur, mask=mask) back.save(" transition.png") back.close()

Ensuite, nous allons définir les couleurs les plus sombres sur transparentes et enregistrer l'image temporairement:

#Créer un masque et un filtre remplacer le noir par alpha

image = cv2.imread("transition.png") hMin = 0 sMin = 0 vMin = 20 hMax = 180 sMax = 255 vMax = 255 inférieur = np.array([hMin, sMin, vMin]) supérieur = np.array([hMax, sMax, vMax]) hsv = cv2.cvtColor(image, cv2. COLOR_BGR2HSV) mask = cv2.inRange(hsv, lower, upper) output = cv2.bitwise_and(image, image, mask=mask) *_, alpha = cv2.split(output) dst = cv2.merge((output, alpha)) output = dst avec open("buffer.png", "w+") comme fichier: pass cv2.imwrite("buffer.png", sortie)

Étape 5: Assemblage d'images dans une projection équirectangulaire

Aperçu

Cette fonction prend plusieurs images et les assemble dans un format pouvant être interprété par le package PhotoSphere.js, en utilisant la bibliothèque PIL (oreiller)

Le code

Tout d'abord, nous devons créer une image qui peut servir d'hôte pour les autres images:

nouveau = Image.nouveau("RVBA", (8000, 4000), couleur=(0, 0, 0))

Ensuite, nous devons parcourir le tableau d'images (qui ont toutes été redimensionnées à 1000x500) et les placer dans l'image:

h = 0

w = 0 i = 0 pour img dans img_arr: new.paste(img, (w, h), img) w += 1000 si w == 8000: h += 500 w = 0 i += 1

Maintenant, nous enveloppons simplement cela dans une fonction qui prend un tableau d'images comme argument et renvoie la nouvelle image:

def stitch_beta(img_arr):

new = Image.new("RGBA", (8000, 4000), color=(0, 0, 0)) h = 0 w = 0 i = 0 pour img dans img_arr: new.paste(img, (w, h), img) w += 1000 if w == 8000: h += 500 w = 0 i += 1 return new

Étape 6: le script Python complet

Il s'agit du script complet du réseau de neurones python, qui est enregistré sous net.py et importé dans le script principal:

# importation de bibliothèques

import os #Fix for issue during train stepn on GPU os.environ['CUDA_VISIBLE_DEVICES'] = '' import tensorflow as tf if tf.test.gpu_device_name(): print('GPU found') else: print("Aucun GPU trouvé ") de keras.preprocessing.image importer ImageDataGenerator de keras.preprocessing importer une image de keras.models importer Sequential de keras.layers importer Conv2D, MaxPooling2D de keras.layers importer Activation, Dropout, Flatten, Dense de keras importer le backend en tant que K de PIL import Image import numpy as np img_width, img_height = 1000, 500 train_data_dir = 'v_data/train' validation_data_dir = 'v_data/test' nb_train_samples = 203 nb_validation_samples = 203 epochs = 10 batch_size = 8 if K.image_data'_formats (): input_shape = (3, img_width, img_height) else: input_shape = (img_width, img_height, 3) model = Sequential() model.add(Conv2D(32, (2, 2), input_shape=input_shape)) model.add(Activation ('relu')) model.add(MaxPooling2D(pool_size=(2, 2))) model.add(Conv2D(32, (2, 2))) modèle. add(Activation('relu')) model.add(MaxPooling2D(pool_size=(2, 2))) model.add(Conv2D(64, (2, 2))) model.add(Activation('relu')) model.add(MaxPooling2D(pool_size=(2, 2))) model.add(Flatten()) model.add(Dense(64)) model.add(Activation('relu')) model.add(Dropout(0.5)) model.add(Dense(1)) model.add(Activation('sigmoid')) model.compile(loss='binary_crossentropy', Optimizer='rmsprop', metrics=['accuracy']) model.load_weights("model_saved.h5") def predict(image_path): img = image.load_img(image_path, target_size=(1000, 500)) img = np.expand_dims(img, axis=0) result=model.predict_classes(img) renvoie le résultat [0][0]

Voici le fichier python principal, api.py:

demandes d'importation, sys, aléatoire, urllib.parse, cv2

de PIL importer Image, ImageFilter de io import BytesIO import numpy as np import net def get_image_search(num, phrase): count = 0 img_arr = for arg in phrase: print(arg) print(f"Current image count: {count }") i = 0 params = {"q": urllib.parse.quote(arg), "media_type": "image"} resultats = request.get("https://images-api.nasa.gov/search ", params=params) data = [result['href'] pour le résultat dans results.json()["collection"]["items"] print(len(data)) if num > len(data): num = len(données) pendant le compte = num: break print(f"\n{count} images récupérées") return img_arr def stitch_beta(img_arr): new = Image.new("RGBA", (8000, 4000), color=(0, 0, 0)) h = 0 w = 0 i = 0 pour img dans img_arr: #pbar.set_description(f"Traitement de l'image {i+1}") new.paste(img, (w, h), img) w += 1000 si w == 8000: h += 500 w = 0 i += 1 return new def processImage(img): RADIUS = 20 # Ouvrir une image im = Image.open("pilbuffer.png") # Coller l'image sur fond blanc diam = 2 * RADIUS back = Image.new('RGB', (im.size[0] + diam, im.size[1] + diam), (0, 0, 0)) back.paste(im, (RADIUS, RADIUS)) # Créer un masque de flou mask = Image.new('L', (im.size[0] + diam, im.size[1] + diam), 255) blck = Image.new('L', (im.size[0] - diam, im.size[1] - diam), 0) mask.paste(blck, (diam, diam)) # Flou l'image et colle le bord flou selon le masque blur = back.filter(ImageFilter. GaussianBlur(RADIUS / 2)) back.paste(blur, mask=mask) back.save("transition.png") back.close() #Créer un masque et un filtre remplacer le noir par une image alpha = cv2.imread(" transit ion.png") hMin = 0 sMin = 0 vMin = 20 hMax = 180 sMax = 255 vMax = 255 inférieur = np.array([hMin, sMin, vMin]) supérieur = np.array([hMax, sMax, vMax]) hsv = cv2.cvtColor(image, cv2. COLOR_BGR2HSV) mask = cv2.inRange(hsv, lower, upper) output = cv2.bitwise_and(image, image, mask=mask) *_, alpha = cv2.split(output) dst = cv2.merge((output, alpha)) output = dst avec open("buffer.png", "w+") comme fichier: passez cv2.imwrite("buffer.png", sortie) #Détection des contours et flou si _name_ == "_main_": search_terms = ["supernova", "planète", "galaxie", "voie lactée", "nébuleuse", "étoiles"] #Les termes de recherche peuvent être modifiés selon ce que vous voulez que le planétarium inclue img_arr = get_image_search(64, search_terms) print("Images récupérées et filtrées par les neurones") img = stitch_beta(img_arr) print("Images assemblées") img.save("stitched.png")

Étape 7: L'application Electron

Aperçu

Nous allons créer une application électronique simple qui positionne et charge simplement l'élément PhotoSphere. Les fichiers main.js et package.json proviennent directement du site Web d'Electron et le code HTML est une version légèrement modifiée du code HTML fourni sur le site Web de PhotoSphere. J'ai inclus les fichiers, mais j'ai tout renommé en.txt, car Instructables n'autorise pas ces types de fichiers. Pour utiliser les fichiers, renommez-les avec l'extension appropriée.

Le code

main.js

const { app, BrowserWindow } = require('electron')

function createWindow () { const win = new BrowserWindow({ width: 800, height: 600, webPreferences: { nodeIntegration: true } }) win.loadFile('index.html') } app.whenReady().then(createWindow) app.on('window-all-closed', () => { if (process.platform !== 'darwin') { app.quit() } }) app.on('activate', () => { if (BrowserWindow.getAllWindows().length === 0) { createWindow() } })

package.json

{

"name": "space", "version": "0.1.0", "main": "main.js", "scripts": { "start": "electron." } }

index.html

Étape 8: Exécution

Création de l'image équirectangulaire

Pour créer l'image, exécutez le script api.py dans l'invite de commande, avec son environnement virtuel activé:

api.py

Une fois l'exécution des scripts terminée, exécutez l'application electron en utilisant:

début npmVoila ! Votre planétarium est actif ! Merci d'avoir lu:)

Conseillé: