CR2RE Pipeline Reference Manual 1.6.2
hdrl_correlation-test.c
1/*
2 * This file is part of the HDRL
3 * Copyright (C) 2017 European Southern Observatory
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#ifdef HAVE_CONFIG_H
21#include <config.h>
22#endif
23
24/*-----------------------------------------------------------------------------
25 Includes
26 -----------------------------------------------------------------------------*/
27
28#include "hdrl_correlation.h"
29
30#include <math.h>
31#include <cpl.h>
32
33cpl_array *
34create_rect(const cpl_size sz, const cpl_size start, const cpl_size stop){
35
36 cpl_array * v = cpl_array_new(sz, CPL_TYPE_DOUBLE);
37
38 for(cpl_size i = 0; i < sz; ++i){
39
40 double p = 0.0;
41
42 if(i >= start && i <= stop)
43 p = 5.0;
44
45 cpl_array_set(v, i, p);
46 }
47
48 return v;
49}
50
51cpl_array *
52create_gaussian(cpl_size num_samples, const double mean, const double stdev,
53 const double center, double * delta_out){
54
55 cpl_array * v = cpl_array_new(num_samples, CPL_TYPE_DOUBLE);
56 const double size = 8.0;
57 const double delta = size * stdev / (double)num_samples;
58 const double start = -size * .5 * stdev + center;
59 for(cpl_size i = 0; i < num_samples; ++i){
60 const double x = delta * ((double)i) + start;
61 const double val = (x - mean) / stdev;
62 const double exponential = -.5 * pow(val, 2.0);
63 const double y = exp(exponential)/(stdev * sqrt(2. * CPL_MATH_PI));
64 cpl_array_set(v, i, y);
65 }
66
67 *delta_out = delta;
68
69 return v;
70}
71
72
73/*----------------------------------------------------------------------------*/
77/*----------------------------------------------------------------------------*/
78
79void test_shift_pixel_precision(const cpl_size in_shift){
80
81 const cpl_size sz = 28;
82 const cpl_size win = 14;
83 cpl_array * v1 = create_rect(sz, 3, 5);
84 cpl_array * v2 = create_rect(sz, 3 + llabs(in_shift), 5 + llabs(in_shift));
85
86 if(in_shift < 0){
87 cpl_array * tmp = v1;
88 v1 = v2;
89 v2 = tmp;
90 }
91
92 hdrl_xcorrelation_result * res =
93 hdrl_compute_xcorrelation(v1, v2, win, CPL_FALSE);
94
95 const cpl_size idx = hdrl_xcorrelation_result_get_peak_pixel(res);
96 const cpl_size shift = idx - win;
97
98 const cpl_array * xcorr = hdrl_xcorrelation_result_get_correlation(res);
99
100 cpl_test_eq(shift, -in_shift);
101
102 if(in_shift == 0){
103 cpl_test_rel(cpl_array_get(xcorr, idx, NULL),
104 25.0 * 3.0 /((double)sz), 1e-5);
105 cpl_test_rel(cpl_array_get(xcorr, idx - 1, NULL),
106 25.0 * 2.0 /((double)sz - 1.0), 1e-5);
107 cpl_test_rel(cpl_array_get(xcorr, idx + 1, NULL),
108 25.0 * 2.0 /((double)sz - 1.0), 1e-5);
109 cpl_test_rel(cpl_array_get(xcorr, idx - 2, NULL),
110 25.0 * 1.0 /((double)sz - 2.0), 1e-5);
111 cpl_test_rel(cpl_array_get(xcorr, idx + 2, NULL),
112 25.0 * 1.0 /((double)sz - 2.0), 1e-5);
113 for(cpl_size i = 0; i < win * 2 + 1; i++){
114 if(i >= idx - 2 && i <= idx + 2) continue;
115 cpl_test_rel(cpl_array_get(xcorr, i, NULL), 0.0, 1e-5);
116 }
117 }
118
120
121 cpl_array_delete(v1);
122 cpl_array_delete(v2);
123}
124
125void test_shift_gaussian_fit(const double mean_diff,
126 const cpl_boolean use_win_refinement){
127
128 const double m1 = 1.0;
129 const double m2 = m1 + mean_diff;
130 const double std_dev = sqrt(.5);
131 const cpl_size sz = 100;
132 cpl_size half_w = 180;
133 double delta = .0;
134 cpl_array * arr1 = create_gaussian(sz, m1, std_dev, .5 * (m1 + m2), &delta);
135 cpl_array * arr2 = create_gaussian(sz, m2, std_dev, .5 * (m1 + m2), &delta);
136
137 hdrl_xcorrelation_result * r = NULL;
138
139 if(use_win_refinement)
140 r = hdrl_compute_offset_gaussian(arr1, arr2,
141 half_w, CPL_TRUE, delta, 0.5);
142 else
144 half_w, CPL_TRUE, delta, 0.5);
145
146 const double peak = hdrl_xcorrelation_result_get_peak_subpixel(r);
147 const cpl_size used_win = hdrl_xcorrelation_result_get_half_window(r);
148 const double tolerance = use_win_refinement ? 5.6e-2 : 6e-2;
149 if (mean_diff != 0.0) { // Needed -> check the definition of the cpl macro
150 cpl_test_rel(-peak + used_win * delta, mean_diff, tolerance);
151 } else {
152 cpl_test_abs(peak, used_win * delta, tolerance);
153 }
154
156 cpl_array_delete(arr1);
157 cpl_array_delete(arr2);
158}
159
160/*----------------------------------------------------------------------------*/
164/*----------------------------------------------------------------------------*/
165int main(void)
166{
167 cpl_test_init(PACKAGE_BUGREPORT, CPL_MSG_WARNING);
168
169 test_shift_pixel_precision(0);
170 test_shift_pixel_precision(2);
171 test_shift_pixel_precision(6);
172 test_shift_pixel_precision(-2);
173 test_shift_pixel_precision(-6);
174
175
176 test_shift_gaussian_fit(2.4, CPL_FALSE);
177 test_shift_gaussian_fit(-2.4, CPL_FALSE);
178 test_shift_gaussian_fit(1.8, CPL_FALSE);
179 test_shift_gaussian_fit(0.0, CPL_FALSE);
180
181 test_shift_gaussian_fit(2.4, CPL_TRUE);
182 test_shift_gaussian_fit(-2.4, CPL_TRUE);
183 test_shift_gaussian_fit(1.8, CPL_TRUE);
184 test_shift_gaussian_fit(0.0, CPL_TRUE);
185
186 cpl_test_error(CPL_ERROR_NONE);
187
188 return cpl_test_end(0);
189}
190
void hdrl_xcorrelation_result_delete(hdrl_xcorrelation_result *self)
Destructor for hdrl_xcorrelation_result.
hdrl_xcorrelation_result * hdrl_compute_xcorrelation(const cpl_array *arr1, const cpl_array *arr2, const cpl_size half_window, const cpl_boolean normalize)
Calculate cross-correlation.
const cpl_array * hdrl_xcorrelation_result_get_correlation(const hdrl_xcorrelation_result *self)
Getter for the cross correlation.
cpl_size hdrl_xcorrelation_result_get_peak_pixel(const hdrl_xcorrelation_result *self)
Get the index where the cross correlation reaches its maximum.
cpl_size hdrl_xcorrelation_result_get_half_window(const hdrl_xcorrelation_result *self)
Get the half_window used to calculate the cross-correlation.
hdrl_xcorrelation_result * hdrl_compute_offset_gaussian_internal(const cpl_array *arr1, const cpl_array *arr2, const cpl_size half_win, const cpl_boolean normalize, const double bin, const double wrange)
Calculate gaussian fit on cross-correlation.
hdrl_xcorrelation_result * hdrl_compute_offset_gaussian(const cpl_array *arr1, const cpl_array *arr2, const cpl_size half_win, const cpl_boolean normalize, const double bin, const double wrange)
Calculate gaussian fit on cross-correlation, does a second fitting for refinement.
double hdrl_xcorrelation_result_get_peak_subpixel(const hdrl_xcorrelation_result *self)
Get the index where the cross correlation reaches its maximum, with sub-pixel precision.