diff options
author | Marek Dvoroznak <dvoromar@gmail.com> | 2013-06-30 01:22:43 +0200 |
---|---|---|
committer | Mikael Magnusson <mikachu@src.gnome.org> | 2015-02-27 18:35:31 +0100 |
commit | 6421ef5936d2fcc27310b38b0e6c70812d2ce116 (patch) | |
tree | e1ce08d8632bf4e45a5567a01a8147040e4e3018 /libs | |
parent | fc1d412590226f971ee90d428b919df5b6a18f32 (diff) |
add part of n-point deformation library
Diffstat (limited to 'libs')
-rw-r--r-- | libs/npd/deformation.c | 203 | ||||
-rw-r--r-- | libs/npd/deformation.h | 46 | ||||
-rw-r--r-- | libs/npd/npd_common.h | 114 |
3 files changed, 363 insertions, 0 deletions
diff --git a/libs/npd/deformation.c b/libs/npd/deformation.c new file mode 100644 index 00000000..415e53b7 --- /dev/null +++ b/libs/npd/deformation.c @@ -0,0 +1,203 @@ +/* + * This file is part of n-point image deformation library. + * + * 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; either version 3 of the License, or + * (at your option) any later version. + * + * 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 <http://www.gnu.org/licenses/>. + * + * Copyright (C) 2013 Marek Dvoroznak <dvoromar@gmail.com> + */ + +#include "deformation.h" +#include <math.h> + +#define NPD_COMPUTE_CENTROID(suffix, arg1, arg2, WEIGHTS, accessor) \ +void \ +npd_compute_centroid_##suffix (gint num_of_points, \ + arg1, \ + arg2, \ + NPDPoint *centroid) \ +{ \ + gfloat x_sum = 0, y_sum = 0, weights_sum = 0; \ + gint i; \ + \ + /* first compute sum of all values for each coordinate */ \ + for (i = 0; i < num_of_points; ++i) \ + { \ + x_sum += (WEIGHTS) * points[i] accessor x; \ + y_sum += (WEIGHTS) * points[i] accessor y; \ + weights_sum += (WEIGHTS); \ + } \ + \ + /* then compute mean */ \ + centroid->x = x_sum / weights_sum; \ + centroid->y = y_sum / weights_sum; \ +} + +NPD_COMPUTE_CENTROID (of_overlapping_points, + NPDPoint *points[], + gfloat weights[], + 1, + ->) +NPD_COMPUTE_CENTROID (from_weighted_points, + NPDPoint points[], + gfloat weights[], + weights[i], + .) + +void +npd_compute_ARSAP_transformation (gint num_of_points, + NPDPoint reference_points[], + NPDPoint current_points[], + gfloat weights[], + gboolean ARAP) +{ + NPDPoint pc = {0, 0}, qc = {0, 0}; + gfloat a = 0, b = 0, mu_part = 0, mu, r1, r2, x0, y0; + gint i; + + /* p - points of reference pose */ + npd_compute_centroid_from_weighted_points (num_of_points, + reference_points, + weights, + &pc); + /* q - points of current pose */ + npd_compute_centroid_from_weighted_points (num_of_points, + current_points, + weights, + &qc); + + /* get rotation */ + for (i = 0; i < num_of_points; ++i) + { + gfloat px_minus_pcx = reference_points[i].x - pc.x; + gfloat py_minus_pcy = reference_points[i].y - pc.y; + gfloat qx_minus_qcx = current_points[i].x - qc.x; + gfloat qy_minus_qcy = current_points[i].y - qc.y; + + a += weights[i] + * ((px_minus_pcx) + * (qx_minus_qcx) + + (py_minus_pcy) + * (qy_minus_qcy)); + b += weights[i] + * ((px_minus_pcx) + * (qy_minus_qcy) + - (py_minus_pcy) + * (qx_minus_qcx)); + + mu_part += weights[i] + * ((px_minus_pcx) + * (px_minus_pcx) + + (py_minus_pcy) + * (py_minus_pcy)); + } + + mu = 1; + if (ARAP) mu = sqrt(a * a + b * b); + else mu = mu_part; + + r1 = a / mu; + r2 = -b / mu; + + /* get translation */ + x0 = qc.x - ( r1 * pc.x + r2 * pc.y); + y0 = qc.y - (-r2 * pc.x + r1 * pc.y); + + /* transform points */ + for (i = 0; i < num_of_points; ++i) + { + if (!current_points[i].fixed) + { + current_points[i].x = r1 * reference_points[i].x + + r2 * reference_points[i].y + x0; + current_points[i].y = -r2 * reference_points[i].x + + r1 * reference_points[i].y + y0; + } + } +} + +void +npd_compute_ARSAP_transformations (NPDHiddenModel *hidden_model) +{ + gint i; + for (i = 0; i < hidden_model->num_of_bones; ++i) + { + NPDBone *reference_bones = &hidden_model->reference_bones[i]; + NPDBone *current_bones = &hidden_model->current_bones[i]; + npd_compute_ARSAP_transformation (reference_bones->num_of_points, + reference_bones->points, + current_bones->points, + current_bones->weights, + hidden_model->ARAP); + } +} + +void +npd_deform_model (NPDModel *model, + gint rigidity) +{ + gint i; + for (i = 0; i < rigidity; ++i) + { + npd_deform_model_once (model); + } +} + +void +npd_deform_model_once (NPDModel *model) +{ + gint i, j; + + /* updates associated overlapping points according to this control point */ + for (i = 0; i < model->control_points->len; ++i) + { + NPDControlPoint *cp = &g_array_index (model->control_points, + NPDControlPoint, + i); + + for (j = 0; j < cp->overlapping_points->num_of_points; ++j) + { + npd_set_point_coordinates (cp->overlapping_points->points[j], + &cp->point); + } + } + + npd_deform_hidden_model_once (model->hidden_model); +} + +void +npd_deform_hidden_model_once (NPDHiddenModel *hidden_model) +{ + gint i, j; + npd_compute_ARSAP_transformations (hidden_model); + + /* overlapping points are not overlapping after the deformation, + so we have to move them to their centroid */ + for (i = 0; i < hidden_model->num_of_overlapping_points; ++i) + { + NPDOverlappingPoints *list_of_ops + = &hidden_model->list_of_overlapping_points[i]; + NPDPoint centroid; + + npd_compute_centroid_of_overlapping_points (list_of_ops->num_of_points, + list_of_ops->points, + NULL, + ¢roid); + + for (j = 0; j < list_of_ops->num_of_points; ++j) + { + list_of_ops->points[j]->x = centroid.x; + list_of_ops->points[j]->y = centroid.y; + } + } +} diff --git a/libs/npd/deformation.h b/libs/npd/deformation.h new file mode 100644 index 00000000..326d14ff --- /dev/null +++ b/libs/npd/deformation.h @@ -0,0 +1,46 @@ +/* + * This file is part of n-point image deformation library. + * + * 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; either version 3 of the License, or + * (at your option) any later version. + * + * 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 <http://www.gnu.org/licenses/>. + * + * Copyright (C) 2013 Marek Dvoroznak <dvoromar@gmail.com> + */ + +#ifndef __NPD_DEFORMATION_H__ +#define __NPD_DEFORMATION_H__ + +#include "npd_common.h" + +void npd_compute_centroid_from_weighted_points + (gint num_of_points, + NPDPoint points[], + gfloat weights[], + NPDPoint *centroid); +void npd_compute_centroid_of_overlapping_points + (gint num_of_points, + NPDPoint *points[], + gfloat weights[], + NPDPoint *centroid); +void npd_compute_ARSAP_transformation (gint num_of_points, + NPDPoint reference_shape[], + NPDPoint current_shape[], + gfloat weights[], + gboolean ARAP); +void npd_compute_ARSAP_transformations (NPDHiddenModel *model); +void npd_deform_model (NPDModel *model, + gint rigidity); +void npd_deform_model_once (NPDModel *model); +void npd_deform_hidden_model_once (NPDHiddenModel *hidden_model); + +#endif /* __NPD_DEFORMATION_H__ */
\ No newline at end of file diff --git a/libs/npd/npd_common.h b/libs/npd/npd_common.h new file mode 100644 index 00000000..c3bb4525 --- /dev/null +++ b/libs/npd/npd_common.h @@ -0,0 +1,114 @@ +/* + * This file is part of n-point image deformation library. + * + * 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; either version 3 of the License, or + * (at your option) any later version. + * + * 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 <http://www.gnu.org/licenses/>. + * + * Copyright (C) 2013 Marek Dvoroznak <dvoromar@gmail.com> + */ + +#ifndef __NPD_COMMON_H__ +#define __NPD_COMMON_H__ + +#include <glib.h> + +/* opaque types for independency on used display library */ +typedef struct _NPDImage NPDImage; +typedef struct _NPDColor NPDColor; +typedef struct _NPDDisplay NPDDisplay; +typedef struct _NPDMatrix NPDMatrix; + +typedef struct +{ + gfloat x; + gfloat y; + gboolean fixed; + gfloat *weight; /* reference to weight in array + of weights */ +} NPDPoint; + +typedef struct +{ + gint num_of_points; + NPDPoint *points; /* array of points */ + gfloat *weights; /* array of weights */ +} NPDBone; + +typedef struct +{ + gint num_of_points; + NPDPoint *representative; /* reference to representative + of cluster */ + NPDPoint **points; /* array of references to points */ +} NPDOverlappingPoints; + +typedef struct +{ + gint num_of_bones; + gint num_of_overlapping_points; + gboolean ARAP; + NPDBone *current_bones; /* array of current bones */ + NPDBone *reference_bones; /* array of reference bones */ + NPDOverlappingPoints *list_of_overlapping_points; /* array of overlapping + points */ +} NPDHiddenModel; + +typedef struct +{ + NPDPoint point; + NPDOverlappingPoints *overlapping_points; /* reference to overlapping + points */ +} NPDControlPoint; + +typedef struct +{ + gint control_point_radius; + gboolean control_points_visible; + gboolean mesh_visible; + gboolean texture_visible; + gint mesh_square_size; + GArray *control_points; /* GArray of control points */ + NPDHiddenModel *hidden_model; + NPDImage *reference_image; + NPDDisplay *display; +} NPDModel; + +void npd_init_model (NPDModel *model); +void npd_destroy_hidden_model (NPDHiddenModel *model); +void npd_destroy_model (NPDModel *model); + +NPDControlPoint *npd_add_control_point (NPDModel *model, + NPDPoint *coord); +void npd_remove_control_point (NPDModel *model, + NPDControlPoint *control_point); +void npd_remove_all_control_points + (NPDModel *model); +void npd_set_control_point_weight + (NPDControlPoint *cp, + gfloat weight); +gboolean npd_equal_coordinates (NPDPoint *p1, + NPDPoint *p2, + gfloat epsilon); +NPDControlPoint *npd_get_control_point_at (NPDModel *model, + NPDPoint *coord); + +void npd_create_list_of_overlapping_points + (NPDHiddenModel *model); +void npd_set_overlapping_points_weight + (NPDOverlappingPoints *op, + gfloat weight); + +void npd_set_point_coordinates (NPDPoint *target, + NPDPoint *source); + +#endif /* __NPD_COMMON_H__ */
\ No newline at end of file |