Download ei-cpp-export/edge-impulse-sdk/classifier/ei_classifier_smooth.h from luisomoreau/fomo-face-detection: direct link, hf CLI and curl.
- Browser
- Download file 5.19 kB
-
https://huggingface.co/luisomoreau/fomo-face-detection/resolve/main/ei-cpp-export/edge-impulse-sdk/classifier/ei_classifier_smooth.h
- Command line
-
hf download hf://luisomoreau/fomo-face-detection/ei-cpp-export/edge-impulse-sdk/classifier/ei_classifier_smooth.h
-
curl -L -o ei_classifier_smooth.h https://huggingface.co/luisomoreau/fomo-face-detection/resolve/main/ei-cpp-export/edge-impulse-sdk/classifier/ei_classifier_smooth.h
5.19 kB
| /* | |
| * Copyright (c) 2022 EdgeImpulse Inc. | |
| * | |
| * Licensed under the Apache License, Version 2.0 (the "License"); | |
| * you may not use this file except in compliance with the License. | |
| * You may obtain a copy of the License at | |
| * http://www.apache.org/licenses/LICENSE-2.0 | |
| * | |
| * Unless required by applicable law or agreed to in writing, | |
| * software distributed under the License is distributed on an "AS | |
| * IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either | |
| * express or implied. See the License for the specific language | |
| * governing permissions and limitations under the License. | |
| * | |
| * SPDX-License-Identifier: Apache-2.0 | |
| */ | |
| 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; | |
| /** | |
| * Initialize a smooth structure. This is useful if you don't want to trust | |
| * single readings, but rather want consensus | |
| * (e.g. 7 / 10 readings should be the same before I draw any ML conclusions). | |
| * This allocates memory on the heap! | |
| * @param smooth Pointer to an uninitialized ei_classifier_smooth_t struct | |
| * @param n_readings Number of readings you want to store | |
| * @param min_readings_same Minimum readings that need to be the same before concluding (needs to be lower than n_readings) | |
| * @param classifier_confidence Minimum confidence in a class (default 0.8) | |
| * @param anomaly_confidence Maximum error for anomalies (default 0.3) | |
| */ | |
| 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; // -1 == uncertain | |
| } | |
| 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; | |
| } | |
| /** | |
| * Call when a new reading comes in. | |
| * @param smooth Pointer to an initialized ei_classifier_smooth_t struct | |
| * @param result Pointer to a result structure (after calling ei_run_classifier) | |
| * @returns Label, either 'uncertain', 'anomaly', or a label from the result struct | |
| */ | |
| const char* ei_classifier_smooth_update(ei_classifier_smooth_t *smooth, ei_impulse_result_t *result) { | |
| // clear out the count array | |
| memset(smooth->count, 0, EI_CLASSIFIER_LABEL_COUNT + 2); | |
| // roll through the last_readings buffer | |
| numpy::roll(smooth->last_readings, smooth->last_readings_size, -1); | |
| int reading = -1; // uncertain | |
| // print the predictions | |
| // printf("["); | |
| for (size_t ix = 0; ix < EI_CLASSIFIER_LABEL_COUNT; ix++) { | |
| if (result->classification[ix].value >= smooth->classifier_confidence) { | |
| reading = (int)ix; | |
| } | |
| } | |
| if (result->anomaly >= smooth->anomaly_confidence) { | |
| reading = -2; // anomaly | |
| } | |
| smooth->last_readings[smooth->last_readings_size - 1] = reading; | |
| // now count last 10 readings and see what we actually see... | |
| 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) { // uncertain | |
| smooth->count[EI_CLASSIFIER_LABEL_COUNT]++; | |
| } | |
| else if (smooth->last_readings[ix] == -2) { // anomaly | |
| smooth->count[EI_CLASSIFIER_LABEL_COUNT + 1]++; | |
| } | |
| } | |
| // then loop over the count and see which is highest | |
| uint8_t top_result = 0; | |
| uint8_t top_count = 0; | |
| bool met_confidence_threshold = false; | |
| uint8_t confidence_threshold = smooth->min_readings_same; // XX% of windows should be the 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"; | |
| } | |
| /** | |
| * Clear up a smooth structure | |
| */ | |
| void ei_classifier_smooth_free(ei_classifier_smooth_t *smooth) { | |
| ei_free(smooth->last_readings); | |
| } | |