Hello, Habr.
As it was written in the recent announcement , from December 24 to December 31, SSTV images are being transmitted from the ISS. The transmission is in the amateur radio band at a frequency of 145.800 MHz and anyone can receive it.
Let's see how it works and how such a signal can be decoded.
General information
" ", - . , SSTV 145.8 . SSTV (Slow-scan television) - . , -3. SSTV , .. . SSTV ( , , ) . - , , - RTL-SDR 35$. , , SSTV .
.. , . - Orbitron, n2yo.com .
, SSTV . 145.800 , , RTL-SDR V3. 35$ , :
, :
, , virtal audio card SDR -.
SSTV, 2-3 . , .
:
SSTV , , PD-120 ( ) 0.5. , 1500 , 2300 .
band-pass , :
import scipy.io.wavfile as wav
import scipy.signal as signal
import numpy as np
import matplotlib.pyplot as plt
from PIL import Image
fs, data = wav.read('HDSDR_20201228_075406Z_145803kHz_AF.wav')
def butter_bandpass(lowcut, highcut, fs, order=5):
nyq = 0.5 * fs
low = lowcut / nyq
high = highcut / nyq
b, a = signal.butter(order, [low, high], btype='band')
return b, a
def butter_bandpass_filter(data, lowcut, highcut, fs, order=5):
b, a = butter_bandpass(lowcut, highcut, fs, order=order)
y = signal.lfilter(b, a, data)
return y
data1 = butter_bandpass_filter(data, 1400, 2200, fs, order=4)
. , , :
data_fsk = np.zeros(len(data1))
pos1 = 0
for p in range(0, len(data1)-1):
if np.sign(data1[p]) != np.sign(data1[p+1]):
pr = p - pos1
data_fsk[pos1:p] = np.full(p - pos1, pr)
pos1 = p
"" 2D-:
frame_width = int(0.5*fs) + 203
w, h = frame_width, data_fsk.shape[0]//frame_width
image = Image.new('RGB', (w, h))
data_2d = data_fsk[:w*h].reshape((h,w))
for py in range(h):
for px in range(w):
lum = int(data_2d[py][px]*16)
if lum < 0: lum = 0
if lum > 255: lum = 255
image.putpixel((px, py), (lum, lum, lum))
:
plt.imshow(image) plt.show()
. 4 . YCrCb, , Y1CrCbY2 - , , . 640480 - 240 , , , 2 .
, 0.5, 240 120, .. 2 . PD-120 .
YCrCb => RGB:
image_rgb = Image.new('RGB', (w//4, 2*h))
for py in range(h):
for px in range(int(0.125*fs)):
# PD-120 – 640×480, 190 ?s/pixel
k = 32
y0 = 255 - k*data_2d[py][px]
cr = 255 - k*data_2d[py][px + int(0.1216*fs)]
cb = 255 - k*data_2d[py][px + 2*int(0.1216*fs)]
y1 = 255 - k*data_2d[py][px + 3*int(0.1216*fs)]
image_rgb.putpixel((px, 2*py), (int(y0 + 1.402 * cr), int(y0 - 0.34414 * cb - 0.71414 * cr), int(y0 + 1.772 * cb)))
image_rgb.putpixel((px, 2*py + 1), (int(y1 + 1.402 * cr), int(y1 - 0.34414 * cb - 0.71414 * cr), int(y1 + 1.772 * cb)))
, - , :
, SSTV, , :
, . , , 31 ( , ). , Python, SSTV .
ARISS (Amateur Radio on the International Space Station) . , .