Taula de continguts:

Planetari amb xarxa neuronal que utilitza Python, Electron i Keras: 8 passos
Planetari amb xarxa neuronal que utilitza Python, Electron i Keras: 8 passos

Vídeo: Planetari amb xarxa neuronal que utilitza Python, Electron i Keras: 8 passos

Vídeo: Planetari amb xarxa neuronal que utilitza Python, Electron i Keras: 8 passos
Vídeo: Обучение Paddle OCR на пользовательском наборе данных | YOLOv7 + OCR на Google Colab 2023 2024, Desembre
Anonim
Planetari amb xarxa neuronal que utilitza Python, Electron i Keras
Planetari amb xarxa neuronal que utilitza Python, Electron i Keras

En aquest instructiu, us mostraré com vaig escriure un generador automàtic de planetari 3D, utilitzant Python i Electron

El vídeo anterior mostra un dels planetaris aleatoris que ha generat el programa.

** Nota: aquest programa no és en cap cas perfecte i, en alguns llocs, no és gaire pitònic. El discriminador de xarxes neuronals només té un ~ 89% de precisió, de manera que algunes imatges estranyes arribaran al planetari **

Especificitats

El planetari consulta una API de la NASA per obtenir imatges relacionades amb l’espai i utilitza una xarxa neuronal convolucional per determinar si la imatge és adequada per al processament. A continuació, el programa utilitza OpenCV per eliminar el fons de la imatge i, finalment, les imatges s’uneixen en una gran imatge equirectangular. Aquesta imatge es desa i una aplicació Electron Node.js obre la imatge i utilitza el paquet PhotoSphere.js per veure la imatge en un format 3D d’estil planetari.

Dependències

Python:

  • Keras
  • Coixí
  • cv2
  • Gronxador
  • Sol·licituds
  • urllib
  • Aleatori
  • temps
  • io

Electró:

PhotoSphere

Pas 1: configuració del vostre entorn

Instal·lació d’Electron i Python

Primer, assegureu-vos que teniu instal·lats node.js i npm (si no, podeu descarregar-lo aquí)

A continuació, heu d’instal·lar Electron. Obriu un indicador d’ordres i introduïu l’ordre següent:

npm instal·lar electron -g

A continuació, necessiteu python, que es pot descarregar aquí

Configuració d’un entorn virtual

Obriu un indicador d’ordres i, a continuació, introduïu les ordres següents per configurar l’entorn virtual:

pip instal·lar virtualenv

espai virtualenv

espai cd

scripts / activate

Instal·lació de dependències de Python

Executeu aquestes ordres a l'indicador d'ordres per instal·lar les vostres dependències de python:

pip instal·lar keras

pip instal·lar coixí

pip instal·lar numpy

peticions d'instal·lació de pip

instal·lar pip opencv-pythonSi voleu entrenar la xarxa vosaltres mateixos, assegureu-vos de configurar l’acceleració de la GPU per a Keras

Pas 2: consulta de l'API de cerca de la NASA

Visió general

La NASA té moltes API realment útils que podeu utilitzar amb els vostres projectes. Per a aquest projecte, utilitzarem l'API de cerca, que ens permet buscar imatges relacionades amb l'espai a la base de dades d'imatges de la NASA.

El codi

En primer lloc, hem de definir una funció python per acceptar un argument que actuï com a terme de cerca:

def get_image_search (frase):

passar

A continuació, convertirem el terme de cerca al format d'URL i, a continuació, utilitzarem la biblioteca de sol·licituds per consultar l'API:

def get_image_search (frase):

params = {"q": urllib.parse.quote (arg), "media_type": "imatge"} resultats = requests.get ("https://images-api.nasa.gov/search", params = params)

Finalment, descodificarem la col·lecció + cadena JSON que ens ha retornat l'API i extreurem una llista d'enllaços a imatges relacionades amb el terme de cerca:

def get_image_search (frase):

