48#define MIN_THRESH_FACT 0.9
49#define MAX_THRESH_FACT 1.1
50#define SPEC_SHADOW_FACT 30.0
51#define SPEC_MAXWIDTH 48
95 cpl_image * filt_image ;
97 cpl_image * collapsed ;
101 cpl_vector * line_filt ;
103 double median, stdev,
max, mean ;
107 cpl_apertures * aperts ;
115 if (in == NULL)
return -1 ;
116 if (orient!=0 && orient!=1)
return -1 ;
120 loc_ima = cpl_image_duplicate(in) ;
121 cpl_image_flip(loc_ima, 1) ;
123 loc_ima = cpl_image_duplicate(in) ;
127 kernel = cpl_matrix_new(3, 3) ;
128 cpl_matrix_fill(kernel, 1.0) ;
130 cpl_matrix_delete(kernel) ;
131 cpl_image_delete(loc_ima) ;
132 cpl_msg_error(cpl_func,
"cannot filter the image") ;
135 cpl_image_delete(loc_ima) ;
136 cpl_matrix_delete(kernel) ;
139 if ((collapsed = cpl_image_collapse_median_create(filt_image, 1, 0,
141 cpl_msg_error(cpl_func,
"collapsing image: aborting spectrum detection");
142 cpl_image_delete(filt_image) ;
145 cpl_image_delete(filt_image) ;
148 line = cpl_vector_new_from_image_column(collapsed, 1) ;
149 cpl_image_delete(collapsed) ;
150 line_filt = cpl_vector_filter_median_create(line,
SPECTRUM_HW) ;
151 cpl_vector_subtract(line, line_filt) ;
152 cpl_vector_delete(line_filt) ;
155 median = cpl_vector_get_median_const(line) ;
156 stdev = cpl_vector_get_stdev(line) ;
157 max = cpl_vector_get_max(line) ;
158 mean = cpl_vector_get_mean(line) ;
166 collapsed = cpl_image_new(1, cpl_vector_get_size(line), CPL_TYPE_FLOAT) ;
167 pcollapsed = cpl_image_get_data_float(collapsed) ;
168 pline = cpl_vector_get_data(line) ;
169 for (i=0 ; i<cpl_vector_get_size(line) ; i++)
170 pcollapsed[i] = (
float)pline[i] ;
171 cpl_vector_delete(line) ;
174 if ((mask = cpl_mask_threshold_image_create(collapsed,
threshold,
176 cpl_msg_error(cpl_func,
"cannot binarise") ;
177 cpl_image_delete(collapsed) ;
180 if (cpl_mask_count(mask) < 1) {
181 cpl_msg_error(cpl_func,
"not enough signal to detect spectra") ;
182 cpl_image_delete(collapsed) ;
183 cpl_mask_delete(mask) ;
187 if ((labels = cpl_image_labelise_mask_create(mask, &nlabels))==NULL) {
188 cpl_msg_error(cpl_func,
"cannot labelise") ;
189 cpl_image_delete(collapsed) ;
190 cpl_mask_delete(mask) ;
193 cpl_mask_delete(mask) ;
196 if ((aperts = cpl_apertures_new_from_image(collapsed, labels)) == NULL) {
197 cpl_msg_error(cpl_func,
"cannot compute apertures") ;
198 cpl_image_delete(collapsed) ;
199 cpl_image_delete(labels) ;
202 cpl_image_delete(labels) ;
206 &n_valid_specs, &valid_specs) == -1) {
207 cpl_msg_debug(cpl_func,
"cannot select valid spectra") ;
208 cpl_image_delete(collapsed) ;
209 cpl_apertures_delete(aperts) ;
212 cpl_image_delete(collapsed) ;
213 if (n_valid_specs < 1) {
214 cpl_msg_error(cpl_func,
"no valid spectrum detected") ;
215 cpl_free(valid_specs) ;
216 cpl_apertures_delete(aperts) ;
221 *pos = cpl_apertures_get_centroid_y(aperts, valid_specs[0]+1) ;
223 brightness = cpl_apertures_get_flux(aperts, valid_specs[0]+1) ;
224 for (i=0 ; i<n_valid_specs ; i++) {
225 if (cpl_apertures_get_flux(aperts, valid_specs[i]+1) > brightness) {
226 *pos = cpl_apertures_get_centroid_y(aperts, valid_specs[i]+1) ;
228 brightness = cpl_apertures_get_flux(aperts, valid_specs[i]+1) ;
231 cpl_apertures_delete(aperts) ;
232 cpl_free(valid_specs) ;
235 if (brightness < min_bright) {
236 cpl_msg_error(cpl_func,
"brightness %f too low <%f", brightness,
256 const cpl_vector * in,
261 cpl_vector * filtered ;
262 cpl_vector * spec_clean ;
263 double * pspec_clean ;
265 cpl_vector * conv_kernel ;
266 cpl_vector * big_detected ;
267 double * pbig_detected ;
268 cpl_vector * detected ;
270 double max, med, stdev, cur_val ;
271 int nb_det, nb_samples ;
275 if (in == NULL)
return NULL ;
278 nb_samples = cpl_vector_get_size(in) ;
282 cpl_msg_info(__func__,
"Low Frequency signal removal") ;
283 if ((filtered=cpl_vector_filter_median_create(in, filt_size))==NULL){
284 cpl_msg_error(__func__,
"Cannot filter the spectrum") ;
287 spec_clean = cpl_vector_duplicate(in) ;
288 cpl_vector_subtract(spec_clean, filtered) ;
289 cpl_vector_delete(filtered) ;
294 "set grid;set xlabel 'Position (pixels)';set ylabel 'Intensity (ADU)';",
295 "t 'Filtered extracted spectrum' w lines",
"", spec_clean);
299 cpl_msg_info(__func__,
"Spectrum convolution") ;
301 if ((conv_kernel = cpl_wlcalib_xc_convolve_create_kernel(fwhm,
303 cpl_msg_error(cpl_func,
"Cannot create convolution kernel") ;
304 cpl_vector_delete(spec_clean) ;
309 if (cpl_wlcalib_xc_convolve(spec_clean, conv_kernel)) {
310 cpl_msg_error(cpl_func,
"Cannot smoothe the signal");
311 cpl_vector_delete(spec_clean) ;
312 cpl_vector_delete(conv_kernel) ;
315 cpl_vector_delete(conv_kernel) ;
320 "set grid;set xlabel 'Position (pixels)';set ylabel 'Intensity (ADU)';",
321 "t 'Convolved extracted spectrum' w lines",
"", spec_clean);
325 big_detected = cpl_vector_duplicate(spec_clean) ;
326 pbig_detected = cpl_vector_get_data(big_detected) ;
327 pspec_clean = cpl_vector_get_data(spec_clean) ;
330 pspec_clean[0] = pspec_clean[nb_samples-1] = 0.0 ;
333 max = cpl_vector_get_max(spec_clean) ;
334 stdev = cpl_vector_get_stdev(spec_clean) ;
335 med = cpl_vector_get_median_const(spec_clean) ;
342 while (pspec_clean[i] <
max) i++ ;
343 if (i<=0 || i>=nb_samples-1) break ;
346 pbig_detected[nb_det] = (pspec_clean[i]*i +
347 pspec_clean[i-1]*(i-1) + pspec_clean[i+1]*(i+1)) /
348 (pspec_clean[i]+pspec_clean[i-1]+pspec_clean[i+1]);
350 pbig_detected[nb_det] ++ ;
357 cur_val = pspec_clean[i] ;
358 while (j>=0 && pspec_clean[j] < cur_val) {
359 cur_val = pspec_clean[j] ;
360 pspec_clean[j] = 0.0 ;
365 cur_val = pspec_clean[i] ;
366 while (j<=nb_samples-1 && pspec_clean[j] < cur_val) {
367 cur_val = pspec_clean[j] ;
368 pspec_clean[j] = 0.0 ;
372 pspec_clean[i] = 0.0 ;
375 max = cpl_vector_get_max(spec_clean) ;
376 stdev = cpl_vector_get_stdev(spec_clean) ;
377 med = cpl_vector_get_median_const(spec_clean) ;
379 cpl_vector_delete(spec_clean) ;
380 cpl_msg_info(__func__,
"%d lines detected", nb_det) ;
386 detected = cpl_vector_new(nb_det) ;
387 pdetected = cpl_vector_get_data(detected) ;
388 pbig_detected = cpl_vector_get_data(big_detected) ;
389 for (i=0 ; i<nb_det ; i++) pdetected[i] = pbig_detected[i] ;
391 cpl_vector_delete(big_detected) ;
414 cpl_apertures * aperts,
425 *valid_specs = NULL ;
426 nb_aperts = cpl_apertures_get_size(aperts) ;
430 if (nb_aperts < 1)
return -1 ;
434 for (i=0 ; i<nb_aperts ; i++)
436 i+1)) (*n_valid_specs)++ ;
439 if (*n_valid_specs) {
440 *valid_specs = cpl_calloc(*n_valid_specs,
sizeof(
int)) ;
442 for (i=0 ; i<nb_aperts ; i++)
445 (*valid_specs)[j] = i ;
467 cpl_apertures * aperts,
474 double valover, valunder, valcenter ;
477 objwidth = cpl_apertures_get_top(aperts, objnum) -
478 cpl_apertures_get_bottom(aperts, objnum) + 1 ;
479 if (objwidth > max_spec_width) {
480 cpl_msg_error(cpl_func,
"object is too wide") ;
485 if (cpl_apertures_get_npix(aperts, objnum) < 2)
return 0 ;
491 valcenter = cpl_apertures_get_median(aperts, objnum) ;
494 if (cpl_apertures_get_bottom(aperts, objnum) - offset < 1) valunder = 0.0 ;
495 else valunder = cpl_image_get_median_window(in, 1,
496 cpl_apertures_get_bottom(aperts, objnum) - offset, 1,
497 cpl_apertures_get_top(aperts, objnum) - offset) ;
499 if (cpl_apertures_get_top(aperts, objnum) + offset > 1024) valover = 0.0 ;
500 else valover = cpl_image_get_median_window(in, 1,
501 cpl_apertures_get_bottom(aperts, objnum) + offset, 1,
502 cpl_apertures_get_top(aperts, objnum) + offset) ;
508 (valunder/valover > 0.5) &&
509 (valunder/valover < 2.0))
return 1 ;
521 cpl_msg_error(cpl_func,
"unknown spec_detect_mode") ;
int xsh_spectrum_find_brightest(const cpl_image *in, int offset, spec_shadows shadows, double min_bright, int orient, double *pos)
Finds the brightest spectrum in an image.
cpl_vector * xsh_spectrum_detect_peaks(const cpl_vector *in, int fwhm, double kappa, int display)
Detect the brightest features in a spectrum.
static int select_valid_spectra(cpl_image *, cpl_apertures *, int, spec_shadows, int, int *, int **)
Selects the valid spectra in a spectral image.
static int valid_spectrum(cpl_image *, cpl_apertures *, int, spec_shadows, int, int)
Helper function to select_valid_spectra.
enum SPEC_SHADOWS spec_shadows
cpl_image * xsh_image_filter_median(const cpl_image *img, const cpl_matrix *mx)