Marcin Modest Trzaska

seestar

Pokusiłem się zbratać z AI, aby sprawdzać pokrycie materiału w mozaice.

☝️
Powiązane wpisy

Seestar Mosaic Coverage, gdzie pojawił się pomysł.

Rekin po raz drugi, gdzie pomysł się rozwinął.

I wpadłem na pomysł, żeby to wykorzystać bardziej praktycznie i zapewnić sobie w miarę równomierne pokrycie.

Mam jakiś stary materiał z IC 1848 — 2617 klatek i zapuściłem skrypt. Oto efekt. wyrównanie mozaiki

Usunął 500 klatek, zmniejszając pokrycie środka i wyrównując tym samym nieco całość.

Teraz przekładając to praktykę:

  1. zgrywam pliki
  2. traktuję je ASTAPem (wywalam najgorsze)
  3. zapuszczam skrypt, aby nieco wyrównać pokrycie
  4. Siril [...]

Nazbieram czegoś nowego i przetestuję.

#Seestar #astrofotografia

— Marcin “czach” Trzaska reply-to: @czach@mastodon.argilus.online

Próbuję po raz drugi ogarnąć Dark Shark Nebula, tym razem na szerzej, to znaczy w trybie mozaiki x2 (czyli pole widzenia Seestara S50 x 4).

Pokrycie fragmentu nieba

Ciekawi mnie, jak to wyjdzie. Na razie za malo materiału, żeby cokolwiek zobaczyć.

Tak przy okazji — na dysku pojawiła się nowa wersja skryptu a tak wygląda wynik jego pracy: Pokrycie fragmentu nieba

#!/usr/bin/env python3
"""
seestar_mosaic_coverage.py

Wczytuje pliki FIT (Seestar, tryb mozaiki) z podanego folderu i rysuje
mape pokrycia nieba: kolorem pokazuje, ile klatek pokrywa dany fragment.
"""

import argparse
import glob
import os
import sys

import numpy as np
from astropy.io import fits
from astropy.wcs import WCS
import matplotlib.pyplot as plt
from matplotlib.path import Path as MplPath
from matplotlib.ticker import MaxNLocator

# ---------- odczyt naglowkow ----------

RA_KEYS = ["RA", "OBJCTRA", "CRVAL1"]
DEC_KEYS = ["DEC", "OBJCTDEC", "CRVAL2"]
ROT_KEYS = ["ROTATION", "PA", "ROTATANG", "ORIENTAT", "ROT"]


def _first_present(header, keys):
    for k in keys:
        if k in header:
            return header[k]
    return None


def _to_decimal_ra(val):
    if isinstance(val, (int, float)):
        return float(val)
    val = str(val).strip()
    if ":" in val:
        h, m, s = [float(x) for x in val.split(":")]
        return (h + m / 60 + s / 3600) * 15.0
    return float(val)


def _to_decimal_dec(val):
    if isinstance(val, (int, float)):
        return float(val)
    val = str(val).strip()
    sign = -1.0 if val.startswith("-") else 1.0
    val = val.lstrip("+-")
    if ":" in val:
        d, m, s = [float(x) for x in val.split(":")]
        return sign * (d + m / 60 + s / 3600)
    return float(val) * sign


def read_frame_pointing(path):
    header = fits.getheader(path)
    if "CTYPE1" in header and "CRVAL1" in header:
        try:
            wcs = WCS(header)
            footprint = wcs.calc_footprint(header=header)
            ra_c, dec_c = footprint.mean(axis=0)
            return ra_c, dec_c, 0.0, footprint
        except Exception:
            pass

    ra_raw = _first_present(header, RA_KEYS)
    dec_raw = _first_present(header, DEC_KEYS)
    if ra_raw is None or dec_raw is None:
        raise ValueError("brak RA/DEC w naglowku")

    ra_deg = _to_decimal_ra(ra_raw)
    dec_deg = _to_decimal_dec(dec_raw)
    rot_raw = _first_present(header, ROT_KEYS)
    rot_deg = float(rot_raw) if rot_raw is not None else 0.0

    return ra_deg, dec_deg, rot_deg, None


# ---------- projekcja i footprinty ----------

def gnomonic(ra_deg, dec_deg, ra0_deg, dec0_deg):
    ra, dec = np.radians(ra_deg), np.radians(dec_deg)
    ra0, dec0 = np.radians(ra0_deg), np.radians(dec0_deg)
    dra = ra - ra0
    denom = np.sin(dec0) * np.sin(dec) + np.cos(dec0) * np.cos(dec) * np.cos(dra)
    x = np.cos(dec) * np.sin(dra) / denom
    y = (np.cos(dec0) * np.sin(dec) - np.sin(dec0) * np.cos(dec) * np.cos(dra)) / denom
    return np.degrees(x), np.degrees(y)