params = {"q": urllib.parse.quote (arg), "media_type": "imatge"} resultats = requests.get ("https://images-api.nasa.gov/search", params = params) dades = [resultat ['href'] per al resultat result.json () ["col·lecció"] ["elements"]

Allà anem! Ara tenim un fragment de codi que pot consultar l'API de cerca d'imatges de la NASA i retornar una llista d'enllaços a imatges relacionades amb el nostre terme de cerca.

Pas 3: la xarxa neuronal convolucional

Visió general

La feina de la xarxa neuronal és classificar si una imatge és d’alguna cosa a l’espai o si no. Per fer-ho, utilitzarem una xarxa neuronal convolucional, o CNN, per realitzar una sèrie d'operacions matricials a la imatge i determinar com és l'espai-y. No ho explicaré tot, perquè hi ha molta teoria al darrere, però si voleu conèixer les xarxes neuronals, us suggereixo "Domini d'aprenentatge automàtic".

El codi

En primer lloc, hem d’importar les nostres dependències:

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 ("No s'ha trobat cap GPU") d'importació keras.preprocessing.image ImageDataGenerator d'importació d'imatges keras.preprocessing d'importació keras.models Seqüencial d'importació keras.layers Conv2D, MaxPooling2D d'importació keras.layers Activació, abandonament, aplanament, densitat del backend d'importació keras com a K d'importació PIL importar numpy com a np

A continuació, hem de definir el nostre model:

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 èpoques = 10 batch_size = 8 if K.image_data_format () == 'channels_first': input_shape =: input_shape =: 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)))) model.add (Activació ('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 (pèrdua = 'binary_crossentropy', optimitzador = 'rmsprop', mètriques = ['precisió'])

He format el model per a vosaltres, però si voleu formar-lo vosaltres mateixos amb el vostre propi conjunt de dades, he adjuntat el codi de formació. En cas contrari, podeu descarregar el fitxer HDF5 del model format. A causa de les restriccions dels fitxers Instructables, he hagut de canviar-lo amb una extensió ".txt". Per utilitzar-lo, canvieu el nom del fitxer per una extensió ".h5" i carregueu-lo amb aquest codi:

model.load_weights ("model_saved.h5")

Per utilitzar la xarxa per predir com és l'espai d'una imatge, definirem aquesta funció:

predir def (ruta_imatge):

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

Pas 4: processament de la imatge

Visió general

Per al processament d’imatges, estic fent servir la biblioteca OpenCV (cv2). Primer, desdibuixarem les vores de la imatge i, a continuació, eliminarem el fons creant una màscara i canviant els valors alfa dels colors més foscos.

El codi

Aquesta és la part de la funció que difumina les vores:

def processImage (img):

RADIUS = 20 # Obre una imatge im = Image.open ("pilbuffer.png") # Enganxa imatge sobre fons blanc diam = 2 * RADIUS back = Image.new ('RGB', (im.size [0] + diam, im.size [1] + diam), (0, 0, 0)) back.paste (im, (RADIUS, RADIUS)) # Crea màscara de desenfocament = Image.new ('L', (im.size [0] + diam, mida im [1] + diam), 255) blck = Image.new ('L', (mida im [0] - diam, mida im [1] - diam), 0) màscara. enganxar (blck, (diam, diam)) # # Desenfocar la imatge i enganxar la vora borrosa segons la màscara desenfocar = tornar.filtre (ImageFilter. GaussianBlur (RADIUS / 2)) back.paste (desenfocar, màscara = màscara) back.save (" transition-p.webp

A continuació, establirem els colors més foscos a transparents i desarem la imatge temporalment:

#Crear màscara i filtre substituir el negre per alfa

image = cv2.imread ("transition.png") hMin = 0 sMin = 0 vMin = 20 hMax = 180 sMax = 255 vMax = 255 inferior = np.array ([hMin, sMin, vMin]) upper = np.array ([hMax, sMax, vMax]) hsv = cv2.cvtColor (imatge, cv2. COLOR_BGR2HSV) màscara = cv2.inRang (hsv, inferior, superior) sortida = cv2.bitwise_and (imatge, imatge, màscara = màscara) * _, alfa = cv2.split (sortida) dst = cv2.merge ((sortida, alfa)) sortida = dst amb obert ("buffer.png", "w +") com a fitxer: passa cv2.imwrite ("buffer.png", sortida)

Pas 5: unir les imatges en una projecció equirectangular

Visió general

Aquesta funció pren diverses imatges i les ajusta en un format que pot ser interpretat pel paquet PhotoSphere.js, mitjançant la biblioteca PIL (coixí)

El codi

En primer lloc, hem de crear una imatge que pugui actuar com a amfitrió de les altres imatges:

new = Image.new ("RGBA", (8000, 4000), color = (0, 0, 0))

A continuació, hem de recórrer la matriu d'imatges (que s'han redimensionat totes a 1000x500) i col·locar-les a la imatge:

h = 0

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

Ara acabem d’acabar-ho amb una funció que pren com a argument una sèrie d’imatges i retorna la nova imatge:

def stitch_beta (img_arr):

new = Image.new ("RGBA", (8000, 4000), color = (0, 0, 0)) h = 0 w = 0 i = 0 per a img a img_arr: new.paste (img, (w, h), img) w + = 1000 si w == 8000: h + = 500 w = 0 i + = 1 torna nou

Pas 6: l'script complet de Python

Aquest és l'script complet de xarxa neuronal de Python, que es desa com a net.py i s'importa a l'script principal:

# importació de biblioteques

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 ("No s'ha trobat cap GPU ") d'importació keras.preprocessing.image ImageDataGenerator d'importació d'imatges keras.preprocessing d'importació keras.models Seqüencial d'importació keras.layers Conv2D, MaxPooling2D d'importació keras.layers Activació, abandonament, aplanament, densitat de backend d'importació de keras com K de PIL importa la importació d'imatges numpy com 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_d =: 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 (Activació ('relu')) model.add (model MaxPooling2D (pool_size = (2, 2)))) model.add (Conv2D (32, (2, 2)))). 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 (Activació ('relu')) model.add (Dropout (0.5))) model.add (Dense (1)) model.add (Activació ('sigmoid')) model.compile (loss = 'binary_crossentropy', optimizer = 'rmsprop', metrics = ['precision']) 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) resultat de retorn [0] [0]

