Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Воган Ли - Python для хакеров (Библиотека программиста) - 2023.pdf
Скачиваний:
5
Добавлен:
07.04.2024
Размер:
14.76 Mб
Скачать

Проект #12. Получение изображений экзопланет      245

Поскольку экзопланеты — круглые, с гладкими контурами, то их кривые блеска имеют гладкие стороны, значения на которых постепенно увеличиваются или уменьшаются. Это важный факт, так как при поиске экзопланет астрономы неоднократно фиксировали неровные кривые. В разделе практических проектов в конце главы вы используете созданную программу для изучения кривых блеска необычной формы, которая может объясняться внеземными инженерными конструкциями.

Проект #12. Получение изображений экзопланет

К 2025 году три мощных телескопа — два на Земле и один в космосе — при помощи инфракрасного и видимого спектра будут искать экзопланеты размером с Землю. В лучшем сценарии такая экзопланета будет выглядеть как единичный насыщенный пиксель, который также влияет на интенсивность в соседних пикселях, но и этого достаточно для того, чтобы понять, вращается ли эта планета, имеет ли на поверхности континенты и моря, есть ли на ней смена сезонов и погодные явления, а также способна ли там существовать жизнь в известной нам форме.

В этом проекте мы будем симулировать анализ изображения, полученного с телескопов. В качестве заместителя отдаленной экзопланеты мы используем Землю. Таким образом, нам удастся легко соотнести проявление известных характеристик, таких как наличие континентов и океанов, с тем, что мы обнаружим в одном пикселе. Мы рассмотрим цветовую композицию и интенсивность отраженного света, на основе чего сделаем выводы относительно атмосферы, особенностей поверхности и вращения экзопланеты.

ЗАДАЧА

НаписатьпрограммунаPython,котораяпикселизуетизображениеЗемлиирисует график интенсивности красного, зеленого и синего цветовых каналов.

Стратегия

Чтобы продемонстрировать возможности выделения особенностей рельефа и облачных формаций с помощью одного насыщенного пикселя, нам понадобятся всего два изображения: по одному для западного и для восточного полушарий. Специалисты NASA уже сфотографировали оба этих полушария из космоса (рис. 8.12) — что нам весьма на руку.

246      Глава 8. Обнаружение далеких экзопланет

earth_west.png

earth_east.png

Рис. 8.12. Изображения западного и восточного полушарий Земли

Размер этих изображений составляет 474 × 474 пикселя, но такое разрешение слишком велико для будущих изображений экзопланет, где экзопланета будет располагаться всего на девяти пикселях, при этом лишь центральный пиксель будет полностью занят планетой (рис. 8.13).

Рис. 8.13. Изображения earth_west.png и earth_east.png с наложением

9-пиксельной сетки

Нужно уменьшить эти изображения, отобразив их в массив 3 × 3. Поскольку OpenCV использует NumPy, сложности это не составит. Для обнаружения

Проект #12. Получение изображений экзопланет      247

изменений в рельефе экзопланеты нужно извлечь преобладающие цвета (синий, зеленый и красный). OpenCV позволит нам усреднить эти цветовые каналы, после чего мы отобразим результаты с помощью matplotlib.

Код для пикселизатора

Программа pixelator.py загружает два изображения Земли, изменяет их до размера 3 × 3 пикселя, после чего снова увеличивает изображения, но уже до 300 × 300 пикселей. Эти итоговые изображения нужны только для визуализации

исодержат ту же цветовую информацию, что и фрагмент 3 × 3 пикселя. Затем программа усредняет цветовые каналы в обоих измененных изображениях

ирисует график в виде удобных для сопоставления круговых диаграмм. Код программы и два сопутствующих изображения (earth_west.png и earth_east.png) можно скачать с сайта книги. Сохраните их в одном каталоге и не переименовывайте изображения.

Импорт модулей и уменьшение разрешения изображений

Код листинга 8.5 импортирует модули для рисования графика и обработки изображений, после чего загружает эти изображения и уменьшает их разрешение. Сначала он уменьшает каждое изображение до 9 пикселей в виде массива 3 × 3, а затем увеличивает эти упрощенные версии до размера 300 × 300 пикселей, делая их достаточно большими для визуального восприятия, и выводит их на экран.

Листинг 8.5. Импорт модулей, а также загрузка, уменьшение и последующий показ изображений

pixelator.py, часть 1

import numpy as np import cv2 as cv

from matplotlib import pyplot as plt

files = ['earth_west.png', 'earth_east.png']

for file in files:

img_ini = cv.imread(file)

pixelated = cv.resize(img_ini, (3, 3), interpolation=cv.INTER_AREA) img = cv.resize(pixelated, (300, 300), interpolation=cv.INTER_AREA) cv.imshow('Pixelated {}'.format(file), img)

cv.waitKey(2000)

Импортируем NumPy и OpenCV для работы с изображениями и используем matplotlib для представления цветов в виде круговых диаграмм. Затем создаем список имен файлов, содержащих два изображения Земли.

248      Глава 8. Обнаружение далеких экзопланет

Теперь перебираем файлы в созданном списке и с помощью OpenCV загружаем их в качестве массивов NumPy. Напомню, что OpenCV по умолчанию загружает цветные изображения, поэтому добавлять аргументы для этого не нужно.

Наша цель — уменьшить изображение Земли до одного насыщенного пикселя, окруженного пикселями с частичным насыщением. Для уменьшения изображения 474 × 474 пикселя до размера 3 × 3 пикселя мы используем метод OpenCV resize(). Сначала даем будущему новому изображению имя pixelated и передаем методу текущее изображение, новую ширину и высоту в пикселях, а также метод интерполяции. Интерполяция происходит, когда мы изменяем размер и используем известные данные для оценки значений в неизвестных точках. В документации OpenCV рекомендуется использовать для уменьшения изображений метод интерполяции INTER_AREA (подробнее — на странице https:// docs.opencv.org/3.4/da/d54/group__imgproc__transform.html).

Итак, у нас получилось изображение, слишком мелкое для визуализации, поэтому мы снова изменяем его размер, но на этот раз до 300 × 300 пикселей, чтобы проверить результаты. Используем для этого методы интерполяции INTER_ NEAREST или INTER_AREA, поскольку они сохраняют границы пикселей.

Отображаем изображение (рис. 8.14) и с помощью waitKey() приостанавливаем программу на две секунды.

Рис. 8.14. Черно-белое представление пикселизированных цветных изображений

Проект #12. Получение изображений экзопланет      249

Имейте в виду, что нельзя восстановить изображения в их исходное состояние обратным изменением размера до 474 × 474. После усреднения значений пикселей до матрицы 3 × 3 все детали утрачиваются навсегда.

Усреднение цветовых каналов и создание круговых диаграмм

Продолжая цикл for, листинг 8.6 создает и отображает круговые диаграммы для синего, зеленого и красного цветов каждого пикселизированного изображения. Можете сравнить их, чтобы сделать выводы относительно погодных условий планеты, объема суши, ее вращения и т. п.

Листинг 8.6. Разделение и усреднение цветовых каналов, а также создание круговых диаграмм цветов

pixelator.py, часть 2

b, g, r = cv.split(pixelated) color_aves = []

for array in (b, g, r): color_aves.append(np.average(array))

labels = 'Blue', 'Green', 'Red' colors = ['blue', 'green', 'red']

fig, ax = plt.subplots(figsize=(3.5, 3.3)) # Размер в дюймах

_, _, autotexts = ax.pie(color_aves, labels=labels, autopct='%1.1f%%', colors=colors)

for autotext in autotexts: autotext.set_color('white')

plt.title('{}\n'.format(file))

plt.show()

С помощью метода OpenCV split() разделяем синий, зеленый и красный цветовые каналы пикселизированного изображения и записываем результаты в переменные b, g, r. Эти переменные являются массивами, и если вызвать print(b), то вывод должен получиться таким:

[[ 49 93 22] [124 108 65] [ 52 118 41]]

Каждое число представляет пиксель — в данном случае значение синего цвета пикселя на изображении 3 × 3. Чтобы усреднить эти массивы, сначала создаем

250      Глава 8. Обнаружение далеких экзопланет

пустой список, после чего перебираем массивы и вызываем предоставляемый NumPy метод усреднения, добавляя в созданный список его результаты.

Теперь можно создать из средних значений цветов каждого пикселизированного изображения круговые диаграммы. Присваиваем имена цветов переменной labels, которую используем для подписи секторов диаграммы. Далее указываем цвета, которые хотим задать в круговой диаграмме. Таким образом, мы переопределим предустановленные в matplotlib варианты. При создании диаграммы используем соглашение именования fig, ax для обозначения фигуры и оси, вызываем метод subplots() и передаем ему размер фигуры в дюймах.

Поскольку цвета изображений будут отличаться мало, нам нужно указать в каждой секции цвета его процент, чтобы сделать наглядной разницу между ними. К сожалению, по умолчанию matplotlib использует черный текст, который сложно различить на фоне темного фона. Чтобы это исправить, вызываем метод ax.pie() для создания круговых диаграмм и используем его список autotexts . Этот метод возвращает три списка autotexts: один для секций диаграммы, второй для их меток и третий для числовых меток. Нам нужен только последний, поэтому первые два мы считаем неиспользуемыми переменными и обозначаем их нижним подчеркиванием.

Передаем ax.pie() список средних значений цветов и список меток, а также устанавливаем его параметр autopct так, чтобы отображать числа с одним десятичным знаком. Если для этого параметра задать None, то список autotexts возвращен не будет. Завершаем аргументы передачей списка цветов для секций диаграммы.

Список autotexts для первого изображения выглядит так:

[Text(0.1832684031431146, 0.5713253822554821, '40.1%'), Text(-0.5646237442340427,

-0.20297789891298565, '30.7%'), Text(0.36574010704848686, -0.47564080364930983, '29.1%')

Каждый объект Text содержит в виде строки координаты (x, y) и значение в процентах. Все эти данные по-прежнему отображаются черным цветом, поэтому нужно перебрать эти объекты и изменить цвет на white, используя метод set_color(). Теперь осталось установить для диаграмм заголовки в соответствии с именами файлов и отобразить их (рис. 8.15).

Несмотря на похожесть этих диаграмм, они демонстрируют значительные различия. Если вы сравните оригинальные цветные изображения, то увидите, что earth_west.png включает больше океанов и должно давать большую долю синего цвета.

Проект #12. Получение изображений экзопланет      251

Рис. 8.15. Круговые диаграммы, созданные pixelator.py

Рисование графика для одного пикселя

Диаграммы на рис. 8.15 относятся ко всему изображению, то есть сюда входит и часть черного пространства. Для получения же чистого образца можно использовать один насыщенный пиксель в центре каждого изображения (листинг 8.7).

Этот код представляет отредактированную копию pixelator.py, в которой были подписаны измененные строки. Его цифровую копию вы найдете в каталоге

Chapter_8 под названием pixelator_saturated_only.py.

Листинг 8.7. Рисование диаграмм для цветов центрального пикселя пикселизированного изображения

pixelator_saturated_only.py

import cv2 as cv

from matplotlib import pyplot as plt

files = ['earth_west.png', 'earth_east.png']

# Уменьшение изображения до размера 3x3 пикселя for file in files:

img_ini = cv.imread(file)

pixelated = cv.resize(img_ini, (3, 3), interpolation=cv.INTER_AREA) img = cv.resize(pixelated, (300, 300), interpolation=cv.INTER_NEAREST) cv.imshow('Pixelated {}'.format(file), img)

cv.waitKey(2000)

color_values = pixelated[1, 1] # Выбор центрального пикселя

252      Глава 8. Обнаружение далеких экзопланет

# Создание диаграмм

labels = 'Blue', 'Green', 'Red' colors = ['blue', 'green', 'red']

fig, ax = plt.subplots(figsize=(3.5, 3.3)) # Размер в дюймах

_, _, autotexts = ax.pie(color_values, labels=labels, autopct='%1.1f%%', colors=colors)

for autotext in autotexts: autotext.set_color('white')

plt.title('{} Saturated Center Pixel \n'.format(file))

plt.show()

Четыре строки кода в листинге 8.6, которые разделяли изображение и усредняли цветовые каналы, можно заменить на одну строку . Переменная pixelated — это массив NumPy, а [1, 1] представляет в этом массиве ряд 1, столбец 1. Напомню, что Python начинает отсчет от 0, значит, эти значения соответствуют центру массива 3 × 3. Если вывести переменную color_values, то мы получим другой массив.

[108 109 109]

Это значения синего, зеленого и красного цветовых каналов для центрального пикселя, и можно передать их непосредственно в matplotlib . Изменим название диаграммы, чтобы показать, что анализируем только центральный пиксель . На рис. 8.16 приведены итоговые диаграммы.

Рис. 8.16. Диаграммы, построенные на основе одного пикселя с помощью программы pixelator_saturated_only.py