Планетариум, захранван от невронна мрежа, използващ Python, Electron и Keras: 8 стъпки
Планетариум, захранван от невронна мрежа, използващ Python, Electron и Keras: 8 стъпки
Anonim
Планетариум, захранван от невронна мрежа, използващ Python, Electron и Keras
Планетариум, захранван от невронна мрежа, използващ Python, Electron и Keras

В тази инструкция ще ви покажа как написах автоматичен 3D планетарен генератор, използвайки Python и Electron

Видеото по -горе показва един от случайните планетариуми, генерирани от програмата.

** Забележка: Тази програма по никакъв начин не е перфектна и на някои места не е много питонична. Дискриминаторът на невронната мрежа е само ~ 89% точен, така че някои странни изображения ще стигнат до планетариума **

Специфика

Планетариумът запитва API на НАСА за изображения, свързани с космоса, и използва конволюционна невронна мрежа, за да определи дали изображението е подходящо за обработка. След това програмата използва OpenCV, за да премахне фона от изображението, и накрая изображенията се съединяват в едно голямо равноправоъгълно изображение. След това това изображение се записва и приложение Electron Node.js отваря изображението и използва пакета PhotoSphere.js за преглед на изображението в 3D формат в стил планетариум.

Зависимости

Python:

  • Керас
  • Възглавница
  • cv2
  • Numpy
  • Искания
  • urllib
  • Случайно
  • време
  • io

Електрон:

PhotoSphere

Стъпка 1: Настройка на вашата среда

Инсталиране на Electron и Python

Първо се уверете, че имате инсталирани node.js и npm (ако не, можете да изтеглите тук)

След това трябва да инсталирате Electron. Отворете командния ред и въведете следната команда:

npm инсталиране на електрон -g

След това се нуждаете от python, който можете да изтеглите от тук

Създаване на виртуална среда

Отворете командния ред, след което въведете следните команди, за да настроите вашата виртуална среда:

pip install virtualenv

virtualenv пространство

cd пространство

скриптове / активиране

Инсталиране на зависимости на Python

Изпълнете тези команди в командния ред, за да инсталирате вашите зависимости на python:

pip install keras

възглавница за инсталиране на пип

pip install numpy

заявки за инсталиране на pip

pip инсталирайте opencv-pythonАко искате сами да тренирате мрежата, не забравяйте да настроите ускорението на графичния процесор за Keras

Стъпка 2: Запитване на API за търсене на НАСА

Общ преглед

НАСА има много наистина полезни API, които можете да използвате с вашите проекти. За този проект ще използваме API за търсене, който ни позволява да търсим в базата данни с изображения на НАСА за изображения, свързани с космоса.

Кодът

Първо, трябва да дефинираме функция на python, за да приемем аргумент, който ще действа като термин за търсене:

def get_image_search (фраза):

пропуск

След това ще преобразуваме думата за търсене в URL формат, след което ще използваме библиотеката с заявки за заявка към API:

def get_image_search (фраза):

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

Накрая ще декодираме низа за събиране+JSON, който API ни върна, и ще извлечем списък с връзки към изображения, свързани с думата за търсене:

def get_image_search (фраза):

