Sommario:

Planetario alimentato da rete neurale che utilizza Python, Electron e Keras: 8 passaggi
Planetario alimentato da rete neurale che utilizza Python, Electron e Keras: 8 passaggi

Video: Planetario alimentato da rete neurale che utilizza Python, Electron e Keras: 8 passaggi

Video: Planetario alimentato da rete neurale che utilizza Python, Electron e Keras: 8 passaggi
Video: Gregory Chaitin: Complessità, Metabiologia, Gödel, Fusione Fredda 2024, Novembre
Anonim
Planetario alimentato da rete neurale che utilizza Python, Electron e Keras
Planetario alimentato da rete neurale che utilizza Python, Electron e Keras

In questo tutorial, ti mostrerò come ho scritto un generatore automatico di planetari 3D, usando Python ed Electron

Il video sopra mostra uno dei planetari casuali generati dal programma.

**Nota: questo programma non è in alcun modo perfetto e in alcuni punti non è molto pitonico. Il discriminatore della rete neurale è preciso solo all'89% circa, quindi alcune immagini strane arriveranno nel planetario**

Specifiche

Il planetario interroga un'API della NASA per immagini relative allo spazio e utilizza una rete neurale convoluzionale per determinare se l'immagine è adatta per l'elaborazione. Il programma utilizza quindi OpenCV per rimuovere lo sfondo dall'immagine e infine le immagini vengono unite in un'unica grande immagine equirettangolare. Questa immagine viene quindi salvata e un'applicazione Electron Node.js apre l'immagine e utilizza il pacchetto PhotoSphere.js per visualizzare l'immagine in un formato 3D in stile planetario.

dipendenze

Pitone:

  • Keras
  • Cuscino
  • cv2
  • Numpy
  • Richieste
  • urllib
  • A caso
  • tempo
  • io

Elettrone:

Fotosfera

Passaggio 1: configurazione dell'ambiente

Installazione di Electron e Python

Innanzitutto, assicurati di aver installato node.js e npm (in caso contrario, puoi scaricarlo qui)

Successivamente, è necessario installare Electron. Apri un prompt dei comandi e inserisci il seguente comando:

npm installa elettrone -g

Successivamente, hai bisogno di Python, che può essere scaricato qui

Configurazione di un ambiente virtuale

Apri un prompt dei comandi, quindi inserisci i seguenti comandi per configurare il tuo ambiente virtuale:

pip install virtualenv

spazio virtualenv

spazio cd

script\activate

Installazione delle dipendenze Python

Esegui questi comandi nel prompt dei comandi per installare le tue dipendenze Python:

pip install keras

pip installa il cuscino

pip install numpy

pip richieste di installazione

pip install opencv-pythonSe vuoi addestrare tu stesso la rete, assicurati di impostare l'accelerazione GPU per Keras

Passaggio 2: interrogazione dell'API di ricerca della NASA

Panoramica

La NASA ha molte API davvero utili che puoi usare con i tuoi progetti. Per questo progetto, utilizzeremo l'API di ricerca, che ci consente di cercare nel database di immagini della NASA immagini relative allo spazio.

Il codice

Innanzitutto, dobbiamo definire una funzione Python per accettare un argomento che fungerà da termine di ricerca:

def get_image_search(frase):

passaggio

Successivamente, convertiremo il termine di ricerca in formato URL, quindi utilizzeremo la libreria delle richieste per interrogare l'API:

def get_image_search(frase):

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

Infine, decodificheremo la stringa collection+JSON che l'API ci ha restituito ed estrarremo un elenco di collegamenti alle immagini relative al termine di ricerca:

def get_image_search(frase):

