ROPO
Loading...
Searching...
No Matches
rave_ropo_generator.c
Go to the documentation of this file.
1/* --------------------------------------------------------------------
2Copyright (C) 2011 Swedish Meteorological and Hydrological Institute, SMHI,
3
4This file is part of bRopo.
5
6bRopo is free software: you can redistribute it and/or modify
7it under the terms of the GNU Lesser General Public License as published by
8the Free Software Foundation, either version 3 of the License, or
9(at your option) any later version.
10
11bRopo is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU Lesser General Public License for more details.
15
16You should have received a copy of the GNU Lesser General Public License
17along with bRopo. If not, see <http://www.gnu.org/licenses/>.
18------------------------------------------------------------------------*/
19
27#include <limits.h>
28#include <math.h>
29#include <stdio.h>
30#include <string.h>
31#include <stdarg.h>
32#include <fmi_util.h>
33#include <fmi_image.h>
34#include <fmi_image_filter.h>
35#include <fmi_image_filter_line.h>
36#include <fmi_image_histogram.h>
37#include <fmi_image_filter_speck.h>
38#include <fmi_image_filter_morpho.h>
39#include <fmi_image_restore.h>
40#include <fmi_meteosat.h>
41#include <fmi_radar_image.h>
42
43#include "rave_ropo_generator.h"
44#include "rave_debug.h"
45#include "rave_alloc.h"
46#include "raveobject_list.h"
47
58
60static const char RopoGenerator_CLEAR_STR[] = "CLEAR:";
61static const char RopoGenerator_CUTOFF_STR[] = "CUTOFF:";
62static const char RopoGenerator_BIOMET_STR[] = "BIOMET:";
63static const char RopoGenerator_SHIP_STR[] = "SHIP:";
64static const char RopoGenerator_SUN_STR[] = "SUN:";
65static const char RopoGenerator_EMITTER_STR[] = "EMITTER:";
66static const char RopoGenerator_EMITTER2_STR[] = "EMITTER2:";
67static const char RopoGenerator_CLUTTER_STR[] = "CLUTTER:";
68static const char RopoGenerator_CLUTTER2_STR[] = "CLUTTER2:";
69static const char RopoGenerator_SPECK_STR[] = "SPECK:";
70static const char RopoGenerator_SPECKNORMOLD_STR[] = "SPECKNORMOLD:";
71static const char RopoGenerator_DOPPLER_STR[] = "DOPPLER:";
72//static const char RopoGenerator_GROUND_STR[] = "GROUND:";
73static const char RopoGenerator_METEOSAT_STR[] = "METEOSAT:";
74static const char RopoGenerator_THRESH1_STR[] = "THRESH1:";
75static const char RopoGenerator_EMITTER3_STR[] = "EMITTER3:";
76static const char RopoGenerator_DATA_MIN_STR[] = "DATA_MIN:";
77static const char RopoGenerator_DATA_MAX_STR[] = "DATA_MAX:";
78static const char RopoGenerator_NO_DATA_STR[] = "NO_DATA:";
79
81 FmiRadarPGMCode type;
82 const char* str;
83};
84
88static const struct RopoGenerator_PgmCodeMapping PGM_CODE_MAPPING[] =
89{
90 {CLEAR, RopoGenerator_CLEAR_STR},
91 {CUTOFF, RopoGenerator_CUTOFF_STR},
92 {BIOMET, RopoGenerator_BIOMET_STR},
93 {SHIP, RopoGenerator_SHIP_STR},
94 {SUN, RopoGenerator_SUN_STR},
95 {EMITTER, RopoGenerator_EMITTER_STR},
96 {EMITTER2, RopoGenerator_EMITTER2_STR},
97 {CLUTTER, RopoGenerator_CLUTTER_STR},
98 {CLUTTER2, RopoGenerator_CLUTTER2_STR},
99 {SPECK, RopoGenerator_SPECK_STR},
100 {SPECK, RopoGenerator_SPECKNORMOLD_STR},
101 {DOPPLER, RopoGenerator_DOPPLER_STR},
102 {METEOSAT, RopoGenerator_METEOSAT_STR},
103 {THRESH1, RopoGenerator_THRESH1_STR},
104 {EMITTER3, RopoGenerator_EMITTER3_STR},
105 {DATA_MIN, RopoGenerator_DATA_MIN_STR},
106 {DATA_MAX, RopoGenerator_DATA_MAX_STR},
107 {NO_DATA, RopoGenerator_NO_DATA_STR},
108 {-1, NULL}
109};
110
114static int RaveRopoGenerator_constructor(RaveCoreObject* obj)
115{
117 this->image = NULL;
118 this->classification = NULL;
119 this->markers = NULL;
120 this->probabilities = RAVE_OBJECT_NEW(&RaveObjectList_TYPE);
121
122 if (this->probabilities == NULL) {
123 goto error;
124 }
125 return 1;
126error:
127 RAVE_OBJECT_RELEASE(this->probabilities);
128 return 0;
129}
130
134static void RaveRopoGenerator_destructor(RaveCoreObject* obj)
135{
137 RAVE_OBJECT_RELEASE(src->image);
138 RAVE_OBJECT_RELEASE(src->probabilities);
139 RAVE_OBJECT_RELEASE(src->classification);
140 RAVE_OBJECT_RELEASE(src->markers);
141}
142
149static int RaveRopoGeneratorInternal_addTask(RaveFmiImage_t* image, const char* taskname)
150{
151 RaveAttribute_t* attribute = NULL;
152 int result = 0;
153 RAVE_ASSERT((image != NULL), "image == NULL");
154 RAVE_ASSERT((taskname != NULL), "taskname == NULL");
155
156 attribute = RaveAttributeHelp_createString("how/task", taskname);
157 if (attribute == NULL || !RaveFmiImage_addAttribute(image, attribute)) {
158 RAVE_CRITICAL0("Failed to add attribute to image");
159 goto done;
160 }
161 result = 1;
162
163done:
164 RAVE_OBJECT_RELEASE(attribute);
165 return result;
166}
167
175static int RaveRopoGeneratorInternal_addTaskArgs(RaveFmiImage_t* image, const char* fmt, ...)
176{
177 RaveAttribute_t* attribute = NULL;
178 int result = 0;
179 char fmtstring[1024];
180 va_list ap;
181 int n = 0;
182
183 RAVE_ASSERT((image != NULL), "image == NULL");
184 RAVE_ASSERT((fmt != NULL), "fmt == NULL");
185
186 va_start(ap, fmt);
187 n = vsnprintf(fmtstring, 1024, fmt, ap);
188 va_end(ap);
189 if (n < 0 || n >= 1024) {
190 RAVE_ERROR0("Failed to generate name");
191 goto done;
192 }
193
194 attribute = RaveAttributeHelp_createString("how/task_args", fmtstring);
195 if (attribute == NULL || !RaveFmiImage_addAttribute(image, attribute)) {
196 RAVE_CRITICAL0("Failed to add attribute to image");
197 goto done;
198 }
199 result = 1;
200
201done:
202 RAVE_OBJECT_RELEASE(attribute);
203 return result;
204}
205
206static int RaveRopoGeneratorInternal_addProbabilityTaskArgs(RaveFmiImage_t* image, RaveObjectList_t* probs, const char* fmt, ...)
207{
208 RaveFmiImage_t* field = NULL;
209 RaveAttribute_t* attr = NULL;
210 int sz = 0;
211 int i = 0;
212 int result = 0;
213 char pstr[1024];
214 char fmtstring[1024];
215 va_list ap;
216 int n = 0;
217
218 RAVE_ASSERT((image != NULL), "image == NULL");
219 RAVE_ASSERT((probs != NULL), "probs == NULL");
220 RAVE_ASSERT((fmt != NULL), "fmt == NULL");
221
222 va_start(ap, fmt);
223 n = vsnprintf(fmtstring, 1024, fmt, ap);
224 va_end(ap);
225 if (n < 0 || n >= 1024) {
226 RAVE_ERROR0("Failed to generate name");
227 goto done;
228 }
229
230 memset(pstr, '\0', 1024);
231
232 sz = RaveObjectList_size(probs);
233 for (i = 0; i < sz; i++) {
234 field = (RaveFmiImage_t*)RaveObjectList_get(probs, i);
235 attr = RaveFmiImage_getAttribute(field, "how/task_args");
236 if (attr != NULL) {
237 char* attrstr = NULL;
238 if (!RaveAttribute_getString(attr, &attrstr) || attrstr == NULL) {
239 goto done;
240 }
241 if (strlen(pstr) > 0) {
242 strcat(pstr, ";");
243 strcat(pstr, attrstr);
244 } else {
245 strcpy(pstr, attrstr);
246 }
247 }
248 RAVE_OBJECT_RELEASE(attr);
249 RAVE_OBJECT_RELEASE(field);
250 }
251
252 if (strlen(fmtstring) > 0) {
253 if (strlen(pstr) > 0) {
254 strcat(pstr, ";");
255 strcat(pstr, fmtstring);
256 } else {
257 strcpy(pstr, fmtstring);
258 }
259 }
260
261 attr = RaveAttributeHelp_createString("how/task_args", pstr);
262 if (attr == NULL || !RaveFmiImage_addAttribute(image, attr)) {
263 RAVE_CRITICAL0("Failed to add attribute to image");
264 goto done;
265 }
266
267 result = 1;
268done:
269 RAVE_OBJECT_RELEASE(field);
270 RAVE_OBJECT_RELEASE(attr);
271 return result;
272}
273
280static FmiRadarPGMCode RaveRopoGeneratorInternal_getPgmCode(RaveFmiImage_t* image)
281{
282 RaveAttribute_t* taskargs = NULL;
283 FmiRadarPGMCode result = CLEAR;
284 RAVE_ASSERT((image != NULL), "image == NULL");
285
286 taskargs = RaveFmiImage_getAttribute(image, "how/task_args");
287 if (taskargs != NULL) {
288 char* argument = NULL;
289 int index = 0;
290 if (!RaveAttribute_getString(taskargs, &argument)) {
291 goto done;
292 }
293 if (argument == NULL) {
294 goto done;
295 }
296 while (PGM_CODE_MAPPING[index].str != NULL) {
297 if (strncmp(PGM_CODE_MAPPING[index].str, argument, strlen(PGM_CODE_MAPPING[index].str))==0) {
298 result = PGM_CODE_MAPPING[index].type;
299 goto done;
300 }
301 index++;
302 }
303 }
304done:
305 RAVE_OBJECT_RELEASE(taskargs);
306 return result;
307}
308
322static int RaveRopoGeneratorInternal_valueToByteRange(int value, RaveFmiImage_t* image)
323{
324 int result = -1;
325 double offset = 0.0;
326 double gain = 0.0;
327
328 RAVE_ASSERT((image != NULL), "image == NULL");
329
330 offset = RaveFmiImage_getOffset(image);
331 gain = RaveFmiImage_getGain(image);
332 if (gain != 0.0) {
333 result = (int)((value - offset)/gain);
334 }
335 if (result <= 0) {
336 result = 0;
337 } else if (result >= 255) {
338 result = 255;
339 }
340 return result;
341}
342
351static int RaveRopoGeneratorInternal_relValueToByteRange(int value, RaveFmiImage_t* image)
352{
353 int result = -1;
354 double gain = 0.0;
355
356 RAVE_ASSERT((image != NULL), "image == NULL");
357
358 gain = RaveFmiImage_getGain(image);
359
360 if (gain != 0.0) {
361 result = (int)(value/gain);
362 }
363 if (result <= 0) {
364 result = 0;
365 } else if (result >= 255) {
366 result = 255;
367 }
368 return result;
369}
370
371
377static void RaveRopoGeneratorInternal_removeClassifications(RaveRopoGenerator_t* self)
378{
379 RAVE_OBJECT_RELEASE(self->classification);
380 RAVE_OBJECT_RELEASE(self->markers);
381}
382
392static int RaveRopoGeneratorInternal_createProbabilityField(
394 RaveFmiImage_t** probability,
395 const char* task,
396 const char* fmt, ...)
397{
398 int result = 0;
399 RaveFmiImage_t* outprob = NULL;
400 char fmtstring[1024];
401 va_list ap;
402 int n = 0;
403
404 RAVE_ASSERT((self != NULL), "self == NULL");
405 RAVE_ASSERT((probability != NULL), "probability == NULL");
406 RAVE_ASSERT((fmt != NULL), "fmt == NULL");
407
408 va_start(ap, fmt);
409 n = vsnprintf(fmtstring, 1024, fmt, ap);
410 va_end(ap);
411 if (n < 0 || n >= 1024) {
412 RAVE_ERROR0("Failed to generate name");
413 goto done;
414 }
415
416 if (self->image == NULL) {
417 RAVE_ERROR0("Creating probability field when there is no image");
418 goto done;
419 }
420
421 outprob = RAVE_OBJECT_CLONE(self->image);
422 if (outprob == NULL) {
423 RAVE_CRITICAL0("Failed to clone image");
424 goto done;
425 }
426 RaveFmiImage_fill(outprob, CLEAR);
427 RaveFmiImage_fillOriginal(outprob, (double)CLEAR);
428
429 if (!RaveRopoGeneratorInternal_addTask(outprob, task) ||
430 !RaveRopoGeneratorInternal_addTaskArgs(outprob, fmtstring)) {
431 RAVE_CRITICAL0("Failed to add task arguments");
432 goto done;
433 }
434
435 RAVE_OBJECT_RELEASE(*probability);
436 *probability = RAVE_OBJECT_COPY(outprob);
437
438 result = 1;
439done:
440 RAVE_OBJECT_RELEASE(outprob);
441 return result;
442}
443
444
449{
450 RAVE_ASSERT((self != NULL), "self == NULL");
451 RAVE_ASSERT((image != NULL), "image == NULL");
452
454 RAVE_OBJECT_RELEASE(self->image);
455 self->image = RAVE_OBJECT_COPY(image);
456}
457
459{
460 RAVE_ASSERT((self != NULL), "self == NULL");
461 return RAVE_OBJECT_COPY(self->image);
462}
463
465{
466 RAVE_ASSERT((self != NULL), "self == NULL");
467
468 if (self->image == NULL) {
469 RAVE_ERROR0("Calling threshold when there is no image to operate on?");
470 return;
471 }
472
473 threshold_image(RaveFmiImage_getImage(self->image),
475 threshold);
476}
477
478int RaveRopoGenerator_speck(RaveRopoGenerator_t* self, int minDbz, int maxA)
479{
480 RaveFmiImage_t* probability = NULL;
481 int result = 0;
482 RAVE_ASSERT((self != NULL), "self == NULL");
483
484 if (!RaveRopoGeneratorInternal_createProbabilityField(self,
485 &probability,
486 "fi.fmi.ropo.detector",
487 "SPECK: %d,%d",minDbz, maxA)) {
488 goto done;
489 }
490
491 detect_specks(RaveFmiImage_getImage(self->image),
492 RaveFmiImage_getImage(probability),
493 RaveRopoGeneratorInternal_valueToByteRange(minDbz, self->image),
494 histogram_area);
495 semisigmoid_image(RaveFmiImage_getImage(probability), maxA);
496 invert_image(RaveFmiImage_getImage(probability));
497 translate_intensity(RaveFmiImage_getImage(probability), 255, 0);
498
499 if (!RaveObjectList_add(self->probabilities, (RaveCoreObject*)probability)) {
500 RAVE_ERROR0("Failed to add probability field to probabilities");
501 goto done;
502 }
503
504 RaveRopoGeneratorInternal_removeClassifications(self);
505
506 result = 1;
507done:
508 RAVE_OBJECT_RELEASE(probability);
509 return result;
510}
511
512int RaveRopoGenerator_speckNormOld(RaveRopoGenerator_t* self, int minDbz, int maxA, int maxN)
513{
514 RaveFmiImage_t* probability = NULL;
515 int result = 0;
516 RAVE_ASSERT((self != NULL), "self == NULL");
517
518 if (!RaveRopoGeneratorInternal_createProbabilityField(self,
519 &probability,
520 "fi.fmi.ropo.detector",
521 "SPECKNORMOLD: %d,%d,%d",minDbz, maxA, maxN)) {
522 goto done;
523 }
524
525 detect_specks(RaveFmiImage_getImage(self->image),
526 RaveFmiImage_getImage(probability),
527 RaveRopoGeneratorInternal_valueToByteRange(minDbz, self->image),
528 histogram_area);
529 distance_compensation_mul(RaveFmiImage_getImage(probability), maxN);
530 semisigmoid_image(RaveFmiImage_getImage(probability),maxA);
531 invert_image(RaveFmiImage_getImage(probability));
532 translate_intensity(RaveFmiImage_getImage(probability),255,0);
533
534 if (!RaveObjectList_add(self->probabilities, (RaveCoreObject*)probability)) {
535 RAVE_ERROR0("Failed to add probability field to probabilities");
536 goto done;
537 }
538
539 RaveRopoGeneratorInternal_removeClassifications(self);
540
541 result = 1;
542done:
543 RAVE_OBJECT_RELEASE(probability);
544 return result;
545}
546
547int RaveRopoGenerator_emitter(RaveRopoGenerator_t* self, int minDbz, int length)
548{
549 RaveFmiImage_t* probability = NULL;
550 int result = 0;
551 RAVE_ASSERT((self != NULL), "self == NULL");
552
553 if (!RaveRopoGeneratorInternal_createProbabilityField(self,
554 &probability,
555 "fi.fmi.ropo.detector",
556 "EMITTER: %d,%d",minDbz, length)) {
557 goto done;
558 }
559
560 detect_emitters(RaveFmiImage_getImage(self->image),
561 RaveFmiImage_getImage(probability),
562 RaveRopoGeneratorInternal_valueToByteRange(minDbz, self->image), length);
563
564 if (!RaveObjectList_add(self->probabilities, (RaveCoreObject*)probability)) {
565 RAVE_ERROR0("Failed to add probability field to probabilities");
566 goto done;
567 }
568
569 RaveRopoGeneratorInternal_removeClassifications(self);
570
571 result = 1;
572done:
573 RAVE_OBJECT_RELEASE(probability);
574 return result;
575}
576
577int RaveRopoGenerator_emitter2(RaveRopoGenerator_t* self, int minDbz, int length, int width)
578{
579 RaveFmiImage_t* probability = NULL;
580 int result = 0;
581 RAVE_ASSERT((self != NULL), "self == NULL");
582
583 if (!RaveRopoGeneratorInternal_createProbabilityField(self,
584 &probability,
585 "fi.fmi.ropo.detector",
586 "EMITTER2: %d,%d,%d",minDbz, length, width)) {
587 goto done;
588 }
589
590 detect_emitters2(RaveFmiImage_getImage(self->image),
591 RaveFmiImage_getImage(probability),
592 RaveRopoGeneratorInternal_valueToByteRange(minDbz, self->image),
593 length,
594 width);
595
596 if (!RaveObjectList_add(self->probabilities, (RaveCoreObject*)probability)) {
597 RAVE_ERROR0("Failed to add probability field to probabilities");
598 goto done;
599 }
600
601 RaveRopoGeneratorInternal_removeClassifications(self);
602
603 result = 1;
604done:
605 RAVE_OBJECT_RELEASE(probability);
606 return result;
607}
608
609int RaveRopoGenerator_clutter(RaveRopoGenerator_t* self, int minDbz, int maxCompactness)
610{
611 RaveFmiImage_t* probability = NULL;
612 int result = 0;
613 RAVE_ASSERT((self != NULL), "self == NULL");
614
615 if (!RaveRopoGeneratorInternal_createProbabilityField(self,
616 &probability,
617 "fi.fmi.ropo.detector",
618 "CLUTTER: %d,%d",minDbz, maxCompactness)) {
619 goto done;
620 }
621
622 detect_specks(RaveFmiImage_getImage(self->image),
623 RaveFmiImage_getImage(probability),
624 RaveRopoGeneratorInternal_valueToByteRange(minDbz, self->image),
625 histogram_compactness);
626 semisigmoid_image(RaveFmiImage_getImage(probability),maxCompactness);
627 invert_image(RaveFmiImage_getImage(probability));
628 translate_intensity(RaveFmiImage_getImage(probability),255,0);
629
630 if (!RaveObjectList_add(self->probabilities, (RaveCoreObject*)probability)) {
631 RAVE_ERROR0("Failed to add probability field to probabilities");
632 goto done;
633 }
634
635 RaveRopoGeneratorInternal_removeClassifications(self);
636
637 result = 1;
638done:
639 RAVE_OBJECT_RELEASE(probability);
640 return result;
641}
642
643int RaveRopoGenerator_clutter2(RaveRopoGenerator_t* self, int minDbz, int maxSmoothness)
644{
645 RaveFmiImage_t* probability = NULL;
646 int result = 0;
647 RAVE_ASSERT((self != NULL), "self == NULL");
648
649 if (!RaveRopoGeneratorInternal_createProbabilityField(self,
650 &probability,
651 "fi.fmi.ropo.detector",
652 "CLUTTER2: %d,%d",minDbz, maxSmoothness)) {
653 goto done;
654 }
655
656 detect_specks(RaveFmiImage_getImage(self->image),
657 RaveFmiImage_getImage(probability),
658 RaveRopoGeneratorInternal_valueToByteRange(minDbz, self->image),
659 histogram_smoothness);
660 invert_image(RaveFmiImage_getImage(probability));
661 translate_intensity(RaveFmiImage_getImage(probability),255,0);
662 semisigmoid_image(RaveFmiImage_getImage(probability),255-maxSmoothness);
663
664 if (!RaveObjectList_add(self->probabilities, (RaveCoreObject*)probability)) {
665 RAVE_ERROR0("Failed to add probability field to probabilities");
666 goto done;
667 }
668
669 RaveRopoGeneratorInternal_removeClassifications(self);
670
671 result = 1;
672done:
673 RAVE_OBJECT_RELEASE(probability);
674 return result;
675}
676
677int RaveRopoGenerator_softcut(RaveRopoGenerator_t* self, int maxDbz, int r, int r2)
678{
679 RaveFmiImage_t* probability = NULL;
680 int result = 0;
681 RAVE_ASSERT((self != NULL), "self == NULL");
682
683 if (!RaveRopoGeneratorInternal_createProbabilityField(self,
684 &probability,
685 "fi.fmi.ropo.detector",
686 "SOFTCUT: %d,%d,%d",maxDbz, r, r2)) {
687 goto done;
688 }
689
690 detect_insect_band(RaveFmiImage_getImage(self->image),
691 RaveFmiImage_getImage(probability),
692 RaveRopoGeneratorInternal_valueToByteRange(maxDbz, self->image),
693 r, r2);
694
695 if (!RaveObjectList_add(self->probabilities, (RaveCoreObject*)probability)) {
696 RAVE_ERROR0("Failed to add probability field to probabilities");
697 goto done;
698 }
699
700 RaveRopoGeneratorInternal_removeClassifications(self);
701
702 result = 1;
703done:
704 RAVE_OBJECT_RELEASE(probability);
705 return result;
706}
707
708int RaveRopoGenerator_biomet(RaveRopoGenerator_t* self, int maxDbz, int dbzDelta, int maxAlt, int altDelta)
709{
710 RaveFmiImage_t* probability = NULL;
711 int result = 0;
712 RAVE_ASSERT((self != NULL), "self == NULL");
713
714 if (!RaveRopoGeneratorInternal_createProbabilityField(self,
715 &probability,
716 "fi.fmi.ropo.detector",
717 "BIOMET: %d,%d,%d,%d",maxDbz, dbzDelta, maxAlt, altDelta)) {
718 goto done;
719 }
720
721 detect_biomet(RaveFmiImage_getImage(self->image),
722 RaveFmiImage_getImage(probability),
723 RaveRopoGeneratorInternal_valueToByteRange(maxDbz, self->image),
724 RaveRopoGeneratorInternal_relValueToByteRange(dbzDelta, self->image),
725 maxAlt,
726 altDelta);
727
728 if (!RaveObjectList_add(self->probabilities, (RaveCoreObject*)probability)) {
729 RAVE_ERROR0("Failed to add probability field to probabilities");
730 goto done;
731 }
732
733 RaveRopoGeneratorInternal_removeClassifications(self);
734
735 result = 1;
736done:
737 RAVE_OBJECT_RELEASE(probability);
738 return result;
739}
740
741int RaveRopoGenerator_ship(RaveRopoGenerator_t* self, int minRelDbz, int minA)
742{
743 RaveFmiImage_t* probability = NULL;
744 int result = 0;
745 RAVE_ASSERT((self != NULL), "self == NULL");
746
747 if (!RaveRopoGeneratorInternal_createProbabilityField(self,
748 &probability,
749 "fi.fmi.ropo.detector",
750 "SHIP: %d,%d",minRelDbz, minA)) {
751 goto done;
752 }
753
754 detect_ships(RaveFmiImage_getImage(self->image),
755 RaveFmiImage_getImage(probability),
756 RaveRopoGeneratorInternal_relValueToByteRange(minRelDbz, self->image),
757 minA);
758
759 if (!RaveObjectList_add(self->probabilities, (RaveCoreObject*)probability)) {
760 RAVE_ERROR0("Failed to add probability field to probabilities");
761 goto done;
762 }
763
764 RaveRopoGeneratorInternal_removeClassifications(self);
765
766 result = 1;
767done:
768 RAVE_OBJECT_RELEASE(probability);
769 return result;
770}
771
772int RaveRopoGenerator_sun(RaveRopoGenerator_t* self, int minDbz, int minLength, int maxThickness)
773{
774 RaveFmiImage_t* probability = NULL;
775 int result = 0;
776 RAVE_ASSERT((self != NULL), "self == NULL");
777
778 if (!RaveRopoGeneratorInternal_createProbabilityField(self,
779 &probability,
780 "fi.fmi.ropo.detector",
781 "SUN: %d,%d,%d", minDbz, minLength, maxThickness)) {
782 goto done;
783 }
784
785 detect_sun(RaveFmiImage_getImage(self->image),
786 RaveFmiImage_getImage(probability),
787 RaveRopoGeneratorInternal_valueToByteRange(minDbz, self->image),
788 maxThickness,
789 minLength);
790
791 if (!RaveObjectList_add(self->probabilities, (RaveCoreObject*)probability)) {
792 RAVE_ERROR0("Failed to add probability field to probabilities");
793 goto done;
794 }
795
796 RaveRopoGeneratorInternal_removeClassifications(self);
797
798 result = 1;
799done:
800 RAVE_OBJECT_RELEASE(probability);
801 return result;
802}
803
804int RaveRopoGenerator_sun2(RaveRopoGenerator_t* self, int minDbz, int minLength, int maxThickness, int azimuth, int elevation)
805{
806 RaveFmiImage_t* probability = NULL;
807 int result = 0;
808 RAVE_ASSERT((self != NULL), "self == NULL");
809
810 if (!RaveRopoGeneratorInternal_createProbabilityField(self,
811 &probability,
812 "fi.fmi.ropo.detector",
813 "SUN2: %d,%d,%d,%d,%d", minDbz, minLength, maxThickness,azimuth,elevation)) {
814 goto done;
815 }
816
817 detect_sun2(RaveFmiImage_getImage(self->image),
818 RaveFmiImage_getImage(probability),
819 RaveRopoGeneratorInternal_valueToByteRange(minDbz, self->image),
820 maxThickness,
821 minLength,
822 azimuth,
823 elevation);
824
825 if (!RaveObjectList_add(self->probabilities, (RaveCoreObject*)probability)) {
826 RAVE_ERROR0("Failed to add probability field to probabilities");
827 goto done;
828 }
829
830 RaveRopoGeneratorInternal_removeClassifications(self);
831
832 result = 1;
833done:
834 RAVE_OBJECT_RELEASE(probability);
835 return result;
836}
837
839{
840 RaveFmiImage_t* probability = NULL;
841 RaveFmiImage_t* markers = NULL;
842 FmiImage* fmiProbImage = NULL;
843 FmiImage* fmiMarkersImage = NULL;
844 RaveAttribute_t* attribute = NULL;
845 int result = 0;
846 int probCount = 0;
847 int i = 0;
848
849 RAVE_ASSERT((self != NULL), "self == NULL");
850
851 if (self->image == NULL) {
852 RAVE_ERROR0("Calling speck when there is no image to operate on?");
853 goto done;
854 }
855
856 probability = RAVE_OBJECT_CLONE(self->image);
857 markers = RAVE_OBJECT_CLONE(self->image);
858 if (probability == NULL || markers == NULL) {
859 RAVE_CRITICAL0("Failed to clone image");
860 goto done;
861 }
862
863 RaveFmiImage_getImage(probability)->original_type = RaveDataType_UCHAR; /* We want the probability and markers field to be of UCHAR type */
864 RaveFmiImage_getImage(markers)->original_type = RaveDataType_UCHAR;
865
866 RaveFmiImage_fill(probability, CLEAR);
867 RaveFmiImage_fill(markers, CLEAR);
868
869 probCount = RaveObjectList_size(self->probabilities);
870
871 fmiProbImage = RaveFmiImage_getImage(probability);
872 fmiMarkersImage = RaveFmiImage_getImage(markers);
873
874
875 for (i = 0; i < probCount; i++) {
876 int j = 0;
877 RaveFmiImage_t* image = (RaveFmiImage_t*)RaveObjectList_get(self->probabilities, i);
878 FmiImage* probImage = RaveFmiImage_getImage(image);
879 FmiRadarPGMCode pgmCode = RaveRopoGeneratorInternal_getPgmCode(image);
880
881 for (j = 0; j < fmiProbImage->volume; j++) {
882 if (probImage->array[j] >= fmiProbImage->array[j]) {
883 /*fprintf(stderr, "Setting fmiProbImage(%d) = %d\n", j, probImage->array[j]); //printout of probablitity value*/
884 fmiMarkersImage->array[j]=pgmCode;
885 fmiProbImage->array[j]=probImage->array[j];
886 }
887 }
888 RAVE_OBJECT_RELEASE(image);
889 }
890 /*fprintf(stderr, "TYPE: %d\n", RaveFmiImage_getImage(probability)->original_type);*/
891 if (!RaveRopoGeneratorInternal_addTask(probability, "fi.fmi.ropo.detector.classification") ||
892 !RaveRopoGeneratorInternal_addProbabilityTaskArgs(probability, self->probabilities, "")) {
893 RAVE_CRITICAL0("Failed to add task arguments");
894 goto done;
895 }
896
897 if (!RaveRopoGeneratorInternal_addTask(markers, "fi.fmi.ropo.detector.classification_marker") ||
898 !RaveRopoGeneratorInternal_addProbabilityTaskArgs(markers, self->probabilities, "")) {
899 RAVE_CRITICAL0("Failed to add task arguments");
900 goto done;
901 }
902
903 RAVE_OBJECT_RELEASE(self->classification);
904 RAVE_OBJECT_RELEASE(self->markers);
905 self->classification = RAVE_OBJECT_COPY(probability);
906
907 /* ODIM's rule for representing quality is that 0=lowest, 1=highest quality.
908 * To minimize impact on ropo, invert the quality indicator only. */
909 attribute = RaveAttributeHelp_createDouble("what/gain", -1/255.0);
910 if (attribute == NULL || !RaveFmiImage_addAttribute(self->classification, attribute)) {
911 RAVE_CRITICAL0("Failed to add gain to image");
912 goto done;
913 }
914 RAVE_OBJECT_RELEASE(attribute);
915 attribute = RaveAttributeHelp_createDouble("what/offset", 1.0);
916 if (attribute == NULL || !RaveFmiImage_addAttribute(self->classification, attribute)) {
917 RAVE_CRITICAL0("Failed to add offset to image");
918 goto done;
919 }
920
921 self->markers = RAVE_OBJECT_COPY(markers);
922
923 result = 1;
924done:
925 RAVE_OBJECT_RELEASE(attribute);
926 RAVE_OBJECT_RELEASE(probability);
927 RAVE_OBJECT_RELEASE(markers);
928 return result;
929}
930
932{
933 RAVE_ASSERT((self != NULL), "self == NULL");
934 RAVE_OBJECT_RELEASE(self->classification);
935 RAVE_OBJECT_RELEASE(self->markers);
936 RaveObjectList_clear(self->probabilities);
937}
938
940{
941 RaveFmiImage_t* restored = NULL;
942 RaveFmiImage_t* result = NULL;
943
944 RAVE_ASSERT((self != NULL), "self == NULL");
945
946 if (self->classification == NULL || self->markers == NULL) {
948 }
949
950 restored = RAVE_OBJECT_CLONE(self->image);
951 if (restored == NULL) {
952 RAVE_CRITICAL0("Failed to clone image");
953 goto done;
954 }
955
956 RaveFmiImage_fill(restored, CLEAR);
957 RaveFmiImage_fillOriginal(restored, (double)CLEAR);
958
959 if (!RaveRopoGeneratorInternal_addTask(restored, "fi.fmi.ropo.restore") ||
960 !RaveRopoGeneratorInternal_addProbabilityTaskArgs(restored, self->probabilities, "RESTORE_THRESH: %d",threshold)) {
961 RAVE_CRITICAL0("Failed to add task arguments");
962 goto done;
963 }
964
965 restore_image(RaveFmiImage_getImage(self->image),
966 RaveFmiImage_getImage(restored),
968 threshold);
969 RaveFmiImage_getImage(self->classification)->original_type=RaveDataType_UCHAR;
971 result = RAVE_OBJECT_COPY(restored);
972done:
973 RAVE_OBJECT_RELEASE(restored);
974 return result;
975}
976
978{
979 RaveFmiImage_t* restored = NULL;
980 RaveFmiImage_t* result = NULL;
981
982 RAVE_ASSERT((self != NULL), "self == NULL");
983
984 if (self->classification == NULL || self->markers == NULL) {
986 }
987 restored = RAVE_OBJECT_CLONE(self->image);
988 if (restored == NULL) {
989 RAVE_CRITICAL0("Failed to clone image");
990 goto done;
991 }
992
993 RaveFmiImage_fill(restored, CLEAR);
994 RaveFmiImage_fillOriginal(restored, (double)CLEAR);
995
996 if (!RaveRopoGeneratorInternal_addTask(restored, "fi.fmi.ropo.restore2") ||
997 !RaveRopoGeneratorInternal_addProbabilityTaskArgs(restored, self->probabilities, "RESTORE2_THRESH: %d",threshold)) {
998 RAVE_CRITICAL0("Failed to add task arguments");
999 goto done;
1000 }
1001
1002 restore_image2(RaveFmiImage_getImage(self->image),
1003 RaveFmiImage_getImage(restored),
1005 threshold);
1006 RaveFmiImage_getImage(self->classification)->original_type=RaveDataType_UCHAR;
1008 result = RAVE_OBJECT_COPY(restored);
1009done:
1010 RAVE_OBJECT_RELEASE(restored);
1011 return result;
1012}
1013
1015{
1016 RaveFmiImage_t* restored = NULL;
1017 int result = 0;
1018
1019 RAVE_ASSERT((self != NULL), "self == NULL");
1020
1021 restored = RaveRopoGenerator_restore(self, threshold);
1022
1023 if (restored == NULL) {
1024 RAVE_ERROR0("Failed to restore self");
1025 goto done;
1026 }
1027
1028 RAVE_OBJECT_RELEASE(self->image);
1029 self->image = RAVE_OBJECT_COPY(restored);
1030
1031 result = 1;
1032done:
1033 RAVE_OBJECT_RELEASE(restored);
1034 return result;
1035}
1036
1038{
1039 RAVE_ASSERT((self != NULL), "self == NULL");
1040 return RaveObjectList_size(self->probabilities);
1041}
1042
1044{
1045 RaveCoreObject* object = NULL;
1046
1047 RAVE_ASSERT((self != NULL), "self == NULL");
1048
1049 object = RaveObjectList_get(self->probabilities, index);
1050
1051 return (RaveFmiImage_t*)object;
1052}
1053
1055{
1056 RAVE_ASSERT((self != NULL), "self == NULL");
1057 if (self->classification == NULL || self->markers == NULL) {
1059 }
1060 return RAVE_OBJECT_COPY(self->classification);
1061}
1062
1064{
1065 RAVE_ASSERT((self != NULL), "self == NULL");
1066 if (self->classification == NULL || self->markers == NULL) {
1068 }
1069 return RAVE_OBJECT_COPY(self->markers);
1070}
1071
1073{
1074 RaveRopoGenerator_t* result = NULL;
1075 RAVE_ASSERT((image != NULL), "image == NULL");
1076
1077 result = RAVE_OBJECT_NEW(&RaveRopoGenerator_TYPE);
1078
1079 if (result == NULL) {
1080 RAVE_CRITICAL0("Failed to allocate memory for generator");
1081 return NULL;
1082 }
1083 result->image = RAVE_OBJECT_COPY(image);
1084
1085 return result;
1086}
1087
1089RaveCoreObjectType RaveRopoGenerator_TYPE = {
1090 "RaveRopoGenerator",
1091 sizeof(RaveRopoGenerator_t),
1092 RaveRopoGenerator_constructor,
1093 RaveRopoGenerator_destructor,
1094 NULL /* No copy constructor */
1095};
FmiImage * RaveFmiImage_getImage(RaveFmiImage_t *self)
void RaveFmiImage_fill(RaveFmiImage_t *self, unsigned char v)
double RaveFmiImage_getOffset(RaveFmiImage_t *self)
int RaveFmiImage_addAttribute(RaveFmiImage_t *self, RaveAttribute_t *attribute)
RaveAttribute_t * RaveFmiImage_getAttribute(RaveFmiImage_t *self, const char *name)
void RaveFmiImage_fillOriginal(RaveFmiImage_t *self, double v)
double RaveFmiImage_getGain(RaveFmiImage_t *self)
RaveCoreObjectType RaveRopoGenerator_TYPE
RaveRopoGenerator_t * RaveRopoGenerator_new(RaveFmiImage_t *image)
int RaveRopoGenerator_getProbabilityFieldCount(RaveRopoGenerator_t *self)
RaveFmiImage_t * RaveRopoGenerator_restore(RaveRopoGenerator_t *self, int threshold)
int RaveRopoGenerator_speckNormOld(RaveRopoGenerator_t *self, int minDbz, int maxA, int maxN)
int RaveRopoGenerator_clutter2(RaveRopoGenerator_t *self, int minDbz, int maxSmoothness)
void RaveRopoGenerator_threshold(RaveRopoGenerator_t *self, int threshold)
RaveFmiImage_t * RaveRopoGenerator_restore2(RaveRopoGenerator_t *self, int threshold)
RaveFmiImage_t * RaveRopoGenerator_getMarkers(RaveRopoGenerator_t *self)
int RaveRopoGenerator_sun2(RaveRopoGenerator_t *self, int minDbz, int minLength, int maxThickness, int azimuth, int elevation)
void RaveRopoGenerator_setImage(RaveRopoGenerator_t *self, RaveFmiImage_t *image)
void RaveRopoGenerator_declassify(RaveRopoGenerator_t *self)
int RaveRopoGenerator_sun(RaveRopoGenerator_t *self, int minDbz, int minLength, int maxThickness)
int RaveRopoGenerator_restoreSelf(RaveRopoGenerator_t *self, int threshold)
RaveFmiImage_t * RaveRopoGenerator_getClassification(RaveRopoGenerator_t *self)
int RaveRopoGenerator_clutter(RaveRopoGenerator_t *self, int minDbz, int maxCompactness)
int RaveRopoGenerator_speck(RaveRopoGenerator_t *self, int minDbz, int maxA)
int RaveRopoGenerator_classify(RaveRopoGenerator_t *self)
RaveFmiImage_t * RaveRopoGenerator_getImage(RaveRopoGenerator_t *self)
int RaveRopoGenerator_ship(RaveRopoGenerator_t *self, int minRelDbz, int minA)
int RaveRopoGenerator_biomet(RaveRopoGenerator_t *self, int maxDbz, int dbzDelta, int maxAlt, int altDelta)
int RaveRopoGenerator_emitter(RaveRopoGenerator_t *self, int minDbz, int length)
int RaveRopoGenerator_emitter2(RaveRopoGenerator_t *self, int minDbz, int length, int width)
int RaveRopoGenerator_softcut(RaveRopoGenerator_t *self, int maxDbz, int r, int r2)
RaveFmiImage_t * RaveRopoGenerator_getProbabilityField(RaveRopoGenerator_t *self, int index)
struct _RaveRopoGenerator_t RaveRopoGenerator_t
RaveObjectList_t * probabilities
RAVE_OBJECT_HEAD RaveFmiImage_t * image
RaveFmiImage_t * classification