30#include "cr2res_detlin.h"
31#include "cr2res_pfits.h"
38#define pow2(x) (x)*(x)
39#define pow3(x) (x)*(x)*(x)
45static int cr2res_detlin_frames_dit_compare(
46 const cpl_frame * in1,
47 const cpl_frame * in2) ;
48static void cr2res_matrix_fill_normal_vandermonde(cpl_matrix * self,
50 const cpl_vector * xhat,
51 cpl_boolean is_eqdist,
53 const cpl_vector * values);
73 const hdrl_imagelist * detlin)
75 const cpl_image * ima ;
76 const cpl_image * erra ;
77 const cpl_image * imb ;
78 const cpl_image * errb ;
79 const cpl_image * imc ;
80 const cpl_image * errc ;
82 const double * perra ;
84 const double * perrb ;
86 const double * perrc ;
91 double correction_factor;
95 if (!in || !detlin)
return -1 ;
110 if (!ima || !imb || !imc ) {
111 cpl_msg_error(cpl_func,
"Cannot access the detlin images") ;
114 pima = cpl_image_get_data_double_const(ima) ;
115 pimb = cpl_image_get_data_double_const(imb) ;
116 pimc = cpl_image_get_data_double_const(imc) ;
117 perra = cpl_image_get_data_double_const(erra);
118 perrb = cpl_image_get_data_double_const(errb);
119 perrc = cpl_image_get_data_double_const(errc);
123 nx = cpl_image_get_size_x(cur_ima) ;
124 ny = cpl_image_get_size_y(cur_ima) ;
125 if ((cpl_image_get_size_x(ima) != nx) ||
126 (cpl_image_get_size_x(imb) != nx) ||
127 (cpl_image_get_size_x(imc) != nx) ||
128 (cpl_image_get_size_y(ima) != ny) ||
129 (cpl_image_get_size_y(imb) != ny) ||
130 (cpl_image_get_size_y(imc) != ny)) {
131 cpl_msg_error(cpl_func,
"Incompatible sizes") ;
136 for (i=0 ; i<nx*ny ; i++) {
139 if (pdata[i] < CR2RES_DETLIN_THRESHOLD) continue ;
142 perr[i] = pow2(perra[i] * pdata[i]) + pow2(perrb[i] * pow2(pdata[i]))
143 + pow2(perrc[i] * pow3(pdata[i]))
144 + pow2(perr[i] * (pima[i] + 2. * pimb[i] * pdata[i]
145 + 3. * pimc[i] * pow2(pdata[i])));
146 perr[i] = sqrt(perr[i]);
148 correction_factor = pima[i] + \
149 ((pimb[i] + pimc[i] * pdata[i]) * pdata[i]);
150 pdata[i] = pdata[i] * correction_factor;
176 const cpl_vector * dits,
177 const cpl_vector * adus,
179 cpl_polynomial ** fitted,
182 cpl_matrix * samppos ;
183 cpl_polynomial * fitted_local ;
184 cpl_vector * error_local ;
185 cpl_vector * adusPsec ;
186 cpl_vector * y_tofit, *tmp;
187 cpl_vector * adus_loc, *dits_loc;
189 cpl_size i=0, first_satur=-1 ;
193 if (fitted == NULL || dits == NULL || adus == NULL)
return -1 ;
194 if (cpl_vector_get_size(dits) != cpl_vector_get_size(adus))
198 if (cpl_vector_get_min(adus) > CR2RES_DETLIN_THRESHOLD)
return -1;
199 if (cpl_vector_get_max(adus) < CR2RES_DETLIN_THRESHOLD)
return -1;
200 for (i = 0; i < cpl_vector_get_size(adus); i++) {
201 if (cpl_vector_get(adus,i) < CR2RES_DETLIN_THRESHOLD ) count_linear++;
202 if (cpl_vector_get(adus,i)>CR2RES_DETLIN_MAXFIT && first_satur==-1)
207 if (first_satur==-1) first_satur= cpl_vector_get_size(dits);
209 if (count_linear > first_satur-1) count_linear = first_satur-1;
211 adus_loc = cpl_vector_extract(adus, 0, first_satur-1, 1);
212 dits_loc = cpl_vector_extract(dits, 0, first_satur-1, 1);
215 adusPsec = cpl_vector_duplicate(adus_loc);
216 cpl_vector_divide(adusPsec, dits_loc);
217 tmp = cpl_vector_extract(adusPsec,0,count_linear-1,1);
218 aduPsec = cpl_vector_get_median(tmp);
219 cpl_vector_delete(tmp);
221 samppos = cpl_matrix_wrap(1,
222 cpl_vector_get_size(adus_loc),
223 cpl_vector_get_data(adus_loc)) ;
225 y_tofit = cpl_vector_new(cpl_vector_get_size(dits_loc));
226 for(i = 0; i < cpl_vector_get_size(dits_loc); i++) {
229 y = aduPsec / cpl_vector_get(adusPsec,i);
230 cpl_vector_set(y_tofit, i, y);
232 cpl_vector_delete(adusPsec);
235 fitted_local = cpl_polynomial_new(1);
237 cpl_polynomial_fit(fitted_local, samppos, NULL, y_tofit, NULL,
238 CPL_FALSE, NULL, &max_degree) != CPL_ERROR_NONE) {
241 cpl_vector_delete(adus_loc);
242 cpl_vector_delete(dits_loc);
243 cpl_matrix_unwrap(samppos) ;
244 cpl_vector_delete(y_tofit);
245 cpl_polynomial_delete(fitted_local) ;
251 error_local = cpl_vector_new(max_degree+1) ;
252 cpl_size nc = max_degree + 1;
253 cpl_size ndata = cpl_vector_get_size(y_tofit);
256 for (i = 0; i < max_degree + 1; i++) {
257 cpl_vector_set(error_local, i, 0);
266 cpl_matrix * hankel = cpl_matrix_new(nc, nc);
267 cpl_matrix * mx = cpl_matrix_new(nc, 1);
271 cr2res_matrix_fill_normal_vandermonde(hankel, mx, adus_loc, CPL_FALSE,
273 cpl_matrix * inverse = cpl_matrix_invert_create(hankel);
274 cpl_vector * resids = cpl_vector_new(ndata);
276 cpl_vector_fill_polynomial_fit_residual(resids, y_tofit, NULL,
277 fitted_local, samppos, NULL);
278 for (i = 0; i < ndata; i++) {
279 cpl_vector_set(resids, i, fabs(cpl_vector_get(resids, i)));
282 cpl_matrix_multiply_scalar(inverse,
283 cpl_vector_get_sum(resids) / (
double)(ndata - nc));
285 for (i = 0; i < max_degree + 1; i++) {
286 cpl_vector_set(error_local, i, sqrt(cpl_matrix_get(inverse, i, i)));
288 cpl_matrix_delete(hankel);
289 cpl_matrix_delete(mx);
290 cpl_matrix_delete(inverse);
291 cpl_vector_delete(resids);
293 cpl_vector_delete(y_tofit);
294 cpl_matrix_unwrap(samppos) ;
295 cpl_vector_delete(dits_loc);
296 cpl_vector_delete(adus_loc);
299 for (i=0 ; i<=max_degree ; i++) {
301 cur_coeff = cpl_polynomial_get_coeff(fitted_local, &i) ;
302 if (isnan(cur_coeff)) {
303 cpl_polynomial_delete(fitted_local) ;
304 cpl_vector_delete(error_local) ;
312 if (cpl_error_get_code()) {
314 cpl_polynomial_delete(fitted_local) ;
315 cpl_vector_delete(error_local) ;
322 *fitted = fitted_local ;
323 if (error != NULL) *error = error_local ;
324 else cpl_vector_delete(error_local) ;
336 const cpl_frameset * in)
338 cpl_frameset * sorted ;
341 if (in == NULL)
return NULL ;
343 sorted = cpl_frameset_duplicate(in) ;
344 if (cpl_frameset_sort(sorted,
345 cr2res_detlin_frames_dit_compare) != CPL_ERROR_NONE) {
346 cpl_frameset_delete(sorted) ;
362static int cr2res_detlin_frames_dit_compare(
363 const cpl_frame * in1,
364 const cpl_frame * in2)
366 cpl_propertylist * plist1 ;
367 cpl_propertylist * plist2 ;
371 if (in1==NULL || in2==NULL)
return 0 ;
374 plist1=cpl_propertylist_load(cpl_frame_get_filename(in1),0) ;
375 plist2=cpl_propertylist_load(cpl_frame_get_filename(in2),0) ;
380 if (plist1 != NULL) cpl_propertylist_delete(plist1) ;
381 if (plist2 != NULL) cpl_propertylist_delete(plist2) ;
382 if (cpl_error_get_code())
return 0 ;
384 if (dit1<dit2)
return -1 ;
385 else if (dit1>dit2)
return 1 ;
404static void cr2res_matrix_fill_normal_vandermonde(cpl_matrix * self,
406 const cpl_vector * xhat,
407 cpl_boolean is_eqdist,
409 const cpl_vector * values)
413 const double * dval = cpl_vector_get_data_const(values);
414 const double * xval = cpl_vector_get_data_const(xhat);
415 cpl_vector * phat = cpl_vector_duplicate(xhat);
416 cpl_vector * qhat = NULL;
417 double * dhat = cpl_vector_get_data(phat);
418 double * ehat = NULL;
419 const cpl_size nc = cpl_matrix_get_ncol(self);
420 const cpl_size np = cpl_vector_get_size(xhat);
431 qhat = mindeg == 1 ? cpl_vector_duplicate(xhat) : cpl_vector_new(np);
432 ehat = cpl_vector_get_data(qhat);
435 for (k=0; k < np; k++) {
436 const double x = xval[k];
438 if (mindeg > 1) ehat[k] = pow(x, (
int)mindeg);
441 hsum += ehat[k] * ehat[k];
443 cpl_matrix_set(self, 0, 0, hsum);
445 cpl_matrix_set(self, 0, 0, (
double)np);
449 for (j=1; j < 2; j++) {
455 for (k=0; k < np; k++) {
456 const double y = dval[k];
458 hsum += mindeg > 0 ? ehat[k] * dhat[k] : dhat[k];
460 vsum0 += mindeg > 0 ? ehat[k] * y : y;
462 cpl_matrix_set(mx, 0, 0, vsum0);
463 cpl_matrix_set(mx, j, 0, vsum);
464 if (is_eqdist)
continue;
466 for (i=0; i <= k; i++, k--) {
467 cpl_matrix_set(self, i, k, hsum);
470 for (; j < nc; j++) {
475 for (k=0; k < np; k++) {
476 const double x = xval[k];
477 const double y = dval[k];
480 hsum += mindeg > 0 ? ehat[k] * dhat[k] : dhat[k];
483 cpl_matrix_set(mx, j, 0, vsum);
484 if (is_eqdist && (j&1))
continue;
486 for (i=0; i <= k; i++, k--) {
487 cpl_matrix_set(self, i, k, hsum);
493 cpl_vector_multiply(phat, qhat);
494 cpl_vector_delete(qhat);
497 for (i = 1; i < nc; i++) {
501 if (is_eqdist && ((i+nc)&1)==0) {
502 cpl_vector_multiply(phat, xhat);
506 for (k=0; k < np; k++) {
507 const double x = xval[k];
513 for (j = nc-1; k <= j; k++, j--) {
514 cpl_matrix_set(self, k, j, hsum);
518 cpl_vector_delete(phat);
cpl_frameset * cr2res_detlin_sort_frames(const cpl_frameset *in)
Sort the frames by increasing DIT.
int cr2res_detlin_compute(const cpl_vector *dits, const cpl_vector *adus, cpl_size max_degree, cpl_polynomial **fitted, cpl_vector **error)
Fits the response of a given pixel to the illumination increase.
int cr2res_detlin_correct(hdrl_image *in, const hdrl_imagelist *detlin)
Apply the detector linearity correction.
double cr2res_pfits_get_dit(const cpl_propertylist *plist)
find out the DIT value
cpl_image * hdrl_image_get_error(hdrl_image *himg)
get error as cpl image
const cpl_image * hdrl_image_get_error_const(const hdrl_image *himg)
get error as cpl image
cpl_image * hdrl_image_get_image(hdrl_image *himg)
get data as cpl image
const cpl_image * hdrl_image_get_image_const(const hdrl_image *himg)
get data as cpl image
const hdrl_image * hdrl_imagelist_get_const(const hdrl_imagelist *himlist, cpl_size inum)
Get an image from a list of images.