Spisu treści:
2025 Autor: John Day | [email protected]. Ostatnio zmodyfikowany: 2025-01-23 15:02
W tej instrukcji pokażę, jak napisałem automatyczny generator planetarium 3D, używając Pythona i Electrona
Powyższy film przedstawia jedno z losowych planetariów wygenerowanych przez program.
**Uwaga: ten program nie jest w żaden sposób doskonały, aw niektórych miejscach niezbyt pytoniczny. Dyskryminator sieci neuronowej jest dokładny tylko w ~89%, więc niektóre dziwne obrazy trafią do planetarium**
Specyfika
Planetarium wysyła zapytanie do NASA API o obrazy związane z przestrzenią kosmiczną i wykorzystuje splotową sieć neuronową, aby określić, czy obraz nadaje się do przetwarzania. Następnie program używa OpenCV do usunięcia tła z obrazu, a na koniec obrazy są łączone w jeden duży, równoprostokątny obraz. Obraz ten jest następnie zapisywany, a aplikacja Electron Node.js otwiera obraz i używa pakietu PhotoSphere.js do wyświetlania obrazu w formacie 3D w stylu planetarium.
Zależności
Pyton:
- Keras
- Poduszka
- cv2
- Numpy
- Upraszanie
- urllib
- Losowy
- czas
- ja
Elektron:
Fotosfera
Krok 1: Konfiguracja środowiska
Instalowanie Electron i Pythona
Najpierw upewnij się, że masz zainstalowane node.js i npm (jeśli nie, możesz pobrać tutaj)
Następnie musisz zainstalować Electron. Otwórz wiersz polecenia i wprowadź następujące polecenie:
npm zainstaluj elektron -g
Następnie potrzebujesz Pythona, który możesz pobrać tutaj
Konfigurowanie środowiska wirtualnego
Otwórz wiersz polecenia, a następnie wprowadź następujące polecenia, aby skonfigurować środowisko wirtualne:
pip zainstaluj virtualenv
przestrzeń wirtualna
miejsce na cd
skrypty\aktywuj
Instalowanie zależności Pythona
Uruchom te polecenia w wierszu poleceń, aby zainstalować zależności Pythona:
pip zainstalować keras
pip zainstalować poduszkę
pip zainstaluj numpy
prośby o instalację pip
pip zainstaluj opencv-pythonJeśli chcesz samodzielnie szkolić sieć, skonfiguruj akcelerację GPU dla Keras
Krok 2: Wysyłanie zapytań do API wyszukiwania NASA
Przegląd
NASA ma wiele naprawdę przydatnych interfejsów API, których możesz używać w swoich projektach. W tym projekcie użyjemy API wyszukiwania, które pozwoli nam przeszukiwać bazę obrazów NASA pod kątem obrazów związanych z przestrzenią kosmiczną.
Kod
Najpierw musimy zdefiniować funkcję Pythona, aby zaakceptować argument, który będzie działał jako wyszukiwany termin:
def get_image_search(fraza):
przechodzić
Następnie skonwertujemy wyszukiwane hasło do formatu adresu URL, a następnie użyjemy biblioteki żądań do zapytania API:
def get_image_search(fraza):
params = {"q": urllib.parse.quote(arg), "media_type": "image"} results = requests.get("https://images-api.nasa.gov/search", params=params)
Na koniec zdekodujemy ciąg kolekcja+JSON zwrócony przez interfejs API i wyodrębnimy listę linków do obrazów związanych z wyszukiwanym terminem:
def get_image_search(fraza):
params = {"q": urllib.parse.quote(arg), "media_type": "image"} results = requests.get("https://images-api.nasa.gov/search", params=params) data = [wynik['href'] dla wyniku w results.json()["kolekcja"]["elementy"]
No to jedziemy! Mamy teraz fragment kodu, który może wysyłać zapytania do interfejsu API wyszukiwania obrazów NASA i zwracać listę linków do obrazów powiązanych z naszym terminem wyszukiwania.
Krok 3: Splotowa sieć neuronowa
Przegląd
Zadaniem sieci neuronowej jest klasyfikowanie, czy obraz przedstawia coś w przestrzeni, czy nie. Aby to zrobić, użyjemy splotowej sieci neuronowej lub CNN, aby wykonać serię operacji na macierzach na obrazie i określić, jaka jest przestrzeń-y. Nie będę tego wszystkiego wyjaśniał, bo kryje się za tym sporo teorii, ale jeśli chcesz poznać sieci neuronowe, proponuję "Machine Learning Mastery"
Kod
Najpierw musimy zaimportować nasze zależności:
importuj system
#Napraw błąd podczas trenowania stepn na GPU os.environ['CUDA_VISIBLE_DEVICES'] = '' import tensorflow jako tf if tf.test.gpu_device_name(): print('Znaleziono GPU') else: print("Nie znaleziono GPU") z keras.preprocessing.image import ImageDataGenerator z keras.preprocessing import obrazu z keras.models import Sequential z keras.layers import Conv2D, MaxPooling2D z keras.layers import Activation, Dropout, Flatten, Dense z keras import Backend jako K z PIL import Image importuj numer jako np
Następnie musimy zdefiniować nasz model:
szerokość_obrazu, wysokość_obrazu = 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_shapeth =, img_shapeth = (3, = (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()). add(Dense(64)) model.add(Aktywacja('relu')) model.add(Dropout(0.5)) model.add(Dense(1)) model.add(Aktywacja('sigmoid')) model.compile (loss='binary_crossentropy', Optimizer='rmsprop', metrics=['accuracy'])
Wytrenowałem model dla Ciebie, ale jeśli chciałbyś sam trenować model na własnym zbiorze danych, to załączam kod treningowy. W przeciwnym razie możesz pobrać plik HDF5 wytrenowanego modelu. Ze względu na ograniczenia plików Instructables musiałem zmienić jego nazwę na rozszerzenie ".txt". Aby z niego skorzystać, zmień nazwę pliku na rozszerzenie ".h5" i załaduj go tym kodem:
model.load_weights("model_saved.h5")
Aby użyć sieci do przewidywania, jak spacja-y jest na obrazie, zdefiniujemy tę funkcję:
def przewidywać(ścieżka_obrazu):
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]
Krok 4: Przetwarzanie obrazu
Przegląd
Do przetwarzania obrazu używam biblioteki OpenCV (cv2). Najpierw rozmyjemy krawędzie obrazu, a następnie usuniemy tło, tworząc maskę i zmieniając wartości alfa ciemniejszych kolorów
Kod
Oto część funkcji, która zaciera krawędzie:
def processImage(img):
RADIUS = 20 # Otwórz obraz im = Image.open("pilbuffer.png") # Wklej obraz na białym tle diam = 2 * RADIUS back = Image.new('RGB', (im.size[0] + diam, im.size[1] + diam), (0, 0, 0)) back.paste(im, (RADIUS, RADIUS)) # Utwórz maskę rozmycia = 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) maska. paste(blck, (diam, diam)) # Rozmyj obraz i wklej rozmytą krawędź zgodnie z maską blur = back.filter(ImageFilter. GaussianBlur(RADIUS / 2)) back.paste(blur, mask=mask) back.save(" przejście.png") wstecz.zamknij()
Następnie ustawimy ciemniejsze kolory na przezroczyste i tymczasowo zapiszemy obraz:
#Utwórz maskę i filtr zamień czarny na alfa
image = cv2.imread("przejście.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(obraz, cv2. COLOR_BGR2HSV) maska = cv2.inRange(hsv, dolny, górny) output = cv2.bitwise_and(obraz, obraz, maska=maska) *_, alpha = cv2.split(wyjście) dst = cv2.merge((wyjście, alfa)) output = dst z open("buffer.png", "w+") jako plik: pass cv2.imwrite("buffer.png", output)
Krok 5: Łączenie obrazów w projekcję równoboczną
Przegląd
Ta funkcja pobiera wiele obrazów i łączy je w format, który może być interpretowany przez pakiet PhotoSphere.js, przy użyciu biblioteki PIL (poduszka)
Kod
Najpierw musimy stworzyć obraz, który może pełnić rolę hosta dla innych obrazów:
nowy = Obraz.nowy("RGBA", (8000, 4000), kolor=(0, 0, 0))
Następnie musimy przejrzeć tablicę obrazów (które zostały przeskalowane do 1000x500) i umieścić je w obrazie:
h = 0
w = 0 i = 0 dla img w img_arr: new.paste(img, (w, h), img) w += 1000 jeśli w == 8000: h += 500 w = 0 i += 1
Teraz po prostu zapakujemy to w funkcję, która jako argument przyjmuje tablicę obrazów i zwraca nowy obraz:
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: new.paste(img, (w, h), img) w += 1000 jeśli w == 8000: h += 500 w = 0 i += 1 return new
Krok 6: Pełny skrypt Pythona
To jest pełny skrypt sieci neuronowej Pythona, który jest zapisany jako net.py i zaimportowany do głównego skryptu:
# importowanie bibliotek
import os #Napraw problem podczas etapu trenowania na GPU os.environ['CUDA_VISIBLE_DEVICES'] = '' import tensorflow jako tf if tf.test.gpu_device_name(): print('Znaleziono GPU') else: print("Nie znaleziono GPU ") z keras.preprocessing.image import ImageDataGenerator z keras.preprocessing import obrazu z keras.models import Sequential z keras.layers import Conv2D, MaxPooling2D z keras.layers import Activation, Dropout, Flatten, Dense z keras import backendu jako K z 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_st '_channel_st (): 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_saved, target_size=(1000, 500)) img = np.expand_dims(img, axis=0) result=model.predict_classes(img) zwróć wynik [0][0]
To jest główny plik Pythona, api.py:
żądania importu, sys, random, urllib.parse, cv2
z PIL import Image, ImageFilter z io import BytesIO import numpy as np import net def get_image_search(num, fraza): count = 0 img_arr = for arg we frazie: print(arg) print(f"Ilość bieżącego obrazu: {count }") i = 0 params = {"q": urllib.parse.quote(arg), "media_type": "image"} results = requests.get("https://images-api.nasa.gov/search ", params=params) data = [wynik['href'] dla wyniku w results.json()["kolekcja"]["elementy"] print(len(data)) if num > len(data): num = len(dane) podczas count
Krok 7: Aplikacja elektronowa
Przegląd
Stworzymy prostą aplikację elektronową, która tylko pozycjonuje i ładuje element PhotoSphere. Pliki main.js i package.json pochodzą bezpośrednio ze strony Electron, a HTML to nieco zmodyfikowana wersja kodu HTML udostępnionego na stronie PhotoSphere. Dołączyłem pliki, ale zmieniłem nazwę na.txt, ponieważ Instructables nie zezwala na te typy plików. Aby użyć plików, zmień ich nazwy z odpowiednim rozszerzeniem.
Kod
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() } })
pakiet.json
{
"name": "space", "version": "0.1.0", "main": "main.js", "scripts": { "start": "electron." } }
index.html
Krok 8: Wykonanie
Tworzenie obrazu równoprostokątnego
Aby utworzyć obraz, uruchom skrypt api.py w wierszu poleceń z aktywowanym środowiskiem wirtualnym:
api.py
Po zakończeniu wykonywania skryptów uruchom aplikację Electron za pomocą:
początek npmVoila! Twoje planetarium jest aktywne! Dziękuje za przeczytanie:)
Zalecana:
Jak stworzyć swoje pierwsze proste oprogramowanie przy użyciu Pythona: 6 kroków
Jak zrobić swoje pierwsze proste oprogramowanie przy użyciu Pythona: Cześć, witaj w tej instrukcji. Tutaj opowiem jak stworzyć własne oprogramowanie. Tak, jeśli masz pomysł… ale wiesz, jak wdrożyć lub jesteś zainteresowany tworzeniem nowych rzeczy, to jest dla Ciebie… Wymagania wstępne: Powinieneś mieć podstawową wiedzę z
Pulpit nawigacyjny COVID19 na mapie świata (przy użyciu Pythona): 16 kroków
Pulpit nawigacyjny COVID19 na mapie świata (przy użyciu Pythona): Wiem, że prawie każdy z nas zna większość informacji o COVID19. A ta instrukcja dotyczy tworzenia mapy bąbelkowej, aby wykreślić dane w czasie rzeczywistym (przypadków) na mapie świata. Dla większej wygody , dodałem program do repozytorium Github: https://github.co
Eksperymenty z zaawansowanym rejestrowaniem danych (przy użyciu Pythona): 11 kroków
Eksperymenty w zaawansowanym rejestrowaniu danych (przy użyciu Pythona): Istnieje wiele instrukcji dotyczących rejestrowania danych, więc kiedy chciałem zbudować własny projekt rejestrowania, rozejrzałem się po kilku. Niektóre były dobre, inne nie, więc postanowiłem wziąć kilka lepszych pomysłów i stworzyć własną aplikację. Ten wynik
Sterowanie ruchem za pomocą Raspberry Pi i LIS3DHTR, 3-osiowy akcelerometr, przy użyciu Pythona: 6 kroków
Sterowanie ruchem z Raspberry Pi i LIS3DHTR, 3-osiowym akcelerometrem, przy użyciu Pythona: Piękno nas otacza, ale zwykle musimy spacerować po ogrodzie, aby je poznać. - RumiJako wykształcona grupa, którą wydajemy się być, większość naszej energii inwestujemy w pracę przed komputerami i telefonami komórkowymi. Dlatego często pozwalamy naszemu dobremu
Neopixel Ws2812 Rainbow LED Glow z M5stick-C - Uruchamianie Rainbow na Neopixel Ws2812 przy użyciu M5stack M5stick C przy użyciu Arduino IDE: 5 kroków
Neopixel Ws2812 Rainbow LED Glow z M5stick-C | Uruchamianie Rainbow na Neopixel Ws2812 Używając M5stack M5stick C Używając Arduino IDE: Cześć chłopaki, w tej instrukcji dowiemy się, jak używać neopikselowych ws2812 LED lub taśmy LED lub matrycy LED lub pierścienia LED z płytką rozwojową m5stack m5stick-C z Arduino IDE i zrobimy wzór tęczy z nim