Оглавление:
2025 Автор: John Day | [email protected]. Последнее изменение: 2025-01-23 15:04
В этом руководстве я покажу вам, как я написал автоматический трехмерный генератор планетария, используя Python и Electron
На видео выше показан один из случайных планетариев, созданных программой.
** Примечание: эта программа никоим образом не идеальна, а в некоторых местах не очень питонична. Дискриминатор нейронной сети имеет точность только ~ 89%, поэтому некоторые странные изображения попадут в планетарий **
Особенности
Планетарий запрашивает у NASA API изображения, связанные с космосом, и использует сверточную нейронную сеть, чтобы определить, подходит ли изображение для обработки. Затем программа использует OpenCV для удаления фона с изображения, и, наконец, изображения объединяются в одно большое равноугольное изображение. Затем это изображение сохраняется, и приложение Electron Node.js открывает изображение и использует пакет PhotoSphere.js для просмотра изображения в формате 3D в стиле планетария.
Зависимости
Python:
- Керас
- Подушка
- cv2
- Numpy
- Запросы
- urllib
- Случайный
- время
- io
Электрон:
ФотоСфера
Шаг 1. Настройка вашей среды
Установка Electron и Python
Во-первых, убедитесь, что у вас установлены node.js и npm (если нет, вы можете скачать здесь)
Далее вам необходимо установить Electron. Откройте командную строку и введите следующую команду:
npm установить электрон -g
Далее вам понадобится python, который можно скачать здесь
Настройка виртуальной среды
Откройте командную строку и введите следующие команды для настройки виртуальной среды:
pip install virtualenv
виртуальное пространство
cd пространство
скрипты / активировать
Установка зависимостей Python
Выполните эти команды в командной строке, чтобы установить зависимости Python:
pip install keras
pip install подушка
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)
Наконец, мы декодируем строку collection + 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 = [результат ['href'] для результата в results.json () ["collection"] ["items"]
Итак, мы идем! Теперь у нас есть фрагмент кода, который может запрашивать API поиска изображений НАСА и возвращать список ссылок на изображения, относящиеся к нашему поисковому запросу.
Шаг 3: сверточная нейронная сеть
Обзор
Задача нейронной сети - определить, является ли изображение чем-то в космосе или нет. Для этого мы будем использовать сверточную нейронную сеть или CNN, чтобы выполнить серию матричных операций с изображением и определить, каково это пространство-y. Я не буду все это объяснять, потому что за этим стоит много теории, но если вы хотите узнать о нейронных сетях, я предлагаю "Мастерство машинного обучения"
Код
Во-первых, нам нужно импортировать наши зависимости:
импорт ОС
# Исправить проблему во время шага обучения на GPU os.environ ['CUDA_VISIBLE_DEVICES'] = '' импортировать тензорный поток как tf, если tf.test.gpu_device_name (): print ('GPU найден') else: print ("Графический процессор не найден") from keras.preprocessing.image import ImageDataGenerator from keras.preprocessing импортировать изображение из keras.models import Sequential from keras.layers import Conv2D, MaxPooling2D from keras.layers import Activation, Dropout, Flatten, Dense from keras import backend as K from PIL import Image импортировать 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 K.image_data_format () == 'channels_first': else, img_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))) модель.add (Conv2D (64, (2, 2))) model.add (Activation ('relu')) model.add (MaxPooling2D (pool_size = (2, 2))) model.add (Flatten ()) модель. 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 = ['precision'])
Я обучил модель для вас, но если вы хотите обучить модель самостоятельно, на своем собственном наборе данных, я прикрепил обучающий код. В противном случае вы можете загрузить файл HDF5 обученной модели. Из-за ограничений файла Instructables мне пришлось переименовать его с расширением «.txt». Чтобы использовать его, переименуйте файл в расширение «.h5» и загрузите его с помощью этого кода:
model.load_weights ("model_saved.h5")
Чтобы использовать сеть для прогнозирования того, насколько объемным является изображение, мы определим эту функцию:
def прогноз (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]
Шаг 4: обработка изображения
Обзор
Для обработки изображений я использую библиотеку OpenCV (cv2). Сначала мы размыем края изображения, а затем удалим фон, создав маску и изменив значения альфа для более темных цветов.
Код
Это часть функции, которая размывает края:
def processImage (img):
RADIUS = 20 # Открыть изображение im = Image.open ("pilbuffer.png") # Вставить изображение на белый фон diam = 2 * RADIUS back = Image.new ('RGB', (im.size [0] + diam, im.size [1] + diam), (0, 0, 0)) back.paste (im, (RADIUS, RADIUS)) # Создать маску размытия 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) маска. paste (blck, (diam, diam)) # Размыть изображение и вставить размытые края в соответствии с маской blur = back.filter (ImageFilter. GaussianBlur (RADIUS / 2)) back.paste (blur, mask = mask) back.save (" transition-p.webp
Затем мы сделаем более темные цвета прозрачными и временно сохраним изображение:
# Создать маску и фильтр заменить черный на альфа
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 with open ("buffer.png", "w +") как файл: передать cv2.imwrite ("buffer.png", output)
Шаг 5: сшивание изображений в равнопрямоугольную проекцию
Обзор
Эта функция берет несколько изображений и сшивает их в формат, который может быть интерпретирован пакетом PhotoSphere.js с помощью библиотеки PIL (подушка).
Код
Во-первых, нам нужно создать изображение, которое может выступать в качестве хоста для других изображений:
new = Image.new ("RGBA", (8000, 4000), color = (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 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 ("Графический процессор не найден ") из keras.preprocessing.image импортировать ImageDataGenerator из keras.preprocessing импортировать изображение из keras.models import Sequential from keras.layers import Conv2D, MaxPooling2D from keras.layers import Activation, Dropout, Flatten, Dense from keras import backend as K from 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_data = 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 (Dropout (0.5)) model.add (Dense (1)) model.add (Activation ('sigmoid')) model.compile (loss = 'binary_crossentropy', optimizer = 'rmsprop', metrics = ['precision']) model.load_weights ("model_saved.h5") def pred (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]
Это основной файл python, api.py:
запросы на импорт, 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, фраза): 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 (data)) if num> len (data): num = len (данные) при подсчете
Шаг 7: приложение Electron
Обзор
Мы создадим простое электронное приложение, которое просто позиционирует и загружает элемент PhotoSphere. Файлы main.js и package.json прямо с веб-сайта Electron, а HTML - это слегка измененная версия HTML, представленная на веб-сайте PhotoSphere. Я включил файлы, но все переименовал в.txt, так как Instructables не поддерживает эти типы файлов. Чтобы использовать файлы, переименуйте их с соответствующим расширением.
Код
main.js
const {приложение, BrowserWindow} = require ('электрон')
function 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 ('активировать', () => {если (BrowserWindow.getAllWindows (). length === 0) {createWindow ()}})
package.json
{
"name": "space", "version": "0.1.0", "main": "main.js", "scripts": {"start": "electronic." }}
index.html
Шаг 8: выполнение
Создание равнопрямоугольного изображения
Чтобы создать образ, запустите сценарий api.py в командной строке с активированной виртуальной средой:
api.py
После завершения выполнения сценариев запустите электронное приложение, используя:
npm startВуаля! Ваш планетарий работает! Спасибо за прочтение:)
Рекомендуемые:
Прототип проекта светофора на базе Atmega16 с использованием 7-сегментного дисплея (моделирование Proteus): 5 шагов
Прототип проекта светофора на основе Atmega16 с использованием 7-сегментного дисплея (моделирование Proteus): В этом проекте мы собираемся создать проект светофора на основе Atmega16. Здесь мы взяли один 7 сегментный и 3 светодиода для обозначения сигналов светофора
Мониторинг ускорения с использованием Raspberry Pi и AIS328DQTR с использованием Python: 6 шагов
Мониторинг ускорения с помощью Raspberry Pi и AIS328DQTR с использованием Python: Ускорение конечно, я думаю, в соответствии с некоторыми законами физики. - Терри Райли Гепард использует удивительное ускорение и быстрое изменение скорости при преследовании. Самое быстрое существо, выброшенное на берег, время от времени использует свой максимальный темп, чтобы поймать добычу
Часы на базе Arduino с использованием модуля часов реального времени DS1307 (RTC) и 0,96: 5 шагов
Часы на основе Arduino с использованием модуля часов реального времени DS1307 (RTC) и 0.96: Привет, ребята, в этом руководстве мы увидим, как создать рабочие часы с помощью модуля часов реального времени DS1307 & Дисплей OLED, поэтому мы будем считывать время с модуля часов DS1307. И распечатать на OLED-экране
Робот нейронной сети Arduino: 21 шаг (с изображениями)
Робот нейронной сети Arduino: это руководство основано на серии из трех частей, которую я сделал для канала Make YouTube, в которой показано, как именно создать прототип, спроектировать, собрать и запрограммировать вашего собственного робота нейронной сети Arduino. После просмотра всей серии вы должны сделать ставку
Защищенный от атмосферных воздействий адаптер беспроводной сети с использованием бутылки с водой: 4 шага (с изображениями)
Утилизированный адаптер беспроводной сети с использованием бутылки с водой: Находясь в Ираке, я использовал бутылку с водой для утепления своего адаптера беспроводной сети. Это простая процедура, но очень эффективная. Очевидно, что это руководство будет наиболее полезно для обслуживания мужчин и женщин на Ближнем Востоке, но также может быть полезно