params = {"q": urllib.parse.quote (arg), "media_type": "image"} results = requests.get ("https://images-api.nasa.gov/search", params = params) data = [result ['href'] за резултат в results.json () ["collection"] ["items"]

Ето! Сега имаме кодов фрагмент, който може да запитва API за търсене на изображения на НАСА и да връща списък с връзки към изображения, свързани с нашия термин за търсене.

Стъпка 3: Конволюционна невронна мрежа

Общ преглед

Работата на невронната мрежа е да класифицира дали изображението е от нещо в космоса или не. За да направим това, ще използваме конволюционна невронна мрежа или CNN, за да извършим поредица от матрични операции върху изображението и да определим колко пространство-y е то. Няма да обяснявам всичко това, защото зад него стои много теория, но ако искате да научите за невронните мрежи, предлагам „Майсторство на машинно обучение“

Кодът

Първо, трябва да импортираме нашите зависимости:

внос os

#Fix за проблем по време на стъпка на влака на GPU os.environ ['CUDA_VISIBLE_DEVICES'] = '' импортиране на тензорния поток като tf, ако tf.test.gpu_device_name (): print ('GPU found') else: print ("Няма намерен GPU") от keras.preprocessing.image импортиране на ImageDataGenerator от keras.preprocess импортиране на изображение от keras.models импортиране последователно от keras.layers импортиране на Conv2D, MaxPooling2D от keras.layers импортиране Активиране, отпадане, изравняване, плътно от керас импортиране на бекенд като K от PIL импортиране на изображение внос numpy като 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 епохи = 10 batch_size = 8, ако K.image_data_format () == 'канали_първа': input_shape_id_thig, = (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))) модел.add (Conv2D (64, (2, 2))) model.add (Activation ('relu')) model.add (MaxPooling2D (pool_size = (2, 2))) model.add (Flatten ()) модел. добавете (Плътен (64)) model.add (Activation ('relu')) model.add (Dropout (0.5)) model.add (Dense (1)) model.add (Activation ('sigmoid')) model.compile (загуба = 'binary_crossentropy', optimizer = 'rmsprop', metrics = ['точност'])

Аз съм обучил модела за вас, но ако искате да обучите модела сами, на свой собствен набор от данни, тогава съм приложил кода за обучение. В противен случай можете да изтеглите HDF5 файла на обучения модел. Поради ограничения на файловете Instructables, трябваше да го преименувам с разширение ".txt". За да го използвате, преименувайте файла на ".h5" разширение и го заредите с този код:

model.load_weights ("model_saved.h5")

За да използваме мрежата, за да предскажем колко пространство-y е изображението, ще дефинираме тази функция:

def predict (image_path):

img = image.load_img (image_path, target_size = (1000, 500)) img = np.expand_dims (img, ос = 0) резултат = model.predict_classes (img) връщане на резултата [0] [0]

Стъпка 4: Обработка на изображението

Общ преглед

За обработка на изображения използвам библиотеката OpenCV (cv2). Първо ще замъглим ръбовете на изображението и след това ще премахнем фона, като създадем маска и променим алфа стойностите на по -тъмните цветове

Кодът

Това е частта от функцията, която замъглява ръбовете:

def processImage (img):

RADIUS = 20 # Отваряне на изображение im = Image.open ("pilbuffer.png") # Поставяне на изображение на бял фон diam = 2 * RADIUS назад = Image.new ('RGB', (im.size [0] + диам, im.size [1] + diam), (0, 0, 0)) back.paste (im, (RADIUS, RADIUS)) # Създаване на маска за размазване = Image.new ('L', (im.size [0] + диаметър, размер на размера [1] + диаметър), 255) blck = Image.new ('L', (im.size [0] - диаметър, размер на размера [1] - диаметър), 0) маска. paste (blck, (diam, diam)) # Размазване на изображението и поставяне на замъгления ръб според mask blur = back.filter (ImageFilter. GaussianBlur (RADIUS / 2)) back.paste (blur, mask = mask) back.save (" transition-p.webp

След това ще настроим по -тъмните цветове на прозрачни и временно ще запазим изображението:

#Създайте маска и филтър, заменете черното с алфа

image = cv2.imread ("переход.png") hMin = 0 sMin = 0 vMin = 20 hMax = 180 sMax = 255 vMax = 255 по -нисък = np.array ([hMin, sMin, vMin]) горен = np.array ([hMax, sMax, vMax]) hsv = cv2.cvtColor (изображение, cv2. COLOR_BGR2HSV) маска = cv2.inRange (hsv, долна, горна) изход = cv2.bitwise_and (изображение, изображение, маска = маска) *_, алфа = cv2.split (output) dst = cv2.merge ((output, alpha)) output = dst с отворен ("buffer.png", "w+") като файл: pass cv2.imwrite ("buffer.png", output)

Стъпка 5: Сшиване на изображения заедно в еднакво правоъгълна проекция

Общ преглед

Тази функция взема множество изображения и ги зашива във формат, който може да бъде интерпретиран от пакета PhotoSphere.js, използвайки библиотеката PIL (възглавница)

Кодът

Първо, трябва да създадем изображение, което може да действа като хост за другите изображения:

нов = Image.new ("RGBA", (8000, 4000), цвят = (0, 0, 0))

След това трябва да повторим масив от изображения (всички те са преоразмерени до 1000x500) и да ги поставим в изображението:

h = 0

w = 0 i = 0 за img в img_arr: new.paste (img, (w, h), img) w += 1000, ако w == 8000: h += 500 w = 0 i += 1

Сега просто завършваме това във функция, която приема масив от изображения като свой аргумент и връща новото изображение:

def stitch_beta (img_arr):

new = Image.new ("RGBA", (8000, 4000), color = (0, 0, 0)) h = 0 w = 0 i = 0 за img в img_arr: new.paste (img, (w, h), img) w += 1000, ако w == 8000: h += 500 w = 0 i += 1 връщане на ново

Стъпка 6: Пълният скрипт на Python

Това е пълният скрипт за невронна мрежа на python, който се записва като net.py и се импортира в основния скрипт:

# импортиращи библиотеки

import os #Fix за проблем по време на стъпка на влака на GPU os.environ ['CUDA_VISIBLE_DEVICES'] = '' импортиране на тензорния поток като tf, ако tf.test.gpu_device_name (): print ('GPU found') else: print ("Няма намерен GPU ") от keras.preprocessing.image импортиране ImageDataGenerator от keras.preprocess импортиране на изображение от keras.models импортиране Последователно от keras.layers импортиране на Conv2D, MaxPooling2D от keras.layers импортиране Активиране, Отпадане, Изравняване, Плътно от керас импортиране като K от PIL импортиране на изображение импортиране numpy като 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 'канали: 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 (Активиране ('relu')) model.add (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 (Activation ('relu')) model.add (Отпадане (0.5)) model.add (Dense (1)) model.add (Activation ('sigmoid')) model.compile (loss = 'binary_crossentropy', optimizer = 'rmsprop', metrics = ['точност']) 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, ос = 0) резултат = model.predict_classes (img) възвръщаем резултат [0] [0]

Това е основният python файл, api.py:

заявки за импортиране, sys, random, urllib.parse, cv2

от PIL за импортиране на изображение, ImageFilter от io за импортиране BytesIO за импортиране numpy като np импортиране net def get_image_search (num, фраза): count = 0 img_arr = за arg във фраза: print (arg) print (f "Текущ брой изображения: {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'] за резултат в results.json () [" collection "] [" items "] print (len (данни)) ако num> len (данни): num = len (данни), докато се брои = num: break print (f "\ n {count} изображения възстановени") return img_arr def stitch_beta (img_arr): new = Image.new ("RGBA", (8000, 4000), color = (0, 0, 0)) h = 0 w = 0 i = 0 за img в img_arr: #pbar.set_description (f "Обработка на изображение {i +1}") new.paste (img, (w, h), img) w += 1000 ако w == 8000: h += 500 w = 0 i += 1 връщане на нов def processImage (img): RADIUS = 20 # Отваряне на изображение im = Image.open ("pilbuffer.png") # Поставяне на изображение на бял фон диам = 2 * RADIUS назад = Image.new ('RGB', (im.size [0] + diam, im.size [1] + diam), (0, 0, 0)) back.paste (im, (RADIUS, RADIUS)) # Създаване на маска за размазване = Image.new ('L', (im.size [0] + diam, im.size [1] + diam), 255) blck = Image.new ('L', (im.size [0] - диам., im.size [1] - диам.), 0) mask.paste (blck, (диам., диам.)) # Размазване на изображението и поставяне на замъгления ръб според размазването на маската = back.filter (ImageFilter. GaussianBlur (RADIUS / 2)) back.paste (blur, mask = mask) back.save ("transition.png") back.close () #Създайте маска и филтър, заменете черното с alpha image = cv2.imread (" транзит ion.png ") hMin = 0 sMin = 0 vMin = 20 hMax = 180 sMax = 255 vMax = 255 по -нисък = np.array ([hMin, sMin, vMin]) горен = np.array ([hMax, sMax, vMax]) hsv = cv2.cvtColor (изображение, cv2. COLOR_BGR2HSV) маска = cv2.inRange (hsv, долна, горна) изход = cv2.bitwise_and (изображение, изображение, маска = маска) *_, alpha = cv2.split (изход) dst = cv2.merge ((изход, алфа)) изход = dst с отворен ("buffer.png", "w+") като файл: преминаване cv2.imwrite ("buffer.png", изход) #Откриване и замъгляване на ръба, ако _name_ == "_main_": search_terms = ["свръхнова", "планета", "галактика", "млечен път", "мъглявина", "звезди"] #Думите за търсене могат да се променят на всичко, което искате да включва планетариумът img_arr = get_image_search (64, search_terms) print ("Извлечени изображения и невронно филтрирани") img = stitch_beta (img_arr) print ("Images stitched") img.save ("stitched.png")

Стъпка 7: Приложението Electron

Общ преглед

Ще създадем просто електронно приложение, което само позиционира и зарежда елемента PhotoSphere. Файловете main.js и package.json са направо от уебсайта на Electron, а HTML е леко модифицирана версия на HTML, предоставена на уебсайта PhotoSphere. Включих файловете, но преименувах всички на.txt, тъй като Instructables не позволява тези типове файлове. За да използвате файловете, преименувайте ги със съответното разширение.

Кодът

main.js

const {app, BrowserWindow} = изисквам ('електрон')

функция createWindow () {const win = new BrowserWindow ({ширина: 800, височина: 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 ('активиране', () => {if (BrowserWindow.getAllWindows (). length === 0) {createWindow ()}})

package.json

{

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

index.html

Стъпка 8: Изпълнение

Създаване на равноправен ъгъл

За да създадете изображението, стартирайте api.py скрипта в командния ред с активирана виртуална среда:

api.py

След като скриптовете завършат изпълнението, стартирайте електронното приложение, като използвате:

npm стартВола! Вашият планетариум е активен! Благодаря за четенето:)

Препоръчано: