View Full Version : TemporalDegrainV2
ErazorTT
13th October 2018, 00:00
Hi all,
I want to share an updated version of the script TemporalDegrain.
The reason for the update was to combine TemporalDegrain with the relevant parts of QTGMC:
Although MDegrain of MVTools with Didees contra-sharpening already performes great, the additional stage of motion compensated fourier denoising can do wonders.
Together with this, the original motion estimation is also much improved using the exceptional approach of QTGMC instead of the very mushy intermediate stream which was losing some vectors in sceenes with low contrast and diverging movement.
With this optional fourier denoising setting the result can be up to completely grainless, much better compressable and together with the optional dithering it is guaranteed to produce no banding, yielding a very natural look in total.
Here a comparison of a scene of s2e1 of Breaking Bad, starting with the original [505KB for the JPEG still]:
https://i.postimg.cc/18PsPjGz/org.jpg (https://postimg.cc/18PsPjGz)
v1.23: TemporalDegrain(degrain=2) [310KB for the JPEG still]
https://i.postimg.cc/6yCtkXGS/v123-tr2.jpg (https://postimg.cc/6yCtkXGS)
v2.0: TemporalDegrain2(degrainTR=2,postFFT=3,postSigma=3) [216KB for the JPEG still]
https://i.postimg.cc/Dm97pZmL/v2-tr2-pf3-ps3-pd-1.jpg (https://postimg.cc/Dm97pZmL)
Compared to V1.23 the out-of-focus regions of V2.0 have almost no remaining grain anymore (can be even better seen on the moving picture) helping compressablity (see the JPEG file sizes as a proxy).
The in-focus regions however have still all details of the original frame.
And now the comparison of why I think it was time for an improved motion estimation over v1 of TemproralDegrain.
original from Breaking Bad s1e1, the camera moves following the car:
https://i.postimg.cc/YhVMBphg/9895-org.jpg (https://postimg.cc/YhVMBphg)
v1.23: TemporalDegrain(degrain=2)
https://i.postimg.cc/ThNXnRjS/9895-v123.jpg (https://postimg.cc/ThNXnRjS)
The motion of the low contrast tarmac is not captured well and thus the details are being washed away.
v2.10: TemporalDegrain2(degrainTR=2)
https://i.postimg.cc/zb6R0QmY/9895-v210.jpg (https://postimg.cc/zb6R0QmY)
More of the details of the tarmac are preserved.
In this thread further down are some movie samples: here (https://forum.doom9.org/showthread.php?p=1855447#post1855447)
I have also made some performance measurements: here (https://forum.doom9.org/showthread.php?p=1856673#post1856673)
Greets,
enjoy!
Changelog:
Dec 20, 2021: v2.3.4 (if you ever had a reason to use something else than postFFT 0, 1 or 2 try again now!)
- dithering is delayed to after contraSharpending which increases quality of dithering, decreasing banding and noise (postDither=2), old behaviour is regained with postDither=1
- postDither argument has been inverted! [new postDither = (-1) * old postDither] <--- if you ever explicitly set the postDither argument, read this line
Dec 21, 2021: v2.4.0 (This and later releases need AviSynth 3.7.1+)
- add BM3D_CPU & BM3D_CUDA (based on BM3D prefilter of Dogway's SMDegrain) and mods by kedautinh12 (Aug 12 - Dec 19)
Dec 21, 2021: v2.4.1
- small speed increase for BM3D (thanks to kedautinh12)
Jan 05, 2022: v2.4.2
- allow enabling or disabling of chroma and luma filtering for BM3D (thanks to kedautinh12)
- allow denoising on different planes at the two stages (degrainPlane vs postPlane)
Feb 15, 2022: v2.4.3
- add limit r to 3 when CUDA=true for BM3D (based on BM3D prefilter of Dogway's SMDegrain) and mods by kedautinh12
- add preset for BM3D (based on BM3D prefilter of Dogway's SMDegrain) and mods by kedautinh12
Apr 05, 2022: v2.5.0
- allow distinct postFFT and postSigma for luma and chroma
May 01, 2022: v2.6.0
- clean chroma more by also using the first degrain step
- tweak scene change detection factors
May 02, 2022: v2.6.1
- fix grainLevelSetup which was broken in previous release
May 10, 2022: v2.6.2
- some fixes and cleanup
Jun 06, 2022: v2.6.3
- increase possible range of grainLevel
- allow for multiple usages of this script
Feb 11, 2023: v2.6.4
- always undot before postFFT stage, increasing FFT efficiency by quite a bit when degrain was disabled
- mention suggested settings inside the script file
Feb 28, 2023: v2.6.6
- cleaning chroma only in one step, to ameliorate the chroma shift bug in mvtools MDegrain
Jan 14, 2024: v2.6.7
- forward device_type and device_id to KNLMeansCL
Link to newest version: >here (https://drive.google.com/file/d/1waGNgIdWx8hq1Ye7ejEJ_pKw6_lXMy2g/view?usp=drive_link)<
All current and old versions can be downloaded: >here (https://drive.google.com/drive/folders/1flOcKBNn_ozvK0D1xgGo0lJ6iTk7EhW9?usp=sharing)<
tormento
13th October 2018, 12:35
I want to share an updated version of the script TemporalDegrain.
I will try ASAP and tell you results.
You did a little mistype in the comments:
# KNLMeansCLL: https://github.com/Khanattila/KNLMeansCL/releases #
I am a bit confused too about the role of KNLMeansCL in the script. You state as optional but I can't see any knob or boolean to use it, even if I see trace of it in the code.
I am a bit puzzled why you use FFT3DFilter and FFT3DGPU and not only one of them.
I'd like also to know if the script is high bitdepth aware or internally working in high bit precision or 8 bit only.
I humbly suggest to use thumbnails for the images, not to send to hell thread formatting :)
johnmeyer
13th October 2018, 18:06
I've tried a lot of noise reduction and degraining plugins and scripts. You really cannot tell much from static shots because many of these approaches can cause really weird artifacts that can only be seen when you watch the resulting video. This is because you sometimes get correlation between grain in adjacent frames which results in really weird alignment of some of the residual grains, as well as other artifacts, none of which are apparent in a single frame.
So, it would be useful to have a side-by-side before/after video.
ErazorTT
14th October 2018, 15:09
Thanks a lot for the quick feedback!! :thanks:
You did a little mistype in the comments:
Oh I will correct that.
I am a bit confused too about the role of KNLMeansCL in the script. You state as optional but I can't see any knob or boolean to use it, even if I see trace of it in the code.
Yeah, right I forgot to mention that in the file. It is being set by postFTT=4.
I am a bit puzzled why you use FFT3DFilter and FFT3DGPU and not only one of them.
I was asuming FFT3DGPU would be a faster version of FFT3DFilter but if I am not mistaken currently only FFT3DFilter is still maintained, thus I though to leave the decission to the user.
I'd like also to know if the script is high bitdepth aware or internally working in high bit precision or 8 bit only.
I have made some of the necessary changes to the inner working as a first step to supporting high bitdepth but I am not there yet. Thats what I plan to do as a next step.
I humbly suggest to use thumbnails for the images, not to send to hell thread formatting :)
Let me see if I can figure out how to do that...
...it would be useful to have a side-by-side before/after video.
Yes very true, I will prepare some samples
StainlessS
14th October 2018, 16:47
Let me see if I can figure out how to do that...
PostImage.org allows anonymous upload, but also easy to make account.
Below, HotLink for forum, and then Thumbnail for forum below that.
https://i.postimg.cc/y6nn9NCr/Post-Image.jpg (https://postimages.org/)
https://i.postimg.cc/hhz9Rcj9/Post-Image.jpg (https://postimg.cc/hhz9Rcj9)
ErazorTT
14th October 2018, 18:21
PostImage.org allows anonymous upload, but also easy to make account.
Awesome :thanks:
tormento
15th October 2018, 11:42
Awesome :thanks:
I use lensdump too.
Forteen88
15th October 2018, 22:02
Thanks! Is this script of yours also great against "dancing grain"?
I've noticed that I can barely stand "dancing grain" in videos anymore :P
Oh, I remember that the movie "The Good, the Bad and the Ugly" Blu-ray had really much annoying grain, I could barely concentrate on the movie.
EDIT: But this does not mean that I hate all grain. I can accept a bit of grain if it's not too much!
hello_hello
16th October 2018, 04:41
Interesting.....
For a long time QTGMC has been my "go to" noise filter. Not that it's perfect, as being a de-interlacer it can sometimes create unwanted side effects "normal" denoising scripts don't, but where there's movement it's blurring to noise removal ratio tends to be pretty good. Only the other day I found myself wondering how hard it'd be to modify QTGMC to remove the de-interlacing completely for progressive video, and if it was possible, would it adversely effect it's ability to denoise.
Anyhow..... for a quick and very unscientific comparison. The "original video" is the script output with only resizing applied. The filtered screenshots were taken after encoding with x264, CRF18, Preset Slower(ish). I'm not sure why I did it that way, but I guess ultimately it's all about how the encoded version looks.
Thumbnails so as not to upset the scrolling police (and because it is annoying). It looks like you need to click on a thumbnail to open an image on the PostImage site, then right click and select "view image" for the full size version.
Screenshot 1. The camera was panning down a little. The playing card top/left shows the most detail difference.
Screenshot 2 was static.
Screenshot 3 had lots of movement. The stripes on the guy's shirt would be typical noise removal victims.
Edit: Whoops. The first three screenshots were off by a frame relative to the others. They're fixed.
Original 1080p video resized to 720p.
Spline36Resize(1280,536)
https://i.postimg.cc/Mntvvfvs/No-Filtering-A.png (https://postimg.cc/Mntvvfvs)
https://i.postimg.cc/K3nYFR6D/No-Filtering-B.png (https://postimg.cc/K3nYFR6D)
https://i.postimg.cc/WDS6Nywy/No-Filtering-C.png (https://postimg.cc/WDS6Nywy)
Spline36Resize(1280,536)
QTGMC(InputType=1, EzDenoise=1.5)
GradFun3()
https://i.postimg.cc/MMT0vYsp/QTGMC-A.png (https://postimg.cc/MMT0vYsp)
https://i.postimg.cc/hXL1wvzc/QTGMC-B.png (https://postimg.cc/hXL1wvzc)
https://i.postimg.cc/cr8mRXdK/QTGMC-C.png (https://postimg.cc/cr8mRXdK)
Spline36Resize(1280,536)
TemporalDegrainV2()
GradFun3()
https://i.postimg.cc/LhWDgrFK/Temporal-Degrain2-A.png (https://postimg.cc/LhWDgrFK)
https://i.postimg.cc/dkHBBf7C/Temporal-Degrain2-B.png (https://postimg.cc/dkHBBf7C)
https://i.postimg.cc/cgbRY8jM/Temporal-Degrain2-C.png (https://postimg.cc/cgbRY8jM)
Spline36Resize(1280,536)
TemporalDegrain()
GradFun3()
https://i.postimg.cc/qgNXrjhm/Temporal-Degrain-A.png (https://postimg.cc/qgNXrjhm)
https://i.postimg.cc/3y3FHhmp/Temporal-Degrain-B.png (https://postimg.cc/3y3FHhmp)
https://i.postimg.cc/5XLsVpGc/Temporal-Degrain-C.png (https://postimg.cc/5XLsVpGc)
ErazorTT
19th October 2018, 22:52
I updated the first post to include a comparison concerning the motion estimation! Since this was one of the main driving points I figured it would be good to show.
Screenshot 1. The camera was panning down a little. The playing card top/left shows the most detail difference.
Screenshot 2 was static.
Screenshot 3 had lots of movement. The stripes on the guy's shirt would be typical noise removal victims.
Hm QTGMC yeilds better results for 1 and 3. I wonder why... What version of QTGMC were you using?
Could you please try to run again with version 2.0.1 and play with options meBlksz=8/16 and/or meTM=true/false for TemporalDegrain2?
(Use the new updated version 2.0.1 from the first post. With the function renamed to TemporalDegrain2 it should also be easier to compare to v1)
ErazorTT
20th October 2018, 01:26
So, it would be useful to have a side-by-side before/after video.
Here you have the motion pricture you requested. I used x264 with crf 16 at "Very Slow" for all three:
Original (https://drive.google.com/open?id=1VUYt0i2FvHI-rlpy3tJV2cDSFk3WwbVV)
TD1.23 (https://drive.google.com/open?id=1qloMD42hR8rJIt-TvURx7pv-iGuVWGdb): TemporalDegrain(degrain=2)
TD2.10 (https://drive.google.com/open?id=1YVCv6yltEcWWpfby5ePGI40jq--9OJC5): TemporalDegrain2(degrainTR=2,postFFT=3,postSigma=3,postDither=-1)
Be sure to actually download the files and do not just watch the preview in the browser! The quality of the browser preview is miserable..
... Is this script of yours also great against "dancing grain"?
Yes you should be able to go from "mostly gone" to "OMG WFT, how is that even possible that a movie looks that clean" :D
Look at the files in this post, the grain is gone.
Taurus
20th October 2018, 16:06
@ErazorTT:
Please upload your Temporaldegrain2.zip to a filehoster.
It can take days, weeks or months for "Attachments Pending Approval" :D
Or just show the avsi in quotes here in this thread.
Thank you.
ErazorTT
20th October 2018, 18:13
@Taurus
Great you made me aware of that! I just updated the first post accordingly. I wonder however why the attachment could be downloaded right after I opened the thread... :confused:
tebasuna51
21st October 2018, 00:21
If you modify the first post I can't know when I need approve the attachment, sorry.
Approved now.
I only read new post.
ErazorTT
21st October 2018, 07:33
@tebasuna51: I have seen in other threads that this is the way people seem to operate, namely having the first post up to date. What would then be the best way to update the attachments? Do other let you know that they want something approved?
tebasuna51
21st October 2018, 10:09
When avsi text is bigger than 16000 chars (like TemporalDegrain2.avsi is) can't be included like text in the post, then you can use:
1) Pastebin (the user can read the source before download it)
2) Other upload free sites: DriveGoogle, Mediafire, Sendspace,... (like you make here)
3) If attach please make a new post with something like:
"New version X.Y attached in first post, please approve it"
hello_hello
21st October 2018, 13:27
What version of QTGMC were you using?
QTGMC 3.357s.
Could you please try to run again with version 2.0.1 and play with options meBlksz=8/16 and/or meTM=true/false for TemporalDegrain2?
(Use the new updated version 2.0.1 from the first post. With the function renamed to TemporalDegrain2 it should also be easier to compare to v1)
I didn't bother uploading screenshots with TemporalDegrain2(meTM=true) as the blurring always increased. It appears to have been true for the last version of the script. Were there any other changes aside from making meTM=false the default? It seems to be better now.
Two of the screenshots are the same frames as before, although this time the screenshots are taken directly from the script output and I increased QTGMC's noise removal a bit as I think it had an advantage there.
The new screenshot is of Val Kilmer's face as he was moving a little. Often the blurring of detail on someone's skin increases dramatically when they move, but it seems to be on a par with QTGMC now. There's a halo above the brim of his hat on the left side. It's in the source but largely hidden by noise. If there's an existing halo, QTGMC sometimes enhances it more than I'd like. TemporalDegrain2 enhanced it too, but so far, not quite as much.
QTGMC 3.357s takes functionality from SMDegrain to expand the levels to full range. I think it's only used for the motion search. The idea is to make it more accurate, but I don't know how much difference it makes. Any thoughts there?
Rather than upload 15 screenshots and post thumbnail links, here's a zip file.
Screenshots.zip (https://bayfiles.com/u8733ajcb0/Screenshots_zip) (13.1MB)
StainlessS
21st October 2018, 13:30
Another moderator suggested using "Report Post", to report where new attachment requires approval,
Report Post is found below avatar of the offending post as Red triangle with ! symbol inside.
ErazorTT
21st October 2018, 22:50
Were there any other changes aside from making meTM=false the default?
Setting truemotion to false was the only functional change.
It seems to be better now.
Thats really awesome! I pretty much forgot that truemotion switch in MVTools. So, huge thanks for you screenshots. Looking at those and comparing back and forth with the ones from QTGMC somehow reminded me of that again.
QTGMC 3.357s takes functionality from SMDegrain to expand the levels to full range. I think it's only used for the motion search. The idea is to make it more accurate, but I don't know how much difference it makes. Any thoughts there?
Hm I will have to analyze that. Right off the top of my head I do not know what exactly you mean. I will look into the code and come back if I see something.
hello_hello
22nd October 2018, 06:30
Hm I will have to analyze that. Right off the top of my head I do not know what exactly you mean. I will look into the code and come back if I see something.
It expands levels from TV range to PC range for the MSuper clip. I don't know how much difference it makes. Have a look under line #187 here.
https://pastebin.com/u1xsPLwK
# Default Auto-Prefilter - Luma expansion TV->PC (up to 16% more values for motion estimation)
Maybe now I understand why I've always thought SMDegrain and other mvtools2 based denoising scripts blur too much when there's motion. A quick look at the SMDegrain script indicates TrueMotion is disabled by default for resolutions above standard definition (although it still blurs more than QTGMC), and it's enabled by default for mvtools2 itself.
It's disabled by default for MCTemporalDenoise and MCTemporalDenoiseMod (MCTD), so maybe that's why they tend to blur less (from memory, I haven't used them for a while).
I hadn't played with the TrueMotion option myself until now.
Cheers.
StainlessS
22nd October 2018, 17:12
Blurring (I believe) occurs where vectors are not so good and done to hide problems/errors.
This script function deliberately blurs bad areas and sharpens good areas, I use it one helluva lot, for almost every encode.
McDegrainSharp:- https://forum.doom9.org/showthread.php?p=1737045#post1737045
EDIT: I usually use Frames=1(default, EDIT: well usually all defaulted).
EDIT:
Function MCDegrainSharp(clip c, int "frames", float "bblur", float "csharp", bool "bsrch",bool "Precise") {
# From:- http://forum.doom9.org/showthread.php?p=1737045#post1737045
# Based on MCDegrain By Didee, http://forum.doom9.org/showthread.php?t=161594
# Also based on DiDee observations in this thread: http://forum.doom9.org/showthread.php?t=161580
# "Denoise with MDegrainX, do slight sharpening where motionmatch is good, do slight blurring where motionmatch is bad"
# In areas where MAnalyse cannot find good matches, the blur() will be dominant.
# In areas where good matches are found, the sharpen()'ed pixels will overweight the blur()'ed pixels
# when the pixel averaging is performed.
#
gispos
22nd October 2018, 19:01
The code uses Undot() but is not specified in the required plugins.
Is there an x64 version of Undot.dll?
I just deleted the line with Undot() :)
thanks
ErazorTT
23rd October 2018, 00:32
@gispos
yes, right thanks for spotting that!
I know that there is a 64bits undot.dll coming with the 64bit MeGui. Which you can get here (https://sourceforge.net/projects/megui/files/megui-test/). But I do not know where they have that from, I would guess they have compiled it themselves. Or does someone know where to get a 64bit undot.dll from?
Anyways, I have put the call to undot after a check that this function actually exists using FunctionExists. Checkout the newest version 2.0.2.
ChaosKing
23rd October 2018, 00:42
Undot == RemoveGrain(mode=1), just replace it
ErazorTT
23rd October 2018, 00:55
@ChaosKing
that was quick and easy, great!
==> checkout new version 2.0.3
hello_hello
24th October 2018, 03:00
Blurring (I believe) occurs where vectors are not so good and done to hide problems/errors.
This script function deliberately blurs bad areas and sharpens good areas, I use it one helluva lot, for almost every encode.
McDegrainSharp:- https://forum.doom9.org/showthread.php?p=1737045#post1737045
I added the TrueMotion argument to MCDegrainSharp where appropriate so I could compare the result with Truemotion enabled and disabled. I don't know if other arguments should have different defaults when it's disabled, but it did make a difference. Not so much for the first frame from post #9, probably because the McDegrainSharp defaults don't remove as much noise as TemporalDegrain does by default, however for the third frame disabling TrueMotion seems like an improvement.
Original
https://i.postimg.cc/XpDnbSrw/3-original.png (https://postimg.cc/XpDnbSrw)
MCDegrainSharp(TrueMotion=false)
https://i.postimg.cc/sv23qDgj/3-false.png (https://postimg.cc/sv23qDgj)
MCDegrainSharp(TrueMotion=true)
https://i.postimg.cc/8sNpdb8r/3-true.png (https://postimg.cc/8sNpdb8r)
As a side note, I assume not too many people are using the FastDegrain script. The version here (http://avisynth.nl/images/FastDegrain.avs) (there's a link for it at the bottom of the TemporalDegrain page (http://avisynth.nl/index.php/Temporal_Degrain)), has an incorrect list of required plugins, the "overshoot=oshot" argument for the LimitedSharpenFaster function should be "overshoot=oshoot", and the MDegrain functions don't include the thSAD option.
The only other versions of the script I could find are here (https://forum.doom9.org/showthread.php?p=1368199#post1368199) and they're the same.
StainlessS
24th October 2018, 08:50
disabling TrueMotion seems like an improvement.
That is a surprise, TrueMotion = true has been MvTools default since v1.4.10.
As TrueMotion is a group setting for some other args, might be interesting to see what Zorr's Avisynth Optimizer thing makes of it (altering individual args).
TemporalDegrain perhaps has higher frame range than McDegrainSharp which uses only 1 frame range by default[EDIT: Actually 2], I like only
a light touch and so am usually happy with single frame range.
YouTube DarkHorse musvid clip is quite amazing video, but adjusting levels to produce 16->235 (think was maybe ~16->255), and applying
McDegrainSharp(frames=1) and NonlinUSM(z=3, pow=1.1, str=0.25, rad=9) or thereabouts produced a clip that knocked the socks off
the YT effort, but demands about 50% higher bitrate than original. (I think I may also have added a very light FFT3DFilter(sigma=1.5) or thereabouts after
the degrain).
Wonder how TemporalDegrain would fair in comparison.
ErazorTT
24th October 2018, 09:54
That is a surprise, TrueMotion = true has been MvTools default since v1.4.10.
In QTGMC it is however disabled by default. so perhaps due to the same reason...
Groucho2004
24th October 2018, 10:43
That is a surprise, TrueMotion = true has been MvTools default since v1.4.10.
Didée (https://forum.doom9.org/showthread.php?p=1407409&highlight=truemotion#post1407409) apparently was never a big fan of this parameter in a denoising context.
StainlessS
24th October 2018, 11:32
And would HD resolution in this case be as anything with width > 1100 or height > 600 as sort of agreed upon in another thread.
Any argument there.
EDIT: Changed '>' to '>=' above.
EDIT: NOPE, had it right the first time, width > 1100 or height > 600
EDIT: And larger block size be about 24 and above.
hello_hello
24th October 2018, 13:48
That is a surprise, TrueMotion = true has been MvTools default since v1.4.10.
Best as I can tell QTGMC uses the default values for options changed by TrueMotion when TrueMotion=true.
When TrueMotion=false two options are set to values other than the MVTools2 defaults. They're lambda and pnew.
I added them to the MCDegrainSharp script but the difference is quite small, and after looking at a bunch of frames I decided the MVTools2 defaults were probably better, at least for MCDegrainSharp. I'll try the same with TemporalDegrain2 later.
Anyhow... here's a version of MCDegrainSharp with TrueMotion disabled. The lambda and pnew defaults when TrueMotion=false are easy to change if you want to try them yourself.
# ========== MCDegrainSharp =====================================================
#
# From: http://forum.doom9.org/showthread.php?p=1737045#post1737045
# Based on MCDegrain By Didee:
# http://forum.doom9.org/showthread.php?t=161594
# Also based on Didee observations in this thread:
# http://forum.doom9.org/showthread.php?t=161580
# Denoise with MDegrainX, do slight sharpening where motionmatch is good,
# do slight blurring where motionmatch is bad.
# In areas where MAnalyse cannot find good matches, the blur() will be dominant.
# In areas where good matches are found, the sharpen()'ed pixels will
# overweight the blur()'ed pixels when the pixel averaging is performed.
#
# 3 Sept 2015 - Mod by StainlessS to add Precise.
# 24 Oct 2018 - Mod by Hello_Hello to disable TrueMotion by default.
# https://forum.doom9.org/showthread.php?p=1855907#post1855907
#
# ===============================================================================
function MCDegrainSharp(clip c, int "frames", float "bblur", float "csharp", bool "bsrch", bool "precise", \
bool "truemotion", int "lambda", int "pnew") {
frames = default(frames, 2)
bblur = default(bblur, 0.6)
csharp = default(csharp, 0.6)
bsrch = default(bsrch, true)
precise = default(precise, false) # Use MRecalculate
truemotion = default(truemotion, false)
bs = (c.width() > 960) ? 16 : 8
c2 = c.blur(bblur)
# Uncommenting the two lines below results in the same truemotion settings as QTGMC when truemotion=false
# lambda = default(lambda, (truemotion ? 1000 : 100 ) * BSize * BSize / 64)
# pnew = default(pnew, truemotion ? 50 : 25)
# Only 1 level required for sharpened Super (not MAnalyse-ing)
super = (frames > 0) ? (bsrch ? c2.MSuper(pel=2, sharp=1) : c.MSuper(pel=2, sharp=1)) : nop()
super_rend = (frames > 0) ? (c.sharpen(csharp).MSuper(pel=2, sharp=1, levels=1)) : nop()
bvec3 = \
(frames > 2) ? MAnalyse(super, isb=true, delta=3, blksize=bs, overlap=bs/2, \
truemotion=truemotion, lambda=lambda, pnew=pnew) : nop()
bvec2 = \
(frames > 1) ? MAnalyse(super, isb=true, delta=2, blksize=bs, overlap=bs/2, \
truemotion=truemotion, lambda=lambda, pnew=pnew) : nop()
bvec1 = \
(frames > 0) ? MAnalyse(super, isb=true, delta=1, blksize=bs, overlap=bs/2, \
truemotion=truemotion, lambda=lambda, pnew=pnew) : nop()
fvec1 = \
(frames > 0) ? MAnalyse(super, isb=false, delta=1, blksize=bs, overlap=bs/2, \
truemotion=truemotion, lambda=lambda, pnew=pnew) : nop()
fvec2 = \
(frames > 1) ? MAnalyse(super, isb=false, delta=2, blksize=bs, overlap=bs/2, \
truemotion=truemotion, lambda=lambda, pnew=pnew) : nop()
fvec3 = \
(frames > 2) ? MAnalyse(super, isb=false, delta=3, blksize=bs, overlap=bs/2, \
truemotion=truemotion, lambda=lambda, pnew=pnew) : nop()
# If Precise, then recalculate on Prefiltered (blurred) Super (NOT the sharpened render super)
bvec3 = \
(frames > 2) ? (!Precise ? bvec3 : \
MRecalculate(super, bvec3, blksize=bs/2, overlap=bs/4, thSAD=100, \
truemotion=truemotion, lambda=lambda, pnew=pnew)) : nop()
bvec2 = \
(frames > 1) ? (!Precise ? bvec2 : \
MRecalculate(super, bvec2, blksize=bs/2, overlap=bs/4, thSAD=100, \
truemotion=truemotion, lambda=lambda, pnew=pnew)) : nop()
bvec1 = \
(frames > 0) ? (!Precise ? bvec1 : \
MRecalculate(super, bvec1, blksize=bs/2, overlap=bs/4, thSAD=100, \
truemotion=truemotion, lambda=lambda, pnew=pnew)) : nop()
fvec1 = \
(frames > 0) ? (!Precise ? fvec1 : \
MRecalculate(super, fvec1, blksize=bs/2, overlap=bs/4, thSAD=100, \
truemotion=truemotion, lambda=lambda, pnew=pnew)) : nop()
fvec2 = \
(frames > 1) ? (!Precise ? fvec2 : \
MRecalculate(super, fvec2, blksize=bs/2, overlap=bs/4, thSAD=100, \
truemotion=truemotion, lambda=lambda, pnew=pnew)) : nop()
fvec3 = \
(frames > 2) ? (!Precise ? fvec3 : \
MRecalculate(super, fvec3, blksize=bs/2, overlap=bs/4, thSAD=100, \
truemotion=truemotion, lambda=lambda, pnew=pnew)) : nop()
return (frames == 0) ? c : \
(frames == 1) ? c2.MDegrain1(super_rend, bvec1, fvec1, thSAD=400) : \
(frames == 2) ? c2.MDegrain2(super_rend, bvec1, fvec1, bvec2, fvec2, thSAD=400) : \
c2.MDegrain3(super_rend, bvec1, fvec1, bvec2, fvec2, bvec3, fvec3, thSAD=400) }
# ===============================================================================
zorr
25th October 2018, 22:26
As TrueMotion is a group setting for some other args, might be interesting to see what Zorr's Avisynth Optimizer thing makes of it (altering individual args).
Sure! The challenge is coming up with an objective and reliable way to measure the quality of the grain removal. I gave it some thought and came up with something that may work...
So first we need to be able to calculate the "graininess" of the frame. Some googling and I found this (https://stackoverflow.com/a/25436112), which looks like something that is possible to implement in Avisynth using MaskTools. I'm not sure about how to sum the pixel values after convolution though, perhaps by doing recursive bilinear downscaling in 16bit or 32bit per pixel colorspace in order not to lose too much precision. And hopefully there's a way to read a single pixel's color value into a script variable.
We also need another criteria, if we only measure graininess and consider it bad then the optimizer is going to find the blurriest image possible... :) We could measure the maximum absolute pixel color difference to the original unprocessed frame based on the idea that the degraining should not make a picture that has large deviations from the original.
With these two measurements the optimizer can create a two dimensional pareto front. After the optimizer is done a human would see which of the pareto front members is the best compromise. That would be a fun experiment to try... can anyone help me with the graininess measurement?
StainlessS
25th October 2018, 23:34
Unfortunately RT_Stats is only 8 bit and only really for Luma Y or RGB, I have no idea how 16/32 bit works in Avs+, never touched the stuff.
No idea how to force convert to some kind of 16->8 Least Significant Byte, Most significant Byte format so that RT could be used.
EDIT: Here are available COMBINED functions for Y, each func available as individual function as well. [down to single 8 bit pixel]
RT_Ystats(clip c,int "n"=current_frame,int "delta"=0,int "x"=0,int "y"=0,int "w"=0,int "h"=0,bool "interlaced"=false,
float "threshold"=0.0,int "lo"=128,int "hi"=lo,int "flgs"=255,string "prefix"="YS_",
float "mu"=0.0,int "d"=1,int "p"=1,int "u"=1, int "Matrix"=(Width>1100||Height>600?3:2),clip "mask"=NOT_USED,int "MaskMin"=128,"MaskMax"=255)
Returns multiple results as for above single frame Luma sampling functions as Local Variables (prefixed with the prefix string arg).
The args up to "interlaced", are as for all other clip functions, "threshold" used only for "RT_YPlaneMin", "RT_YPlaneMax" and
"RT_YPlaneMinMaxDifference" equivalent routines with same functionality.
"lo" and "hi" are used only with the "RT_YInRange" equivalent routine with same functionality.
"mu" and "d" and "p" and "u" are used only with the "RT_YPNorm" equivalent routine with same functionality.
The new arg "Flgs" selects which results you want returned and the string "Prefix" that is prepended
to the returned Local variable names.
The actual return result is a copy of the flgs arg with any non valid bits reset, ie the Local variables that were set.
Local variables are NOT altered for any function not selected in flgs.
Returns 0 if no pixels found in search area of mask within MaskMin and MaskMax.
Flgs_Bit_Number Add_To_Flgs Equivalent_Function Local_Var_Set_Excluding_Prefix
0 1($01) RT_YPlaneMin() "yMin" (0->255)
1 2($02) RT_YPlaneMax() "yMax" (0->255)
2 4($04) RT_YPlaneMinMaxDifference() "yMinMaxDiff" (0->255)
3 8($08) RT_YPlaneMedian() "yMed" (0->255)
4 16($10) RT_AverageLuma() "yAve" (0.0->255.0)
5 32($20) RT_YPlaneStdev() "yStdev" (0.0->255.0)
6 64($40) RT_YInRange() "yInRng" (0.0->1.0)
7 128($80) RT_YPNorm() "yPNorm" (0.0->??? depends upon d and u)
RT_Ystats() allows you to inquire multiple results simultaneously, with not much more overhead than calling a single individual
routine, however, you should not select sub functions that you dont need as there may be an additional unnecessary overhead.
The Default flgs=255($FF) are all bits set and so sets ALL Local vars at once.
RT_Ystats(flgs=1+2+16) would set Local vars "YS_yMin", "YS_yMax" and "YS_yAve" for full frame current_frame.
In addition to above Local Variables, RT_YStats() sets an int Local variable (where default prefix) of "YS_PixelCount" being
the number of pixels in mask area X,Y,W,H between MaskMin and MaskMax inclusive, or pixels scanned in X,Y,W,H area where mask
not used.
NOTE, If no valid flg bits set (eg $FF00), then returns 0, YS_PixelCount and all other variables remain as before call.
Assuming some valid flg bits, if no valid pixels were found in mask then function returns 0, and only YS_PixelCount would be set
to 0, no other variables are touched (remain as before call, undefined if not previously existing).
Example usage:
ScriptClip("""
got = RT_Ystats(c,mask=Mask,flgs=$10) # AverageLuma
(got != 0) ? RT_debug("AverageLuma = " + String(YS_yAve) + "PixelCount = " + String(YS_PixelCount)) : RT_Debug("NO VALID PIXELS FOUND")
""")
RT_YPNorm, is a weird one as requested by martin53, [below is the individual routine, also available in above combined results routine]
RT_YPNorm(clip c,int "n"=current_frame,int "delta"=0,int "x"=0,int "y"=0,int "w"=0,int "h"=0,bool "interlaced"=false,
float "mu"=0.0,int "d"=1,int "p"=1,int "u"=1,int "Matrix"=(Width>1100||Height>600?3:2),clip "mask"=NOT_USED,int "MaskMin"=128,"MaskMax"=255)
Return int -1 if no valid pixels in Mask clip.
Returns FLOAT value greater or equal to 0.0, being the "Minkowski P-norm" (range depends upon values of 'd' and 'u') for frame(n+delta)
area x,y,w,h.
mu, Float, default 0.0 (0.0 -> 255.0)
d, int, default 1 (1 -> 255) # downscale
p, int, default 1 (1 -> 16) # power
u, int, default 1 (1 -> 255) # final upscale before returning result (experimental)
Formula is: sum_over_pixels[ ((pixel-mu)/d)^p ]^(1/p) * u
or in words: d and u are scaling aids. The differences between the pixel values and mu are scaled, taken to the power of p and added up
over the frame. The sum is taken to the p-th root and finally rescaled.
mu=0, d=1, p=1, u=1 yields the average.
mu=average, d=1, p=2, u=1 yields the standard deviation (uncorrected sample standard deviation).
Implemented as requested by Martin53 (thankyou). *** EXPERIMENTAL ***
http://en.wikipedia.org/wiki/P-norm#The_p-norm_in_finite_dimensions
http://en.wikipedia.org/wiki/Minkowski_distance
EDIT: Fastest will be RT_AverageLuma (even for single pixel, but with int result as float 0.0->255.0, ie no fractional part), as others create count arrays,
whereas RT_AverageLuma sums on-the-fly [same for combined RT_YStats where AverageLuma is sole requested result].
ErazorTT
26th October 2018, 01:45
@zorr: I guess the easiest AND most precise way would be to start with a very clean clip, add noise to it and use this as input for the denoiser. The output of the denoiser and the original ground truth are than be subtracted pixel by pixel. Finally all the pixel differences are summed frame by frame. The best denoiser setting will have smallest departure from the original.
For this to work there is thus no need for any measure of noise/grain. Just summing up the difference of all pixels in a frame gives the answer.
StainlessS
26th October 2018, 01:57
Good suggestion methinks.
Would Tears Of Steel be a good test source, with both live and CGI content.
Source from Avisynth Usage Forum Sticky, "Consolidated list of test video clip resources",
https://media.xiph.org/
We have a lossless version of the short film Tears of Steel. (17620 frames 2.40:1)
[ y4m 4k (67 GB compressed) ]
[ png 1920x800 (30 GB) ]
[ tiff 4k 16 bit (598 GB) ]
[ flac stereo (80 MB) | 5.1 surround (331 MB) ]
[ exr frames by scene (226 GB) | cleaned footage (330 GB) | raw footage (4 TB) ]
Bit big mind you. Could probably find shorter smaller sequence somewhere on net.
Some Lossy Compressed Versions, various compression / sizes:- https://mango.blender.org/download/
EDIT: Maybe someone already has big download and could spare a 30 second snippit for testing.
VoodooFX
26th October 2018, 05:02
And now the comparison of why I think it was time for an improved motion estimation over v1 of TemproralDegrain.
original from Breaking Bad s1e1, the camera moves following the car:
https://i.postimg.cc/YhVMBphg/9895-org.jpg (https://postimg.cc/YhVMBphg)
v1.23: TemporalDegrain(degrain=2)
https://i.postimg.cc/ThNXnRjS/9895-v123.jpg (https://postimg.cc/ThNXnRjS)
The motion of the low contrast tarmac is not captured well and thus the details are being washed away.
v2.03: TemporalDegrain2(degrainTR=2)
https://i.postimg.cc/yW8ywBq7/9895-v201.jpg (https://postimg.cc/yW8ywBq7)
More of the details of the tarmac are preserved.
Very nice overall improvement. Why v2.03 fails on this part?:
original vs v1.23 vs v2.03
https://images2.imgbox.com/be/ce/oImXS8ZF_o.png
ErazorTT
26th October 2018, 20:54
@VoodooFX
This one is tricky, since it results from the motion estimation I took from QTGMC. I tried to tweak the motion estimation in a way to improve the detection of moving fine detail as the rim in this example but without putting either the motion detection of big objects or the degraining/denoising at risk.
original, v1.23, v2.03, v2.10
https://i.postimg.cc/3JzS9RtZ/comp.jpg
As you can see v2.10 has gotten a little better when compared to v2.03 however it cannot match the detail of v1.23 in this case.
I would consider this issue a corner case, since there are a couple of factors driving this: the very fast movement of this detail, the total time the detail is visible and its size.
VoodooFX
27th October 2018, 00:48
Not the same as v1.23, but still huge improvement. Fast moving details not that important so better not to compromise with slow moving or static details.
tormento
28th October 2018, 10:58
Strangely enough I get the following error, both in VirtualDub2 and in Simple x264 launcher:
[2018-10-28][10:56:47] error: Script error: There is no function named 'ConvertToStacked'.
[2018-10-28][10:56:47] (D:/Programmi/Media/AviSynth+/plugins64/TemporalDegrain-2.1.1—ErazorTT.avsi, line 236)
My script:
SetMemoryMax(8000)
SetFilterMTMode("DEFAULT_MT_MODE", 2)
LoadPlugin("D:\eseguibili\media\DGDecNV\x64\DGDecodeNV.dll")
DGSource("E:\in\2_01 sacrificio del cervo sacro, Il\sacrificio.dgi")
CompTest(1)
TemporalDegrain2(degrainTR=4,postFFT=4,postSigma=3,postDither=-1)
Prefetch(6)
EDIT: solved.
ErazorTT
28th October 2018, 21:49
You will need Avisynth+ in a recent version.
hello_hello
29th October 2018, 03:56
Out of curiosity, which settings require Avisynth+? The defaults run fine on "classic" Avisynth.
RieGo
29th October 2018, 13:22
Very nice script. Well documented and easy to tune. nice job.
Thank you very much for this!
StainlessS
29th October 2018, 18:13
ErazorTT, report post #1 as having "waiting approval of attachment", or post on some file host eg PasteBin.
(or maybe this post will do it).
tormento
29th October 2018, 18:18
You will need Avisynth+ in a recent version.
Problem solved, now I have this:
[2018-10-29][18:16:26] error: ConvertToStacked: Input clip must be native 16 bit: YUV420P16, YUV422P16, YUV444P16, Y16 :p
Taurus
29th October 2018, 18:57
Out of curiosity, which settings require Avisynth+? The defaults run fine on "classic" Avisynth.
Here the same.
The only setting I could not get working was postFFT=4.
As far as I understand this will enable KNLMeansCL.
KNLMeansCL itself runs rockstable on this machine.
Groucho2004's AVSMeter silently crashes, preview on MPC-HC hangs and closes.
Virtualdub shows this:
https://i.postimg.cc/3R4NZTds/Crash.png (https://postimages.org/)
FFT3DGPU (aka postFFT=2) runs fine without any multithreading
in the script.
I think it's because I'm on avisynth 2.6.06 32bit and the script is calling for a stacked format.
But nevermind the only denoisers/degrainers I'm using are dfttest (aka postFFT=3) or FFT3DFilter (aka postFFT=1)
and they both are doing fine.
This was just for information and feedback.
Right now I'm struggeling with the settings compared to good ol TemporalDegrain.
I have used it quite a bit some years ago and made some templates of my favorit settings. But my memory is leaking about each knob and bells and whistles.
So I have to refresh my thinking and start a new.
Thanks for maintaining this wonderful script.
It saved my life a few times in the past ;):D
ErazorTT
29th October 2018, 23:05
@tormento, what are the exact parameters you are trying to use? This would help to figure out whats going on.
ErazorTT
29th October 2018, 23:33
@Taurus
Well I would actually suggest to not try to copy over the old setting used for TemporalDegrain v1.23, since the settings have changed considerably.
As a starting point I would use the recommended 5 step procedure together with the 5 parameters, which both are mentioned in the comments inside the script.
Only if one is willing to spend hours in testing should one start reviewing other settings. In which case however it would be great if people shared their findings!
Taurus
30th October 2018, 09:02
@Taurus
Well I would actually suggest to not try to copy over the old setting used for TemporalDegrain v1.23, since the settings have changed considerably.
As a starting point I would use the recommended 5 step procedure together with the 5 parameters, which both are mentioned in the comments inside the script.
Only if one is willing to spend hours in testing should one start reviewing other settings. In which case however it would be great if people shared their findings!
No,no,
I'm not copying the settings from old temporalgrain to v2!
I'm just comparing the final outcome of my old tweaked and approved temporalgrain settings with your suggested settings in new v2.
But because I forgot almost everything about good old temporalgrain, I have to rebuild a testing environment from scratch and start all over again :mad: .
But your attempt looks real promising.
Really appreciated.
tormento
30th October 2018, 17:33
@tormento, what are the exact parameters you are trying to use? This would help to figure out whats going on.
Here (https://forum.doom9.org/showthread.php?p=1856262#post1856262).
P.S: There is no reference to dfttest neither in the required plugins nor in the optional ones.
Taurus
30th October 2018, 18:27
Here (https://forum.doom9.org/showthread.php?p=1856262#post1856262).
P.S: There is no reference to dfttest neither in the required plugins nor in the optional ones.
You are right, dfttest is not mentioned in the top lines of the temporaldegrain2 script.
But a few lines down ErazorTT explains exactly what and why you should use for postFFT=3 (dfttest).
Just verified with process exlorer: dfttestdll and dither.dll are correctly loaded when postFFT=3 is enabled.
Maybe ErazorTT should update the dependency list a little.....
vBulletin® v3.8.11, Copyright ©2000-2026, vBulletin Solutions Inc.