/* * SPDX-License-Identifier: MIT * * Copyright (C) 2013-2025 OpenMV, LLC. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. * * Averaging utility functions. */ #include "average.h" #include void rgb_moving_average_init(rgb_moving_average_t *ma, uint32_t max_ms, size_t size, rgb_moving_average_val_t *buffer) { memset(ma, 0, sizeof(rgb_moving_average_t)); ma->size = size; ma->max_ms = max_ms; ma->buffer = buffer; } void rgb_moving_average_update(rgb_moving_average_t *ma, uint32_t *r_value, uint32_t *g_value, uint32_t *b_value, uint32_t current_ms) { if (!ma->size) { return; } // Drop if the buffer is full and all values older than max_ms (handles wrap-around correctly). while (ma->count == ma->size || (ma->count > 0 && (current_ms - ma->buffer[ma->head].timestamp_ms) > ma->max_ms)) { rgb_moving_average_val_t *val = &ma->buffer[ma->head]; ma->r_sum -= val->r_value; ma->g_sum -= val->g_value; ma->b_sum -= val->b_value; ma->head = (ma->head + 1) % ma->size; ma->count--; } // Add the new value. rgb_moving_average_val_t *val = &ma->buffer[ma->tail]; val->r_value = *r_value; val->g_value = *g_value; val->b_value = *b_value; val->timestamp_ms = current_ms; ma->tail = (ma->tail + 1) % ma->size; ma->count++; ma->r_sum += val->r_value; ma->g_sum += val->g_value; ma->b_sum += val->b_value; // Return the current average. *r_value = (ma->r_sum / ma->count); *g_value = (ma->g_sum / ma->count); *b_value = (ma->b_sum / ma->count); } void rgb_moving_average_get(rgb_moving_average_t *ma, uint32_t *r_value, uint32_t *g_value, uint32_t *b_value) { if (!ma->size || ma->count == 0) { return; } *r_value = (ma->r_sum / ma->count); *g_value = (ma->g_sum / ma->count); *b_value = (ma->b_sum / ma->count); }