Browse code

avfilter/vf_vectorscope: add threshold option

Useful to only display lows/mids/highs.

Signed-off-by: Paul B Mahol <onemda@gmail.com>

Paul B Mahol authored on 2016/03/04 04:44:38
Showing 2 changed files
... ...
@@ -12639,6 +12639,20 @@ Draw graticule for black point.
12639 12639
 
12640 12640
 @item bgopacity, b
12641 12641
 Set background opacity.
12642
+
12643
+@item lthreshold, l
12644
+Set low threshold for color component not represented on X or Y axis.
12645
+Values lower than this value will be ignored. Default is 0.
12646
+Note this value is multiplied with actual max possible value one pixel component
12647
+can have. So for 8-bit input and low threshold value of 0.1 actual threshold
12648
+is 0.1 * 255 = 25.
12649
+
12650
+@item hthreshold, h
12651
+Set high threshold for color component not represented on X or Y axis.
12652
+Values higher than this value will be ignored. Default is 1.
12653
+Note this value is multiplied with actual max possible value one pixel component
12654
+can have. So for 8-bit input and high threshold value of 0.9 actual threshold
12655
+is 0.9 * 255 = 230.
12642 12656
 @end table
12643 12657
 
12644 12658
 @anchor{vidstabdetect}
... ...
@@ -56,6 +56,10 @@ typedef struct VectorscopeContext {
56 56
     int graticule;
57 57
     float opacity;
58 58
     float bgopacity;
59
+    float lthreshold;
60
+    float hthreshold;
61
+    int tmin;
62
+    int tmax;
59 63
     int flags;
60 64
     int cs;
61 65
     uint8_t peak[1024][1024];
... ...
@@ -101,6 +105,10 @@ static const AVOption vectorscope_options[] = {
101 101
     {   "black", "draw black point", 0, AV_OPT_TYPE_CONST, {.i64=2}, 0, 0, FLAGS, "flags" },
102 102
     { "bgopacity", "set background opacity", OFFSET(bgopacity), AV_OPT_TYPE_FLOAT, {.dbl=0.3}, 0, 1, FLAGS},
103 103
     { "b",         "set background opacity", OFFSET(bgopacity), AV_OPT_TYPE_FLOAT, {.dbl=0.3}, 0, 1, FLAGS},
104
+    { "lthreshold", "set low threshold",  OFFSET(lthreshold), AV_OPT_TYPE_FLOAT, {.dbl=0}, 0, 1, FLAGS},
105
+    { "l",          "set low threshold",  OFFSET(lthreshold), AV_OPT_TYPE_FLOAT, {.dbl=0}, 0, 1, FLAGS},
106
+    { "hthreshold", "set high threshold", OFFSET(hthreshold), AV_OPT_TYPE_FLOAT, {.dbl=1}, 0, 1, FLAGS},
107
+    { "h",          "set high threshold", OFFSET(hthreshold), AV_OPT_TYPE_FLOAT, {.dbl=1}, 0, 1, FLAGS},
104 108
     { NULL }
105 109
 };
106 110
 
... ...
@@ -371,6 +379,8 @@ static void vectorscope16(VectorscopeContext *s, AVFrame *in, AVFrame *out, int
371 371
     uint16_t *dpd = dst[pd];
372 372
     const int max = s->size - 1;
373 373
     const int mid = s->size / 2;
374
+    const int tmin = s->tmin;
375
+    const int tmax = s->tmax;
374 376
     int i, j, k;
375 377
 
376 378
     for (k = 0; k < 4 && dst[k]; k++) {
... ...
@@ -388,11 +398,16 @@ static void vectorscope16(VectorscopeContext *s, AVFrame *in, AVFrame *out, int
388 388
             for (i = 0; i < h; i++) {
389 389
                 const int iwx = i * slinesizex;
390 390
                 const int iwy = i * slinesizey;
391
+                const int iwd = i * slinesized;
391 392
                 for (j = 0; j < w; j++) {
392 393
                     const int x = FFMIN(spx[iwx + j], max);
393 394
                     const int y = FFMIN(spy[iwy + j], max);
395
+                    const int z = spd[iwd + j];
394 396
                     const int pos = y * dlinesize + x;
395 397
 
398
+                    if (z < tmin || z > tmax)
399
+                        continue;
400
+
396 401
                     dpd[pos] = FFMIN(dpd[pos] + intensity, max);
397 402
                     if (dst[3])
398 403
                         dst[3][pos] = max;
... ...
@@ -402,11 +417,16 @@ static void vectorscope16(VectorscopeContext *s, AVFrame *in, AVFrame *out, int
402 402
             for (i = 0; i < h; i++) {
403 403
                 const int iwx = i * slinesizex;
404 404
                 const int iwy = i * slinesizey;
405
+                const int iwd = i * slinesized;
405 406
                 for (j = 0; j < w; j++) {
406 407
                     const int x = FFMIN(spx[iwx + j], max);
407 408
                     const int y = FFMIN(spy[iwy + j], max);
409
+                    const int z = spd[iwd + j];
408 410
                     const int pos = y * dlinesize + x;
409 411
 
412
+                    if (z < tmin || z > tmax)
413
+                        continue;
414
+
410 415
                     dst[0][pos] = FFMIN(dst[0][pos] + intensity, max);
411 416
                     dst[1][pos] = FFMIN(dst[1][pos] + intensity, max);
412 417
                     dst[2][pos] = FFMIN(dst[2][pos] + intensity, max);
... ...
@@ -421,11 +441,16 @@ static void vectorscope16(VectorscopeContext *s, AVFrame *in, AVFrame *out, int
421 421
             for (i = 0; i < h; i++) {
422 422
                 const int iw1 = i * slinesizex;
423 423
                 const int iw2 = i * slinesizey;
424
+                const int iwd = i * slinesized;
424 425
                 for (j = 0; j < w; j++) {
425 426
                     const int x = FFMIN(spx[iw1 + j], max);
426 427
                     const int y = FFMIN(spy[iw2 + j], max);
428
+                    const int z = spd[iwd + j];
427 429
                     const int pos = y * dlinesize + x;
428 430
 
431
+                    if (z < tmin || z > tmax)
432
+                        continue;
433
+
429 434
                     if (!dpd[pos])
430 435
                         dpd[pos] = FFABS(mid - x) + FFABS(mid - y);
431 436
                     dpx[pos] = x;
... ...
@@ -438,11 +463,16 @@ static void vectorscope16(VectorscopeContext *s, AVFrame *in, AVFrame *out, int
438 438
             for (i = 0; i < h; i++) {
439 439
                 const int iw1 = i * slinesizex;
440 440
                 const int iw2 = i * slinesizey;
441
+                const int iwd = i * slinesized;
441 442
                 for (j = 0; j < w; j++) {
442 443
                     const int x = FFMIN(spx[iw1 + j], max);
443 444
                     const int y = FFMIN(spy[iw2 + j], max);
445
+                    const int z = spd[iwd + j];
444 446
                     const int pos = y * dlinesize + x;
445 447
 
448
+                    if (z < tmin || z > tmax)
449
+                        continue;
450
+
446 451
                     if (!dpd[pos])
447 452
                         dpd[pos] = FFMIN(x + y, max);
448 453
                     dpx[pos] = x;
... ...
@@ -457,11 +487,16 @@ static void vectorscope16(VectorscopeContext *s, AVFrame *in, AVFrame *out, int
457 457
         for (i = 0; i < h; i++) {
458 458
             const int iw1 = i * slinesizex;
459 459
             const int iw2 = i * slinesizey;
460
+            const int iwd = i * slinesized;
460 461
             for (j = 0; j < w; j++) {
461 462
                 const int x = FFMIN(spx[iw1 + j], max);
462 463
                 const int y = FFMIN(spy[iw2 + j], max);
464
+                const int z = spd[iwd + j];
463 465
                 const int pos = y * dlinesize + x;
464 466
 
467
+                if (z < tmin || z > tmax)
468
+                    continue;
469
+
465 470
                 dpd[pos] = FFMIN(max, dpd[pos] + intensity);
466 471
                 dpx[pos] = x;
467 472
                 dpy[pos] = y;
... ...
@@ -478,9 +513,13 @@ static void vectorscope16(VectorscopeContext *s, AVFrame *in, AVFrame *out, int
478 478
             for (j = 0; j < in->width; j++) {
479 479
                 const int x = FFMIN(spx[iwx + (j >> hsub)], max);
480 480
                 const int y = FFMIN(spy[iwy + (j >> hsub)], max);
481
+                const int z = spd[iwd + j];
481 482
                 const int pos = y * dlinesize + x;
482 483
 
483
-                dpd[pos] = FFMAX(spd[iwd + j], dpd[pos]);
484
+                if (z < tmin || z > tmax)
485
+                    continue;
486
+
487
+                dpd[pos] = FFMAX(z, dpd[pos]);
484 488
                 dpx[pos] = x;
485 489
                 dpy[pos] = y;
486 490
                 if (dst[3])
... ...
@@ -537,6 +576,8 @@ static void vectorscope8(VectorscopeContext *s, AVFrame *in, AVFrame *out, int p
537 537
     uint8_t *dpx = dst[px];
538 538
     uint8_t *dpy = dst[py];
539 539
     uint8_t *dpd = dst[pd];
540
+    const int tmin = s->tmin;
541
+    const int tmax = s->tmax;
540 542
     int i, j, k;
541 543
 
542 544
     for (k = 0; k < 4 && dst[k]; k++)
... ...
@@ -552,11 +593,16 @@ static void vectorscope8(VectorscopeContext *s, AVFrame *in, AVFrame *out, int p
552 552
             for (i = 0; i < h; i++) {
553 553
                 const int iwx = i * slinesizex;
554 554
                 const int iwy = i * slinesizey;
555
+                const int iwd = i * slinesized;
555 556
                 for (j = 0; j < w; j++) {
556 557
                     const int x = spx[iwx + j];
557 558
                     const int y = spy[iwy + j];
559
+                    const int z = spd[iwd + j];
558 560
                     const int pos = y * dlinesize + x;
559 561
 
562
+                    if (z < tmin || z > tmax)
563
+                        continue;
564
+
560 565
                     dpd[pos] = FFMIN(dpd[pos] + intensity, 255);
561 566
                     if (dst[3])
562 567
                         dst[3][pos] = 255;
... ...
@@ -566,11 +612,16 @@ static void vectorscope8(VectorscopeContext *s, AVFrame *in, AVFrame *out, int p
566 566
             for (i = 0; i < h; i++) {
567 567
                 const int iwx = i * slinesizex;
568 568
                 const int iwy = i * slinesizey;
569
+                const int iwd = i * slinesized;
569 570
                 for (j = 0; j < w; j++) {
570 571
                     const int x = spx[iwx + j];
571 572
                     const int y = spy[iwy + j];
573
+                    const int z = spd[iwd + j];
572 574
                     const int pos = y * dlinesize + x;
573 575
 
576
+                    if (z < tmin || z > tmax)
577
+                        continue;
578
+
574 579
                     dst[0][pos] = FFMIN(dst[0][pos] + intensity, 255);
575 580
                     dst[1][pos] = FFMIN(dst[1][pos] + intensity, 255);
576 581
                     dst[2][pos] = FFMIN(dst[2][pos] + intensity, 255);
... ...
@@ -585,11 +636,16 @@ static void vectorscope8(VectorscopeContext *s, AVFrame *in, AVFrame *out, int p
585 585
             for (i = 0; i < h; i++) {
586 586
                 const int iw1 = i * slinesizex;
587 587
                 const int iw2 = i * slinesizey;
588
+                const int iwd = i * slinesized;
588 589
                 for (j = 0; j < w; j++) {
589 590
                     const int x = spx[iw1 + j];
590 591
                     const int y = spy[iw2 + j];
592
+                    const int z = spd[iwd + j];
591 593
                     const int pos = y * dlinesize + x;
592 594
 
595
+                    if (z < tmin || z > tmax)
596
+                        continue;
597
+
593 598
                     if (!dpd[pos])
594 599
                         dpd[pos] = FFABS(128 - x) + FFABS(128 - y);
595 600
                     dpx[pos] = x;
... ...
@@ -602,11 +658,16 @@ static void vectorscope8(VectorscopeContext *s, AVFrame *in, AVFrame *out, int p
602 602
             for (i = 0; i < h; i++) {
603 603
                 const int iw1 = i * slinesizex;
604 604
                 const int iw2 = i * slinesizey;
605
+                const int iwd = i * slinesized;
605 606
                 for (j = 0; j < w; j++) {
606 607
                     const int x = spx[iw1 + j];
607 608
                     const int y = spy[iw2 + j];
609
+                    const int z = spd[iwd + j];
608 610
                     const int pos = y * dlinesize + x;
609 611
 
612
+                    if (z < tmin || z > tmax)
613
+                        continue;
614
+
610 615
                     if (!dpd[pos])
611 616
                         dpd[pos] = FFMIN(x + y, 255);
612 617
                     dpx[pos] = x;
... ...
@@ -621,11 +682,16 @@ static void vectorscope8(VectorscopeContext *s, AVFrame *in, AVFrame *out, int p
621 621
         for (i = 0; i < h; i++) {
622 622
             const int iw1 = i * slinesizex;
623 623
             const int iw2 = i * slinesizey;
624
+            const int iwd = i * slinesized;
624 625
             for (j = 0; j < w; j++) {
625 626
                 const int x = spx[iw1 + j];
626 627
                 const int y = spy[iw2 + j];
628
+                const int z = spd[iwd + j];
627 629
                 const int pos = y * dlinesize + x;
628 630
 
631
+                if (z < tmin || z > tmax)
632
+                    continue;
633
+
629 634
                 dpd[pos] = FFMIN(255, dpd[pos] + intensity);
630 635
                 dpx[pos] = x;
631 636
                 dpy[pos] = y;
... ...
@@ -642,9 +708,13 @@ static void vectorscope8(VectorscopeContext *s, AVFrame *in, AVFrame *out, int p
642 642
             for (j = 0; j < in->width; j++) {
643 643
                 const int x = spx[iwx + (j >> hsub)];
644 644
                 const int y = spy[iwy + (j >> hsub)];
645
+                const int z = spd[iwd + j];
645 646
                 const int pos = y * dlinesize + x;
646 647
 
647
-                dpd[pos] = FFMAX(spd[iwd + j], dpd[pos]);
648
+                if (z < tmin || z > tmax)
649
+                    continue;
650
+
651
+                dpd[pos] = FFMAX(z, dpd[pos]);
648 652
                 dpx[pos] = x;
649 653
                 dpy[pos] = y;
650 654
                 if (dst[3])
... ...
@@ -963,12 +1033,20 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in)
963 963
 static int config_input(AVFilterLink *inlink)
964 964
 {
965 965
     const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format);
966
-    VectorscopeContext *s = inlink->dst->priv;
966
+    AVFilterContext *ctx = inlink->dst;
967
+    VectorscopeContext *s = ctx->priv;
967 968
 
968 969
     s->is_yuv = !(desc->flags & AV_PIX_FMT_FLAG_RGB);
969 970
     s->size = 1 << desc->comp[0].depth;
970 971
     s->mult = s->size / 256;
971 972
     s->depth = desc->comp[0].depth;
973
+    s->tmin = s->lthreshold * (s->size - 1);
974
+    s->tmax = s->hthreshold * (s->size - 1);
975
+
976
+    if (s->tmin > s->tmax) {
977
+        av_log(ctx, AV_LOG_ERROR, "low threshold should be less than high threshold\n");
978
+        return AVERROR(EINVAL);
979
+    }
972 980
 
973 981
     if (s->mode == GRAY && s->is_yuv)
974 982
         s->pd = 0;