|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#ifndef _EI_CLASSIFIER_SMOOTH_H_ |
|
|
#define _EI_CLASSIFIER_SMOOTH_H_ |
|
|
|
|
|
#if EI_CLASSIFIER_OBJECT_DETECTION != 1 |
|
|
|
|
|
#include <stdint.h> |
|
|
|
|
|
typedef struct ei_classifier_smooth { |
|
|
int *last_readings; |
|
|
size_t last_readings_size; |
|
|
uint8_t min_readings_same; |
|
|
float classifier_confidence; |
|
|
float anomaly_confidence; |
|
|
uint8_t count[EI_CLASSIFIER_LABEL_COUNT + 2] = { 0 }; |
|
|
size_t count_size = EI_CLASSIFIER_LABEL_COUNT + 2; |
|
|
} ei_classifier_smooth_t; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void ei_classifier_smooth_init(ei_classifier_smooth_t *smooth, size_t n_readings, |
|
|
uint8_t min_readings_same, float classifier_confidence = 0.8, |
|
|
float anomaly_confidence = 0.3) { |
|
|
smooth->last_readings = (int*)ei_malloc(n_readings * sizeof(int)); |
|
|
for (size_t ix = 0; ix < n_readings; ix++) { |
|
|
smooth->last_readings[ix] = -1; |
|
|
} |
|
|
smooth->last_readings_size = n_readings; |
|
|
smooth->min_readings_same = min_readings_same; |
|
|
smooth->classifier_confidence = classifier_confidence; |
|
|
smooth->anomaly_confidence = anomaly_confidence; |
|
|
smooth->count_size = EI_CLASSIFIER_LABEL_COUNT + 2; |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const char* ei_classifier_smooth_update(ei_classifier_smooth_t *smooth, ei_impulse_result_t *result) { |
|
|
|
|
|
memset(smooth->count, 0, EI_CLASSIFIER_LABEL_COUNT + 2); |
|
|
|
|
|
|
|
|
numpy::roll(smooth->last_readings, smooth->last_readings_size, -1); |
|
|
|
|
|
int reading = -1; |
|
|
|
|
|
|
|
|
|
|
|
for (size_t ix = 0; ix < EI_CLASSIFIER_LABEL_COUNT; ix++) { |
|
|
if (result->classification[ix].value >= smooth->classifier_confidence) { |
|
|
reading = (int)ix; |
|
|
} |
|
|
} |
|
|
#if EI_CLASSIFIER_HAS_ANOMALY == 1 |
|
|
if (result->anomaly >= smooth->anomaly_confidence) { |
|
|
reading = -2; |
|
|
} |
|
|
#endif |
|
|
|
|
|
smooth->last_readings[smooth->last_readings_size - 1] = reading; |
|
|
|
|
|
|
|
|
for (size_t ix = 0; ix < smooth->last_readings_size; ix++) { |
|
|
if (smooth->last_readings[ix] >= 0) { |
|
|
smooth->count[smooth->last_readings[ix]]++; |
|
|
} |
|
|
else if (smooth->last_readings[ix] == -1) { |
|
|
smooth->count[EI_CLASSIFIER_LABEL_COUNT]++; |
|
|
} |
|
|
else if (smooth->last_readings[ix] == -2) { |
|
|
smooth->count[EI_CLASSIFIER_LABEL_COUNT + 1]++; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
uint8_t top_result = 0; |
|
|
uint8_t top_count = 0; |
|
|
bool met_confidence_threshold = false; |
|
|
uint8_t confidence_threshold = smooth->min_readings_same; |
|
|
for (size_t ix = 0; ix < EI_CLASSIFIER_LABEL_COUNT + 2; ix++) { |
|
|
if (smooth->count[ix] > top_count) { |
|
|
top_result = ix; |
|
|
top_count = smooth->count[ix]; |
|
|
} |
|
|
if (smooth->count[ix] >= confidence_threshold) { |
|
|
met_confidence_threshold = true; |
|
|
} |
|
|
} |
|
|
|
|
|
if (met_confidence_threshold) { |
|
|
if (top_result == EI_CLASSIFIER_LABEL_COUNT) { |
|
|
return "uncertain"; |
|
|
} |
|
|
else if (top_result == EI_CLASSIFIER_LABEL_COUNT + 1) { |
|
|
return "anomaly"; |
|
|
} |
|
|
else { |
|
|
return result->classification[top_result].label; |
|
|
} |
|
|
} |
|
|
return "uncertain"; |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void ei_classifier_smooth_free(ei_classifier_smooth_t *smooth) { |
|
|
ei_free(smooth->last_readings); |
|
|
} |
|
|
|
|
|
#endif |
|
|
|
|
|
#endif |
|
|
|