רשת עצבית מונעת פלנטריום באמצעות פייתון, אלקטרון וקראס: 8 שלבים
רשת עצבית מונעת פלנטריום באמצעות פייתון, אלקטרון וקראס: 8 שלבים
Anonim
רשת עצבית מונעת פלנטריום באמצעות פייתון, אלקטרון וקראס
רשת עצבית מונעת פלנטריום באמצעות פייתון, אלקטרון וקראס

במדריך זה, אראה לך כיצד כתבתי מחולל פלנטריום תלת מימדי אוטומטי, באמצעות פייתון ואלקטרון

הסרטון למעלה מציג את אחד הפלנטריומים האקראיים שהתוכנית יצרה.

** הערה: התוכנית הזו בשום אופן לא מושלמת ובמקומות מסוימים לא מאוד פיתונית. מפלה הרשת העצבית מדויקת רק ~ 89%, כך שתמונות מוזרות יכנסו לפלנטריום **

פרטים

הפלנטריום מבקש API של NASA לתמונות הקשורות לחלל, ומשתמש ברשת עצבית מתפתלת כדי לקבוע אם התמונה מתאימה לעיבוד. לאחר מכן התוכנית משתמשת ב- OpenCV כדי להסיר את הרקע מהתמונה, ולבסוף התמונות נתפרות יחד לתמונה אחת גדולה -מלבנית. תמונה זו נשמרת ואז יישום Electron Node.js פותח את התמונה ומשתמש בחבילת PhotoSphere.js כדי להציג את התמונה בפורמט תלת מימדי בסגנון פלנטריום.

תלות

פִּיתוֹן:

  • קראס
  • כרית
  • cv2
  • מגושם
  • בקשות
  • urllib
  • אַקרַאִי
  • זְמַן
  • io

אֶלֶקטרוֹן:

PhotoSphere

שלב 1: הגדרת הסביבה שלך

התקנת אלקטרון ופייתון

ראשית, ודא שהתקנת node.js ו- npm (אם לא, תוכל להוריד כאן)

לאחר מכן, עליך להתקין את אלקטרון. פתח שורת פקודה והזן את הפקודה הבאה:

npm התקן אלקטרון -g

לאחר מכן, אתה צריך פייתון, אותו ניתן להוריד כאן

הקמת סביבה וירטואלית

פתח שורת פקודה ולאחר מכן הזן את הפקודות הבאות כדי להגדיר את הסביבה הווירטואלית שלך:

pip להתקין virtualenv

שטח virtualenv

שטח תקליטורים

סקריפטים / הפעל

התקנת תלות ב- Python

הפעל פקודות אלה בשורת הפקודה כדי להתקין את התלות שלך בפייתון:

pip להתקין keras

פיפ להתקין כרית

pip להתקין numpy

בקשות להתקנת pip

pip התקן opencv-pythonאם אתה רוצה לאמן את הרשת בעצמך, הקפד להגדיר האצת GPU עבור Keras

שלב 2: שאילתת ה- API של חיפוש NASA

סקירה כללית

ל- NASA יש הרבה ממשקי API ממש שימושיים שתוכלו להשתמש בהם עם הפרויקטים שלכם. עבור פרויקט זה נשתמש בממשק API לחיפוש, המאפשר לנו לחפש במאגר התמונות של נאס א תמונות הקשורות לחלל.

הקוד

ראשית, עלינו להגדיר פונקציית פייתון כדי לקבל טיעון שישמש כמונח החיפוש:

def get_image_search (ביטוי):

לַעֲבוֹר

לאחר מכן, נמיר את מונח החיפוש לתבנית כתובת אתר, ולאחר מכן נשתמש בספריית הבקשות לשאילתת ה- 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 של חיפוש תמונות של NASA, ולהחזיר רשימה של קישורים לתמונות הקשורות למונח החיפוש שלנו.

שלב 3: הרשת העצבית המתפתחת

סקירה כללית

תפקידה של הרשת העצבית הוא לסווג אם דימוי הוא של משהו בחלל, או לא. לשם כך נשתמש ברשת עצבית מתפתלת, או CNN, לביצוע שורה של פעולות מטריצה בתמונה, ונקבע עד כמה היא רווח- y. אני לא אסביר את כל זה, כי יש הרבה תיאוריה מאחורי זה, אבל אם אתה רוצה ללמוד על רשתות עצביות, אני מציע "לימוד מכונה שליטה"

הקוד

ראשית, עלינו לייבא את התלות שלנו:

ייבוא מערכת הפעלה

#תיקון לבעיה במהלך שלב רכבת ב- GPU os.environ ['CUDA_VISIBLE_DEVICES'] = '' ייבא tensorflow כ- tf אם tf.test.gpu_device_name (): הדפס ('GPU נמצא') אחר: הדפס ("לא נמצא GPU") מאת keras.preprocessing.image import ImageDataGenerator מאת keras.preprosing image image from keras.models יבוא רצף מ- keras.layers ייבוא Conv2D, MaxPooling2D מ- keras.layers ייבוא הפעלה, נשירה, שיטוח, צפוף מאחזור יבוא של keras כמו 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 () == 'channel_first': input_shape = (3, img_ = (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 (הפעלה ('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 ()) דגם. הוסף (Dense (64)) model.add (Activation ('relu')) model.add (Dropout (0.5)) model.add (Dense (1)) model.add (Activation ('sigmoid')) model.compile (loss = 'binary_crossentropy', אופטימיזר = 'rmsprop', מדדים = ['דיוק'])

הכשרתי את המודל עבורך, אבל אם תרצה לאמן את המודל בעצמך, על בסיס הנתונים שלך, אז צירפתי את קוד האימון. אחרת, תוכל להוריד את קובץ ה- 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, axis = 0) result = model.predict_classes (img) תוצאת החזרה [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)) # צור מסכת טשטוש לטשטוש = 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) מסכה. הדבק (blck, (diam, diam)) # טשטוש תמונה והדבק קצה מטושטש לפי טשטוש מסכה = back.filter (ImageFilter. GaussianBlur (RADIUS / 2)) back.paste (טשטוש, מסכה = מסכה) 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, תחתון, עליון) פלט = cv2.bitwise_and (תמונה, תמונה, מסכה = מסכה) *_, אלפא = cv2.split (פלט) dst = cv2.merge ((פלט, אלפא)) פלט = dst עם פתוח ("buffer.png", "w+") כקובץ: העבר cv2.imwrite ("buffer.png", פלט)

שלב 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 += החזר אחד חדש

שלב 6: סקריפט Python המלא

זהו סקריפט הרשת העצבית המלאה של פייתון, השמורה כ- net.py, ומיובאת לתסריט הראשי:

# ייבוא ספריות

יבוא OS #תיקון להנפקה במהלך שלב רכבת ב- GPU os.environ ['CUDA_VISIBLE_DEVICES'] = '' ייבא tensorflow כ- tf אם tf.test.gpu_device_name (): הדפס ('GPU נמצא') אחר: הדפס ("לא נמצא GPU ") מאת keras.preprocessing.image ייבוא ImageDataGenerator מ keras.preprosing תמונת יבוא מ keras.models יבוא רצף מ- keras.layers ייבוא Conv2D, MaxPooling2D מ- keras.layers ייבוא הפעלה, נשירה, שטחים, צפוף מאחורי יבוא keras כמו K מ- 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 = 8 if K.imat_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 (הפעלה ('relu')) model.add (MaxPooling2D (pool_size = (2, 2))) model.add (Conv2D (32, (2, 2))) דגם. הוסף (הפעלה ('relu')) model.add (MaxPooling2D (pool_size = (2, 2))) model.add (Conv2D (64, (2, 2))) model.add (הפעלה ('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, axis = 0) result = model.predict_classes (img) תוצאה חזרה [0] [0]

זהו קובץ הפיתון הראשי, api.py:

בקשות ייבוא, sys, random, urllib.parse, cv2

מ- PIL image image, ImageFilter מ- io import BytesIO import numpy as np import net def get_image_search (num, phrase): 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 (נתונים) בזמן הספירה = num: print print (f "\ n {count} images retreived") החזר 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 if w == 8000: h += 500 w = 0 i += 1 החזר תהליך def חדש חדש תמונה (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] - diam, im.size [1] - diam), 0) mask.paste (blck, (diam, diam)) # טשטוש תמונה והדבק קצה מטושטש לפי טשטוש מסכה = back.filter (ImageFilter. GaussianBlur (RADIUS / 2)) back.paste (טשטוש, מסכה = מסכה) back.save ("transit.png") back.close () #צור מסכה וסנן החלף שחור באלפא image = cv2.imread (" מַעֲבָר ion.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, תחתון, עליון) פלט = 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) הדפסה ("תמונות שאוחזרו וסיננו עצבי") img = stitch_beta (img_arr) הדפסה ("תמונות תפורות") img.save ("stitched.png")

שלב 7: אפליקציית האלקטרונים

סקירה כללית

ניצור אפליקציית אלקטרונים פשוטה שממקמת ומטעינה רק את אלמנט ה- PhotoSphere. הקבצים main.js ו- package.json מגיעים ישירות מאתר Electron, ו- HTML הוא גרסה מעט שונה של ה- HTML המסופק באתר PhotoSphere. צירפתי את הקבצים, אך שמתי את כולם ל.txt, מכיוון ש- Instructables אינו מתיר סוגי קבצים אלה. כדי להשתמש בקבצים, שנה את שמו בתוסף המתאים.

הקוד

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 (). לאחר מכן (createWindow) app.on ('window-all-closed', () => {if (process.platform! == 'darwin') {app.quit ()}}) app.on ('activ', () => {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 התחלהוואלה! הפלנטריום שלך פעיל! תודה שקראתם:)

מוּמלָץ: