diff --git a/src/mixer2/CMakeLists.txt b/src/mixer2/CMakeLists.txt index ee327af1..7d93f654 100644 --- a/src/mixer2/CMakeLists.txt +++ b/src/mixer2/CMakeLists.txt @@ -19,6 +19,7 @@ add_subdirectory (darken) add_subdirectory (difference) add_subdirectory (divide) add_subdirectory (dodge) +add_subdirectory (euclid_eraser) add_subdirectory (grain_extract) add_subdirectory (grain_merge) add_subdirectory (hardlight) diff --git a/src/mixer2/euclid_eraser/CMakeLists.txt b/src/mixer2/euclid_eraser/CMakeLists.txt new file mode 100644 index 00000000..4e020adc --- /dev/null +++ b/src/mixer2/euclid_eraser/CMakeLists.txt @@ -0,0 +1,11 @@ +set (SOURCES euclid_eraser.cpp) +set (TARGET euclid_eraser) + +if (MSVC) + set (SOURCES ${SOURCES} ${FREI0R_1_1_DEF}) +endif (MSVC) + +add_library (${TARGET} MODULE ${SOURCES}) +set_target_properties (${TARGET} PROPERTIES PREFIX "") + +install (TARGETS ${TARGET} LIBRARY DESTINATION ${LIBDIR}) diff --git a/src/mixer2/euclid_eraser/euclid_eraser.cpp b/src/mixer2/euclid_eraser/euclid_eraser.cpp new file mode 100644 index 00000000..35c9073b --- /dev/null +++ b/src/mixer2/euclid_eraser/euclid_eraser.cpp @@ -0,0 +1,119 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +// Copyright (C) 2024 Erik H. Beck, bacon@tahomasoft.com +// https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html + +/* This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA + * + * Also see: + * + * https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html + * + */ + +/** This is the source file for the euclid eraser two-input mixer for + frei0r. It uses euclidean distance to remove a static background + from a video. See file ./euclid_eraser.md for more info +*/ + +#include +#include "frei0r.hpp" +#include "frei0r/math.h" + +#define NBYTES 4 +#define CHANNELS 3 // Actually 4; 0-3 + +double euclidDistance(uint8_t x_r, uint8_t x_g, uint8_t x_b, + uint8_t y_r, uint8_t y_g, uint8_t y_b) + { + //calculating color channel differences for next steps + double red_d = x_r - y_r; + double green_d = x_g - y_g; + double blue_d = x_b - y_b; + + double sq_sum, dist; + + //calculating Euclidean distance + sq_sum = pow(red_d, 2) + pow(green_d, 2) + pow (blue_d, 2); + dist = sqrt(sq_sum); + + return dist; + } + + +class euclid_eraser : public frei0r::mixer2 +{ + +public: + euclid_eraser(unsigned int width, unsigned int height) + { + threshold = 5.6; // Default distance threshold value + register_param(threshold, "threshold", "Matching Threshold"); + } + + void update(double time, + uint32_t* out, + const uint32_t* in1, + const uint32_t* in2) + { + + const uint8_t *src1 = reinterpret_cast(in1); //frst track (0) + const uint8_t *src2 = reinterpret_cast(in2); //second trk (1) + uint8_t *dst = reinterpret_cast(out); + + double e_dist; + + uint32_t sizeCounter = size; + uint32_t b; + + while (sizeCounter--) + { + + // Loop over rgb + // Copy pixels from src2 to destination + + for (b=0; b<3; b++) + { + dst[b]=src2[b]; + } + e_dist=euclidDistance(src1[0],src1[1],src1[2], + src2[0],src2[1],src2[2]); + + if (e_dist <= euclid_eraser::threshold) { + // Make alpha channel for pixel fully transparent + dst[3]=0; + } + else { + // Make alpha channel for the pixel fully opaque + dst[3]=255; + } + + src1 += NBYTES; + src2 += NBYTES; + dst += NBYTES; + } + + } +private: + double threshold; + +}; + +frei0r::construct plugin("euclid_eraser", + "Erasing backgrounds with euclidian distance", + "Erik H. Beck", + 0,1, + F0R_COLOR_MODEL_RGBA8888); + diff --git a/src/mixer2/euclid_eraser/euclid_eraser.md b/src/mixer2/euclid_eraser/euclid_eraser.md new file mode 100644 index 00000000..313ba70f --- /dev/null +++ b/src/mixer2/euclid_eraser/euclid_eraser.md @@ -0,0 +1,88 @@ +# Euclid Eraser Notes # + +## Overview ## +This is about the Euclid Eraser mixer. + + +## Description ## + +This class is intended to operate as a mixer, taking two inputs and +yielding one output. + +The first input is a reference input, such as a single image or a +stretched video of a single image. + +The second input is the video stream to operate on. + +The output is a clone of the RGB data of the second input, but with +the alpha channel modified. + +This mixer takes the (first) reference input, such as a static +background, and removes it from every frame in the video stream of the +second input. + +The alpha channel on the output is based on the euclidian distance of +the two input coordinates in 3-d RGB space. If the calculated distance +betwen the two inputs for a given pixel is less than a provided +(variable) threshold amount, that indicates the pixel in the +background (reference) image is the same or similar enough to the +operational (second) input that is part of the background to be +removed, and the transparency is set to fully transparent via the +alpha channel (set to 0). + +If the calcuated distance exceeds the threshold, then that pixel is +part of the foreground image to be retained, and the transparency +of it is set to be fully opaque (alpha channel for that pixel set +to 255). + +## Basic Algorithm ## +The basic comparison algorithm is: + + +x is reference image +y is comparison image to remove reference image from + + +``` +float euclidDistance (int x_r, int x_g, int x_b, int y_r, int y_g, int y_b) +{ + //calculating color channel differences for next steps + float red_d = x_r - y_r; + float green_d = x_g - y_g; + float blue_d = x_b - y_b; + + float sq_sum, dist; + + //calculating Euclidean distance + sq_sum = pow(red_d, 2) + pow(green_d, 2) + pow (blue_d) + dist = sqrt(sq_sum); + + return dist; +} +``` + +## Note ## + +Here's a handy reminder on how the bits map up. + +``` + red_src1 = src1[0]; + green_src1 = src1[1]; + blue_src1 = src1[2]; + alpha_src1 = src1[3] + + red_src2 = src2[0]; + green_src2 = src2[1]; + blue_src2 = src2[2]; + alpha_src2 = src2[3] +``` +## Further Work ## + +Some potential improvements are: + +- Faster performance (math calculations, others) +- Options beyond binary for alpha + + + +