commit d3cd95e055f50df97979bcca7bb26a3edd4b82ee
Author:     Mattias Andrée <[email protected]>
AuthorDate: Sun May 14 20:13:16 2017 +0200
Commit:     Mattias Andrée <[email protected]>
CommitDate: Sun May 14 20:13:37 2017 +0200

    Add blind-tempral-mean
    
    Signed-off-by: Mattias Andrée <[email protected]>

diff --git a/Makefile b/Makefile
index 6f87816..518bac5 100644
--- a/Makefile
+++ b/Makefile
@@ -21,7 +21,6 @@ BIN =\
        blind-from-video\
        blind-gauss-blur\
        blind-invert-luma\
-       blind-kernel\
        blind-make-kernel\
        blind-next-frame\
        blind-read-head\
@@ -44,6 +43,10 @@ BIN =\
        blind-transpose\
        blind-write-head
 
+# TODO Not tested yet (and doesn't have any manpages):
+#    blind-kernel
+#    blind-temporal-mean
+
 SCRIPTS =\
        blind-rotate-90\
        blind-rotate-180\
diff --git a/TODO b/TODO
index bf925a5..f1d1b30 100644
--- a/TODO
+++ b/TODO
@@ -32,6 +32,14 @@ blind-roberts-cross  
https://en.wikipedia.org/wiki/Roberts_cross
 ---                    https://en.wikipedia.org/wiki/Canny_edge_detector
 ---                    https://en.wikipedia.org/wiki/Deriche_edge_detector
 ---                    https://en.wikipedia.org/wiki/Edge_detection
+blind-mean             mean of multiple streams
+                       means from blind-temporal-mean
+                       https://en.wikipedia.org/wiki/Heinz_mean
+                       https://en.wikipedia.org/wiki/Heronian_mean
+                       https://en.wikipedia.org/wiki/Identric_mean
+                       https://en.wikipedia.org/wiki/Logarithmic_mean
+                       https://en.wikipedia.org/wiki/Stolarsky_mean
+blind-temporal-arithm  blind-arithm but over all frames in a video instead of 
over all streams
 
 blind-from-video: add options to:
        * just run ffmpeg just print the output
@@ -41,6 +49,8 @@ blind-from-video: add options to:
          print to stdout (up to user to direct to /dev/null
          for discarding)
 
+blind-arithm: add support for multiple streams
+
 Add [-j jobs] to blind-from-video and blind-to-video.
 
 Add -f (framewise) to blind-repeat
diff --git a/src/blind-temporal-mean.c b/src/blind-temporal-mean.c
new file mode 100644
index 0000000..437a928
--- /dev/null
+++ b/src/blind-temporal-mean.c
@@ -0,0 +1,186 @@
+/* See LICENSE file for copyright and license details. */
+#include "stream.h"
+#include "util.h"
+
+#include <math.h>
+#include <string.h>
+
+USAGE("[-g | -h | -l power | -p power]")
+/* TODO add -w weight-stream */
+
+/* Because the syntax for a function returning a function pointer is 
disgusting. */
+typedef void (*process_func)(struct stream *stream, void *buffer, void *image, 
size_t frame);
+
+/*
+ * X-parameter 1: method enum value
+ * X-parameter 2: identifier-friendly name
+ * X-parameter 3: images
+ * X-parameter 4: action for first frame
+ * X-parameter 5: pre-process assignments
+ * X-parameter 6: subcell processing
+ * X-parameter 7: pre-finalise assignments
+ * X-parameter 8: subcell finalisation
+ */
+#define LIST_MEANS(TYPE, SUFFIX)\
+       /* [default] arithmetic mean */\
+       X(ARITHMETIC, arithmetic, 1, COPY_FRAME,, *img1 += *buf,\
+         a = (TYPE)1.0 / (TYPE)frame, *img1 *= a)\
+       /* geometric mean */\
+       X(GEOMETRIC, geometric, 1, COPY_FRAME,, *img1 *= *buf,\
+         a = (TYPE)1.0 / (TYPE)frame, *img1 = nnpow##SUFFIX(*img1, a))\
+       /* harmonic mean */\
+       X(HARMONIC, harmonic, 1, ZERO_AND_PROCESS_FRAME,, *img1 += (TYPE)1 / 
*buf,\
+         a = (TYPE)frame, *img1 = a / *img1)\
+       /* lehmer mean */\
+       X(LEHMER, lehmer, 2, ZERO_AND_PROCESS_FRAME, (a = (TYPE)power, b = a - 
(TYPE)1),\
+         (*img1 += nnpow##SUFFIX(*buf, a), *img2 += nnpow##SUFFIX(*buf, b)),, 
*img1 /= *img2)\
+       /* power mean (Hölder mean) (m = 2 for root square mean; m = 3 for 
cubic mean) */\
+       X(POWER, power, 1, ZERO_AND_PROCESS_FRAME, a = (TYPE)power,\
+         *img1 += nnpow##SUFFIX(*buf, a), (a = (TYPE)1 / (TYPE)frame, b = 
(TYPE)(1.0 / power)),\
+         *img1 = a * nnpow##SUFFIX(*img1, b))
+
+enum first_frame_action {
+       COPY_FRAME,
+       PROCESS_FRAME,
+       ZERO_AND_PROCESS_FRAME,
+};
+
+#define X(V, ...) V,
+enum method { LIST_MEANS(,) };
+#undef X
+
+static double power;
+
+static inline double
+nnpow(double a, double b)
+{
+       int neg = a < 0;
+       a = pow(neg ? -a : a, b);
+       return neg ? -a : a;
+}
+
+static inline float
+nnpowf(float a, float b)
+{
+       int neg = a < 0;
+       a = powf(neg ? -a : a, b);
+       return neg ? -a : a;
+}
+
+#define MAKE_PROCESS(PIXFMT, TYPE, SUFFIX,\
+                    _1, NAME, _3, _4, PRE_PROCESS, PROCESS_SUBCELL, 
PRE_FINALISE, FINALISE_SUBCELL)\
+       static void\
+       process_##PIXFMT##_##NAME(struct stream *stream, void *buffer, void 
*image, size_t frame)\
+       {\
+               TYPE *buf = buffer, *img1 = image, a, b;\
+               TYPE *img2 = (TYPE *)(((char *)image) + stream->frame_size);\
+               size_t x, y;\
+               if (!stream) {\
+                       PRE_FINALISE;\
+                       for (y = 0; y < stream->height; y++)\
+                               for (x = 0; x < stream->width; x++, img1++, 
img2++, buf++)\
+                                       FINALISE_SUBCELL;\
+               } else {\
+                       PRE_PROCESS;\
+                       for (y = 0; y < stream->height; y++)\
+                               for (x = 0; x < stream->width; x++, img1++, 
img2++, buf++)\
+                                       PROCESS_SUBCELL;\
+               }\
+               (void) img2, (void) a, (void) b;\
+       }
+#define X(...) MAKE_PROCESS(xyza, double,, __VA_ARGS__)
+LIST_MEANS(double,)
+#undef X
+#define X(...) MAKE_PROCESS(xyzaf, float, f, __VA_ARGS__)
+LIST_MEANS(float, f)
+#undef X
+#undef MAKE_PROCESS
+
+#define X(ID, NAME, ...) [ID] = process_xyza_##NAME,
+static const process_func process_functions_xyza[] = { LIST_MEANS(,) };
+#undef X
+
+#define X(ID, NAME, ...) [ID] = process_xyzaf_##NAME,
+static const process_func process_functions_xyzaf[] = { LIST_MEANS(,) };
+#undef X
+
+int
+main(int argc, char *argv[])
+{
+       struct stream stream;
+       void *buf, *img;
+       process_func process;
+       size_t frames, images;
+       enum method method = ARITHMETIC;
+       enum first_frame_action first_frame_action;
+
+       ARGBEGIN {
+       case 'g':
+               method = GEOMETRIC;
+               break;
+       case 'h':
+               method = HARMONIC;
+               break;
+       case 'l':
+               method = LEHMER;
+               power = etolf_flag('l', UARGF());
+               break;
+       case 'p':
+               method = POWER;
+               power = etolf_flag('p', UARGF());
+               break;
+       default:
+               usage();
+       } ARGEND;
+
+       if (argc)
+               usage();
+
+#define X(ID, _2, IMAGES, FIRST_FRAME_ACTION, ...)\
+       case ID:\
+               images = IMAGES;\
+               first_frame_action = FIRST_FRAME_ACTION;\
+               break;
+       switch (method) {
+       LIST_MEANS(,)
+       default:
+               abort();
+       }
+#undef X
+
+       eopen_stream(&stream, NULL);
+
+        if (!strcmp(stream.pixfmt, "xyza"))
+                process = process_functions_xyza[method];
+        else if (!strcmp(stream.pixfmt, "xyza f"))
+                process = process_functions_xyzaf[method];
+        else
+                eprintf("pixel format %s is not supported, try xyza\n", 
stream.pixfmt);
+
+       stream.frames = 1;
+       echeck_dimensions(&stream, WIDTH | HEIGHT, NULL);
+       fprint_stream_head(stdout, &stream);
+       efflush(stdout, "<stdout>");
+       buf = emalloc(stream.frame_size);
+       if (first_frame_action == ZERO_AND_PROCESS_FRAME)
+               img = ecalloc(images, stream.frame_size);
+       else
+               img = emalloc2(images, stream.frame_size);
+
+       frames = 0;
+       if (first_frame_action == COPY_FRAME) {
+               if (!eread_frame(&stream, buf))
+                       eprintf("video is no frames\n");
+               frames++;
+       }
+       for (; eread_frame(&stream, buf); frames++)
+               process(&stream, buf, img, frames);
+       if (!frames)
+               eprintf("video is no frames\n");
+       process(&stream, NULL, img, frames);
+
+       ewriteall(STDOUT_FILENO, img, stream.frame_size, "<stdout>");
+       free(buf);
+       free(img);
+       return 0;
+}

Reply via email to