def frame_corners_tangent(ra_c, dec_c, rot_deg, fov_w, fov_h, ra0, dec0):
    xc, yc = gnomonic(ra_c, dec_c, ra0, dec0)
    hw, hh = fov_w / 2, fov_h / 2
    local = np.array([(-hw, -hh), (hw, -hh), (hw, hh), (-hw, hh)])
    theta = np.radians(rot_deg)
    rot = np.array([[np.cos(theta), -np.sin(theta)],
                    [np.sin(theta), np.cos(theta)]])
    rotated = local @ rot.T
    return rotated + np.array([xc, yc])


def wcs_corners_tangent(footprint_radec, ra0, dec0):
    x, y = gnomonic(footprint_radec[:, 0], footprint_radec[:, 1], ra0, dec0)
    return np.column_stack([x, y])


# ---------- glowna logika ----------

def build_coverage(folder, fov_w, fov_h, grid_n):
    files = sorted(glob.glob(os.path.join(folder, "*.fit")) +
                   glob.glob(os.path.join(folder, "*.fits")))
    if not files:
        sys.exit(f"Nie znaleziono plikow .fit/.fits w: {folder}")

    raw = []
    for f in files:
        try:
            ra_c, dec_c, rot, footprint = read_frame_pointing(f)
            raw.append((f, ra_c, dec_c, rot, footprint))
        except Exception as e:
            print(f"[pomijam] {os.path.basename(f)}: {e}")

    if not raw:
        sys.exit("Nie udalo sie odczytac zadnej klatki.")

    ra0 = float(np.mean([r[1] for r in raw]))
    dec0 = float(np.mean([r[2] for r in raw]))

    polygons = []
    for f, ra_c, dec_c, rot, footprint in raw:
        if footprint is not None:
            corners = wcs_corners_tangent(footprint, ra0, dec0)
        else:
            corners = frame_corners_tangent(ra_c, dec_c, rot, fov_w, fov_h, ra0, dec0)
        polygons.append(corners)

    all_pts = np.vstack(polygons)
    pad = 0.15 * max(fov_w, fov_h)
    xmin, ymin = all_pts.min(axis=0) - pad
    xmax, ymax = all_pts.max(axis=0) + pad

    xs = np.linspace(xmin, xmax, grid_n)
    ys = np.linspace(ymin, ymax, grid_n)
    XX, YY = np.meshgrid(xs, ys)
    pts = np.column_stack([XX.ravel(), YY.ravel()])

    count = np.zeros(pts.shape[0], dtype=int)
    for corners in polygons:
        path = MplPath(corners)
        count += path.contains_points(pts)

    count = count.reshape(XX.shape)
    return XX, YY, count, polygons, len(raw), ra0, dec0


def plot_coverage(XX, YY, count, polygons, n_frames, ra0, dec0, out_path):
    # Ciemny motyw pasuje do astronomii i poprawia kontrast
    plt.style.use('dark_background')
    fig, ax = plt.subplots(figsize=(10, 9))

    # Maskowanie obszarów gdzie count == 0, żeby tło było czyste
    count_masked = np.ma.masked_equal(count, 0)

    max_count = max(1, int(count.max()))
    
    # Użycie palety 'plasma' lub 'magma' – są bardziej czytelne niż viridis na czarnym tle
    mesh = ax.pcolormesh(XX, YY, count_masked, shading="auto",
                         cmap="plasma", vmin=1, vmax=max_count)
    
    cbar = fig.colorbar(mesh, ax=ax, boundaries=np.arange(0.5, max_count + 1.5, 1))
    cbar.set_label("Liczba nakładających się klatek", color='white')
    cbar.locator = MaxNLocator(integer=True)
    cbar.update_ticks()

    # Rysowanie klatek tylko wtedy, gdy jest ich rozsądna liczba, 
    # żeby nie zrobić z wykresu białej plamy
    if len(polygons) <= 150:
        for corners in polygons:
            closed = np.vstack([corners, corners[0]])
            ax.plot(closed[:, 0], closed[:, 1], color="cyan", linewidth=0.3, alpha=0.4)

    ax.set_xlabel(f"Odsunięcie ΔRA [deg] względem RA={ra0:.3f}°", fontsize=11)
    ax.set_ylabel(f"Odsunięcie ΔDec [deg] względem Dec={dec0:.3f}°", fontsize=11)
    ax.set_title(f"Mapa pokrycia mozaiki ({n_frames} klatek)", fontsize=13, pad=12)
    
    ax.invert_xaxis()  # Konwencja astronomiczna: RA rośnie w lewo
    ax.set_aspect("equal")
    ax.grid(True, color='gray', linestyle='--', linewidth=0.5, alpha=0.3)

    fig.tight_layout()
    fig.savefig(out_path, dpi=200, facecolor=fig.get_facecolor(), edgecolor='none')
    print(f"Zapisano ulepszoną mapę: {out_path}")
    plt.show()


def main():
    ap = argparse.ArgumentParser(description="Mapa pokrycia mozaiki Seestar z plikow FIT.")
    ap.add_argument("folder", help="Folder z plikami .fit/.fits")
    ap.add_argument("--fov-w", type=float, default=0.75, help="Szerokość FOV w stopniach")
    ap.add_argument("--fov-h", type=float, default=1.33, help="Wysokość FOV w stopniach")
    ap.add_argument("--grid", type=int, default=500, help="Rozdzielczość siatki (domyślnie 500 dla wyższej gładkości)")
    ap.add_argument("--out", default="coverage_improved.png", help="Plik wyjściowy PNG")
    args = ap.parse_args()

    XX, YY, count, polygons, n, ra0, dec0 = build_coverage(
        args.folder, args.fov_w, args.fov_h, args.grid
    )
    plot_coverage(XX, YY, count, polygons, n, ra0, dec0, args.out)


if __name__ == "__main__":
    main()

#Seestar #S50 #astrofotografia

— Marcin “czach” Trzaska reply-to: @czach@mastodon.argilus.online

Tak coś mnie tknęło… dawno nie robiłem żadnej mozaiki Seestarem. Nie robiłem, bo się zniechęciłem — jakoś nie wychodziło to najlepiej…

No i coś mnie tknęło, żeby sprawdzić pokrycie na mapie/obrazku…

I takie coś mam od Klaudiusza[^1]. ;–)

#!/usr/bin/env python3
"""
seestar_mosaic_coverage.py

Wczytuje pliki FIT (Seestar, tryb mozaiki) z podanego folderu i rysuje
mape pokrycia nieba: kolorem pokazuje, ile klatek pokrywa dany fragment.

Wymagania:
    pip install astropy numpy matplotlib

Uzycie:
    python seestar_mosaic_coverage.py /sciezka/do/folderu_z_fit
    python seestar_mosaic_coverage.py /sciezka --fov-w 0.75 --fov-h 1.33 --grid 400
"""

import argparse
import glob
import os
import sys

import numpy as np
from astropy.io import fits
from astropy.wcs import WCS
import matplotlib.pyplot as plt
from matplotlib.path import Path as MplPath

# ---------- odczyt naglowkow ----------

RA_KEYS = ["RA", "OBJCTRA", "CRVAL1"]
DEC_KEYS = ["DEC", "OBJCTDEC", "CRVAL2"]
ROT_KEYS = ["ROTATION", "PA", "ROTATANG", "ORIENTAT", "ROT"]


def _first_present(header, keys):
    for k in keys:
        if k in header:
            return header[k]
    return None


def _to_decimal_ra(val):
    """RA moze byc liczba (stopnie) albo string HH:MM:SS."""
    if isinstance(val, (int, float)):
        return float(val)
    val = str(val).strip()
    if ":" in val:
        h, m, s = [float(x) for x in val.split(":")]
        return (h + m / 60 + s / 3600) * 15.0
    return float(val)


def _to_decimal_dec(val):
    if isinstance(val, (int, float)):
        return float(val)
    val = str(val).strip()
    sign = -1.0 if val.startswith("-") else 1.0
    val = val.lstrip("+-")
    if ":" in val:
        d, m, s = [float(x) for x in val.split(":")]
        return sign * (d + m / 60 + s / 3600)
    return float(val) * sign


def read_frame_pointing(path):
    """Zwraca (ra_deg, dec_deg, rotation_deg, footprint_lub_None) dla jednej klatki FIT."""
    header = fits.getheader(path)

    # Sciezka 1: pelne WCS (jesli plik byl plate-solved, np. przez ASTAP)
    if "CTYPE1" in header and "CRVAL1" in header:
        try:
            wcs = WCS(header)
            footprint = wcs.calc_footprint(header=header)  # 4x2 [ra,dec] w stopniach
            ra_c, dec_c = footprint.mean(axis=0)
            return ra_c, dec_c, 0.0, footprint
        except Exception:
            pass

    # Sciezka 2: naglowek Seestara (RA/DEC srodka klatki + ewentualna rotacja)
    ra_raw = _first_present(header, RA_KEYS)
    dec_raw = _first_present(header, DEC_KEYS)
    if ra_raw is None or dec_raw is None:
        raise ValueError("brak RA/DEC w naglowku")

    ra_deg = _to_decimal_ra(ra_raw)
    dec_deg = _to_decimal_dec(dec_raw)
    rot_raw = _first_present(header, ROT_KEYS)
    rot_deg = float(rot_raw) if rot_raw is not None else 0.0

    return ra_deg, dec_deg, rot_deg, None


# ---------- projekcja i footprinty ----------

def gnomonic(ra_deg, dec_deg, ra0_deg, dec0_deg):
    """Rzutuje RA/Dec na plaszczyzne styczna wzgledem (ra0, dec0). Zwraca stopnie."""
    ra, dec = np.radians(ra_deg), np.radians(dec_deg)
    ra0, dec0 = np.radians(ra0_deg), np.radians(dec0_deg)
    dra = ra - ra0
    denom = np.sin(dec0) * np.sin(dec) + np.cos(dec0) * np.cos(dec) * np.cos(dra)
    x = np.cos(dec) * np.sin(dra) / denom
    y = (np.cos(dec0) * np.sin(dec) - np.sin(dec0) * np.cos(dec) * np.cos(dra)) / denom
    return np.degrees(x), np.degrees(y)


def frame_corners_tangent(ra_c, dec_c, rot_deg, fov_w, fov_h, ra0, dec0):
    """Rogi klatki (prostokat obrocony o rot_deg) w ukladzie stycznym."""
    xc, yc = gnomonic(ra_c, dec_c, ra0, dec0)
    hw, hh = fov_w / 2, fov_h / 2
    local = np.array([(-hw, -hh), (hw, -hh), (hw, hh), (-hw, hh)])
    theta = np.radians(rot_deg)
    rot = np.array([[np.cos(theta), -np.sin(theta)],
                    [np.sin(theta), np.cos(theta)]])
    rotated = local @ rot.T
    return rotated + np.array([xc, yc])


def wcs_corners_tangent(footprint_radec, ra0, dec0):
    x, y = gnomonic(footprint_radec[:, 0], footprint_radec[:, 1], ra0, dec0)
    return np.column_stack([x, y])


# ---------- glowna logika ----------

def build_coverage(folder, fov_w, fov_h, grid_n):
    files = sorted(glob.glob(os.path.join(folder, "*.fit")) +
                    glob.glob(os.path.join(folder, "*.fits")))
    if not files:
        sys.exit(f"Nie znaleziono plikow .fit/.fits w: {folder}")

    raw = []
    for f in files:
        try:
            ra_c, dec_c, rot, footprint = read_frame_pointing(f)
            raw.append((f, ra_c, dec_c, rot, footprint))
        except Exception as e:
            print(f"[pomijam] {os.path.basename(f)}: {e}")

    if not raw:
        sys.exit("Nie udalo sie odczytac zadnej klatki - sprawdz nazwy kluczy w naglowku (patrz ponizej).")

    ra0 = float(np.mean([r[1] for r in raw]))
    dec0 = float(np.mean([r[2] for r in raw]))

    polygons = []
    for f, ra_c, dec_c, rot, footprint in raw:
        if footprint is not None:
            corners = wcs_corners_tangent(footprint, ra0, dec0)
        else:
            corners = frame_corners_tangent(ra_c, dec_c, rot, fov_w, fov_h, ra0, dec0)
        polygons.append(corners)

    all_pts = np.vstack(polygons)
    pad = 0.1 * max(fov_w, fov_h)
    xmin, ymin = all_pts.min(axis=0) - pad
    xmax, ymax = all_pts.max(axis=0) + pad

    xs = np.linspace(xmin, xmax, grid_n)
    ys = np.linspace(ymin, ymax, grid_n)
    XX, YY = np.meshgrid(xs, ys)
    pts = np.column_stack([XX.ravel(), YY.ravel()])

    count = np.zeros(pts.shape[0], dtype=int)
    for corners in polygons:
        path = MplPath(corners)
        count += path.contains_points(pts)

    count = count.reshape(XX.shape)
    return XX, YY, count, polygons, len(raw), ra0, dec0


def plot_coverage(XX, YY, count, polygons, n_frames, ra0, dec0, out_path):
    fig, ax = plt.subplots(figsize=(9, 8))

    max_count = max(1, int(count.max()))
    mesh = ax.pcolormesh(XX, YY, count, shading="auto",
                          cmap="viridis", vmin=0, vmax=max_count)
    cbar = fig.colorbar(mesh, ax=ax)
    cbar.set_label("Liczba nakladajacych sie klatek")

    for corners in polygons:
        closed = np.vstack([corners, corners[0]])
        ax.plot(closed[:, 0], closed[:, 1], color="white", linewidth=0.4, alpha=0.6)

    ax.set_xlabel(f"Odsuniecie RA [deg] wzgledem {ra0:.3f}")
    ax.set_ylabel(f"Odsuniecie Dec [deg] wzgledem {dec0:.3f}")
    ax.set_title(f"Pokrycie mozaiki - {n_frames} klatek")
    ax.invert_xaxis()  # konwencja: RA rosnie w lewo
    ax.set_aspect("equal")

    fig.tight_layout()
    fig.savefig(out_path, dpi=150)
    print(f"Zapisano: {out_path}")
    plt.show()


def main():
    ap = argparse.ArgumentParser(description="Mapa pokrycia mozaiki Seestar z plikow FIT.")
    ap.add_argument("folder", help="Folder z plikami .fit/.fits")
    ap.add_argument("--fov-w", type=float, default=0.75,
                    help="Szerokosc FOV w stopniach (domyslnie 0.75 - Seestar S50)")
    ap.add_argument("--fov-h", type=float, default=1.33,
                    help="Wysokosc FOV w stopniach (domyslnie 1.33 - Seestar S50)")
    ap.add_argument("--grid", type=int, default=300,
                    help="Rozdzielczosc siatki liczacej nakladki (domyslnie 300)")
    ap.add_argument("--out", default="coverage.png", help="Plik wyjsciowy PNG")
    args = ap.parse_args()

    XX, YY, count, polygons, n, ra0, dec0 = build_coverage(
        args.folder, args.fov_w, args.fov_h, args.grid
    )
    plot_coverage(XX, YY, count, polygons, n, ra0, dec0, args.out)


if __name__ == "__main__":
    main()

Najpierw

$ python3 -m venv astro
$ source astro/bin/activate

a później, na przykład:

$ python seestar_mosaic_coverage.py SeestarS50/Messier/M\ 31_manual_mosaic
pokrycie mozaiki pokrycie mozaiki
pokrycie mozaiki pokrycie mozaiki

pokrycie M31 pokrycie NGC700

No i te dwa ostatnie obrazki pokazują mi dobitnie, dlaczego mozaiki były fallusowe.

[^1]: Claude AI

#seestar #mosaic #mozaika #astrophotography #astrofotografia

— Marcin “czach” Trzaska reply-to: @czach@mastodon.argilus.online

Tym razem prognozy pogody się sprawdziły i noc z sierpnia na wrzesień ;–) była z (w miarę) czystym niebem. Tak w sam raz, aby dokończyć Galaktykę Fajerwerk i Mgławicę Czarodzieja.

Czarodziej

O ile z Czarodziejem nie miałem problemów i tak się prezentuje: Mgławica Czarodzieja

870x30 sek = 7h15m

Fajerwerk

Tak z galaktyką coś mi nie pasowało i mam 4 wersje. Trzy pierwsze to efekt stackowania skryptem Naztronomy

galaktyka Fajerwerk galaktyka Fajerwerk galaktyka Fajerwerk
918x30 sek = 7h39
A ostatni stackowany skryptem Seestara. Galaktyka Fajerwerk

*953x30 sek = 7h56m30s*

#astrofotografia #astrophotography #Seestar #WizardNebula #FireworksGalaxy

— Marcin “czach” Trzaska reply-to: @czach@mastodon.argilus.online

Chmurwy się trochę zlitowały i udało mi się zebrać dodatkowego materiału. Ponieważ nie miałem pewności, kiedy znów nadejdą, więc zbierałem tylko fajerwerka.

A chmurwy zbliżały się. Gdy zakończyłem zabawę miałem 902 klatki po 30 sekund, trochę odrzucił ASTAP a trochę Siril. Ostatecznie plik wynikowy jest złożony z 765 klatek.

Dalsza obróbka zaowocowała czterema wersjami pliku JPG.

Wersja Generalised Hyperbolic Stretch transformations (GHS)
NGC 6946 765x30s 2 NGC 6946 765x30s
bez ekstra wyostrzania w LRz wyostrzeniem w LR


Wersja Histogram transformation
NGC 6946 765x30s b 2 NGC 6946 765x30s b
bez ekstra wyostrzania w LRz wyostrzeniem w LR
765x30 sek = 6h22m30s

#astrofotografia #astrophotography #Seestar #FireworksGalaxy

— Marcin “czach” Trzaska reply-to: @czach@mastodon.argilus.online

Chciałem zrobić/sprawdzić plamy na Słońcu. Jakieś tam zdjęcia zrobiłem a później coś sprawdziłem i okazało się, że szkło w teleskopie jest brudne jak… Generalnie różnice temperatur w nocy, kurz, mgła itp zrobiły swoje i zrobiła się taka skorupa. Może dlatego moje zdjęcia są takie kiepskie.

IMG 3479

IMG 3480

IMG 3481

☀️ Solar Track 💽 🎸 🔭

🎼Plamy na Słońcu, upał w okolicy
Cierpi tu z gorąca niemal pół dzielnicy🎶

— Kult, Plamy na Słońcu

🔥 Flare Level: X-Class 🎧 132 BPM

#Seestar #S50 #BlackHoleSun #SunSpots #astrophotography

— Marcin “czach” Trzaska reply-to: @czach@mastodon.argilus.online

Kolejne obiekty astrofoto trafiły na tapet. * Galaktyka Fajerwerk * Mgławica Czarodzieja

Poprzednie wersje, są… Nie dość dobre, więc zbieram material od nowa. Po pierwszej nocy wygląda to tak:

*Galaktyka Fajerwerk*

noc pierwsza: 228x30 sek = 1h46min

*Mgławica Czarodzieja*

noc pierwsza: 500x30 sek = 4h10min

Niestety, prognozy pogody nie są optymistyczne. Następna sesja może w pierwszą noc września. Zobaczymy.

#astrofotografia #astrophotography #Seestar #S50 #FireworksGalaxy #WizardNebula

— Marcin “czach” Trzaska reply-to: @czach@mastodon.argilus.online

Częściowe zaćmienie Księżyca, 28 sierpnia 2028 roku. Trochę skiepściłem, bo zamiast patrzyć na ekran bawiłem się VPNem. No i jest jak jest. Śledzenie zglupiało, bo Księżyca ubywalo.

Potem przyszły chmurwy a pod koniec Księżyc mi się ukazał na tle żurawia budowlanego.

#ZacmienieKsiezyca #Seestar #LunarEclipse

— Marcin “czach” Trzaska reply-to: @czach@mastodon.argilus.online

Trzecia noc[^1] z Pelikanem. Wczoraj zacząłem wcześniej, bo przed 23:00, i skończyłem ok. 4:40.

Łącznie zebrałem 11h11 minut materiału (1342x30 sekund) z czego do stackowania wybranych zostało 1161 najlepszych.

Poniższy obraz to wynik złożenia 901 klatek (część została odrzucona). Tym razem odpuściłem sobie jedną czynność (SPCC — Spectrophotometric Color Calibration) i wydaje mi się, że wygląda to atrakcyjniej.

Mgławica Pelikan

901x30 sek = 7h30min

[^1]: I chyba ostatnia

#astrofotografia #Seestar #S50 #IC5070 #MgławicaPelikan

— Marcin “czach” Trzaska reply-to: @czach@mastodon.argilus.online

Kolejna noc, więcej materiału. Dziś będzie krótko, bez rozpisywania się. Zebrany materiał po dwóch nocach — 574 lub 562 klatki po 30 sekund

Wybrałem dwie różne ścieżki stackowania (składania) materiału i mam trzy pliki wynikowe.

Najpierw zdjęcie po pierwszej nocy a później trzy z różnym podejściem do stackowania i strechingu.

Wczorajszy plik 122x30s / 2026 (2026-08-23)

122x30 sek = 1h1min

Dwa zdjęcia — stackowanie za pomocą skryptu w Pythonie 562x30s / 2026 (2026-08-23)

562x30s / 2026 (2026-08-23)

562x30 sek = 4h51min

Stackowanie za pomocą skryptu Sirila 574x30s Obi / 2026 (2026-08-23)

574x30 sek = 4h57min

#astrofotografia #Seestar #S50 #MgławicaPelikan #IC5070

— Marcin “czach” Trzaska reply-to: @czach@mastodon.argilus.online