From 46fd8bff60ba54d80b92059395ee7fe5ec73b43c Mon Sep 17 00:00:00 2001 From: c0ntrol Date: Tue, 29 Mar 2016 20:38:23 +0200 Subject: [PATCH] add new FX, binary threshold via otsu's method (issue #42) --- .../veejay-server/libvje/Makefile.am | 2 +- .../veejay-server/libvje/effects/bwotsu.c | 147 ++++++++++++++++++ .../veejay-server/libvje/effects/bwotsu.h | 29 ++++ .../veejay-server/libvje/internal.h | 5 +- .../veejay-server/libvje/vj-effect.c | 2 + .../veejay-server/libvje/vj-effman.c | 3 + veejay-current/veejay-server/libvje/vje.h | 2 +- 7 files changed, 187 insertions(+), 3 deletions(-) create mode 100644 veejay-current/veejay-server/libvje/effects/bwotsu.c create mode 100644 veejay-current/veejay-server/libvje/effects/bwotsu.h diff --git a/veejay-current/veejay-server/libvje/Makefile.am b/veejay-current/veejay-server/libvje/Makefile.am index 113ddad8..4acc9817 100644 --- a/veejay-current/veejay-server/libvje/Makefile.am +++ b/veejay-current/veejay-server/libvje/Makefile.am @@ -58,6 +58,6 @@ libvje_la_SOURCES = vj-effect.c vj-effman.c effects/common.c \ effects/alphaselect2.c effects/alphablend.c effects/porterduff.c effects/alphanegate.c effects/lumakeyalpha.c \ effects/chromamagickalpha.c effects/magicoverlaysalpha.c effects/gaussblur.c effects/levelcorrection.c \ effects/masktransition.c effects/alphadampen.c effects/passthrough.c effects/alphatransition.c effects/randnoise.c \ - effects/bgsubtractgauss.c + effects/bgsubtractgauss.c effects/bwotsu.c diff --git a/veejay-current/veejay-server/libvje/effects/bwotsu.c b/veejay-current/veejay-server/libvje/effects/bwotsu.c new file mode 100644 index 00000000..cee17b36 --- /dev/null +++ b/veejay-current/veejay-server/libvje/effects/bwotsu.c @@ -0,0 +1,147 @@ +/* + * Linux VeeJay + * + * Copyright(C)2016 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ +#include +#include +#include +#include +#include "bwotsu.h" +#include "common.h" +vj_effect *bwotsu_init(int w, int h) +{ + vj_effect *ve = (vj_effect *) vj_calloc(sizeof(vj_effect)); + ve->num_params = 3; + ve->defaults = (int *) vj_calloc(sizeof(int) * ve->num_params); /* default values */ + ve->limits[0] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* min */ + ve->limits[1] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* max */ + ve->defaults[0] = 0; + ve->defaults[1] = 0xff; + ve->defaults[2] = 0; + + ve->limits[0][0] = 0; + ve->limits[1][0] = 1; + ve->limits[0][1] = 0; + ve->limits[1][1] = 0xff; + ve->limits[0][2] = 0; + ve->limits[1][2] = 1; + + ve->description = "Binary Threshold via Otsu's method"; + + ve->sub_format = -1; + ve->extra_frame = 0; + ve->has_user =0; + ve->parallel = 1; + + ve->alpha = FLAG_ALPHA_OUT | FLAG_ALPHA_OPTIONAL; + + ve->param_description = vje_build_param_list( ve->num_params, "To Alpha", "Skew", "Invert" ); + + return ve; +} + +//@see https://en.wikipedia.org/wiki/Otsu's_method +static uint32_t bwotsu( uint32_t *H, const int N ) +{ + uint32_t threshold = 0; + double wF, wB=0.0, mB, mF, between, max = 0.0; + double sum = 0.0, sumB=0.0; + uint32_t i; + + for( i = 0; i < 256; i++ ) + { + wB += H[i]; + if( wB == 0 ) + continue; + wF = N - wB; + if( wF == 0 ) + break; + sumB += ( i * H[i] ); + mB = sumB / wB; + mF = (sum - sumB) / wF; + between = wB * wF * pow( mB - mF , 2 ); + if( between > max ) { + max = between; + threshold = i; + } + } + return threshold; +} + +void bwotsu_apply(VJFrame *frame, int mode, int skew, int invert) +{ + uint32_t Histogram[256]; + unsigned int i; + const int len = frame->len; + uint8_t *Y = frame->data[0]; + uint8_t *A = frame->data[3]; + + veejay_memset( Histogram, 0, sizeof( Histogram ) ); + + if( skew != 0xff ) + { + uint8_t Lookup[256]; + __init_lookup_table( Lookup, 256, 0.0f, 255.0f, 0.0f, (float)skew ); + for( i = 0; i < len; i ++ ) + { + Histogram[ Lookup[ Y[i] ] ] += 1; + } + } + else + { + for( i = 0; i < len; i++ ) + { + Histogram[ Y[i] ] += 1; + } + } + + uint32_t threshold = bwotsu( Histogram, len ); + + uint8_t l = 0; + uint8_t h = 0xff; + + if( invert ) { + l = 0xff; + h = 0; + } + + switch( mode ) { + case 0: + for( i = 0; i < len; i ++ ) + { + if( Y[i] < threshold ) + Y[i] = l; + else + Y[i] = h; + } + veejay_memset( frame->data[1], 128, (frame->ssm ? frame->len : frame->uv_len) ); + veejay_memset( frame->data[2], 128, (frame->ssm ? frame->len : frame->uv_len) ); + + break; + case 1: + for( i = 0; i < len; i ++ ) + { + if( Y[i] < threshold ) + A[i] = l; + else + A[i] = h; + } + break; + } +} + diff --git a/veejay-current/veejay-server/libvje/effects/bwotsu.h b/veejay-current/veejay-server/libvje/effects/bwotsu.h new file mode 100644 index 00000000..6bbe7f64 --- /dev/null +++ b/veejay-current/veejay-server/libvje/effects/bwotsu.h @@ -0,0 +1,29 @@ +/* + * Linux VeeJay + * + * Copyright(C)2016 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + +#ifndef BWOTSU_H +#define BWOTSU_H +#include +#include +#include + +vj_effect *bwotsu_init(); +void bwotsu_apply(VJFrame *frame, int mode, int skew, int invert ); +#endif diff --git a/veejay-current/veejay-server/libvje/internal.h b/veejay-current/veejay-server/libvje/internal.h index e39f2e23..6d4edfc9 100644 --- a/veejay-current/veejay-server/libvje/internal.h +++ b/veejay-current/veejay-server/libvje/internal.h @@ -26,7 +26,7 @@ #define VJE_SUCCESS 0 #include -#define VJ_IMAGE_EFFECT_MIN 94 +#define VJ_IMAGE_EFFECT_MIN 93 #define VJ_IMAGE_EFFECT_MAX 199 #define VJ_VIDEO_EFFECT_MIN 200 @@ -252,6 +252,7 @@ enum { VJ_IMAGE_EFFECT_ALPHADAMPEN = 96, VJ_IMAGE_EFFECT_RANDNOISE = 95, VJ_IMAGE_EFFECT_BGSUBTRACTGAUSS = 94, + VJ_IMAGE_EFFECT_BWOTSU = 93, VJ_IMAGE_EFFECT_DUMMY=0, }; @@ -460,6 +461,8 @@ int opacity); extern void bwselect_apply(VJFrame *frame, int w, int h, int a , int b, int c, int g); +extern void bwotsu_apply(VJFrame *frame, int mode, int skew,int invert); + extern void complexinvert_apply(VJFrame *frame, int w, int h, int angle, int r, int g, int b, int i_noise); extern void complexsaturation_apply(VJFrame *frame, int w, int h, int angle, int r, int g, int b, int adj, int adjv, int inoise); diff --git a/veejay-current/veejay-server/libvje/vj-effect.c b/veejay-current/veejay-server/libvje/vj-effect.c index 62f3cae3..56ae20c3 100644 --- a/veejay-current/veejay-server/libvje/vj-effect.c +++ b/veejay-current/veejay-server/libvje/vj-effect.c @@ -99,6 +99,7 @@ #include "effects/keyselect.h" #include "effects/greyselect.h" #include "effects/bwselect.h" +#include "effects/bwotsu.h" #include "effects/complexinvert.h" #include "effects/complexthreshold.h" #include "effects/complexsaturate.h" @@ -608,6 +609,7 @@ void vj_effect_initialize(int width, int height, int full_range) vj_effects[VJ_IMAGE_EFFECT_DISTORTION] = distortion_init(width, height); vj_effects[VJ_IMAGE_EFFECT_GREYSELECT] = greyselect_init(width,height); vj_effects[VJ_IMAGE_EFFECT_BWSELECT] = bwselect_init(width,height); + vj_effects[VJ_IMAGE_EFFECT_BWOTSU] = bwotsu_init(width,height); vj_effects[VJ_IMAGE_EFFECT_COMPLEXINVERT] = complexinvert_init(width,height); vj_effects[VJ_IMAGE_EFFECT_COMPLEXSATURATE] = complexsaturation_init(width,height); vj_effects[VJ_IMAGE_EFFECT_ISOLATE] = isolate_init(width,height); diff --git a/veejay-current/veejay-server/libvje/vj-effman.c b/veejay-current/veejay-server/libvje/vj-effman.c index a5c5ac6c..73092d18 100644 --- a/veejay-current/veejay-server/libvje/vj-effman.c +++ b/veejay-current/veejay-server/libvje/vj-effman.c @@ -350,6 +350,9 @@ static void vj_effman_apply_image_effect( case VJ_IMAGE_EFFECT_BWSELECT: bwselect_apply(frames[0], frames[0]->width, frames[0]->height, arg[0], arg[1], arg[2], arg[3]); break; + case VJ_IMAGE_EFFECT_BWOTSU: + bwotsu_apply( frames[0], arg[0],arg[1],arg[2] ); + break; case VJ_IMAGE_EFFECT_GREYSELECT: greyselect_apply(frames[0], frames[0]->width, frames[0]->height,arg[0],arg[1],arg[2],arg[3],arg[4]); break; diff --git a/veejay-current/veejay-server/libvje/vje.h b/veejay-current/veejay-server/libvje/vje.h index c15d3929..871f1456 100644 --- a/veejay-current/veejay-server/libvje/vje.h +++ b/veejay-current/veejay-server/libvje/vje.h @@ -22,7 +22,7 @@ #define FX_LIMIT 1024 -#define MAX_EFFECTS 165 +#define MAX_EFFECTS 166 #define PARAM_WIDTH (1<<0x2) #define PARAM_HEIGHT (1<<0x3) #define PARAM_FADER (1<<0x1)