Обработка снимка звездного неба и получение координат звезд

Автор
avatar-nkapyrinnkapyrin
Notebook

Обработка изображения звездного неба и получение координат звезд

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

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

Входная информация для алгоритма

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

Полезным источником снимков звездного неба, сделанных в любых условиях, является сайт проекта https://nova.astrometry.net/

Типичный кадр со звездного датчика выглядит следующим образом:

photo1713619559.jpeg

Мы видим немного шума, разные зоны яркости (погрешности сенсора или первичной обработки) и размытие движением. Всё это не помешает нам найти центроиды звезд, а затем, зная параметры камеры, определить координаты каждой звезды в сферической системе координат, привязанной к камере.

Прежде всего – вот сокращенный вариант кода, который мы получим после всех испытаний.

In [ ]:
#using Pkg; Pkg.add( [ "Images", "IndirectArrays", "ImageBinarization", "ImageContrastAdjustment", "ImageDraw", "ImageFiltering", "ImageMorphology", "FFTW",  ], io=devnull )

using Images, ImageDraw, FileIO, FFTW, Statistics, IndirectArrays
using ImageBinarization, ImageContrastAdjustment, ImageFiltering, ImageMorphology
gr( leg=:false )

# Загрузка и предобработка
img = load( "photo1713619559.jpeg" )[1:end, 1:end-2]
img = binarize(img, MinimumError() ) 
#img = adjust_histogram( img, AdaptiveEqualization(nbins = 256, rblocks = 4, cblocks = 4, clip = 0.2))

# Сегментация
bw = Gray.(img) .> 0.7
labels = label_components( bw )
centers = component_centroids( labels )

# Первый график
src_img_temp = load( "photo1713619559.jpeg" )[1:end, 1:end-2]
[ draw!( src_img_temp, Ellipse(CirclePointRadius( Point(Int32.(round.([cy, cx]))...), 10; thickness = 5, fill = false)), RGB{N0f8}(1,0,0) ) for (cx,cy) in centers ]
p1 = plot( src_img_temp, showaxis=:false, grid=:false, ticks=:false, aspect_ratio=:equal )

# Второй график
(w,h), f = floor.(size(img)), 0.05
p2 = plot3d( camera=(60,20) )
for (cx,cy) in centers
    (scx,scy) = (.1 .* [w/h, 1] ./ 2) .* ([cx,cy] .- [w,h]./2) ./ [w,h]./2
    Pi = 1/(sqrt(scx^2 + scy^2 + f^2)) * [f; scy;-scx]
    plot!( p2, [0,Pi[1]], [0,Pi[2]], [0,Pi[3]], leg=:false, xlimits=(-0.1,1.1), ylimits=(-.3,.3), zlimits=(-.3,.3),
        showaxis=:true, grid=:true, ticks=:true, linealpha=.4, markershape=[:none, :star], markersize=[0, 2.5],
        title="Количество звезд: $(length(centers))", titlefontsize=10)
end

plot( p1, p2, size=(800,300) )
Out[0]: