diff options
author | bradleys <[email protected]> | 2014-06-19 21:44:37 +0000 |
---|---|---|
committer | bradleys <[email protected]> | 2014-06-19 21:44:37 +0000 |
commit | 7fba1c6ad31aa1002624223ef34b612efa8262f4 (patch) | |
tree | ee459af7c2ab4ef7fe01e17a532bf5f6767f73cf /test/test.c | |
parent | 80a124ff2567ac45b26a606d425420a1ee590506 (diff) |
libhb: New denoiser, nlmeans.
Non-local means averages multiple patches of similar pixels together, preserving similarities and attenuating variance (usually noise). This is typically more effective than lowpass and more faithfully restores the appearance of structure and detail found in the original source, especially in the high frequency range. Parameters for origin patch weight tuning and pre-filtering further improve on the original algorithm.
git-svn-id: svn://svn.handbrake.fr/HandBrake/trunk@6216 b64f7644-9d1e-0410-96f1-a4d463321fa5
Diffstat (limited to 'test/test.c')
-rw-r--r-- | test/test.c | 205 |
1 files changed, 205 insertions, 0 deletions
diff --git a/test/test.c b/test/test.c index c35a8fc96..249f8adcf 100644 --- a/test/test.c +++ b/test/test.c @@ -60,6 +60,9 @@ static int deblock = 0; static char * deblock_opt = 0; static int denoise = 0; static char * denoise_opt = 0; +static int nlmeans = 0; +static char * nlmeans_opt = NULL; +static char * nlmeans_tune_opt = NULL; static int detelecine = 0; static char * detelecine_opt = 0; static int decomb = 0; @@ -435,6 +438,8 @@ int main( int argc, char ** argv ) free(advanced_opts); free(h264_profile); free(h264_level); + free(nlmeans_opt); + free(nlmeans_tune_opt); // write a carriage return to stdout // avoids overlap / line wrapping when stderr is redirected @@ -1705,6 +1710,11 @@ static int HandleEvents( hb_handle_t * h ) filter = hb_filter_init( HB_FILTER_DENOISE ); hb_add_filter( job, filter, denoise_opt ); } + if( nlmeans ) + { + filter = hb_filter_init( HB_FILTER_NLMEANS ); + hb_add_filter( job, filter, nlmeans_opt ); + } if( rotate ) { filter = hb_filter_init( HB_FILTER_ROTATE ); @@ -3464,6 +3474,15 @@ if (hb_qsv_available()) " or\n" " <SL:SCb:SCr:TL:TCb:TCr>\n" " (default: 4:3:3:6:4.5:4.5)\n" + " --nlmeans Denoise video with nlmeans filter\n" + " <ultralight/light/medium/strong> or omitted\n" + " or\n" + " <SY:OTY:PSY:RY:FY:PY:Sb:OTb:PSb:Rb:Fb:Pb:Sr:OTr:PSr:Rr:Fr:Pr>\n" + " (default 8:1:7:3:2:0)\n" + " --nlmeans-tune Tune nlmeans filter to content type\n" + " Note: only works in conjunction with presets\n" + " ultralight/light/medium/strong.\n" + " <none/film/grain/highmotion/animation> or omitted (default none)\n" " -7, --deblock Deblock video with pp7 filter\n" " <QP:M> (default 5:2)\n" " --rotate Flips images axes\n" @@ -3695,6 +3714,8 @@ static int ParseOptions( int argc, char ** argv ) #define QSV_BASELINE 295 #define QSV_ASYNC_DEPTH 296 #define QSV_IMPLEMENTATION 297 + #define FILTER_NLMEANS 298 + #define FILTER_NLMEANS_TUNE 299 for( ;; ) { @@ -3753,6 +3774,8 @@ static int ParseOptions( int argc, char ** argv ) { "deinterlace", optional_argument, NULL, 'd' }, { "deblock", optional_argument, NULL, '7' }, { "denoise", optional_argument, NULL, '8' }, + { "nlmeans", optional_argument, NULL, FILTER_NLMEANS }, + { "nlmeans-tune",required_argument, NULL, FILTER_NLMEANS_TUNE }, { "detelecine", optional_argument, NULL, '9' }, { "decomb", optional_argument, NULL, '5' }, { "grayscale", no_argument, NULL, 'g' }, @@ -4109,6 +4132,30 @@ static int ParseOptions( int argc, char ** argv ) } denoise = 1; break; + case FILTER_NLMEANS: + if(optarg != NULL) + { + free(nlmeans_opt); + nlmeans_opt = strdup(optarg); + } + nlmeans = 1; + break; + case FILTER_NLMEANS_TUNE: + if (!strcmp(optarg, "none") || + !strcmp(optarg, "film") || + !strcmp(optarg, "grain") || + !strcmp(optarg, "highmotion") || + !strcmp(optarg, "animation")) + { + free(nlmeans_tune_opt); + nlmeans_tune_opt = strdup(optarg); + } + else + { + fprintf(stderr, "invalid nlmeans tune (%s)\n", optarg); + return -1; + } + break; case '9': if( optarg != NULL ) { @@ -4409,6 +4456,164 @@ static int ParseOptions( int argc, char ** argv ) fprintf( stderr, "unknown option (%s)\n", argv[cur_optind] ); return -1; } + + } + + /* NL-means presets (--nlmeans) and tunes (--nlmeans-tune) + * + * Presets adjust strength: + * ultralight - visually transparent + * light + * medium + * strong + * + * Tunes adjust settings to the specified content type: + * none + * film - most content, live action + * grain - like film but preserves luma grain + * highmotion - like film but avoids color smearing with stronger settings + * animation - cel animation such as cartoons, anime + */ + if (nlmeans == 1 && nlmeans_opt != NULL) + { + if (!strcmp(nlmeans_opt, "ultralight") || + !strcmp(nlmeans_opt, "light") || + !strcmp(nlmeans_opt, "medium") || + !strcmp(nlmeans_opt, "strong")) + { + char opt[1024]; + double strength[2], + origin_tune[2]; + int patch_size[2], + range[2], + frames[2], + prefilter[2]; + + if (nlmeans_tune_opt == NULL || !strcmp(nlmeans_tune_opt, "none")) + { + strength[0] = strength[1] = 6; + origin_tune[0] = origin_tune[1] = 1; + patch_size[0] = patch_size[1] = 7; + range[0] = range[1] = 3; + frames[0] = frames[1] = 2; + prefilter[0] = prefilter[1] = 0; + if (!strcmp(nlmeans_opt, "ultralight")) + { + strength[0] = strength[1] = 1.5; + } + else if (!strcmp(nlmeans_opt, "light")) + { + strength[0] = strength[1] = 3; + } + else if (!strcmp(nlmeans_opt, "strong")) + { + strength[0] = strength[1] = 10; + } + } + else if (!strcmp(nlmeans_tune_opt, "film")) + { + strength[0] = 6; strength[1] = 8; + origin_tune[0] = origin_tune[1] = 0.8; + patch_size[0] = patch_size[1] = 7; + range[0] = range[1] = 3; + frames[0] = frames[1] = 2; + prefilter[0] = prefilter[1] = 0; + if (!strcmp(nlmeans_opt, "ultralight")) + { + strength[0] = 1.5; strength[1] = 2.4; + origin_tune[0] = 0.9; origin_tune[1] = 0.9; + } + else if (!strcmp(nlmeans_opt, "light")) + { + strength[0] = 3; strength[1] = 4; + origin_tune[0] = 0.9; origin_tune[1] = 0.9; + } + else if (!strcmp(nlmeans_opt, "strong")) + { + strength[0] = 8; strength[1] = 10; + origin_tune[0] = 0.6; origin_tune[1] = 0.6; + } + } + else if (!strcmp(nlmeans_tune_opt, "grain")) + { + strength[0] = 0; strength[1] = 6; + origin_tune[0] = origin_tune[1] = 0.8; + patch_size[0] = patch_size[1] = 7; + range[0] = range[1] = 3; + frames[0] = frames[1] = 2; + prefilter[0] = prefilter[1] = 0; + if (!strcmp(nlmeans_opt, "ultralight")) + { + strength[0] = 0; strength[1] = 2.4; + origin_tune[0] = 0.9; origin_tune[1] = 0.9; + } + else if (!strcmp(nlmeans_opt, "light")) + { + strength[0] = 0; strength[1] = 3.5; + origin_tune[0] = 0.9; origin_tune[1] = 0.9; + } + else if (!strcmp(nlmeans_opt, "strong")) + { + strength[0] = 0; strength[1] = 8; + origin_tune[0] = 0.6; origin_tune[1] = 0.6; + } + } + else if (!strcmp(nlmeans_tune_opt, "highmotion")) + { + strength[0] = 6; strength[1] = 6; + origin_tune[0] = 0.8; origin_tune[1] = 0.7; + patch_size[0] = 7; patch_size[1] = 7; + range[0] = 3; range[1] = 5; + frames[0] = 2; frames[1] = 1; + prefilter[0] = 0; prefilter[1] = 0; + if (!strcmp(nlmeans_opt, "ultralight")) + { + strength[0] = 1.5; strength[1] = 2.4; + origin_tune[0] = 0.9; origin_tune[1] = 0.9; + } + else if (!strcmp(nlmeans_opt, "light")) + { + strength[0] = 3; strength[1] = 3.25; + origin_tune[0] = 0.9; origin_tune[1] = 0.8; + } + else if (!strcmp(nlmeans_opt, "strong")) + { + strength[0] = 8; strength[1] = 6.75; + origin_tune[0] = 0.6; origin_tune[1] = 0.5; + } + } + else if (!strcmp(nlmeans_tune_opt, "animation")) + { + strength[0] = 5; strength[1] = 4; + origin_tune[0] = origin_tune[1] = 0.15; + patch_size[0] = patch_size[1] = 5; + range[0] = range[1] = 7; + frames[0] = frames[1] = 4; + prefilter[0] = prefilter[1] = 0; + if (!strcmp(nlmeans_opt, "ultralight")) + { + strength[0] = 2.5; strength[1] = 2; + frames[0] = 2; frames[1] = 2; + } + else if (!strcmp(nlmeans_opt, "light")) + { + strength[0] = 3; strength[1] = 2.25; + frames[0] = 3; frames[1] = 3; + } + else if (!strcmp(nlmeans_opt, "strong")) + { + strength[0] = 10; strength[1] = 8; + } + } + + sprintf(opt, "%lf:%lf:%d:%d:%d:%d:%lf:%lf:%d:%d:%d:%d", + strength[0], origin_tune[0], patch_size[0], range[0], frames[0], prefilter[0], + strength[1], origin_tune[1], patch_size[1], range[1], frames[1], prefilter[1]); + + free(nlmeans_opt); + nlmeans_opt = strdup(opt); + + } } return 0; |