您好,登錄后才能下訂單哦!
本文小編為大家詳細介紹“如何用Python監控NASA TV直播畫面”,內容詳細,步驟清晰,細節處理妥當,希望這篇“如何用Python監控NASA TV直播畫面”文章能幫助大家解決疑惑,下面跟著小編的思路慢慢深入,一起來學習新知識吧。
https://replit.com/@PaoloAmoroso/spacestills
這是一個具有GUI的簡單系統,它訪問feed流并從Web下載數據。該程序僅需350行代碼,并依賴于一些開源的Python庫。
Spacestills會定期從feed流中下載NASA TV靜止幀并將其顯示在GUI中。
該程序可以校正幀的縱橫比,并將其保存為PNG格式。它會自動下載最新的幀,并提供手動重新加載,禁用自動重新加載或更改下載頻率的選項。
Spacestillsis是一個比較初級的版本,但是它可以做一些有用的事情:捕獲并保存NASA TV直播的太空事件圖像。太空愛好者經常在社交網絡或論壇共享他們從NASA TV手動獲取的屏幕截圖。Spacestills節省了使用屏幕捕獲工具的時間,并保存了可供共享的圖像文件。您可以在Replit上在線運行Spacestills。
筆者用Replit開發了Spacestills。Replit是云上的開發,部署和協作環境,它支持包括Python在內的數十種編程語言和框架。作為Chrome操作系統和云計算愛好者,筆者非常喜歡Replit,因為它可以在瀏覽器中完全正常運行,無需下載或安裝任何內容。
Spacestills依賴于一些外部資源和Python庫。
肯尼迪航天中心的網站上有一個頁面,其中包含精選的NASA視頻流,包括NASA電視公共頻道。feed流顯示最新的靜止幀并自動更新。
每個feed都帶有三種尺寸的幀,Spacestills依賴于具有704x408像素幀的最大NASA TV feed流。最大更新頻率為每45秒一次。因此,檢索最新的靜止幀就像從feed流的URL下載JPEG圖像一樣簡單。
原始圖像被垂直拉伸,看起來很奇怪。因此,該程序可以通過壓縮圖像并生成未失真的16:9版本來校正縱橫比。
因PySimpleGUI的原因需要安裝 Python 3.6 版本。
Pillow:圖像處理
PySimpleGUI:GUI框架(Spacestills使用Tkinter后端)
Request:HTTP請求
from io import BytesIO
from datetime import datetime, timedelta
from pathlib import Path
import requests
from requests.exceptions import Timeout
from PIL import Image
import PySimpleGUI as sg
FEED_URL = 'https://science.ksc.nasa.gov/shuttle/countdown/video/chan2large.jpg'
# Frame size without and with 16:9 aspect ratio correction
WIDTH = 704
HEIGHT = 480
HEIGHT_16_9 = 396
# Minimum, default, and maximum autoreload interval in seconds
MIN_DELTA = 45
DELTA = MIN_DELTA
MAX_DELTA = 300
class StillFrame():
"""Holds a still frame.
The image is stored as a PNG PIL.Image and kept in PNG format.
Attributes
----------
image : PIL.Image
A still frame
original : PIL.Image
Original frame with wchich the instance is initialized, cached in case of
resizing to the original size
Methods
-------
bytes : Return the raw bytes
resize : Resize the screenshot
new_size : Calculate new aspect ratio
"""
def __init__(self, image):
"""Convert the image to PNG and cache the converted original.
Parameters
----------
image : PIL.Image
Image to store
"""
self.image = image
self._topng()
self.original = self.image
def _topng(self):
"""Convert image format of frame to PNG.
Returns
-------
StillFrame
Frame with image in PNG format
"""
if not self.image.format == 'PNG':
png_file = BytesIO()
self.image.save(png_file, 'png')
png_file.seek(0)
png_image = Image.open(png_file)
self.image = png_image
return self
def bytes(self):
"""Return raw bytes of a frame image.
Returns
-------
bytes
Byte stream of the frame image
"""
file = BytesIO()
self.image.save(file, 'png')
file.seek(0)
return file.read()
def new_size(self):
"""Return image size toggled between original and 16:9.
Returns
-------
2-tuple
New size
"""
size = self.image.size
original_size = self.original.size
new_size = (WIDTH, HEIGHT_16_9) if size == original_size else (WIDTH, HEIGHT)
return new_size
def resize(self, new_size):
"""Resize frame image.
Parameters
----------
new_size : 2-tuple
New size
Returns
-------
StillFrame
Frame with image resized
"""
if not(self.image.size == new_size):
self.image = self.image.resize(new_size)
return self
def make_blank_image(size=(WIDTH, HEIGHT)):
"""Create a blank image with a blue background.
Parameters
----------
size : 2-tuple
Image size
Returns
-------
PIL.Image
Blank image
"""
image = Image.new('RGB', size=size, color='blue')
return image
def download_image(url):
"""Download current NASA TV image.
Parameters
----------
url : str
URL to download the image from
Returns
-------
PIL.Image
Downloaded image if no errors, otherwise blank image
"""
try:
response = requests.get(url, timeout=(0.5, 0.5))
if response.status_code == 200:
image = Image.open(BytesIO(response.content))
else:
image = make_blank_image()
except Timeout:
image = make_blank_image()
return image
def refresh(window, resize=False, feed=FEED_URL):
"""Display the latest still frame in window.
Parameters
----------
window : sg.Window
Window to display the still to
feed : string
Feed URL
Returns
-------
StillFrame
Refreshed screenshot
"""
still = StillFrame(download_image(feed))
if resize:
still = change_aspect_ratio(window, still, new_size=(WIDTH, HEIGHT_16_9))
else:
window['-IMAGE-'].update(data=still.bytes())
return still
def change_aspect_ratio(window, still, new_size=(WIDTH, HEIGHT_16_9)):
"""Change the aspect ratio of the still displayed in window.
Parameters
----------
window : sg.Window
Window containing the still
new_size : 2-tuple
New size of the still
Returns
-------
StillFrame
Frame containing the resized image
"""
resized_still = still.resize(new_size)
window['-IMAGE-'].update(data=resized_still.bytes())
return resized_still
def save(still, path):
"""Save still to a file.
Parameters
----------
still : StillFrame
Still to save
path : string
File name
Returns
-------
Boolean
True if file saved with no errors
"""
filename = Path(path)
try:
with open(filename, 'wb') as file:
file.write(still.bytes())
saved = True
except OSError:
saved = False
return saved
def next_timeout(delta):
"""Return the moment in time right now + delta seconds from now.
Parameters
----------
delta : int
Time in seconds until the next timeout
Returns
-------
datetime.datetime
Moment in time of the next timeout
"""
rightnow = datetime.now()
return rightnow + timedelta(seconds=delta)
def timeout_due(next_timeout):
"""Return True if the next timeout is due.
Parameters
----------
next_timeout : datetime.datetime
Returns
-------
bool
True if the next timeout is due
"""
rightnow = datetime.now()
return rightnow >= next_timeout
def validate_delta(value):
"""Check if value is an int within the proper range for a time delta.
Parameters
----------
value : int
Time in seconds until the next timeout
Returns
-------
int
Time in seconds until the next timeout
bool
True if the argument is a valid time delta
"""
isinteger = False
try:
isinteger = type(int(value)) is int
except Exception:
delta = DELTA
delta = int(value) if isinteger else delta
isvalid = MIN_DELTA <= delta <= MAX_DELTA
delta = delta if isvalid else DELTA
return delta, isinteger and isvalid
LAYOUT = [[sg.Image(key='-IMAGE-')],
[sg.Checkbox('Correct aspect ratio', key='-RESIZE-', enable_events=True),
sg.Button('Reload', key='-RELOAD-'),
sg.Button('Save', key='-SAVE-'),
sg.Exit()],
[sg.Checkbox('Auto-reload every (seconds):', key='-AUTORELOAD-',
default=True),
sg.Input(DELTA, key='-DELTA-', size=(3, 1), justification='right'),
sg.Button('Set', key='-UPDATE_DELTA-')]]
def main(layout):
"""Run event loop."""
window = sg.Window('Spacestills', layout, finalize=True)
current_still = refresh(window)
delta = DELTA
next_reload_time = datetime.now() + timedelta(seconds=delta)
while True:
event, values = window.read(timeout=100)
if event in (sg.WIN_CLOSED, 'Exit'):
break
elif ((event == '-RELOAD-') or
(values['-AUTORELOAD-'] and timeout_due(next_reload_time))):
current_still = refresh(window, values['-RESIZE-'])
if values['-AUTORELOAD-']:
next_reload_time = next_timeout(delta)
elif event == '-RESIZE-':
current_still = change_aspect_ratio(
window, current_still, current_still.new_size())
elif event == '-SAVE-':
filename = sg.popup_get_file(
'File name', file_types=[('PNG', '*.png')], save_as=True,
title='Save image', default_extension='.png')
if filename:
saved = save(current_still, filename)
if not saved:
sg.popup_ok('Error while saving file:', filename, title='Error')
elif event == '-UPDATE_DELTA-':
# The current cycle should complete at the already scheduled time. So
# don't update next_reload_time yet because it'll be taken care of at the
# next -AUTORELOAD- or -RELOAD- event.
delta, valid = validate_delta(values['-DELTA-'])
if not valid:
window['-DELTA-'].update(str(DELTA))
window.close()
del window
if __name__ == '__main__':
main(LAYOUT)
讀到這里,這篇“如何用Python監控NASA TV直播畫面”文章已經介紹完畢,想要掌握這篇文章的知識點還需要大家自己動手實踐使用過才能領會,如果想了解更多相關內容的文章,歡迎關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。