params = {"q": urllib.parse.quote(arg), "media_type": "image"} results = request.get("https://images-api.nasa.gov/search", params=params) data = [result['href'] per il risultato in results.json()["collection"]["items"]

Ci siamo! Ora abbiamo uno snippet di codice che può interrogare l'API di ricerca di immagini della NASA e restituire un elenco di collegamenti alle immagini relative al nostro termine di ricerca.

Passaggio 3: la rete neurale convoluzionale

Panoramica

Il compito della rete neurale è classificare se un'immagine è di qualcosa nello spazio o se non lo è. Per fare ciò, utilizzeremo una rete neurale convoluzionale, o CNN, per eseguire una serie di operazioni matriciali sull'immagine e determinare quanto è spazio-y. Non spiegherò tutto questo, perché c'è molta teoria dietro, ma se vuoi conoscere le reti neurali, ti suggerisco "Machine Learning Mastery"

Il codice

Per prima cosa, dobbiamo importare le nostre dipendenze:

importare il sistema operativo

#Risolto il problema durante il passaggio del treno sulla GPU os.environ['CUDA_VISIBLE_DEVICES'] = '' import tensorflow as tf if tf.test.gpu_device_name(): print('GPU trovata') else: print("Nessuna GPU trovata") da keras.preprocessing.image import ImageDataGenerator da keras.preprocessing importa immagine da keras.models import Sequential da keras.layers import Conv2D, MaxPooling2D da keras.layers import Activation, Dropout, Flatten, Dense from keras import backend as K from PIL import Image importa numpy come np

Successivamente dobbiamo definire il nostro modello:

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 epoche = 10 batch_size = 8 if K.image_data_format() == 'channels_first': input_shape_= (3, img_height) = (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))) 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 (perdita='binary_crossentropy', ottimizzatore='rmsprop', metriche=['accuratezza'])

Ho addestrato il modello per te, ma se desideri addestrare il modello da solo, sul tuo set di dati, ho allegato il codice di addestramento. Altrimenti, puoi scaricare il file HDF5 del modello addestrato. A causa delle restrizioni sui file di Instructables, ho dovuto rinominarlo con un'estensione ".txt". Per usarlo, rinomina il file con un'estensione ".h5" e caricalo con questo codice:

model.load_weights("model_saved.h5")

Per utilizzare la rete per prevedere quanto è spazio-y un'immagine, definiremo questa funzione:

def predire (percorso_immagine):

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

Passaggio 4: elaborazione dell'immagine

Panoramica

Per l'elaborazione delle immagini, sto usando la libreria OpenCV (cv2). Innanzitutto, sfocamo i bordi dell'immagine, quindi rimuoveremo lo sfondo creando una maschera e modificando i valori alfa dei colori più scuri

Il codice

Questa è la parte della funzione che sfoca i bordi:

def processImage(img):

RAGGIO = 20 # Apri un'immagine im = Image.open("pilbuffer.png") # Incolla l'immagine su sfondo bianco diam = 2 * RAGGIO back = Image.new('RGB', (im.size[0] + diam, im.size[1] + diam), (0, 0, 0)) back.paste(im, (RADIUS, RADIUS)) # Crea maschera di sfocatura 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)) # Sfoca l'immagine e incolla il bordo sfocato in base alla maschera blur = back.filter(ImageFilter. GaussianBlur(RADIUS / 2)) back.paste(blur, mask=mask) back.save(" transizione.png") back.close()

Successivamente, imposteremo i colori più scuri su trasparenti e salveremo temporaneamente l'immagine:

#Crea maschera e filtro sostituisci il nero con l'alfa

image = cv2.imread("transition.png") hMin = 0 sMin = 0 vMin = 20 hMax = 180 sMax = 255 vMax = 255 lower = 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((output, alpha)) output = dst con open("buffer.png", "w+") come file: passa cv2.imwrite("buffer.png", output)

Passaggio 5: unire le immagini in una proiezione equirettangolare

Panoramica

Questa funzione prende più immagini e le unisce in un formato che può essere interpretato dal pacchetto PhotoSphere.js, utilizzando la libreria PIL (cuscino)

Il codice

Innanzitutto, dobbiamo creare un'immagine che possa fungere da host per le altre immagini:

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

Successivamente, dobbiamo scorrere l'array di immagini (che sono state tutte ridimensionate a 1000x500) e inserirle nell'immagine:

h = 0

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

Ora lo avvolgiamo in una funzione che accetta un array di immagini come argomento e restituisce la nuova immagine:

