Inhoudsopgave:

Neural Network Powered Planetarium met Python, Electron en Keras - Ajarnpa
Neural Network Powered Planetarium met Python, Electron en Keras - Ajarnpa

Video: Neural Network Powered Planetarium met Python, Electron en Keras - Ajarnpa

Video: Neural Network Powered Planetarium met Python, Electron en Keras - Ajarnpa
Video: Gregory Chaitin: Complexity, Metabiology, Gödel, Cold Fusion 2024, November
Anonim
Neural Network Powered Planetarium met Python, Electron en Keras
Neural Network Powered Planetarium met Python, Electron en Keras

In deze instructable laat ik je zien hoe ik een automatische 3D-planetariumgenerator heb geschreven met Python en Electron

De video hierboven toont een van de willekeurige planetaria die het programma heeft gegenereerd.

**Opmerking: dit programma is op geen enkele manier perfect en op sommige plaatsen niet erg pythonisch. De neurale netdiscriminator is slechts ~89% nauwkeurig, dus enkele vreemde beelden zullen het planetarium halen**

Bijzonderheden

Het planetarium vraagt een NASA-API op voor ruimtegerelateerde afbeeldingen en maakt gebruik van een convolutioneel neuraal netwerk om te bepalen of het beeld geschikt is voor verwerking. Het programma gebruikt vervolgens OpenCV om de achtergrond van de afbeelding te verwijderen en tenslotte worden de afbeeldingen aan elkaar genaaid tot één grote, rechthoekige afbeelding. Deze afbeelding wordt vervolgens opgeslagen en een Electron Node.js-toepassing opent de afbeelding en gebruikt het PhotoSphere.js-pakket om de afbeelding in een 3D-indeling in planetariumstijl te bekijken.

afhankelijkheden

Python:

  • Keras
  • Kussen
  • cv2
  • Numpy
  • Verzoeken
  • urllib
  • Willekeurig
  • tijd
  • io

Elektron:

Fotosfeer

Stap 1: Uw omgeving instellen

Electron en Python installeren

Zorg er eerst voor dat node.js en npm zijn geïnstalleerd (zo niet, dan kunt u hier downloaden)

Vervolgens moet u Electron installeren. Open een opdrachtprompt en voer de volgende opdracht in:

npm installeer elektron -g

Vervolgens heb je python nodig, die je hier kunt downloaden

Een virtuele omgeving opzetten

Open een opdrachtprompt en voer de volgende opdrachten in om uw virtuele omgeving in te stellen:

pip virtualenv installeren

virtuele ruimte

cd-ruimte

scripts\activeren

Python-afhankelijkheden installeren

Voer deze opdrachten uit in de opdrachtprompt om uw python-afhankelijkheden te installeren:

pip installeer keras

pip installeren kussen

pip installeer numpy

pip installatieverzoeken

pip installeer opencv-pythonAls je het netwerk zelf wilt trainen, zorg er dan voor dat je GPU-versnelling instelt voor Keras

Stap 2: De NASA Search API opvragen

Overzicht

NASA heeft veel echt nuttige API's die u met uw projecten kunt gebruiken. Voor dit project zullen we de zoek-API gebruiken, waarmee we in de beelddatabase van NASA kunnen zoeken naar ruimtegerelateerde afbeeldingen.

De code

Eerst moeten we een python-functie definiëren om een argument te accepteren dat als zoekterm zal fungeren:

def get_image_search(zin):

doorgang

Vervolgens zullen we de zoekterm converteren naar het URL-formaat en vervolgens de verzoekenbibliotheek gebruiken om de API te doorzoeken:

def get_image_search(zin):

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

Ten slotte zullen we de collection+JSON-reeks decoderen die de API aan ons heeft geretourneerd, en een lijst met links naar afbeeldingen extraheren die verband houden met de zoekterm:

def get_image_search(zin):

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

Daar gaan we! We hebben nu een codefragment dat de NASA-beeldzoek-API kan doorzoeken en een lijst met links naar afbeeldingen met betrekking tot onze zoekterm kan retourneren.

Stap 3: Het convolutionele neurale netwerk

Overzicht

De taak van het neurale netwerk is om te classificeren of een afbeelding van iets in de ruimte is, of niet. Om dit te doen, zullen we een convolutioneel neuraal netwerk, of CNN, gebruiken om een reeks matrixbewerkingen op het beeld uit te voeren en te bepalen hoe ruimtelijk het is. Ik zal dit niet allemaal uitleggen, omdat er veel theorie achter zit, maar als je meer wilt weten over neurale netwerken, raad ik "Machine Learning Mastery" aan

De code

Eerst moeten we onze afhankelijkheden importeren:

importeer os

#Fix voor probleem tijdens treinstap op GPU os.environ['CUDA_VISIBLE_DEVICES'] = '' import tensorflow als tf if tf.test.gpu_device_name(): print('GPU gevonden') else: print("Geen GPU gevonden") van keras.preprocessing.image import ImageDataGenerator van keras.preprocessing import image van keras.models import Sequential van keras.layers import Conv2D, MaxPooling2D van keras.layers import Activation, Dropout, Flatten, Dense van keras import backend als K van PIL import Image importeer numpy als np

Vervolgens moeten we ons model definiëren:

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_format() == 'channels_first': input_shape = (3, img_heightsha) = (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=['nauwkeurigheid'])

Ik heb het model voor je getraind, maar als je het model zelf wilt trainen, op je eigen dataset, dan heb ik de trainingscode bijgevoegd. Anders kunt u het HDF5-bestand van het getrainde model downloaden. Vanwege bestandsbeperkingen van Instructables moest ik het hernoemen met de extensie ".txt". Om het te gebruiken, hernoemt u het bestand naar de extensie ".h5" en laadt u het met deze code:

model.load_weights("model_saved.h5")

Om het netwerk te gebruiken om te voorspellen hoe ruimte-y een afbeelding is, zullen we deze functie definiëren:

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) resultaat retourneren[0][0]

Stap 4: De afbeelding verwerken

Overzicht

Voor beeldverwerking gebruik ik de OpenCV (cv2) bibliotheek. Eerst vervagen we de randen van de afbeelding en vervolgens verwijderen we de achtergrond door een masker te maken en de alfawaarden van de donkere kleuren te wijzigen

De code

Dit is het deel van de functie dat de randen vervaagt:

def processImage(img):

RADIUS = 20 # Open een afbeelding im = Image.open("pilbuffer.png") # Plak de afbeelding op een witte achtergrond diam = 2 * RADIUS back = Image.new('RGB', (im.size[0] + diam, im.size[1] + diam), (0, 0, 0)) back.paste(im, (RADIUS, RADIUS)) # Create blur mask 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. plakken(blck, (diam, diam)) # Blur afbeelding en plak wazige rand volgens masker blur = back.filter(ImageFilter. GaussianBlur(RADIUS / 2)) back.paste(blur, mask=mask) back.save(" transitie.png") terug.close()

Vervolgens zullen we de donkere kleuren op transparant zetten en de afbeelding tijdelijk opslaan:

#Maak masker en filter vervang zwart door alpha

image = cv2.imread("transition.png") hMin = 0 sMin = 0 vMin = 20 hMax = 180 sMax = 255 vMax = 255 lager = np.array([hMin, sMin, vMin]) hoger = 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 met open("buffer.png", "w+") als bestand: geef cv2.imwrite("buffer.png", output door)

Stap 5: Afbeeldingen samenvoegen tot een gelijkhoekige projectie

Overzicht

Deze functie neemt meerdere afbeeldingen en voegt ze samen tot een formaat dat kan worden geïnterpreteerd door het PhotoSphere.js-pakket, met behulp van de PIL-bibliotheek (pillow).

De code

Eerst moeten we een afbeelding maken die als host kan fungeren voor de andere afbeeldingen:

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

Vervolgens moeten we de reeks afbeeldingen doorlopen (die allemaal zijn verkleind tot 1000x500) en deze in de afbeelding plaatsen:

h = 0

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

Nu pakken we dit gewoon in een functie in die een array van afbeeldingen als argument neemt en de nieuwe afbeelding retourneert:

def stitch_beta(img_arr):

new = Image.new("RGBA", (8000, 4000), color=(0, 0, 0)) h = 0 w = 0 i = 0 voor img in img_arr: new.paste(img, (w, h), img) w += 1000 als w == 8000: h += 500 w = 0 i += 1 retourneer nieuw

Stap 6: Het volledige Python-script

Dit is het volledige neurale netwerkscript van Python, dat wordt opgeslagen als net.py en geïmporteerd in het hoofdscript:

# bibliotheken importeren

import os #Fix voor probleem tijdens treinstap op GPU os.environ['CUDA_VISIBLE_DEVICES'] = '' import tensorflow als tf if tf.test.gpu_device_name(): print('GPU gevonden') else: print("Geen GPU gevonden ") van keras.preprocessing.image import ImageDataGenerator van keras.preprocessing import image van keras.models import Sequential van keras.layers import Conv2D, MaxPooling2D van keras.layers import Activation, Dropout, Flatten, Dense van keras import backend als K van 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_data_dir = 'v_data/train' validation_data_dir = 'v_data/test' nb_train_samples = 203 nb_validation_samples = 203 epochs = 10 batch_size = 8channel()image_data_format K.image_data: 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 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) return resultaat [0][0]

Dit is het belangrijkste python-bestand, api.py:

importverzoeken, sys, willekeurig, 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"Huidige aantal afbeeldingen: {count }") i = 0 params = {"q": urllib.parse.quote(arg), "media_type": "image"} results = requests.get("https://images-api.nasa.gov/search ", params=params) data = [resultaat['href'] voor resultaat in results.json()["collection"]["items"] print(len(data)) if num > len(data): num = len(data) terwijl tellen = num: break print(f"\n{count} images opgehaald") return img_arr def stitch_beta(img_arr): new = Image.new("RGBA", (8000, 4000), color=(0, 0, 0)) h = 0 w = 0 i = 0 voor img in img_arr: #pbar.set_description(f"Bezig met verwerken van afbeelding {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 # Open een afbeelding im = Image.open("pilbuffer.png") # Plak de afbeelding op een witte achtergrond diam = 2 * RADIUS terug = Image.new('RGB', (im.size[0] + diam, im.size[1] + diam), (0, 0, 0)) back.paste(im, (RADIUS), RADIUS)) # Maak vervagingsmasker 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)) # Blur afbeelding en plak wazige rand volgens mask blur = back.filter(ImageFilter. GaussianBlur(RADIUS / 2)) back.paste(blur, mask=mask) back.save("transition.png") back.close() #Maak masker en filter vervang zwart door alpha image = cv2.imread(" doorvoer ion.png") hMin = 0 sMin = 0 vMin = 20 hMax = 180 sMax = 255 vMax = 255 lager = np.array([hMin, sMin, vMin]) hoger = 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 met open("buffer.png", "w+") als bestand: geef cv2.imwrite("buffer.png", output) #Randdetectie en vervaging als _name_ == "_main_": search_terms = ["supernova", "planet", "galaxy", "milky way", "nebula", "stars"] #De zoektermen kunnen worden gewijzigd in wat u maar wilt in het planetarium img_arr = get_image_search(64, search_terms) print("Afbeeldingen opgehaald en neuraal gefilterd") img = stitch_beta(img_arr) print("Afbeeldingen genaaid") img.save("stitched.png")

Stap 7: De Electron-app

Overzicht

We zullen een eenvoudige elektronen-app maken die alleen het PhotoSphere-element positioneert en laadt. De main.js- en package.json-bestanden komen rechtstreeks van de Electron-website en de HTML is een licht gewijzigde versie van de HTML op de PhotoSphere-website. Ik heb de bestanden opgenomen, maar hernoemd naar.txt, omdat Instructables deze bestandstypen niet toestaat. Om de bestanden te gebruiken, hernoemt u ze met de juiste extensie.

De code

main.js

const { app, BrowserWindow } = vereisen ('elektron')

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

pakket.json

{

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

index.html

Stap 8: Uitvoering

De equirechthoekige afbeelding maken

Om de afbeelding te maken, voert u het api.py-script uit in de opdrachtprompt, met de virtuele omgeving geactiveerd:

api.py

Nadat de scripts zijn uitgevoerd, voert u de elektron-app uit met:

npm startVoila! Je planetarium is actief! Bedankt voor het lezen:)

Aanbevolen: