CR2RE Pipeline Reference Manual 1.6.8
hdrl_cat_filter.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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19
20#include "hdrl_cat_filter.h"
21
22#include "hdrl_cat_statistics.h"
23
24
25/*** Prototypes ***/
26
27static void filt1d( double ybuf[], cpl_size mpt, cpl_size mfilt);
28static void hanning(double xbuf[], cpl_size npt);
29
30
31/*---------------------------------------------------------------------------*/
39/*----------------------------------------------------------------------------*/
40
43/* ---------------------------------------------------------------------------*/
56/* ---------------------------------------------------------------------------*/
57cpl_error_code hdrl_bfilt(double **xbuf, cpl_size nx, cpl_size ny)
58{
59 /* Allocate temporary storage */
60 double *ybuf = (double *)cpl_malloc(CPL_MAX(nx, ny) * sizeof(double));
61 double *save = (double *)cpl_malloc((nx + 1) * ny * sizeof(double));
62
63 cpl_size mfilt = 5;
64
65 /* median filter across */
66 for (cpl_size k = 0; k < ny; k++) {
67
68 for (cpl_size j = 0; j < nx; j++) {
69
70 save[(nx + 1) * k + j] = xbuf[k][j];
71
72 ybuf[j] = xbuf[k][j];
73 }
74
75 filt1d(ybuf, nx, mfilt);
76
77 for (cpl_size j = 0; j < nx; j++) {
78 xbuf[k][j] = ybuf[j];
79 }
80 }
81
82 /* and now down */
83 for (cpl_size k = 0; k < nx; k++) {
84
85 for (cpl_size j = 0; j < ny; j++) {
86 ybuf[j] = xbuf[j][k];
87 }
88
89 filt1d(ybuf, ny, mfilt);
90
91 for (cpl_size j = 0; j < ny; j++) {
92
93 /* make sure median filtered values are not large than original */
94 if (save[(nx + 1) * j + k] > -1000.) {
95 xbuf[j][k] = CPL_MIN(save[(nx + 1) * j + k], ybuf[j]);
96 }
97 }
98 }
99
100 /* now repeat with linear filters across */
101 for (cpl_size k = 0; k < ny; k++) {
102
103 for (cpl_size j = 0; j < nx; j++) {
104 ybuf[j] = xbuf[k][j];
105 }
106
107 hanning(ybuf, nx);
108
109 for (cpl_size j = 0; j < nx; j++) {
110 xbuf[k][j] = ybuf[j];
111 }
112 }
113
114 /* and now down */
115 for (cpl_size k = 0; k < nx; k++) {
116
117 for (cpl_size j = 0; j < ny; j++) {
118 ybuf[j] = xbuf[j][k];
119 }
120
121 hanning(ybuf, ny);
122
123 for (cpl_size j = 0; j < ny; j++) {
124 xbuf[j][k] = ybuf[j];
125 }
126 }
127
128 /* Free temporary storage */
129 cpl_free((void *)ybuf);
130 cpl_free((void *)save);
131
132 return CPL_ERROR_NONE;
133}
134
135/* ---------------------------------------------------------------------------*/
145/* ---------------------------------------------------------------------------*/
146void padext(double x[], cpl_size n)
147{
148 /* elements <= -1000.0 are treated as missing */
149 cpl_size ii = 0;
150 while (ii < n && x[ii] <= -1000.) {
151 ii++;
152 }
153 cpl_size ilow = ii;
154 cpl_size ihih = 0;
155
156 for (cpl_size i = ilow + 1; i < n; i++){
157
158 if (x[i] <= -1000.) {
159
160 cpl_size ic = 1;
161 if (i < n - 1) {
162
163 while (x[i + ic] <= -1000.) {
164
165 ic++;
166
167 if (i + ic >= n - 1) {
168 break;
169 }
170 }
171 }
172
173 if (i + ic < n - 1){
174
175 double xlow = x[i - 1];
176 double xhih = x[i + ic];
177
178 for (cpl_size j = 0; j < ic; j++){
179
180 double t2 = ((double)j + 1.) / ((double)ic + 1.);
181 double t1 = 1. - t2;
182
183 x[i + j] = t1 * xlow + t2 * xhih;
184 }
185 }
186
187 } else {
188
189 ihih = i;
190 }
191 }
192
193
194 /* linear extrapolation of ends */
195 if (ilow > 0 && ilow < n){
196
197 double slope;
198 if (ilow < n - 1) {
199 slope = x[ilow + 1] - x[ilow];
200 } else {
201 slope = 0.;
202 }
203
204 for (cpl_size i = 0; i < ilow; i++) {
205 x[i] = x[ilow] - slope * (ilow - i);
206 }
207 }
208
209 if (ihih < n - 1) {
210
211 double slope;
212 if (ihih > 0) {
213 slope = x[ihih] - x[ihih - 1];
214 } else {
215 slope = 0.;
216 }
217
218 for (cpl_size i = ihih + 1; i < n; i++) {
219 x[i] = x[ihih] + slope * (i - ihih);
220 }
221 }
222}
223
226/* ---------------------------------------------------------------------------*/
237/* ---------------------------------------------------------------------------*/
238static void filt1d(double ybuf[], cpl_size mpt, cpl_size mfilt)
239{
240 /* Allocate temporary storage */
241 double *wbuf = (double *)cpl_malloc(mpt * sizeof(double));
242
243 cpl_size irc = 0;
244 for (cpl_size i = 0; i < mpt; i++){
245 if (ybuf[i] > -1000.){
246 wbuf[irc] = ybuf[i];
247 irc++;
248 }
249 }
250
251 if (irc != 0) {
252
253 hdrl_median(wbuf, irc, mfilt);
254
255 irc = 0;
256 for (cpl_size i = 0; i < mpt; i++){
257 if (ybuf[i] > -1000.){
258 ybuf[i] = wbuf[irc];
259 irc++;
260 }
261 }
262
263 padext(ybuf, mpt);
264 }
265
266 /* Free temporary storage */
267 cpl_free((void *)wbuf);
268}
269
270/* ---------------------------------------------------------------------------*/
280/* ---------------------------------------------------------------------------*/
281static void hanning(double xbuf[], cpl_size npt)
282{
283 cpl_size nfilt = 3;
284 if (npt <= nfilt) {
285 return;
286 }
287
288 /* set first and last edges equal */
289 cpl_size il = nfilt / 2;
290
291 cpl_size ilow = CPL_MAX(3, nfilt / 4);
292 ilow = (ilow / 2) * 2 + 1;
293
294 double sum = 0.;
295 for (cpl_size i = 0; i < ilow; i++) {
296 sum += xbuf[i];
297 }
298 double xmns = sum / (double)ilow;
299
300 sum = 0.;
301 for (cpl_size i = 0; i < ilow; i++) {
302 sum += xbuf[npt - 1 - i];
303 }
304 double xmnf = sum / (double)ilow;
305
306 /* allocate ybuf array */
307 cpl_size nelem = npt + nfilt; /* Max. number of elements req'd */
308 double *ybuf = (double *)cpl_malloc(nelem * sizeof(double));
309
310 /* reflect edges before filtering */
311 for (cpl_size i = 0; i < il; i++) {
312 ybuf[i] = 2. * xmns - xbuf[il + ilow - 1 - i];
313 ybuf[npt + i + il] = 2. * xmnf - xbuf[npt - i - ilow - 1];
314 }
315
316 for (cpl_size i = 0; i < npt; i++) {
317 ybuf[i + il] = xbuf[i];
318 }
319
320 /* do linear filtering on rest */
321 for (cpl_size i = 0; i < npt; i++) {
322 /* 1-2-1 Hanning weighting */
323 xbuf[i] = 0.25 * (ybuf[i] + 2. * ybuf[i + 1] + ybuf[i + 2]);
324 }
325
326 /* clean up */
327 cpl_free((void *) ybuf);
328}
cpl_error_code hdrl_bfilt(double **xbuf, cpl_size nx, cpl_size ny)
Do bilinear median and linear filtering on background values.
void padext(double x[], cpl_size n)
Pads out array with missing points and linearly extrapolates the ends.
cpl_error_code hdrl_median(double xbuf[], cpl_size npt, cpl_size nfilt)
compute median