def stitch_beta(img_arr):

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

Passaggio 6: lo script completo di Python

Questo è lo script completo della rete neurale Python, che viene salvato come net.py e importato nello script principale:

# importazione di librerie

import os #Risolto problema durante la fase di addestramenton su GPU os.environ['CUDA_VISIBLE_DEVICES'] = '' import tensorflow as tf if tf.test.gpu_device_name(): print('GPU trovata') else: print("Nessuna GPU trovata ") da keras.preprocessing.image import ImageDataGenerator da keras.preprocessing import image from keras.models import Sequential da keras.layers import Conv2D, MaxPooling2D da keras.layers import Activation, Dropout, Flatten, Dense from keras import backend come K da 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 se K.image_data_format_first: 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))) model. 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 forecast(image_path): img = image.load_img(image_path, target_size=(1000, 500)) img = np.expand_dims(img, axis=0) risultato=model.predict_classes(img) return risultato [0][0]

Questo è il file Python principale, api.py:

richieste di importazione, sys, random, urllib.parse, cv2

from PIL import 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"Conteggio immagine attuale: {count }") i = 0 parametri = {"q": urllib.parse.quote(arg), "media_type": "image"} risultati = request.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(dati) mentre conta = num: break print(f"\n{count} immagini recuperate") return img_arr def stitch_beta(img_arr): new = Image.new("RGBA", (8000, 4000), color=(0, 0, 0)) h = 0 w = 0 i = 0 for img in img_arr: #pbar.set_description(f"Elaborazione immagine {i+1}") new.paste(img, (w, h), img) w += 1000 if w == 8000: h += 500 w = 0 i += 1 return new def processImage(img): RADIUS = 20 # Apri un'immagine im = Image.open("pilbuffer.png") # Incolla l'immagine su sfondo bianco diam = 2 * RAGGIO back = Image.new('RGB', (im.size[0] + diam, im.size[1] + diam), (0, 0, 0)) back.paste(im, (RADIUS, RADIUS)) # Crea maschera di sfocatura 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)) # Sfoca l'immagine e incolla il bordo sfocato in base alla maschera blur = back.filter(ImageFilter. GaussianBlur(RADIUS / 2)) back.paste(blur, mask=mask) back.save("transition.png") back.close() #Crea maschera e filtro sostituisci il nero con alpha image = cv2.imread(" transito ion.png") hMin = 0 sMin = 0 vMin = 20 hMax = 180 sMax = 255 vMax = 255 inferiore = np.array([hMin, sMin, vMin]) superiore = 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 con open("buffer.png", "w+") come file: passa cv2.imwrite("buffer.png", output) #Rilevamento dei bordi e sfocatura se _name_ == "_main_": search_terms = ["supernova", "pianeta", "galaxy", "via lattea", "nebulosa", "stelle"] #I termini di ricerca possono essere modificati in base a ciò che si desidera includere nel planetario img_arr = get_image_search(64, search_terms) print("Immagini recuperate e filtrate neuralmente") img = stitch_beta(img_arr) print("Immagini cucite") img.save("stitched.png")

Passaggio 7: l'app Electron

Panoramica

Creeremo una semplice app di elettroni che posiziona e carica solo l'elemento PhotoSphere. I file main.js e package.json provengono direttamente dal sito Web Electron e l'HTML è una versione leggermente modificata dell'HTML fornito sul sito Web PhotoSphere. Ho incluso i file, ma ho rinominato tutti in.txt, poiché Instructables non consente questi tipi di file. Per utilizzare i file, rinominarli con l'estensione appropriata.

Il codice

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() } })

pacchetto.json

{

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

index.html

Passaggio 8: esecuzione

Creazione dell'immagine equirettangolare

Per creare l'immagine, esegui lo script api.py nel prompt dei comandi, con il suo ambiente virtuale attivato:

api.py

Al termine dell'esecuzione degli script, eseguire l'app di elettroni utilizzando:

npm inizioEcco! Il tuo planetario è attivo! Grazie per aver letto:)

Consigliato: