Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding Euclid Eraser to mixer2 #198

Merged
merged 1 commit into from
Sep 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/mixer2/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
11 changes: 11 additions & 0 deletions src/mixer2/euclid_eraser/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -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})
119 changes: 119 additions & 0 deletions src/mixer2/euclid_eraser/euclid_eraser.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
// SPDX-License-Identifier: GPL-2.0-or-later
// Copyright (C) 2024 Erik H. Beck, [email protected]
// 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 <math.h>
#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<const uint8_t*>(in1); //frst track (0)
const uint8_t *src2 = reinterpret_cast<const uint8_t*>(in2); //second trk (1)
uint8_t *dst = reinterpret_cast<uint8_t*>(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<euclid_eraser> plugin("euclid_eraser",
"Erasing backgrounds with euclidian distance",
"Erik H. Beck",
0,1,
F0R_COLOR_MODEL_RGBA8888);

88 changes: 88 additions & 0 deletions src/mixer2/euclid_eraser/euclid_eraser.md
Original file line number Diff line number Diff line change
@@ -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




Loading