Skip to content

Commit

Permalink
Merge images with different projections (#187)
Browse files Browse the repository at this point in the history
* Update copyright
* Implement shifting and resizing
* Add drop-weight command
* show more info on `image info` command
  • Loading branch information
vladtcvs authored Dec 20, 2024
1 parent c2ee3ff commit 326b432
Show file tree
Hide file tree
Showing 10 changed files with 253 additions and 82 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ jobs:
python -m pip install -r requirements.txt
- name: Lint with pylint
run: |
pylint --rcfile=pylintrc --fail-under=9 src/
pylint --rcfile=pylintrc --fail-under=9 src/vstarstack
- name: Build & Install
run: |
python -m build . --wheel -n
Expand Down
58 changes: 57 additions & 1 deletion src/c_modules/movements/lib/sphere.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2023 Vladislav Tsendrovskii
* Copyright (c) 2023-2024 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
Expand Down Expand Up @@ -90,6 +90,34 @@ void sphere_movement_apply_forward(struct SphereMovement *mov,
}
}

void sphere_movement_apply_forward_lonlat(struct SphereMovement *mov,
const double *posi, double *poso, size_t num)
{
unsigned i;
for (i = 0; i < num; i++)
{
double x, y, z;
double lon = posi[i*2];
double lat = posi[i*2+1];
x = cos(lon)*cos(lat);
y = sin(lon)*cos(lat);
z = sin(lat);
struct quat v = quat_from_vec(x, y, z);
struct quat vf = quat_mul(mov->forward, quat_mul(v, mov->reverse));
x = vf.x;
y = vf.y;
z = vf.z;
if (z > 1)
z = 1;
if (z < -1)
z = -1;
lon = atan2(y, x);
lat = asin(z);
poso[2*i] = lon;
poso[2*i+1] = lat;
}
}

void sphere_movement_apply_reverse(struct SphereMovement *mov,
const double *posi, double *poso, size_t num,
const struct ProjectionDef *in_proj,
Expand Down Expand Up @@ -123,3 +151,31 @@ void sphere_movement_apply_reverse(struct SphereMovement *mov,
poso[2*i+1] = yo;
}
}

void sphere_movement_apply_reverse_lonlat(struct SphereMovement *mov,
const double *posi, double *poso, size_t num)
{
unsigned i;
for (i = 0; i < num; i++)
{
double x, y, z;
double lon = posi[i*2];
double lat = posi[i*2+1];
x = cos(lon)*cos(lat);
y = sin(lon)*cos(lat);
z = sin(lat);
struct quat v = quat_from_vec(x, y, z);
struct quat vf = quat_mul(mov->reverse, quat_mul(v, mov->forward));
x = vf.x;
y = vf.y;
z = vf.z;
if (z > 1)
z = 1;
if (z < -1)
z = -1;
lon = atan2(y, x);
lat = asin(z);
poso[2*i] = lon;
poso[2*i+1] = lat;
}
}
6 changes: 6 additions & 0 deletions src/c_modules/movements/lib/sphere.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,13 @@ void sphere_movement_apply_forward(struct SphereMovement *mov,
const struct ProjectionDef *in_proj,
const struct ProjectionDef *out_proj);

void sphere_movement_apply_forward_lonlat(struct SphereMovement *mov,
const double *posi, double *poso, size_t num);

void sphere_movement_apply_reverse(struct SphereMovement *mov,
const double *posi, double *poso, size_t num,
const struct ProjectionDef *in_proj,
const struct ProjectionDef *out_proj);

void sphere_movement_apply_reverse_lonlat(struct SphereMovement *mov,
const double *posi, double *poso, size_t num);
79 changes: 79 additions & 0 deletions src/c_modules/movements/module.c
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,10 @@ typedef void (*action_f)(struct SphereMovement *mov,
const struct ProjectionDef *in_proj,
const struct ProjectionDef *out_proj);

typedef void (*action_lonlat_f)(struct SphereMovement *mov,
const double *posi, double *poso, size_t num);


static PyObject *apply_action(PyObject *_self,
PyObject *args,
PyObject *kwds,
Expand Down Expand Up @@ -187,25 +191,100 @@ static PyObject *apply_action(PyObject *_self,
return (PyObject *)output_points;
}

static PyObject *apply_action_lonlat(PyObject *_self,
PyObject *args,
PyObject *kwds,
action_lonlat_f fun)
{
PyArrayObject *points;
struct SphereMovementObject *self = (struct SphereMovementObject *)_self;

static char *kwlist[] = {"points", NULL};
if (!PyArg_ParseTupleAndKeywords(args, kwds, "O", kwlist, &points))
{
PyErr_SetString(PyExc_ValueError, "invalid function arguments");
Py_INCREF(Py_None);
return Py_None;
}

if (PyArray_TYPE(points) != NPY_DOUBLE)
{
PyErr_SetString(PyExc_ValueError, "invalid function arguments - should be dtype == double");
Py_INCREF(Py_None);
return Py_None;
}

if (PyArray_NDIM(points) != 2)
{
PyErr_SetString(PyExc_ValueError, "invalid function arguments - should be len(shape) == 2");
Py_INCREF(Py_None);
return Py_None;
}

npy_intp *dims = PyArray_SHAPE(points);

if (dims[1] != 2)
{
PyErr_SetString(PyExc_ValueError, "invalid function arguments - should be shape[1] == 2");
Py_INCREF(Py_None);
return Py_None;
}

size_t num = dims[0];
//printf("Processing %i points\n", (int)num);

const double *posi = PyArray_DATA(points);

PyArrayObject *output_points = (PyArrayObject *)PyArray_ZEROS(2, dims, NPY_DOUBLE, 0);
if (output_points == NULL)
{
PyErr_SetString(PyExc_ValueError, "can not allocate memory");
Py_INCREF(Py_None);
return Py_None;
}
double *poso = PyArray_DATA(output_points);

fun(&self->mov, posi, poso, num);
return (PyObject *)output_points;
}

static PyObject *Sphere_forward(PyObject *_self,
PyObject *args,
PyObject *kwds)
{
return apply_action(_self, args, kwds, sphere_movement_apply_forward);
}

static PyObject *Sphere_forward_lonlat(PyObject *_self,
PyObject *args,
PyObject *kwds)
{
return apply_action_lonlat(_self, args, kwds, sphere_movement_apply_forward_lonlat);
}

static PyObject *Sphere_reverse(PyObject *_self,
PyObject *args,
PyObject *kwds)
{
return apply_action(_self, args, kwds, sphere_movement_apply_reverse);
}

static PyObject *Sphere_reverse_lonlat(PyObject *_self,
PyObject *args,
PyObject *kwds)
{
return apply_action_lonlat(_self, args, kwds, sphere_movement_apply_reverse_lonlat);
}

static PyMethodDef _SphereMovements_methods[] = {
{"apply_forward", (PyCFunction)Sphere_forward, METH_VARARGS | METH_KEYWORDS,
"Apply forward rotation"},
{"apply_forward_lonlat", (PyCFunction)Sphere_forward_lonlat, METH_VARARGS | METH_KEYWORDS,
"Apply forward rotation in lon, lat coordinates"},
{"apply_reverse", (PyCFunction)Sphere_reverse, METH_VARARGS | METH_KEYWORDS,
"Apply reverse rotation"},
{"apply_reverse_lonlat", (PyCFunction)Sphere_reverse_lonlat, METH_VARARGS | METH_KEYWORDS,
"Apply reverse rotation in lon, lat coordinates"},
{NULL} /* Sentinel */
};

Expand Down
2 changes: 1 addition & 1 deletion src/c_modules/projections/lib/perspective.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ bool perspective_projection_init(struct PerspectiveProjection *self,
double kw, double kh, double F,
double w, double h)
{
if (h <= 0 || w <= 0 ||
if (h < 0 || w < 0 ||
kw <= 0 || kh <= 0 ||
F <= 0)
{
Expand Down
2 changes: 1 addition & 1 deletion src/c_modules/projections/module.c
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ static PyObject *Perspective_reverse(PyObject *_self,

static PyMethodDef _PerspectiveProjection_methods[] = {
{"project", (PyCFunction)Perspective_forward, METH_VARARGS | METH_KEYWORDS,
"Project x,y to lat,lon"},
"Project x,y to lon,lat"},
{"reverse", (PyCFunction)Perspective_reverse, METH_VARARGS | METH_KEYWORDS,
"Project lon,lat to x,y"},
{NULL} /* Sentinel */
Expand Down
12 changes: 10 additions & 2 deletions src/vstarstack/library/movement/sphere.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,13 +54,21 @@ class Movement(vstarstack.library.movement.basic_movement.Movement):
"""Class of spherical movements"""

def apply(self, positions : np.ndarray, input_proj, output_proj):
"""Apply movement"""
"""Apply movement in (x,y) coordinates"""
return self.mov.apply_forward(positions, input_proj, output_proj)

def apply_lonlat(self, positions : np.ndarray):
"""Apply movement in (lon,lat) coordinates"""
return self.mov.apply_forward_lonlat(positions)

def reverse(self, positions : np.ndarray, input_proj, output_proj):
"""Apply reverse movement"""
"""Apply reverse movement in (x,y) coordinates"""
return self.mov.apply_reverse(positions, input_proj, output_proj)

def reverse_lonlat(self, positions : np.ndarray):
"""Apply reverse movement in (lon,lat) coordinates"""
return self.mov.apply_reverse_lonlat(positions)

def __init__(self, rot):
self.rot = rot
self.rev = rot.inv()
Expand Down
3 changes: 2 additions & 1 deletion src/vstarstack/tool/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@

_module_configuration = {
"output" : {
"projection" : (str, "COPY"),
"projection_type" : (str, "COPY"),
"projection_desc" : (str, "COPY"),
},
"paths": {
"light" : {
Expand Down
18 changes: 16 additions & 2 deletions src/vstarstack/tool/image.py
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,8 @@ def _show(_project, argv):
subplot = axs[index]
else:
subplot = axs
img = frames[channel].astype(np.float64)
logger.info(f"Channel {channel} has values {np.amin(img)} - {np.amax(img)}")
img = frames[channel].astype(np.float32)
img = compress(img, SLOPE)

if len(img.shape) == 2:
Expand Down Expand Up @@ -302,12 +303,25 @@ def _select_bpp(_project, argv):
else:
_select_bpp_file(inpath, format, outpath)

def _drop_weight(_project, argv):
import vstarstack.library.data
inpath = argv[0]
outpath = argv[1]
df = vstarstack.library.data.DataFrame.load(inpath)
df.add_parameter(1, "weight")
for channel in list(df.get_channels()):
if df.get_channel_option(channel, "weight"):
layer, opts = df.get_channel(channel)
layer = (layer != 0).astype("int")
df.replace_channel(layer, channel, **opts)
df.store(outpath)

commands = {
"show": (_show, "show image"),
"convert": (_convert, "convert image"),
"cut": (_cut, "cut part of image", "path/ <left> <top> <right> <bottom> out/"),
"rename-channel": (_rename_channel, "filename.zip original_name target_name - rename channel"),
"info": (_exposures, "display image info", "(file.zip | path/)"),
"bpp" : (_select_bpp, "select format", "(input.zip | input/) (float16 | float32 | float64) (output.zip | output/)")
"bpp" : (_select_bpp, "select format", "(input.zip | input/) (float16 | float32 | float64) (output.zip | output/)"),
"drop-weight" : (_drop_weight, "drop weight info", "input.zip output.zip"),
}
Loading

0 comments on commit 326b432

Please sign in to comment.