Привет, Хабр.

Как было написано в недавнем анонсе, с 24 по 31 декабря производится передача изображений формата SSTV с МКС. Передача идет в радиолюбительском диапазоне на частоте 145.800 МГц и принять её может любой желающий.

МКС (c) https://en.wikipedia.org/wiki/International_Space_Station

Посмотрим, как это работает и как такой сигнал можно декодировать.

Общие сведения

Передача изображений с МКС производится в рамках проекта “О Гагарине из космоса”, вполне благородная цель которого – привлечь внимание к космонавтике. Передачи осуществляются несколько раз в год, любой желающий в любой точке мира может принять изображения формата SSTV на частоте 145.8 МГц. SSTV (Slow-scan television) – это формат передачи изображений с малой скоростью. Сам формат появился весьма давно, таким способом передавались еще изображения обратной стороны Луны со станции “Луна-3“. Гораздо позже он нашел популярность у радиолюбителей, т.к. позволял передавать изображения на коротких волнах при помощи обычного радиопередатчика. С некоторыми изменениями формат 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 – в одной линии передаются каналы яркости для двух строк и общий канал цвета, таким образом, цветовое разрешение картинки вдвое меньше чем яркостное. Итоговое разрешение составляет 640х480 – всего передается 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) за то, что проводят и поддерживают подобные акции. Это отличная возможность для радиолюбителей, школьников и студентов прикоснуться к освоению космоса.

Let’s block ads! (Why?)

Read More

Recent Posts

VK купила 40% билетной платформы Intickets.ru

VK объявляет о приобретении 40% компании Intickets.ru (Интикетс). Это облачный сервис для контроля и управления продажей билетов на мероприятия. Сумма…

11 часов ago

OpenAI готовится запустить поисковую систему на базе ChatGPT

OpenAI готовится запустить собственную поисковую систему на базе ChatGPT. Информацию об этом публикуют западные издания. Ожидается, что новый поисковик может…

20 часов ago

Роскомнадзор рекомендовал хостинг-провайдерам ограничить сбор данных с сайтов для иностранных ботов

Центр управления связью общего пользования (ЦМУ ССОП) Роскомнадзора рекомендовал компаниям из реестра провайдеров ограничить доступ поисковых ботов к информации на российских сайтах.…

2 дня ago

Apple возобновила переговоры с OpenAI и Google для интеграции ИИ в iPhone

Apple возобновила переговоры с OpenAI о возможности внедрения ИИ-технологий в iOS 18, на основе данной операционной системы будут работать новые…

7 дней ago

Российская «дочка» Google подготовила 23 иска к крупнейшим игрокам рекламного рынка

Конкурсный управляющий российской «дочки» Google подготовил 23 иска к участникам рекламного рынка. Общая сумма исков составляет 16 млрд рублей –…

7 дней ago

Google завершил обновление основного алгоритма March 2024 Core Update

Google завершил обновление основного алгоритма March 2024 Core Update. Раскатка обновлений была завершена 19 апреля, но сообщил об этом поисковик…

7 дней ago