Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 21 additions & 5 deletions src/vstarstack/library/loaders/classic.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,11 @@
import exifread

import vstarstack.library.data
from vstarstack.library.loaders.datatype import check_datatype

def readjpeg(fname: str):
"""Read single image (jpg, png, tiff) file"""
rgb = np.asarray(Image.open(fname)).astype(np.float32)
rgb = np.asarray(Image.open(fname))
shape = rgb.shape
shape = (shape[0], shape[1])

Expand All @@ -47,14 +48,29 @@ def readjpeg(fname: str):

params["weight"] = params["exposure"] * params["gain"]

max_value = np.iinfo(rgb.dtype).max

dataframe = vstarstack.library.data.DataFrame(params, tags)

if len(rgb.shape) == 3:
dataframe.add_channel(rgb[:, :, 0], "R", brightness=True, signal=True)
dataframe.add_channel(rgb[:, :, 1], "G", brightness=True, signal=True)
dataframe.add_channel(rgb[:, :, 2], "B", brightness=True, signal=True)
for channel_name, channel_index in [("R",0), ("G", 1), ("B", 2)]:
data = rgb[:,:,channel_index]
dataframe.add_channel(check_datatype(data), channel_name, brightness=True, signal=True)
overlight_idx = np.where(data >= max_value*0.99)
if len(overlight_idx) > 0:
weight = np.ones(data.shape)*params["weight"]
weight[overlight_idx] = 0
dataframe.add_channel(weight, f"weight-{channel_name}", weight=True)
dataframe.add_channel_link(channel_name, f"weight-{channel_name}", "weight")

elif len(rgb.shape) == 2:
dataframe.add_channel(rgb[:, :], "L", brightness=True, signal=True)
dataframe.add_channel(check_datatype(rgb), "L", brightness=True, signal=True)
overlight_idx = np.where(rgb >= max_value*0.99)
if len(overlight_idx) > 0:
weight = np.ones(rgb.shape)*params["weight"]
weight[overlight_idx] = 0
dataframe.add_channel(weight, f"weight-L", weight=True)
dataframe.add_channel_link("L", f"weight-L", "weight")
else:
# unknown shape!
pass
Expand Down
23 changes: 23 additions & 0 deletions src/vstarstack/library/loaders/datatype.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
"""convert 8 and 16 bit data to 32 bit"""
#
# Copyright (c) 2025 Vladislav Tsendrovskii
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, version 3 of the License.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
#

import numpy as np
def check_datatype(data : np.ndarray) -> np.ndarray:
"""If 8 bit or 16 bit convert to 32 bit"""
if data.dtype == np.int8 or data.dtype == np.int16:
return data.astype(np.int32)
if data.dtype == np.uint8 or data.dtype == np.uint16:
return data.astype(np.uint32)
return data
19 changes: 16 additions & 3 deletions src/vstarstack/library/loaders/fits.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,13 @@
# along with this program. If not, see <https://www.gnu.org/licenses/>.
#

import numpy as np
import logging
from astropy.io import fits

import vstarstack.library.data
from vstarstack.library.loaders.datatype import check_datatype

logger = logging.getLogger(__name__)

def readfits(filename: str):
Expand All @@ -32,11 +35,13 @@ def readfits(filename: str):

shape = plane.data.shape
if len(shape) == 2:
original = plane.data.reshape((1, shape[0], shape[1]))
original : np.ndarray = plane.data.reshape((1, shape[0], shape[1]))
else:
original = plane.data
original : np.ndarray = plane.data
shape = original.shape

max_value = np.iinfo(original.dtype).max

params = {
"w": shape[2],
"h": shape[1],
Expand Down Expand Up @@ -67,6 +72,7 @@ def readfits(filename: str):
slice_names = []

params["weight"] = params["exposure"]*params["gain"]

dataframe = vstarstack.library.data.DataFrame(params, tags)

if shape[0] == 1:
Expand All @@ -87,8 +93,15 @@ def readfits(filename: str):
yield None

for i, slice_name in enumerate(slice_names):
dataframe.add_channel(original[i, :, :], slice_name,
data = original[i, :, :]
overlight_idx = np.where(data >= max_value*0.99)
dataframe.add_channel(check_datatype(data), slice_name,
brightness=True, signal=True, encoded=encoded)
if len(overlight_idx) > 0:
weight = np.ones(data.shape)*params["weight"]
weight[overlight_idx] = 0
dataframe.add_channel(weight, f"weight-{slice_name}", weight=True)
dataframe.add_channel_link(slice_name, f"weight-{slice_name}", "weight")
if bayer is not None:
dataframe.add_parameter(bayer, "format")
yield dataframe
12 changes: 10 additions & 2 deletions src/vstarstack/library/loaders/nef.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,10 @@

import rawpy
import exifread
import numpy as np

import vstarstack.library.data

from vstarstack.library.loaders.datatype import check_datatype

def readnef(filename: str):
"""Read NEF file"""
Expand Down Expand Up @@ -55,7 +56,14 @@ def readnef(filename: str):
for tag_name in tags:
printable_tags[tag_name] = tags[tag_name].printable

max_value = np.iinfo(image.dtype).max
dataframe = vstarstack.library.data.DataFrame(params, printable_tags)
dataframe.add_channel(image, "raw", encoded=True, brightness=True, signal=True)
dataframe.add_channel(check_datatype(image), "raw", encoded=True, brightness=True, signal=True)
overlight_idx = np.where(image >= max_value*0.99)
if len(overlight_idx) > 0:
weight = np.ones(image.shape)*params["weight"]
weight[overlight_idx] = 0
dataframe.add_channel(weight, f"weight-raw", weight=True)
dataframe.add_channel_link("raw", f"weight-raw", "weight")
dataframe.add_parameter(bayer, "format")
yield dataframe
14 changes: 12 additions & 2 deletions src/vstarstack/library/loaders/ser.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import numpy as np

import vstarstack.library.data
from vstarstack.library.loaders.datatype import check_datatype

logger = logging.getLogger(__name__)

Expand All @@ -43,7 +44,7 @@ def _serread8(file):
"""Read 8-byte integer"""
return _serread(file, 8, True)

def _read_to_npy(file, bpp, little_endian, shape):
def _read_to_npy(file, bpp, little_endian, shape) -> np.ndarray:
"""Read block of SER file"""
num = 1
for _, dim in enumerate(shape):
Expand Down Expand Up @@ -200,6 +201,8 @@ def readser(fname: str):
"weight" : 1,
}

max_value = 2**depth - 1

with open(fname, "rb") as trailer_f:
trailer_offset = 178 + frames * width * height * (bpp * vpp)
trailer_f.seek(trailer_offset, 0)
Expand All @@ -213,5 +216,12 @@ def readser(fname: str):
dataframe = vstarstack.library.data.DataFrame(params, tags)
index = 0
for index, channel in enumerate(channels):
dataframe.add_channel(frame[:, :, index], channel, **opts)
data = frame[:, :, index]
dataframe.add_channel(check_datatype(data), channel, **opts)
overlight_idx = np.where(data >= max_value*0.99)
if len(overlight_idx) > 0:
weight = np.ones(data.shape)*params["weight"]
weight[overlight_idx] = 0
dataframe.add_channel(weight, f"weight-{channel}", weight=True)
dataframe.add_channel_link(channel, f"weight-{channel}", "weight")
yield dataframe
16 changes: 13 additions & 3 deletions src/vstarstack/library/loaders/video.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,10 @@
#

import cv2
import numpy as np

import vstarstack.library.data
from vstarstack.library.loaders.datatype import check_datatype

def read_video(fname: str):
"""Read frames from video file"""
Expand All @@ -38,9 +40,17 @@ def read_video(fname: str):
"weight" : 1,
}

max_value = np.iinfo(frame.dtype).max
dataframe = vstarstack.library.data.DataFrame(params, tags)
dataframe.add_channel(frame[:, :, 0], "R", brightness=True, signal=True)
dataframe.add_channel(frame[:, :, 1], "G", brightness=True, signal=True)
dataframe.add_channel(frame[:, :, 2], "B", brightness=True, signal=True)
for channel_name, channel_index in [("R",0), ("G", 1), ("B", 2)]:
data = frame[:,:,channel_index]
dataframe.add_channel(check_datatype(data), channel_name, brightness=True, signal=True)
overlight_idx = np.where(data >= max_value*0.99)
if len(overlight_idx) > 0:
weight = np.ones(data.shape)*params["weight"]
weight[overlight_idx] = 0
dataframe.add_channel(weight, f"weight-{channel_name}", weight=True)
dataframe.add_channel_link(channel_name, f"weight-{channel_name}", "weight")

yield dataframe
frame_id += 1
4 changes: 3 additions & 1 deletion src/vstarstack/library/loaders/yuv.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
import numpy as np

import vstarstack.library.data
from vstarstack.library.loaders.datatype import check_datatype

logger = logging.getLogger(__name__)

def readyuv(fname: str, width: int, height: int):
Expand Down Expand Up @@ -47,6 +49,6 @@ def readyuv(fname: str, width: int, height: int):
logger.info(f"processing frame {frame_id}")

dataframe = vstarstack.library.data.DataFrame(params, tags)
dataframe.add_channel(yuv, "raw", encoded=True, signal=True)
dataframe.add_channel(check_datatype(yuv), "raw", encoded=True, signal=True)
yield dataframe
frame_id += 1
1 change: 1 addition & 0 deletions src/vstarstack/library/stars/detect.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ def _find_stars(gray_image : np.ndarray):
"""Find stars on image"""
shape = gray_image.shape

gray_image = (gray_image.astype(np.float32) / np.amax(gray_image) * 255).astype(np.uint8)
gray_image = cv2.GaussianBlur(gray_image, (3, 3), 0)

thresh = _threshold(gray_image, _detector_cfg["THRESHOLD_BLOCK_SIZE"],
Expand Down