Aquest és el fitxer principal de python, api.py:

sol·licituds d’importació, sys, random, urllib.parse, cv2

des de la importació PIL Image, ImageFilter from 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 "Recompte d'imatges actuals: {count } ") i = 0 params = {" q ": urllib.parse.quote (arg)," media_type ":" image "} results = requests.get (" https://images-api.nasa.gov/search ", params = params) data = [result ['href'] for result in results.json () [" collection "] [" items "] print (len (data)) if num> len (data): num = len (dades) mentre es compta = num: break print (f "\ n {count} imatges recuperades") return img_arr def stitch_beta (img_arr): new = Image.new ("RGBA", (8000, 4000), color = (0, 0, 0)) h = 0 w = 0 i = 0 per a img a img_arr: # pbar.set_description (f "Processant imatge {i + 1}") new.paste (img, (w, h), img) w + = 1000 if w == 8000: h + = 500 w = 0 i + = 1 torna un procés de definició nova Imatge (img): RADIUS = 20 # Obre una imatge im = Image.open ("pilbuffer.png") # Enganxa imatge sobre fons blanc diam = 2 * RADIUS tornar = Image.new ('RGB', (mida im [0] + diam, mida im [1] + diam), (0, 0, 0)) back.paste (im, (RADIUS), RADIUS)) # Crea una màscara de màscara de desenfocament = 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)) # Desenfoca la imatge i enganxa la vora borrosa segons la màscara blur = back.filter (ImageFilter. GaussianBlur (RADIUS / 2)) back.paste (desenfocament, màscara = màscara) back.save ("transition.png") back.close () #Create mask and filter replace black by alpha image = cv2.imread (" trànsit ion.png ") hMin = 0 sMin = 0 vMin = 20 hMax = 180 sMax = 255 vMax = 255 inferior = np.array ([hMin, sMin, vMin]) upper = 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 ((sortida, alfa)) sortida = dst amb obert ("buffer.png", "w +") com a fitxer: passa cv2.imwrite ("buffer.png", sortida) # Detecció de vora i desenfocament si _name_ == "_main_": search_terms = ["supernova", "planeta", "galàxia", "via làctia", "nebulosa", "estrelles"] # Els termes de cerca es poden modificar per allò que vulgueu que inclogui el planetari img_arr = get_image_search (64, search_terms) print ("Imatges recuperades i filtrades neuronals") img = stitch_beta (img_arr) print ("Imatges cosides") img.save ("stitched.png")

Pas 7: l'aplicació Electron

Visió general

Crearem una aplicació electrònica senzilla que només posiciona i carrega l’element PhotoSphere. Els fitxers main.js i package.json provenen directament del lloc web Electron i l'HTML és una versió lleugerament modificada de l'HTML proporcionat al lloc web de PhotoSphere. He inclòs els fitxers, però he canviat el nom de tots a.txt, ja que Instructables no permet aquests tipus de fitxers. Per utilitzar els fitxers, canvieu-los amb l'extensió adequada.

El codi

main.js

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

funció 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

Pas 8: execució

Creació de la imatge equirectangular

Per crear la imatge, executeu l'script api.py a l'indicador d'ordres, amb el seu entorn virtual activat:

api.py

Un cop finalitzats els scripts, executeu l'aplicació electron mitjançant:

npm d'iniciVoila! El vostre planetari està actiu. Gràcies per llegir:)

Recomanat: