Índice:
2025 Autor: John Day | [email protected]. Última modificação: 2025-01-23 15:03
Neste instrutível, mostrarei como escrevi um gerador de planetário 3D automático, usando Python e Electron
O vídeo acima mostra um dos planetários aleatórios que o programa gerou.
** Nota: Este programa não é de forma alguma perfeito e, em alguns lugares, não é muito pitônico. O discriminador da rede neural é apenas ~ 89% preciso, então algumas imagens estranhas vão chegar ao planetário **
Especificidades
O planetário consulta uma API da NASA para imagens relacionadas ao espaço e utiliza uma rede neural convolucional para determinar se a imagem é adequada para processamento. O programa então usa OpenCV para remover o fundo da imagem e, finalmente, as imagens são costuradas em uma grande imagem equirretangular. Esta imagem é então salva e um aplicativo Electron Node.js abre a imagem e usa o pacote PhotoSphere.js para visualizar a imagem em um formato 3D estilo planetário.
Dependências
Pitão:
- Keras
- Almofada
- cv2
- Numpy
- solicitações de
- urllib
- Aleatória
- Tempo
- io
Elétron:
Fotosfera
Etapa 1: Configurando Seu Ambiente
Instalando Electron e Python
Primeiro, certifique-se de ter o node.js e o npm instalados (se não, você pode fazer o download aqui)
Em seguida, você precisa instalar o Electron. Abra um prompt de comando e digite o seguinte comando:
npm instalar elétron -g
Em seguida, você precisa do python, que pode ser baixado aqui
Configurando um Ambiente Virtual
Abra um prompt de comando e digite os seguintes comandos para configurar seu ambiente virtual:
pip install virtualenv
espaço virtualenv
espaço do cd
scripts / ativar
Instalação de dependências Python
Execute estes comandos no prompt de comando para instalar suas dependências Python:
pip install keras
pip instalar travesseiro
pip install numpy
pedidos de instalação pip
pip install opencv-pythonSe você quiser treinar a rede sozinho, certifique-se de configurar a aceleração de GPU para Keras
Etapa 2: Consultando a API de pesquisa da NASA
Visão geral
A NASA tem muitas APIs realmente úteis que você pode usar em seus projetos. Para este projeto, usaremos a API de pesquisa, que nos permite pesquisar no banco de dados de imagens da NASA por imagens relacionadas ao espaço.
O código
Primeiro, precisamos definir uma função python para aceitar um argumento que funcionará como o termo de pesquisa:
def get_image_search (frase):
passar
Em seguida, converteremos o termo de pesquisa para o formato de URL e, em seguida, usaremos a biblioteca de solicitações para consultar a API:
def get_image_search (frase):
params = {"q": urllib.parse.quote (arg), "media_type": "image"} resultados = requests.get ("https://images-api.nasa.gov/search", params = params)
Por fim, decodificaremos a coleção + string JSON que a API retornou para nós e extrairemos uma lista de links para imagens relacionadas ao termo de pesquisa:
def get_image_search (frase):
params = {"q": urllib.parse.quote (arg), "media_type": "image"} resultados = requests.get ("https://images-api.nasa.gov/search", params = params) data = [result ['href'] para resultado em results.json () ["coleção"] ["itens"]
Aqui vamos nós! Agora temos um trecho de código que pode consultar a API de pesquisa de imagens da NASA e retornar uma lista de links para imagens relacionadas ao nosso termo de pesquisa.
Etapa 3: a rede neural convolucional
Visão geral
O trabalho da rede neural é classificar se uma imagem é de algo no espaço ou não. Para fazer isso, usaremos uma rede neural convolucional, ou CNN, para realizar uma série de operações de matriz na imagem e determinar o quão espacial ela é. Não vou explicar tudo isso, porque há muita teoria por trás disso, mas se você quiser aprender sobre redes neurais, sugiro "Domínio do aprendizado de máquina"
O código
Primeiro, precisamos importar nossas dependências:
importar os
#Fix for issue during train stepn on GPU os.environ ['CUDA_VISIBLE_DEVICES'] = '' importar tensorflow as tf if tf.test.gpu_device_name (): print ('GPU found') else: print ("No GPU found") from keras.preprocessing.image import ImageDataGenerator from keras.preprocessing importar imagem de keras.models import Sequential from keras.layers import Conv2D, MaxPooling2D de keras.layers import Activation, Dropout, Flatten, Dense from keras import backend como K from PIL import Image importar numpy como np
Em seguida, precisamos definir nosso modelo:
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_firsthape': img_firsthape = (3, img_hewidth) = (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 (Ativação ('relu')) model.add (MaxPooling2D (pool_size = (2, 2))) modelo.add (Conv2D (64, (2, 2))) model.add (Activation ('relu')) model.add (MaxPooling2D (pool_size = (2, 2))) model.add (Flatten ()) model. add (Denso (64)) model.add (Ativação ('relu')) model.add (Dropout (0,5)) model.add (Denso (1)) model.add (Ativação ('sigmoid')) model.compile (perda = 'binary_crossentropy', otimizador = 'rmsprop', metrics = ['precisão'])
Eu treinei o modelo para você, mas se você quiser treinar o modelo sozinho, em seu próprio conjunto de dados, anexei o código de treinamento. Caso contrário, você pode baixar o arquivo HDF5 do modelo treinado. Devido às restrições do arquivo Instructables, tive que renomeá-lo com uma extensão ".txt". Para usá-lo, renomeie o arquivo com a extensão ".h5" e carregue-o com este código:
model.load_weights ("model_saved.h5")
Para usar a rede para prever quão espacial é uma imagem, definiremos esta função:
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 result [0] [0]
Etapa 4: Processando a imagem
Visão geral
Para o processamento de imagens, estou usando a biblioteca OpenCV (cv2). Primeiro, borraremos as bordas da imagem e, em seguida, removeremos o fundo criando uma máscara e alterando os valores alfa das cores mais escuras
O código
Esta é a parte da função que desfoca as bordas:
def processImage (img):
RADIUS = 20 # Abra uma imagem im = Image.open ("pilbuffer.png") # Cole a imagem no fundo branco diam = 2 * RADIUS back = Image.new ('RGB', (im.size [0] + diam, im.size [1] + diam), (0, 0, 0)) back.paste (im, (RADIUS, RADIUS)) # Criar máscara de máscara de desfoque = 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) máscara. paste (blck, (diam, diam)) # Desfoque a imagem e cole a borda desfocada de acordo com a máscara blur = back.filter (ImageFilter. GaussianBlur (RADIUS / 2)) back.paste (blur, mask = mask) back.save (" transição-p.webp
Em seguida, definiremos as cores mais escuras como transparentes e salvaremos a imagem temporariamente:
#Criar máscara e filtro substituir preto por alfa
image = cv2.imread ("transaction.png") hMin = 0 sMin = 0 vMin = 20 hMax = 180 sMax = 255 vMax = 255 inferior = np.array ([hMin, sMin, vMin]) superior = np.array ([hMax, sMax, vMax]) hsv = cv2.cvtColor (imagem, cv2. COLOR_BGR2HSV) mask = cv2.inRange (hsv, inferior, superior) output = cv2.bitwise_and (imagem, imagem, máscara = máscara) * _, alfa = cv2.split (output) dst = cv2.merge ((output, alpha)) output = dst com open ("buffer.png", "w +") como arquivo: passe cv2.imwrite ("buffer.png", saída)
Etapa 5: juntando imagens em uma projeção equirretangular
Visão geral
Esta função pega várias imagens e as une em um formato que pode ser interpretado pelo pacote PhotoSphere.js, usando a biblioteca PIL (travesseiro)
O código
Primeiro, precisamos criar uma imagem que possa atuar como hospedeira para as outras imagens:
novo = Image.new ("RGBA", (8000, 4000), cor = (0, 0, 0))
Em seguida, precisamos iterar pela matriz de imagens (que foram redimensionadas para 1000 x 500) e colocá-las na imagem:
h = 0
w = 0 i = 0 para img em img_arr: new.paste (img, (w, h), img) w + = 1000 se w == 8000: h + = 500 w = 0 i + = 1
Agora, acabamos de encerrar isso em uma função que recebe uma matriz de imagens como argumento e retorna a nova imagem:
def stitch_beta (img_arr):
new = Image.new ("RGBA", (8000, 4000), color = (0, 0, 0)) h = 0 w = 0 i = 0 para img em img_arr: new.paste (img, (w, h), img) w + = 1000 se w == 8000: h + = 500 w = 0 i + = 1 return new
Etapa 6: o script Python completo
Este é o script de rede neural Python completo, salvo como net.py e importado para o script principal:
# bibliotecas de importação
import os #Fix para o problema durante a etapa do trem na GPU os.environ ['CUDA_VISIBLE_DEVICES'] = '' importar tensorflow como tf if tf.test.gpu_device_name (): print ('GPU encontrada') else: print ("Nenhuma GPU encontrada ") from keras.preprocessing.image import ImageDataGenerator from keras.preprocessing import image from keras.models import Sequential from keras.layers import Conv2D, MaxPooling2D de keras.layers import Activation, Dropout, Flatten, Dense from keras import backend como K de PIL importar imagem importar numpy como 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._firstata_format = ': 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 (Ativação ('relu')) model.add (MaxPooling2D (pool_size = (2, 2))) model.add (Conv2D (32, (2, 2))) modelo. 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 (Ativação ('relu')) model.add (Dropout (0,5)) model.add (Dense (1)) model.add (Ativação ('sigmoid')) model.compile (loss = 'binary_crossentropy', otimizador = 'rmsprop', metrics = ['precisão']) 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) resultado de retorno [0] [0]
Este é o arquivo python principal, api.py:
solicitações de importação, sys, aleatório, urllib.parse, cv2
from PIL import Image, ImageFilter from io import BytesIO import numpy as np import net def get_image_search (num, frase): count = 0 img_arr = para arg na frase: print (arg) print (f "Contagem de imagem atual: {count } ") i = 0 params = {" q ": urllib.parse.quote (arg)," media_type ":" imagem "} resultados = requests.get (" https://images-api.nasa.gov/search ", params = params) data = [result ['href'] para o resultado em results.json () [" coleção "] [" itens "] print (len (data)) if num> len (data): num = len (dados) enquanto contagem
Etapa 7: o aplicativo Electron
Visão geral
Criaremos um aplicativo de elétrons simples que apenas posiciona e carrega o elemento PhotoSphere. Os arquivos main.js e package.json vêm direto do site Electron, e o HTML é uma versão ligeiramente modificada do HTML fornecido no site PhotoSphere. Incluí os arquivos, mas renomei todos para.txt, pois o Instructables não permite esses tipos de arquivo. Para usar os arquivos, renomeie-os com a extensão apropriada.
O código
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 ()}})
package.json
{
"name": "space", "version": "0.1.0", "main": "main.js", "scripts": {"start": "electron." }}
index.html
Etapa 8: Execução
Criação da imagem equirretangular
Para criar a imagem, execute o script api.py no prompt de comando, com seu ambiente virtual ativado:
api.py
Após a conclusão dos scripts de execução, execute o aplicativo electron usando:
npm startVoila! Seu planetário está ativo! Obrigado por ler:)
Recomendado:
Relógio digital de hora da rede usando o ESP8266: 4 etapas (com imagens)
Relógio digital de horário de rede usando o ESP8266: Aprendemos como construir um pequeno relógio digital bonito que se comunica com servidores NTP e exibe o horário da rede ou da Internet. Usamos o WeMos D1 mini para conectar a uma rede WiFi, obter o tempo NTP e exibi-lo em um módulo OLED. O vídeo acima t
Meça a frequência da rede elétrica usando o Arduino: 7 etapas (com imagens)
Medir a frequência da rede elétrica usando o Arduino: Em 3 de abril, o primeiro-ministro da Índia, Shri. Narendra Modi apelou aos indianos para que apagassem suas luzes e acendessem uma lâmpada (Diya) às 21h do dia 5 de abril para marcar a luta da Índia contra o vírus Corona. Logo após o anúncio, houve um grande caos
Inversor conectado à rede DIY (não alimenta a rede) Alternativa de UPS: 7 etapas (com fotos)
Inversor DIY Grid Tied (não alimenta a rede) Alternativa de UPS: Este é um post de acompanhamento do meu outro Instructable sobre como fazer um inversor de rede que não realimenta a rede, uma vez que agora é sempre possível fazer isso em certas áreas como um projeto DIY e alguns lugares não permitem a alimentação lá g
Isso é uma mão? (Câmera Raspberry Pi + Rede Neural) Parte 1/2: 16 etapas (com imagens)
Isso é uma mão? (Câmera Raspberry Pi + Rede Neural) Parte 1/2: Alguns dias atrás, machuquei meu pulso direito na academia. Depois disso, toda vez que eu usava o mouse do computador, ele causava muita dor por causa do ângulo inclinado do pulso. Foi quando me dei conta " não seria ótimo se pudéssemos converter qualquer superfície em um trackp
Robô de rede neural Arduino: 21 etapas (com imagens)
Robô de rede neural Arduino: este instrutível é baseado em uma série de 3 partes que fiz para o canal Make YouTube, que mostra exatamente como prototipar, projetar, montar e programar seu próprio robô de rede neural Arduino. Depois de assistir a série completa, você deve ter uma bette