View Full Version : Oyster, placebo compression artifacts buster
feisty2
16th February 2017, 13:38
Post your full script
Jindadil007
16th February 2017, 13:40
Post your full script
import vapoursynth as vs
import adjust
import Vine
import Oyster
import mvmulti
import finesharp
import havsfunc as haf
import mvsfunc as mvf
core = vs.get_core()
core.max_cache_size = 12000
video = core.lsmas.LWLibavSource(r'C:\DVD\Sample\Vine.mkv')
video = core.fmtc.bitdepth(video,bits=32,fulls=False,fulld=True)
y = core.std.ShufflePlanes(video,0,vs.GRAY)
y = Oyster.Basic(y, super=None, radius=6, pel=4, sad=2000.0, short_time=False)
video = core.std.ShufflePlanes([y,video], [0,1,2], vs.YUV)
video = core.fmtc.bitdepth(video,bits=8,fulls=False,fulld=True)
video.set_output()
feisty2
16th February 2017, 13:44
Read the documentation of fmtconv then you'll know the answer, Oyster has nothing to do with your problem
Key words: fulls fulld
Jindadil007
16th February 2017, 13:55
Read the documentation of fmtconv then you'll know the answer, Oyster has nothing to do with your problem
Key words: fulls fulld
Many Thanks...Read the documentation...Changed fulld to TV Range=False and it did the trick...:thanks:
Cary Knoop
20th February 2017, 07:02
Hello,
I tried to use Oyster on a de-interlaced PAL clip (768x576), and it failed with :
Failed to evaluate the script:
Python exception: BlankClip: color value out of range
Traceback (most recent call last):
File "src\cython\vapoursynth.pyx", line 1712, in vapoursynth.vpy_evaluateScript (src\cython\vapoursynth.c:34991)
File "C:/Video/Ori/Capture OK/WES-2003/WES 2003.vpy", line 167, in
y= Oyster.Destaircase(src, ref)
File "C:\Program Files\Python36\lib\site-packages\Oyster.py", line 383, in Destaircase
thr, elast, lowpass, matrix)
File "C:\Program Files\Python36\lib\site-packages\Oyster.py", line 173, in destaircase
mask = core.GenBlockMask(core.ShufflePlanes(src, 0, vs.GRAY))
File "C:\Program Files\Python36\lib\site-packages\Oyster.py", line 89, in GenBlockMask
clip = self.BlankClip(src, 24, 24, color=0.0)
File "src\cython\vapoursynth.pyx", line 1604, in vapoursynth.Function.__call__ (src\cython\vapoursynth.c:33131)
vapoursynth.Error: BlankClip: color value out of range
I just encountered exactly the same error. Any hint as to what might be the problem?
Oyster is called in the following way:
clip = core.fmtc.bitdepth(c, bits=32, fulls=False, fulld=False)
y = core.std.ShufflePlanes(clip, 0, vs.GRAY)
ref = Oyster.Basic(y, Oyster.Super(y))
y = Oyster.Deblocking(y, ref, block_step=2)
y = Oyster.Deringing(y, ref, sigma=24.0, h=10.8, block_step=2)
clip = core.std.ShufflePlanes([y, clip], [0, 1, 2], vs.YUV)
feisty2
22nd February 2017, 09:01
I just encountered exactly the same error. Any hint as to what might be the problem?
Oyster is called in the following way:
clip = core.fmtc.bitdepth(c, bits=32, fulls=False, fulld=False)
y = core.std.ShufflePlanes(clip, 0, vs.GRAY)
ref = Oyster.Basic(y, Oyster.Super(y))
y = Oyster.Deblocking(y, ref, block_step=2)
y = Oyster.Deringing(y, ref, sigma=24.0, h=10.8, block_step=2)
clip = core.std.ShufflePlanes([y, clip], [0, 1, 2], vs.YUV)
I got 2 things to say here,
1. before the next release of KNLMeansCL, please manually change line 67 to
nlm = self.KNLMeansCL(pad, d=d, a=a, s=s, h=h * math.sqrt(3), channels="YUV" if color else "Y", wref=1.0, rclip=rclip)
to fix a bug introduced in v1.0 (https://forum.doom9.org/showpost.php?p=1797511&postcount=1134)
2. what version of vaporsynth are you using? (the latest one?), will it work if you comment out "Oyster.Deringing"?
Are_
22nd February 2017, 10:35
Using VapourSynth and Oyster at current git.
Deblocking, Deringin, Destaircase, anything triggers this bug.
Even this script raises an error:
import vapoursynth as vs
core = vs.get_core()
clip = core.std.BlankClip(format=vs.GRAYS, color=0.0)
clip.set_output()
And I'm not sure anything should be wrong there.
Also documentation being so scarce on BlankClip does not help either.
So welp, I'm pretty sure the bug is in VapourSynth, maybe I will fill a bug if I gather the strength to do it. :/
EDIT: Hohum, same problem with vapoursynth-36, now I'm not sure anymore about anything.
jackoneill
22nd February 2017, 11:52
Using VapourSynth and Oyster at current git.
Deblocking, Deringin, Destaircase, anything triggers this bug.
Even this script raises an error:
import vapoursynth as vs
core = vs.get_core()
clip = core.std.BlankClip(format=vs.GRAYS, color=0.0)
clip.set_output()
And I'm not sure anything should be wrong there.
Also documentation being so scarce on BlankClip does not help either.
So welp, I'm pretty sure the bug is in VapourSynth, maybe I will fill a bug if I gather the strength to do it. :/
EDIT: Hohum, same problem with vapoursynth-36, now I'm not sure anymore about anything.
What's missing from the documentation? I can fix that.
feisty2
22nd February 2017, 11:59
Using VapourSynth and Oyster at current git.
Deblocking, Deringin, Destaircase, anything triggers this bug.
Even this script raises an error:
import vapoursynth as vs
core = vs.get_core()
clip = core.std.BlankClip(format=vs.GRAYS, color=0.0)
clip.set_output()
And I'm not sure anything should be wrong there.
Also documentation being so scarce on BlankClip does not help either.
So welp, I'm pretty sure the bug is in VapourSynth, maybe I will fill a bug if I gather the strength to do it. :/
EDIT: Hohum, same problem with vapoursynth-36, now I'm not sure anymore about anything.
http://i.imgur.com/nWnCbCG.png
that's weird cuz I couldn't reproduce the error..
maybe just a bug exclusive to Linux vaporsynth?
Are_
22nd February 2017, 12:17
What's missing from the documentation? I can fix that.
Well, I expected color to be a float from the documentation, but the error got me confused about the actual allowed range for it. Maybe saying something like it mapping to the format range and if chroma in float formats maps to -0.5 too. If bugs didn't exist this will be not a problem, though.
Are_
22nd February 2017, 12:19
that's weird cuz I couldn't reproduce the error..
maybe just a bug exclusive to Linux vaporsynth?
Then it looks like this was a bug introduced in R36 for posix targets https://github.com/vapoursynth/vapoursynth/issues/290
Cary Knoop
24th February 2017, 02:45
I got 2 things to say here,
1. before the next release of KNLMeansCL, please manually change line 67 to
nlm = self.KNLMeansCL(pad, d=d, a=a, s=s, h=h * math.sqrt(3), channels="YUV" if color else "Y", wref=1.0, rclip=rclip)
to fix a bug introduced in v1.0 (https://forum.doom9.org/showpost.php?p=1797511&postcount=1134)
2. what version of vaporsynth are you using? (the latest one?), will it work if you comment out "Oyster.Deringing"?
Sorry for the late reply.
The error was found on Windows using:
Vapoursynth: R36
KNLMeansCL. 1.01
Jindadil007
25th February 2017, 09:15
Sorry for the late reply.
The error was found on Windows using:
Vapoursynth: R36
KNLMeansCL. 1.01
KNLMeansCL. 1.01 has a bug...Use version 0.7.7
feisty2
25th February 2017, 14:43
Sorry for the late reply.
The error was found on Windows using:
Vapoursynth: R36
KNLMeansCL. 1.01
I think that's a vaporsynth bug and there's really nothing I can do..
https://github.com/vapoursynth/vapoursynth/issues/290
Cary Knoop
25th February 2017, 18:03
KNLMeansCL. 1.01 has a bug...Use version 0.7.7
Which bug are you referring to?
I did not see any open bugs on GitHub.
Are_
25th February 2017, 18:15
h parameter is scaled differently, to have the same strength in 1.0.x you had in 0.7.x series you need to do h * math.sqrt(3) as feisty2 pointed out. The author knows about it and it will be solved in next release, probably.
Cary Knoop
25th February 2017, 20:04
h parameter is scaled differently, to have the same strength in 1.0.x you had in 0.7.x series you need to do h * math.sqrt(3) as feisty2 pointed out. The author knows about it and it will be solved in next release, probably.
The author should probably express his intent so others can anticipate, if it stays that way many scripts would have to be updated, if it is going to change then it is probably best to wait for 1.02.
Are_
25th February 2017, 20:09
He expressed it in his main thread, it's a bug introduced in 1.x.x series and will be fixed, eventually. :(
Tormaid
18th January 2018, 19:45
This script (taken from the "examples" section on the github page) is consistently crashing Vaporusynth for me. I'm running R42.1 and using the most up-to-date versions of all of the prerequisite filters and scripts, as far as I am aware. The one I'm not 100% sure about is the version of libfftw3-3.dll I got from this site (http://www.fftw.org/install/windows.html).
import vapoursynth as vs
import Oyster
core = vs.get_core()
v = core.ffms2.Source(r"clip.mp4")
v = core.fmtc.bitdepth(v, bits=32)
y = core.std.ShufflePlanes(v, 0, vs.GRAY)
sup = Oyster.Super(y)
ref_f = Oyster.Basic(y, sup, short_time=False)
ref_s = Oyster.Basic(y, sup, short_time=True)
y = Oyster.Destaircase(y, ref_f, sigma=24.0, block_step=2)
y = Oyster.Deringing(y, ref_s, sigma=24.0, h=9.6, block_step=2)
y.set_output()
It crashes whether I'm opening it in vsedit or directly using vspipe.
Edit: I've tested it on two different computers, both running Windows 10, and had the same results.
leon
1st February 2018, 01:47
When I try to import Oyster I get this error:
Traceback (most recent call last):
File "src\cython\vapoursynth.pyx", line 1841, in vapoursynth.vpy_evaluateScript
File "C:/Users/.../Desktop/Untitled.vpy", line 3, in
import Oyster
File "C:\Users\...\AppData\Local\Programs\Python\Python36\lib\site-packages\Oyster.py", line 3, in
import mvmulti
ModuleNotFoundError: No module named 'mvmulti'
What am I doing wrong ?
WolframRhodium
1st February 2018, 02:10
When I try to import Oyster I get this error:
Traceback (most recent call last):
File "src\cython\vapoursynth.pyx", line 1841, in vapoursynth.vpy_evaluateScript
File "C:/Users/Admin/Desktop/Untitled.vpy", line 3, in
import Oyster
File "C:\Users\Admin\AppData\Local\Programs\Python\Python36\lib\site-packages\Oyster.py", line 3, in
import mvmulti
ModuleNotFoundError: No module named 'mvmulti'
What am I doing wrong ?
https://github.com/IFeelBloated/vapoursynth-mvtools-sf/blob/master/src/mvmulti.py
leon
1st February 2018, 04:09
https://github.com/IFeelBloated/vapoursynth-mvtools-sf/blob/master/src/mvmulti.py
I'd tried that before posting but oddly it didn't work(maybe wrong folder).
It works now :thanks:
Max_143
6th February 2018, 15:07
vapoursynth-nnedi3-v11-win64.7z and nnedi3_weights.bin
I took here https://github.com/dubhater/vapoursynth-nnedi3
Script
sup = Oyster.Super(y)
ref_f = Oyster.Basic(y, sup, short_time=False)
ref_s = Oyster.Basic(y, sup, short_time=True)
y = Oyster.Destaircase(y, ref_f, sigma=24.0, block_step=2)
y = Oyster.Deringing(y, ref_s, sigma=24.0, h=9.6, block_step=2)
y.set_output()
I get an error
Failed to evaluate the script:
Python exception: nnedi3: 'D:/Instal/Video/Vapoursynth/Instal/python-3.6.4-embed-amd64/vapoursynth64/plugins/nnedi3_weights.bin' has the wrong size. Expected 13574928 bytes, got 41011 bytes.
Traceback (most recent call last):
File "src\cython\vapoursynth.pyx", line 1847, in vapoursynth.vpy_evaluateScript
File "D:/Klipy/Obrabotka/VsPipe/2/vs2.vpy", line 44, in
sup = Oyster.Super(y)
File "D:\Instal\Video\Vapoursynth\Instal\python-3.6.4-embed-amd64\Oyster.py", line 230, in Super
clip = internal.super(core, src, pel)
File "D:\Instal\Video\Vapoursynth\Instal\python-3.6.4-embed-amd64\Oyster.py", line 108, in super
clip = core.Transpose(core.NNEDI(core.Transpose(core.NNEDI(src, **nnedi_args)), **nnedi_args))
File "src\cython\vapoursynth.pyx", line 1739, in vapoursynth.Function.__call__
vapoursynth.Error: nnedi3: 'D:/Instal/Video/Vapoursynth/Instal/python-3.6.4-embed-amd64/vapoursynth64/plugins/nnedi3_weights.bin' has the wrong size. Expected 13574928 bytes, got 41011 bytes.
I need another file nnedi3_weights.bin or error in another?
(Windows 7 x64)
P.S.
thanks, figured out)
Cary Knoop
2nd September 2018, 04:52
This script is excellent, the default settings are great as well but I made some compromises for speed.
On a deinterlaced PAL video I am using this:
ref_s = Oyster.Basic(y, short_time=True, pel=4)
y = Oyster.Deringing(y, ref_s, radius=3, sigma=24.0, h=8, block_step=6)
It's slow, I get about 3 fps on using 45GB of memory.
Would be interesting to see if the Threadripper 2 can improve speed.
Using a Threadripper 1950X with 64GB of memory and a 1080TI GPU.
To improve speed could a GPU implementation of bm3d be of help? Especially when having multiple GPUs.
https://github.com/JeffOwOSun/gpu-bm3d
zorr
7th February 2019, 00:36
been hours and I tried like a million sets of parameters to investigate if there's any chance of quality-speed tradeoff, and, failed to get rid of the abysmal performance
...
I'm out of ideas of performance boost..
and also you HAVE TO create intermediate raw files for your process chain.
it will probably be hundreds times faster unless you have 1TB of RAM or so
I sped up one of my Avisynth processes by creating intermediate files for each phase (QTGMC -> SMDegrain -> other filters). It speeds up processing tremendously especially when using temporal filters. In theory the frames could be cached but perhaps there just isn't enough memory or maybe the caches are just too small.
Just wondering if doing that for the sub-processes inside Oyster functions would also give speedup. So for example Deblocking could make files between core.NLMeans and core.BMBasic etc. It would of course make calling the filters convoluted, you'd have to pass in a phase number and some extra input files and do the processing in multiple scripts. But I think it might be worth investigating if any speedup is possible that way.
asarian
6th March 2019, 01:11
Holy crap! This Oyster thing is wickedly good! :) Here's a sample from an old DVD of mine, called Old Enough (https://1drv.ms/u/s!AhSxhQ9g_mrMlgx9eSJeXQifBgvR). On the left is the restored image, on the right the original. Notice how extremely well the MPEG 'smudginess' has disappeared! (Look around the hair, for instance)
Oyster is not the fastest filter in the book, though. :)
asarian
6th March 2019, 06:42
I sped up one of my Avisynth processes by creating intermediate files for each phase (QTGMC -> SMDegrain -> other filters).
What kind of intermediate file-size are we talking about here? I tried a 'Super' intermediate pass, but ran out of hard disk space (Sic!) at several hundred G (for a 720x480p source).
zorr
6th March 2019, 10:55
What kind of intermediate file-size are we talking about here? I tried a 'Super' intermediate pass, but ran out of hard disk space (Sic!) at several hundred G (for a 720x480p source).
Im my case it was all 8bit and the clips were not that long. Super will need much more because it's 4x the resolution (assuming pel=4) and in 32bits per component. If you run out of hd space then maybe try to do the processing in segments. Also using a compressed (but still lossless) intermediate file such as FFV1 will help.
asarian
6th March 2019, 11:07
Im my case it was all 8bit and the clips were not that long. Super will need much more because it's 4x the resolution (assuming pel=4) and in 32bits per component. If you run out of hd space then maybe try to do the processing in segments. Also using a compressed (but still lossless) intermediate file such as FFV1 will help.
My 720x480p source was a full-length movie. :) So, a compressed output is good idea. :thanks:
poisondeathray
6th March 2019, 15:59
Holy crap! This Oyster thing is wickedly good! :) Here's a sample from an old DVD of mine, called Old Enough (https://1drv.ms/u/s!AhSxhQ9g_mrMlgx9eSJeXQifBgvR). On the left is the restored image, on the right the original. Notice how extremely well the MPEG 'smudginess' has disappeared! (Look around the hair, for instance)
Oyster is not the fastest filter in the book, though. :)
It does look impressive
One thing that stands out is the left cheek blemish - it looks over enhanced. Was that temporally consistent on other frames ? (or are you still waiting for it to finish processing other frames? :devil: :) )
asarian
7th March 2019, 02:10
It does look impressive
One thing that stands out is the left cheek blemish - it looks over enhanced. Was that temporally consistent on other frames ? (or are you still waiting for it to finish processing other frames? :devil: :) )
That left-cheek blemish was actually a small glitch, it seems, in the original video (only lasting 2 frames). So, good thing Oyster got rid of it. :)
As for still waiting, my poor i7 6700K is going to take 54 hours to complete the job. :scared:
Revan654
31st March 2019, 19:46
I've been trying to get Oyster to work, I always run into either Subsampling not support, which I can easily get around, But it's the whole Blocksize issue. I've tried many source but always run into the same issue. Anyone know what else needs to be added to get this to work?
Python exception: Analyze: the block size must be 4x4, 8x4, 8x8, 16x2, 16x8, 16x16, 32x16, or 32x32.
Example of the Script:
clip = core.fmtc.bitdepth( clip, bits = 32 )
clip = core.fmtc.resample( clip, css = "444" )
ref_s = Oyster.Basic(clip, short_time=True)
clip = Oyster.Deringing(clip, ref_s, block_step=2)
jackoneill
31st March 2019, 21:57
I've been trying to get Oyster to work, I always run into either Subsampling not support, which I can easily get around, But it's the whole Blocksize issue. I've tried many source but always run into the same issue. Anyone know what else needs to be added to get this to work?
Python exception: Analyze: the block size must be 4x4, 8x4, 8x8, 16x2, 16x8, 16x16, 32x16, or 32x32.
Example of the Script:
clip = core.fmtc.bitdepth( clip, bits = 32 )
clip = core.fmtc.resample( clip, css = "444" )
ref_s = Oyster.Basic(clip, short_time=True)
clip = Oyster.Deringing(clip, ref_s, block_step=2)
You have an old copy of MVTools or MVToolsSF. Update them to the latest and that error should go away.
SoupRKnowva
31st May 2020, 02:52
I have a question about doing the process in a series of steps rather than all in one go.
When i run my script and set the output as the results of Oyster.Basic(), using "vspipe exmaple.vpy example_basic.rgb", when i import it again on the second part with core.raws.Source("example_basic.rgb"), I get an error "TypeError: Oyster.Destaircase: the sample type of ref has to be single precision!"
At first i thought the autoloader was using the wrong mvtools, so i removed the non _sf version. Same problem. I tried using example.raw instead of example.rgb, thinking maybe vspipe or the importer were doing something weird. same problem.
But if i feel the output of Basic() straight into Oyster.Destaircase, without saving it out, it works just fine.
Is there something I am missing with writing the file with vspipe or with the import with raws.source()?
feisty2
31st May 2020, 06:52
as the error suggested, the input must be of fp32 sample type, you have to specify the sample type in core.raws.Source
Cary Knoop
7th July 2020, 07:08
Oyster is great but the performance is highly impractical.
Using a GPU-based BM3D implementation would put this slowly into the world of practicality (Optimizing KNLMeans for CUDA instead of CL would probably help as well).
Any updates on a BM3D implementation in CUDA?
Cary Knoop
18th July 2020, 20:36
What is function of sstring in Oyster.py?
43 def FreqMerge(self, low, hi, sbsize, sstring):
44 hif = self.MakeDiff(hi, self.DFTTest(hi, sbsize=sbsize, sstring=sstring, **dfttest_args))
45 clip = self.MergeDiff(self.DFTTest(low, sbsize=sbsize, sstring=sstring, **dfttest_args), hif)
Does this perhaps refer to an older version of DFTTest?
feisty2
19th July 2020, 02:01
things have been updated in the GitHub repo
Cary Knoop
19th July 2020, 02:37
things have been updated in the GitHub repo
Got it, thanks!
Emulgator
23rd January 2023, 10:18
2023, Oyster in VapourSynth R61:
I would welcome a helping tip towards replacement of depreciated function calls
I tried, but I am a VS noob, and I would welcome a full documentation...
I have hacked at Oyster.py but I get "SyntaxError: Invalid syntax for"
core = import core
Split in 2 parts (forum 16000 chars limit)
from vapoursynth import core
import math
fmtc_args = dict(fulls=True, fulld=True)
msuper_args = dict(hpad=0, vpad=0, sharp=2, levels=0)
manalyze_args = dict(search=3, truemotion=False, trymany=True, levels=0, badrange=-24, divide=0, dct=0)
mrecalculate_args = dict(truemotion=False, search=3, smooth=1, divide=0, dct=0)
mdegrain_args = dict(thscd1=16711680.0, thscd2=255.0)
nnedi_args = dict(field=1, dh=True, nns=4, qual=2, etype=1, nsize=0)
dfttest_args = dict(smode=0, sosize=0, tbsize=1, tosize=0, tmode=0)
class core:
def __init__(self):
self.core = vs.core()
self.MSuper = self.core.mvsf.Super
self.MAnalyze = self.core.mvsf.Analyze
self.MRecalculate = self.core.mvsf.Recalculate
self.MDegrain = self.core.mvsf.Degrain
self.RGB2OPP = self.core.bm3d.RGB2OPP
self.OPP2RGB = self.core.bm3d.OPP2RGB
self.BMBasic = self.core.bm3d.VBasic
self.BMFinal = self.core.bm3d.VFinal
self.Aggregate = self.core.bm3d.VAggregate
self.DFTTest = self.core.dfttest.DFTTest
self.KNLMeansCL = self.core.knlm.KNLMeansCL
self.NNEDI = self.core.nnedi3.nnedi3
self.Resample = self.core.fmtc.resample
self.Expr = self.core.std.Expr
self.MakeDiff = self.core.std.MakeDiff
self.MergeDiff = self.core.std.MergeDiff
self.Crop = self.core.std.CropRel
self.CropAbs = self.core.std.CropAbs
self.Transpose = self.core.std.Transpose
self.BlankClip = self.core.std.BlankClip
self.AddBorders = self.core.std.AddBorders
self.StackHorizontal = self.core.std.StackHorizontal
self.StackVertical = self.core.std.StackVertical
self.MaskedMerge = self.core.std.MaskedMerge
self.ShufflePlanes = self.core.std.ShufflePlanes
self.SetFieldBased = self.core.std.SetFieldBased
def FreqMerge(self, low, hi, sbsize, slocation):
hif = self.MakeDiff(hi, self.DFTTest(hi, sbsize=sbsize, slocation=slocation, **dfttest_args))
clip = self.MergeDiff(self.DFTTest(low, sbsize=sbsize, slocation=slocation, **dfttest_args), hif)
return clip
def Pad(self, src, left, right, top, bottom):
w = src.width
h = src.height
clip = self.Resample(src, w+left+right, h+top+bottom, -left, -top, w+left+right, h+top+bottom, kernel="point", **fmtc_args)
return clip
def NLMeans(self, src, d, a, s, h, rclip, color):
def duplicate(src):
if d > 0:
blank = self.Expr(src[0], "0.0") * d
clip = blank + src + blank
else:
clip = src
return clip
pad = self.AddBorders(src, a+s, a+s, a+s, a+s)
pad = duplicate(pad)
if rclip is not None:
rclip = self.AddBorders(rclip, a+s, a+s, a+s, a+s)
rclip = duplicate(rclip)
nlm = self.KNLMeansCL(pad, d=d, a=a, s=s, h=h, channels="YUV" if color else "Y", wref=1.0, rclip=rclip)
clip = self.Crop(nlm, a+s, a+s, a+s, a+s)
return clip[d:clip.num_frames - d]
def ThrMerge(self, flt, src, ref=None, thr=0.0009765625, elast=None):
ref = src if ref is None else ref
elast = thr / 2 if elast is None else elast
BExp = ["x {thr} {elast} + z - 2 {elast} * / * y {elast} z + {thr} - 2 {elast} * / * +".format(thr=thr, elast=elast)]
BDif = self.Expr(src, "0.0")
PDif = self.Expr([flt, src], "x y - 0.0 max")
PRef = self.Expr([flt, ref], "x y - 0.0 max")
PBLD = self.Expr([PDif, BDif, PRef], BExp)
NDif = self.Expr([flt, src], "y x - 0.0 max")
NRef = self.Expr([flt, ref], "y x - 0.0 max")
NBLD = self.Expr([NDif, BDif, NRef], BExp)
BLDD = self.MakeDiff(PBLD, NBLD)
BLD = self.MergeDiff(src, BLDD)
UDN = self.Expr([flt, ref, BLD], ["x y - abs {thr} {elast} - > z x ?".format(thr=thr, elast=elast)])
clip = self.Expr([flt, ref, UDN, src], ["x y - abs {thr} {elast} + < z a ?".format(thr=thr, elast=elast)])
return clip
def GenBlockMask(self, src):
clip = self.BlankClip(src, 24, 24, color=0.0)
clip = self.AddBorders(clip, 4, 4, 4, 4, color=1.0)
clip = self.StackHorizontal([clip, clip, clip, clip])
clip = self.StackVertical([clip, clip, clip, clip])
clip = self.Resample(clip, 32, 32, kernel="point", **fmtc_args)
clip = self.Expr(clip, ["x 0.0 > 1.0 0.0 ?"])
clip = self.StackHorizontal([clip, clip, clip, clip, clip, clip, clip, clip])
clip = self.StackVertical([clip, clip, clip, clip, clip, clip])
clip = self.StackHorizontal([clip, clip, clip, clip, clip, clip])
clip = self.StackVertical([clip, clip, clip, clip, clip])
clip = self.StackHorizontal([clip, clip, clip, clip, clip, clip])
clip = self.StackVertical([clip, clip, clip, clip, clip])
clip = self.CropAbs(clip, src.width, src.height, 0, 0)
return clip
class internal:
def super(core, src, pel):
src = core.Pad(src, 128, 128, 128, 128)
clip = core.Transpose(core.NNEDI(core.Transpose(core.NNEDI(src, **nnedi_args)), **nnedi_args))
if pel == 4:
clip = core.Transpose(core.NNEDI(core.Transpose(core.NNEDI(clip, **nnedi_args)), **nnedi_args))
return clip
def basic(core, src, super, radius, pel, sad, short_time, color):
plane = 4 if color else 0
src = core.Pad(src, 128, 128, 128, 128)
supersoft = core.MSuper(src, pelclip=super, rfilter=4, pel=pel, chroma=color, **msuper_args)
supersharp = core.MSuper(src, pelclip=super, rfilter=2, pel=pel, chroma=color, **msuper_args)
if short_time:
constant = 0.0001989762736579584832432989326
me_sad = [constant * math.pow(sad, 2.0) * math.log(1.0 + 1.0 / (constant * sad))]
me_sad += [sad]
vmulti = core.MAnalyze(supersoft, radius=radius, chroma=color, overlap=4, blksize=8, **manalyze_args)
vmulti = core.MRecalculate(supersoft, vmulti, chroma=color, overlap=2, blksize=4, thsad=me_sad[0], **mrecalculate_args)
vmulti = core.MRecalculate(supersoft, vmulti, chroma=color, overlap=1, blksize=2, thsad=me_sad[1], **mrecalculate_args)
else:
constant = 0.0000139144247313257680589719533
me_sad = constant * math.pow(sad, 2.0) * math.log(1.0 + 1.0 / (constant * sad))
vmulti = core.MAnalyze(supersoft, radius=radius, chroma=color, overlap=64, blksize=128, **manalyze_args)
vmulti = core.MRecalculate(supersoft, vmulti, chroma=color, overlap=32, blksize=64, thsad=me_sad, **mrecalculate_args)
vmulti = core.MRecalculate(supersoft, vmulti, chroma=color, overlap=16, blksize=32, thsad=me_sad, **mrecalculate_args)
vmulti = core.MRecalculate(supersoft, vmulti, chroma=color, overlap=8, blksize=16, thsad=me_sad, **mrecalculate_args)
vmulti = core.MRecalculate(supersoft, vmulti, chroma=color, overlap=4, blksize=8, thsad=me_sad, **mrecalculate_args)
vmulti = core.MRecalculate(supersoft, vmulti, chroma=color, overlap=2, blksize=4, thsad=me_sad, **mrecalculate_args)
clip = core.MDegrain(src, supersharp, vmulti, thsad=sad, plane=plane, **mdegrain_args)
clip = core.Crop(clip, 128, 128, 128, 128)
return clip
def deringing(core, src, ref, radius, h, sigma, \
mse, hard_thr, block_size, block_step, group_size, bm_range, bm_step, ps_num, ps_range, ps_step, \
lowpass, color, matrix):
c1 = 0.1134141984932795312503328847998
c2 = 2.8623043756241389436528021745239
strength = [h]
strength += [h * math.pow(c1 * h, c2) * math.log(1.0 + 1.0 / math.pow(c1 * h, c2))]
strength += [None]
def loop(flt, init, src, n):
strength[2] = n * strength[0] / 4 + strength[1] * (1 - n / 4)
window = int(32 / math.pow(2, n))
flt = init if n == 4 else flt
dif = core.MakeDiff(src, flt)
dif = core.NLMeans(dif, 0, window, 1, strength[2], flt, color)
fnl = core.MergeDiff(flt, dif)
n -= 1
return fnl if n == -1 else loop(fnl, init, src, n)
ref = core.FreqMerge(src, ref, block_size // 2 * 2 + 1, lowpass)
dif = core.MakeDiff(src, ref)
dif = core.BMBasic(dif, ref, radius=radius, th_mse=mse[0], hard_thr=hard_thr, sigma=sigma, \
block_size=block_size, block_step=block_step, group_size=group_size, bm_range=bm_range, bm_step=bm_step, \
ps_num=ps_num, ps_range=ps_range, ps_step=ps_step, matrix=matrix)
dif = core.Aggregate(dif, radius, 1)
ref = core.MergeDiff(ref, dif)
refined = loop(None, ref, src, 4)
bm3d = core.BMFinal(refined, ref, radius=radius, th_mse=mse[1], sigma=sigma, \
block_size=block_size, block_step=block_step, group_size=group_size, bm_range=bm_range, bm_step=bm_step, \
ps_num=ps_num, ps_range=ps_range, ps_step=ps_step, matrix=matrix)
bm3d = core.Aggregate(bm3d, radius, 1)
bm3d = core.FreqMerge(refined, bm3d, block_size // 2 * 2 + 1, lowpass)
clip = loop(None, bm3d, refined, 4)
return clip
def destaircase(core, src, ref, radius, sigma, \
mse, hard_thr, block_size, block_step, group_size, bm_range, bm_step, ps_num, ps_range, ps_step, \
thr, elast, lowpass, matrix):
mask = core.GenBlockMask(core.ShufflePlanes(src, 0, vs.GRAY))
ref = core.FreqMerge(src, ref, block_size // 2 * 2 + 1, lowpass)
ref = core.ThrMerge(src, ref, thr=thr, elast=elast)
dif = core.MakeDiff(src, ref)
dif = core.BMBasic(dif, ref, radius=radius, th_mse=mse[0], hard_thr=hard_thr, sigma=sigma, \
block_size=block_size, block_step=block_step, group_size=group_size, bm_range=bm_range, bm_step=bm_step, \
ps_num=ps_num, ps_range=ps_range, ps_step=ps_step, matrix=matrix)
dif = core.Aggregate(dif, radius, 1)
ref = core.MergeDiff(ref, dif)
dif = core.MakeDiff(src, ref)
dif = core.BMFinal(dif, ref, radius=radius, th_mse=mse[1], sigma=sigma, \
block_size=block_size, block_step=block_step, group_size=group_size, bm_range=bm_range, bm_step=bm_step, \
ps_num=ps_num, ps_range=ps_range, ps_step=ps_step, matrix=matrix)
dif = core.Aggregate(dif, radius, 1)
ref = core.MergeDiff(ref, dif)
clip = core.MaskedMerge(src, ref, mask, first_plane=True)
return clip
def deblocking(core, src, ref, radius, h, sigma, \
mse, hard_thr, block_size, block_step, group_size, bm_range, bm_step, ps_num, ps_range, ps_step, \
lowpass, color, matrix):
mask = core.GenBlockMask(core.ShufflePlanes(src, 0, vs.GRAY))
cleansed = core.NLMeans(ref, radius, block_size, math.ceil(block_size / 2), h, ref, color)
dif = core.MakeDiff(ref, cleansed)
dif = core.BMBasic(dif, cleansed, radius=radius, th_mse=mse[0], hard_thr=hard_thr, sigma=sigma, \
block_size=block_size, block_step=block_step, group_size=group_size, bm_range=bm_range, bm_step=bm_step, \
ps_num=ps_num, ps_range=ps_range, ps_step=ps_step, matrix=matrix)
dif = core.Aggregate(dif, radius, 1)
cleansed = core.MergeDiff(cleansed, dif)
dif = core.MakeDiff(ref, cleansed)
dif = core.BMFinal(dif, cleansed, radius=radius, th_mse=mse[1], sigma=sigma, \
block_size=block_size, block_step=block_step, group_size=group_size, bm_range=bm_range, bm_step=bm_step, \
ps_num=ps_num, ps_range=ps_range, ps_step=ps_step, matrix=matrix)
dif = core.Aggregate(dif, radius, 1)
cleansed = core.MergeDiff(cleansed, dif)
ref = core.FreqMerge(cleansed, ref, block_size // 2 * 2 + 1, lowpass)
src = core.FreqMerge(cleansed, src, block_size // 2 * 2 + 1, lowpass)
clip = core.MaskedMerge(src, ref, mask, first_plane=True)
return clip
Emulgator
23rd January 2023, 10:20
def Super(src, pel=4):
if not isinstance(src, vs.VideoNode):
raise TypeError("Oyster.Super: src has to be a video clip!")
elif src.format.sample_type != vs.FLOAT or src.format.bits_per_sample < 32:
raise TypeError("Oyster.Super: the sample type of src has to be single precision!")
elif src.format.subsampling_w > 0 or src.format.subsampling_h > 0:
raise RuntimeError("Oyster.Super: subsampled stuff not supported!")
if not isinstance(pel, int):
raise TypeError("Oyster.Super: pel has to be an integer!")
elif pel != 2 and pel != 4:
raise RuntimeError("Oyster.Super: pel has to be 2 or 4!")
core = import core
src = core.SetFieldBased(src, 0)
colorspace = src.format.color_family
if colorspace == vs.RGB:
src = core.RGB2OPP(src, 1)
clip = internal.super(core, src, pel)
del core
return clip
def Basic(src, super=None, radius=6, pel=4, sad=2000.0, short_time=False):
if not isinstance(src, vs.VideoNode):
raise TypeError("Oyster.Basic: src has to be a video clip!")
elif src.format.sample_type != vs.FLOAT or src.format.bits_per_sample < 32:
raise TypeError("Oyster.Basic: the sample type of src has to be single precision!")
elif src.format.subsampling_w > 0 or src.format.subsampling_h > 0:
raise RuntimeError("Oyster.Basic: subsampled stuff not supported!")
if not isinstance(super, vs.VideoNode) and super is not None:
raise TypeError("Oyster.Basic: super has to be a video clip or None!")
elif super is not None:
if super.format.sample_type != vs.FLOAT or super.format.bits_per_sample < 32 or super.format.subsampling_w > 0 or super.format.subsampling_h > 0:
raise RuntimeError("Oyster.Basic: corrupted super clip!")
if not isinstance(radius, int):
raise TypeError("Oyster.Basic: radius has to be an integer!")
elif radius < 1:
raise RuntimeError("Oyster.Basic: radius has to be greater than 0!")
if not isinstance(pel, int):
raise TypeError("Oyster.Basic: pel has to be an integer!")
elif pel != 1 and pel != 2 and pel != 4:
raise RuntimeError("Oyster.Basic: pel has to be 1, 2 or 4!")
if not isinstance(sad, float) and not isinstance(sad, int):
raise TypeError("Oyster.Basic: sad has to be a real number!")
elif sad <= 0.0:
raise RuntimeError("Oyster.Basic: sad has to be greater than 0!")
if not isinstance(short_time, bool):
raise TypeError("Oyster.Basic: short_time has to be boolean!")
core = import core
color = True
rgb = False
colorspace = src.format.color_family
if colorspace == vs.RGB:
src = core.RGB2OPP(src, 1)
rgb = True
if colorspace == vs.GRAY:
color = False
src = core.SetFieldBased(src, 0)
super = core.SetFieldBased(super, 0) if super is not None else None
clip = internal.basic(core, src, super, radius, pel, sad, short_time, color)
clip = core.OPP2RGB(clip, 1) if rgb else clip
del core
return clip
def Deringing(src, ref, radius=6, h=6.4, sigma=16.0, \
mse=[None, None], hard_thr=3.2, block_size=8, block_step=1, group_size=32, bm_range=24, bm_step=1, ps_num=2, ps_range=8, ps_step=1, \
lowpass=None):
if not isinstance(src, vs.VideoNode):
raise TypeError("Oyster.Deringing: src has to be a video clip!")
elif src.format.sample_type != vs.FLOAT or src.format.bits_per_sample < 32:
raise TypeError("Oyster.Deringing: the sample type of src has to be single precision!")
elif src.format.subsampling_w > 0 or src.format.subsampling_h > 0:
raise RuntimeError("Oyster.Deringing: subsampled stuff not supported!")
if not isinstance(ref, vs.VideoNode):
raise TypeError("Oyster.Deringing: ref has to be a video clip!")
elif ref.format.sample_type != vs.FLOAT or ref.format.bits_per_sample < 32:
raise TypeError("Oyster.Deringing: the sample type of ref has to be single precision!")
elif ref.format.subsampling_w > 0 or ref.format.subsampling_h > 0:
raise RuntimeError("Oyster.Deringing: subsampled stuff not supported!")
if not isinstance(radius, int):
raise TypeError("Oyster.Deringing: radius has to be an integer!")
elif radius < 1:
raise RuntimeError("Oyster.Deringing: radius has to be greater than 0!")
if not isinstance(h, float) and not isinstance(h, int):
raise TypeError("Oyster.Deringing: h has to be a real number!")
elif h <= 0:
raise RuntimeError("Oyster.Deringing: h has to be greater than 0!")
if not isinstance(mse, list):
raise TypeError("Oyster.Deringing: mse parameter has to be an array!")
elif len(mse) != 2:
raise RuntimeError("Oyster.Deringing: mse parameter has to contain 2 elements exactly!")
for i in range(2):
if not isinstance(mse[i], float) and not isinstance(mse[i], int) and mse[i] is not None:
raise TypeError("Oyster.Deringing: elements in mse must be real numbers or None!")
if not isinstance(lowpass, list) and lowpass is not None:
raise TypeError("Oyster.Deringing: lowpass has to be a list or None!")
core = import core
rgb = False
color = True
mse[0] = sigma * 160.0 + 1200.0 if mse[0] is None else mse[0]
mse[1] = sigma * 120.0 + 800.0 if mse[1] is None else mse[1]
lowpass = [0.0,sigma, 0.48,1024.0, 1.0,1024.0] if lowpass is None else lowpass
matrix = None
colorspace = src.format.color_family
if colorspace == vs.RGB:
rgb = True
matrix = 100
src = core.RGB2OPP(src, 1)
ref = core.RGB2OPP(ref, 1)
if colorspace == vs.GRAY:
color = False
src = core.SetFieldBased(src, 0)
ref = core.SetFieldBased(ref, 0)
clip = internal.deringing(core, src, ref, radius, h, sigma, \
mse, hard_thr, block_size, block_step, group_size, bm_range, bm_step, ps_num, ps_range, ps_step, \
lowpass, color, matrix)
clip = core.OPP2RGB(clip, 1) if rgb else clip
del core
return clip
def Destaircase(src, ref, radius=6, sigma=16.0, \
mse=[None, None], hard_thr=3.2, block_size=8, block_step=1, group_size=32, bm_range=24, bm_step=1, ps_num=2, ps_range=8, ps_step=1, \
thr=0.03125, elast=0.015625, lowpass=None):
if not isinstance(src, vs.VideoNode):
raise TypeError("Oyster.Destaircase: src has to be a video clip!")
elif src.format.sample_type != vs.FLOAT or src.format.bits_per_sample < 32:
raise TypeError("Oyster.Destaircase: the sample type of src has to be single precision!")
elif src.format.subsampling_w > 0 or src.format.subsampling_h > 0:
raise RuntimeError("Oyster.Destaircase: subsampled stuff not supported!")
if not isinstance(ref, vs.VideoNode):
raise TypeError("Oyster.Destaircase: ref has to be a video clip!")
elif ref.format.sample_type != vs.FLOAT or ref.format.bits_per_sample < 32:
raise TypeError("Oyster.Destaircase: the sample type of ref has to be single precision!")
elif ref.format.subsampling_w > 0 or ref.format.subsampling_h > 0:
raise RuntimeError("Oyster.Destaircase: subsampled stuff not supported!")
if not isinstance(radius, int):
raise TypeError("Oyster.Destaircase: radius has to be an integer!")
elif radius < 1:
raise RuntimeError("Oyster.Destaircase: radius has to be greater than 0!")
if not isinstance(mse, list):
raise TypeError("Oyster.Destaircase: mse parameter has to be an array!")
elif len(mse) != 2:
raise RuntimeError("Oyster.Destaircase: mse parameter has to contain 2 elements exactly!")
for i in range(2):
if not isinstance(mse[i], float) and not isinstance(mse[i], int) and mse[i] is not None:
raise TypeError("Oyster.Destaircase: elements in mse must be real numbers or None!")
if not isinstance(thr, float) and not isinstance(thr, int):
raise TypeError("Oyster.Destaircase: thr has to be a real number!")
elif thr < 0 or thr > 1:
raise RuntimeError("Oyster.Destaircase: thr has to fall in [0, 1]!")
if not isinstance(elast, float) and not isinstance(elast, int):
raise TypeError("Oyster.Destaircase: elast has to be a real number!")
elif elast < 0 or elast > thr:
raise RuntimeError("Oyster.Destaircase: elast has to fall in [0, thr]!")
if not isinstance(lowpass, list) and lowpass is not None:
raise TypeError("Oyster.Destaircase: lowpass has to be a list or None!")
core = import core
rgb = False
mse[0] = sigma * 160.0 + 1200.0 if mse[0] is None else mse[0]
mse[1] = sigma * 120.0 + 800.0 if mse[1] is None else mse[1]
lowpass = [0.0,sigma, 0.48,1024.0, 1.0,1024.0] if lowpass is None else lowpass
matrix = None
colorspace = src.format.color_family
if colorspace == vs.RGB:
rgb = True
matrix = 100
src = core.RGB2OPP(src, 1)
ref = core.RGB2OPP(ref, 1)
src = core.SetFieldBased(src, 0)
ref = core.SetFieldBased(ref, 0)
clip = internal.destaircase(core, src, ref, radius, sigma, \
mse, hard_thr, block_size, block_step, group_size, bm_range, bm_step, ps_num, ps_range, ps_step, \
thr, elast, lowpass, matrix)
clip = core.OPP2RGB(clip, 1) if rgb else clip
del core
return clip
def Deblocking(src, ref, radius=6, h=6.4, sigma=16.0, \
mse=[None, None], hard_thr=3.2, block_size=8, block_step=1, group_size=32, bm_range=24, bm_step=1, ps_num=2, ps_range=8, ps_step=1, \
lowpass=[0.0,0.0, 0.12,1024.0, 1.0,1024.0]):
if not isinstance(src, vs.VideoNode):
raise TypeError("Oyster.Deblocking: src has to be a video clip!")
elif src.format.sample_type != vs.FLOAT or src.format.bits_per_sample < 32:
raise TypeError("Oyster.Deblocking: the sample type of src has to be single precision!")
elif src.format.subsampling_w > 0 or src.format.subsampling_h > 0:
raise RuntimeError("Oyster.Deblocking: subsampled stuff not supported!")
if not isinstance(ref, vs.VideoNode):
raise TypeError("Oyster.Deblocking: ref has to be a video clip!")
elif ref.format.sample_type != vs.FLOAT or ref.format.bits_per_sample < 32:
raise TypeError("Oyster.Deblocking: the sample type of ref has to be single precision!")
elif ref.format.subsampling_w > 0 or ref.format.subsampling_h > 0:
raise RuntimeError("Oyster.Deblocking: subsampled stuff not supported!")
if not isinstance(radius, int):
raise TypeError("Oyster.Deblocking: radius has to be an integer!")
elif radius < 1:
raise RuntimeError("Oyster.Deblocking: radius has to be greater than 0!")
if not isinstance(h, float) and not isinstance(h, int):
raise TypeError("Oyster.Deblocking: h has to be a real number!")
elif h <= 0:
raise RuntimeError("Oyster.Deblocking: h has to be greater than 0!")
if not isinstance(mse, list):
raise TypeError("Oyster.Deblocking: mse parameter has to be an array!")
elif len(mse) != 2:
raise RuntimeError("Oyster.Deblocking: mse parameter has to contain 2 elements exactly!")
for i in range(2):
if not isinstance(mse[i], float) and not isinstance(mse[i], int) and mse[i] is not None:
raise TypeError("Oyster.Deblocking: elements in mse must be real numbers or None!")
if not isinstance(lowpass, list):
raise TypeError("Oyster.Deblocking: lowpass has to be a list!")
core = import core
rgb = False
color = True
mse[0] = sigma * 160.0 + 1200.0 if mse[0] is None else mse[0]
mse[1] = sigma * 120.0 + 800.0 if mse[1] is None else mse[1]
matrix = None
colorspace = src.format.color_family
if colorspace == vs.RGB:
rgb = True
matrix = 100
src = core.RGB2OPP(src, 1)
ref = core.RGB2OPP(ref, 1)
if colorspace == vs.GRAY:
color = False
src = core.SetFieldBased(src, 0)
ref = core.SetFieldBased(ref, 0)
clip = internal.deblocking(core, src, ref, radius, h, sigma, \
mse, hard_thr, block_size, block_step, group_size, bm_range, bm_step, ps_num, ps_range, ps_step, \
lowpass, color, matrix)
clip = core.OPP2RGB(clip, 1) if rgb else clip
del core
return clip
ChaosKing
23rd January 2023, 10:46
First vs.core() is old syntax. Now it's simply vs.core (you still need to have import vapoursynth as vs)
Never saw something like this core = import core (no a python pro here) but I think you can also replace it with vs.core.
Oh in case you didn't know, scripts/plugins by feisty2 are very very very slow :p
Emulgator
23rd January 2023, 10:53
Thanks, that helped ! Getting futher.
Now next comes up:
2023-01-23 10:50:22.589
Failed to evaluate the script:
Python exception: name 'vs' is not defined
Traceback (most recent call last):
File "src\cython\vapoursynth.pyx", line 2832, in vapoursynth._vpy_evaluate
File "src\cython\vapoursynth.pyx", line 2833, in vapoursynth._vpy_evaluate
File "C:/_SOFT/! Vapoursynth/VapourSynth64PortableFatpack_2021_10_16/userscripts/Haley A.vpy", line 49, in
ref_s = Oyster.Basic(clip, short_time=True)
File "C:\_SOFT\! Vapoursynth\VapourSynth64PortableFatpack_2021_10_16\Scripts\Oyster.py", line 233, in Basic
if not isinstance(src, vs.VideoNode):
NameError: name 'vs' is not defined
P.S. Slooow: Yes, I heard.. Hoping for some newer HW to deliver someting like >0,05fps ;-)
At the same time trying to get Dogway's Oyster rewrite for AviSynth+ 3.7.3 to run, unsuccessful so far as well..
ChaosKing
24th January 2023, 11:03
I got Oyster to work.
I think you are using an older version of Oyster. Download the newest version from his github page https://github.com/IFeelBloated/Oyster
It also needs the latest version (r10) of mvtools-sf https://github.com/IFeelBloated/vapoursynth-mvtools-sf
Delete libmvtools_sf_em64t.dll (it's the old one. Otherwise there will be a namespace conflict and only one of the plugins will be loaded)
All you have to fix is line 14 in Oyster.py
self.core = vs.get_core()
to
self.core = vs.core
import vapoursynth as vs
import Oyster
core = vs.core
clip = core.lsmas.LWLibavSource(source=r"F:\video.mkv")
clip = core.fmtc.bitdepth( clip, bits = 32 )
clip = core.fmtc.resample( clip, css = "444" )
ref_s = Oyster.Basic(clip, short_time=True)
clip = Oyster.Deringing(clip, ref_s, block_step=2)
clip.set_output()
This took about a minute to display one frame (720x480) in vsedit
p.s. If you make changes to a python script (Oyster.py) make sure to restart vsedit!
kedautinh12
24th January 2023, 11:05
Dogway's Oyster don't work cause W.I.P
Emulgator
25th January 2023, 03:02
Chaosking, you are a hero. Indeed r10-prerelease was needed.
Many thanks ! This is with your fatpack 2021 10 16:
Script loaded, no fault comments, i9-11900K CPU breathing hot air @ 100%,
waiting for the first frame to emerge...
10...48...128GB RAM used up, then 69GB...then 29GB, then 14GB
And here it is ! 1 frame deringing only like 3 minutes...
Lets see if I can move this to my R61 portable.
Selur
25th January 2023, 21:06
Small question seeing:
self.core = vs.core()
self.MSuper = self.core.mvsf.Super
self.MAnalyze = self.core.mvsf.Analyze
self.MRecalculate = self.core.mvsf.Recalculate
self.MDegrain = self.core.mvsf.Degrain
self.RGB2OPP = self.core.bm3d.RGB2OPP
self.OPP2RGB = self.core.bm3d.OPP2RGB
self.BMBasic = self.core.bm3d.VBasic
self.BMFinal = self.core.bm3d.VFinal
self.Aggregate = self.core.bm3d.VAggregate
self.DFTTest = self.core.dfttest.DFTTest
self.KNLMeansCL = self.core.knlm.KNLMeansCL
self.NNEDI = self.core.nnedi3.nnedi3
self.Resample = self.core.fmtc.resample
self.Expr = self.core.std.Expr
self.MakeDiff = self.core.std.MakeDiff
self.MergeDiff = self.core.std.MergeDiff
self.Crop = self.core.std.CropRel
self.CropAbs = self.core.std.CropAbs
self.Transpose = self.core.std.Transpose
self.BlankClip = self.core.std.BlankClip
self.AddBorders = self.core.std.AddBorders
self.StackHorizontal = self.core.std.StackHorizontal
self.StackVertical = self.core.std.StackVertical
self.MaskedMerge = self.core.std.MaskedMerge
self.ShufflePlanes = self.core.std.ShufflePlanes
self.SetFieldBased = self.core.std.SetFieldBased
Woud it speed things up to use:
BM3DCUDA instead of BM3D ?
NNEDI3CL instead of NNEDI3? (or at least znedi3?)
ChaosKing
26th January 2023, 00:18
You can replace nnedi3 with: self.NNEDI = self.core.nnedi3cl.NNEDI3CL
I removed RGB2OPP() and replaced bm3d with
vs.core.bm3dcuda_rtc.BM3Dv2(dif, cleansed, radius=radius, sigma=sigma, \
block_step=block_step, bm_range=bm_range, \
ps_num=ps_num, ps_range=ps_range)
I had to remove some parameters since they are not present in bm3dcuda. Not sure if I replaced it correctly, but at least it looks very similar (not much tested)
For this example it is twice as fast for me.
ref_s = Oyster.Basic(clip, short_time=True)
clip = Oyster.Deringing(clip, ref_s, block_step=2)
With radius=2 it is actually usable now with ~15sec for a single frame
import Oystergpu as Oy
ref_s = Oy.Basic(clip, short_time=True, radius=2)
clip = Oy.Deringing(clip, ref_s, block_step=2, radius=2)
Download here
https://gist.github.com/theChaosCoder/314900908082a67901cb54994eacf9ca
EDIT
Just found this https://github.com/AmusementClub/vs-nlm-cuda
EDIT2
Replaced knlm with nlm_cuda
Dogway
26th January 2023, 09:00
Dogway's Oyster don't work cause W.I.P
I've been following the thread and decided to finish the filter for AVS+
The main problem with Deringing is the use of NLMeans, which loops KNLMeansCL several times, maybe not in VS but in AVS that causes an out of resources error when used more than twice (1 loop in 2 dif calls), and I have 32Gb of RAM.
Aside of that for BM3D I found that radius doesn't make a big difference, and blockstep=1 is only a slightly bit sharper than with 2, but at the expense of magnitudes times slower.
The main trick I did to speed it up was to remake FreqMerge() using GuidedBlur() (at half res) instead of DFTTest which is known to be slow.
Here are my tests using oyster_Deblocking, and some further custom filtering to recover back some structure.
src
http://i.imgur.com/l3hUCCFm.png (https://i.imgur.com/l3hUCCF.png)
blockstep = 1..........................................................blockstep = 2
http://i.imgur.com/5VAzF1Gm.png (https://i.imgur.com/5VAzF1G.png)_______http://i.imgur.com/qAQermkm.png (https://i.imgur.com/qAQermk.png)
Structure sharpen......................................................Recover smearing
http://i.imgur.com/OecMKy1m.png (https://i.imgur.com/OecMKy1.png)_______http://i.imgur.com/F8mF7xsm.png (https://i.imgur.com/F8mF7xs.png)
ConverttoYUV444().ConvertBits(32)
clp = last
sup = oyster_Super(clp)
ref_s = oyster_Basic(clp, sup, short_time=true)
dbl = oyster_Deblocking (clp, radius=4, ref_s, block_step=1)
dbl
# De-smearing
ex_lfr(clp,LFR=130)
# Re-structure
ex_unsharp(0.4, Fc=400, th=0, safe=true)
# Recover some saturation
ex_vibrance(1.15)
ChaosKing
26th January 2023, 10:38
Aside of that for BM3D I found that radius doesn't make a big difference, and blockstep=1 is only a slightly bit sharper than with 2, but at the expense of magnitudes times slower.
ex_vibrance(1.15)[/CODE]
In the deringing function bm3d basic is called, then It's "refined" with loop(None, ref, src, 4), so called x4 again and finally bm3d final.
So bm3d is called at least 6 times. Combine this with radius=6 und you know why it takes 3 minutes to process a single frame. feisty2 makes zero compromises :devil:
Missed the dfttest part: dfttest could be replaced with neo_dfttest or https://github.com/AmusementClub/vs-dfttest2
EDIT: Oh you're right NLMeans is called 4 times, not bm3d. Well never code when tired xD
vBulletin® v3.8.11, Copyright ©2000-2025, vBulletin Solutions Inc.