View Full Version : Vine, cutting edge quality de-halo filter and morphology stuff
ChaosKing
30th November 2016, 00:42
Are there any other dehalo VapourSynth options? Ones that do run fast for video processing? Don't care what visual quality as long as it's fast and usable.
DeHalo_alpha & YAHR:
http://forum.doom9.org/showthread.php?t=166582
captaiŋadamo
30th November 2016, 16:23
nnedi3 shouldn't run on CPU, none image processing plugins should. It's insane to run that alg. on CPU.
So you're volunteering to rewrite all Avisynth/Vapoursynth plugins to run on the GPU? :sly:
JackCY
30th November 2016, 20:55
DeHalo_alpha & YAHR:
http://forum.doom9.org/showthread.php?t=166582
Thanks will try them if I can hunt down all the dependencies.
Result:
DeHalo_alpha
# rx=3., ss = 1.0 # Output 1000 frames in 9.56 seconds (104.62 fps) # disables resampling and uses repair instead
# rx=3., ss = 1.5 # Output 1000 frames in 14.41 seconds (69.38 fps)
YAHR
# blur=2, depth=32 # Output 1000 frames in 33.02 seconds (30.28 fps)
Vine.Dehalo (no nnedi3, cutoff original)
# [3, None], a=3, sigma=1.3, alpha=0.27, h=24, cutoff=4 # Output 1000 frames in 46.09 seconds (21.70 fps)
DeHalo_alpha - general dehalo, easily strong, relatively easy to tweak it's strength up and down
YAHR - only affect 1st halo ring not 2nd, such as black + white halos only white gets removed, black stays, for me impossible to make stronger or weaker I suppose too
Vine.Dehalo - nnedi3 needs to go for it to be usable, might use the DeHalo_alpha resampling and repair instead but simply none is fine too and keeps edges original instead of smoothed via nnedi3 resampling
I even doubt any resamplings in these scripts are done with a mask, so that only used pixels (filtered edges) are resampled say 5% of the image and not all pixels 100% of the image, which would alone provide a big speed up. Resampler scripts probably weren't made with that in mind.
On my test sample with denoise etc.:
DeHalo_alpha
Output 1000 frames in 16.35 seconds (61.16 fps)
encoded 1000 frames, 68.57 fps, 4505.42 kbps, 22.40 MB
encode time 0:00:14 / CPU Usage: 8.68%
No dehalo
Output 1000 frames in 14.83 seconds (67.42 fps)
encoded 1000 frames, 80.33 fps, 5468.65 kbps, 27.19 MB
encode time 0:00:12 / CPU Usage: 11.23%
feisty2
1st December 2016, 14:51
I even doubt any resamplings in these scripts are done with a mask, so that only used pixels (filtered edges) are resampled say 5% of the image and not all pixels 100% of the image, which would alone provide a big speed up. Resampler scripts probably weren't made with that in mind.
"pscrn" is the internal masking for nnedi3, set it 0 and you'll know how slow nnedi3 could be when its working on the entire image..
The edges might be changed by doing some other cheaper operation, such as convolution blur to reduce sharpness or the opposite since the sharpness argument is now defunct, no problem to emulate 0.5 sharpness which helped to remove more of the halos.
This is with "a=3" which is enough for KNLMeansCL. Radius 3.
supersampling(nnedi3) is supposed to remove aliasing, there's gonna be the aliasing-ringing tradeoff like all convolution filters, supersampling makes sure you get the best result from both sides and simply avoid the tradeoff.
a=3 is not "non-local"
Vine is a quality solution rather than realtime solution, but go ahead and remove things you think are pointless, I'm not stopping you...
Motenai Yoda
4th December 2016, 13:57
"pscrn" is the internal masking for nnedi3, set it 0 and you'll know how slow nnedi3 could be when its working on the entire image...
actually nnedi3 pscrn mask where nnedi is applied but all the other pixels are rescaled with a bicubic resample, so a resample is still applied to the entire frame
feisty2
4th December 2016, 14:06
actually nnedi3 pscrn mask where nnedi is applied but all the other pixels are rescaled with a bicubic resample, so a resample is still applied to the entire frame
Bicubic is negligible performance-wise
xekon
5th December 2016, 22:18
I am trying to use Vine, as soon as I hit F5 to generate a preview in VSedit, it crashes. After reading though this thread I am assuming its because of one of my prerequisites. I seen the post about using Myrsloik's build of fmtconv. Where could I find his current build? I am currently using R20 of cretindesalpes' build. I am not sure where to look for a crash log. I dont know if Vapoursynth or VSedit has one when its a Fatal Crash.
here is my code:
original_format = ret.format
float_format = core.register_format(original_format.color_family, vs.FLOAT, 32, original_format.subsampling_w, original_format.subsampling_h)
ret = core.resize.Bicubic(ret, format=float_format.id)
ret = Vine.Dehalo(ret, [3, None], sigma=1.6, alpha=0.18, h=12, sharp=0.5, cutoff=2)
ret = Vine.Dehalo(ret, [3, None], sigma=2.2, alpha=0.18, h=24, sharp=0.5, cutoff=2)
ret = core.resize.Bicubic(ret, format=original_format.id)
ret.set_output()
EDIT: I found and tried jackoneill's fmtconv: https://github.com/dubhater/fmtconv/tree/master/build/unix
Vine still crashes immediately every time I hit F5, not sure how to go about finding the culprit.
feisty2
4th January 2017, 19:33
r5:
a blending operation is now appended after super-sampling, weight determined by the "sharp" parameter
mathematical expression: weight = constant * sharp * ln(1 + 1 / (constant * sharp)) (constant determines how fast weight gets near 1.0 as sharp gets larger)
the mathematical limit for weight is 0 (simply returns the resampled result) as sharp goes infinitely close to 0, or 1 (simply returns the clip before resampling) as sharp goes towards infinity
now if you feel like to barf any time math is somewhere around you, and would like not to analyze that weight expression with differential calculus, all you gotta know is a larger "sharp" value also results in less percentage of super-sampling
bebs
4th February 2017, 13:14
It seems that KNLMeansCL breaks Vine, i keep having an error KNLMeansCL: 'rclip' does not match the source clip! when using KNLMeansCL 1.0.0.
KNLMeansCL .77 is working fine.
Jindadil007
4th February 2017, 13:19
It seems that KNLMeansCL breaks Vine, i keep having an error KNLMeansCL: 'rclip' does not match the source clip! when using KNLMeansCL 1.0.0.
KNLMeansCL .77 is working fine.
Correctly Reported...i am also using .77 for the same reason...
feisty2
4th February 2017, 13:33
It seems that KNLMeansCL breaks Vine, i keep having an error KNLMeansCL: 'rclip' does not match the source clip! when using KNLMeansCL 1.0.0.
KNLMeansCL .77 is working fine.
v1.0.0 is buggy, I already reported that bug in the KNLMeansCL thread
feisty2
4th February 2017, 15:39
r6:
redesigned the super-sampling process
feisty2
14th February 2017, 15:31
r7:
redesigned the dehalo filter (Basic+Final)
Jindadil007
14th February 2017, 17:48
r7:
redesigned the dehalo filter (Basic+Final)
Update on New Script : Dehalo command is not recognised anymore. Tested with Basic + Final ... Earlier (Script) fps was 0.23 now it has dropped to 0.14 ... Plus there are Memory Leaks with same dependencies :
Core freed but 87 filter instances still exist
Core freed but 87 filter instances still exist
Core freed but 1525568512 bytes still allocated in framebuffers
Core freed but 1525568512 bytes still allocated in framebuffers
feisty2
14th February 2017, 17:55
Update on New Script : Dehalo command is not recognised anymore. Tested with Basic + Final ... Earlier (Script) fps was 0.23 now it has dropped to 0.14 ... Plus there are Memory Leaks with same dependencies :
Core freed but 87 filter instances still exist
Core freed but 87 filter instances still exist
Core freed but 1525568512 bytes still allocated in framebuffers
Core freed but 1525568512 bytes still allocated in framebuffers
please don't use the latest version for now, I'll let you know when it's ready
Jindadil007
14th February 2017, 18:01
please don't use the latest version for now, I'll let you know when it's ready
Oops !!! I replaced the earlier script file and I can't find it anymore. Pl. share from where i can download the previous script...Thanks
feisty2
14th February 2017, 18:03
Oops !!! I replaced the earlier script file and I can't find it anymore. Pl. share from where i can download the previous script...Thanks
https://github.com/IFeelBloated/Vine/blob/2ca260dc287f59ef124375e209d86a7b3cda1150/Vine.py
Jindadil007
14th February 2017, 18:09
https://github.com/IFeelBloated/Vine/blob/2ca260dc287f59ef124375e209d86a7b3cda1150/Vine.py
:thanks:
feisty2
15th February 2017, 13:47
:thanks:
you can use the latest version now if you want to
and..
1. stop complaining about memory leaks in this thread, if there're memory leaks in certain plugin(s), Vine is not what's causing all that, as I already told you here, https://forum.doom9.org/showpost.php?p=1795833&postcount=37
complain in the thread for the exact plugin that has memory leaks if you know which plugin is the one to blame, or
complain in the main vaporsynth thread if you don't, Myrsloik or jackoneill will probably help you out if they're in a good mood..
2. yeah, the new version is slower but the quality is better, you can stick to the previous version if you're not okay with the performance.
Jindadil007
15th February 2017, 13:49
you can use the latest version now if you want to
and..
1. stop complaining about memory leaks in this thread, if there're memory leaks in certain plugin(s), Vine is not what's causing all that, as I already told you here, https://forum.doom9.org/showpost.php?p=1795833&postcount=37
complain in the thread for the exact plugin that has memory leaks if you know which plugin is the one to blame, or
complain in the main vaporsynth thread if you don't, Myrsloik or jackoneill will probably help you out if they're in a good mood..
2. yeah, the new version is slower but the quality is better, you can stick to the previous version if you're not okay with the performance.
Thanks...Would Check it surely...
Cary Knoop
11th January 2018, 23:32
Running Vine using a SMPTE RP 219 test chart with the following commands:
ref = Vine.Basic(c, h=31.18, sharp=0.48)
ref = Vine.Basic(ref, h=13.86, sharp=0.16)
c = Vine.Final([c, ref], [Vine.Super(c), Vine.Super(ref)], [6, 2, 4], sigma=2.2, alpha=0.18)
I notice a levels adjustment. Source is video levels, after Vine the levels are squeezed.
poisondeathray
15th January 2018, 04:16
Running Vine using a SMPTE RP 219 test chart with the following commands:
ref = Vine.Basic(c, h=31.18, sharp=0.48)
ref = Vine.Basic(ref, h=13.86, sharp=0.16)
c = Vine.Final([c, ref], [Vine.Super(c), Vine.Super(ref)], [6, 2, 4], sigma=2.2, alpha=0.18)
I notice a levels adjustment. Source is video levels, after Vine the levels are squeezed.
How "squeezed ?" What is your full script ?
I noticed no significant change in levels. Slightly different source. YUV422P8 bars with pluge
pre / post vine
https://s9.postimg.org/m4y9dncsf/input_postvine.png (https://postimages.org/)
Cary Knoop
15th January 2018, 05:35
Squeezed as if the video levels are interpreted as full range and "squeezed" to video.
source = 'VideoLevelsRec709CineformSMPTE1080P.mov'
c = core.lsmas.LWLibavSource(source)
c = core.fmtc.bitdepth (c, bits=32)
ref = Vine.Basic(c, h=31.18, sharp=0.48)
ref = Vine.Basic(ref, h=13.86, sharp=0.16)
c = Vine.Final([c, ref], [Vine.Super(c), Vine.Super(ref)], [6, 2, 4], sigma=2.2, alpha=0.18)
return core.fmtc.bitdepth (c, bits=8)
c.set_output()
Was your source full range?
poisondeathray
15th January 2018, 05:46
Was your source full range?
No, it's legal range video levels except for the pluge; you can see the waveform in IRE in my post, I added it
Check each step with histogram ; for example comment out everything, except for lsmash source filter, check levels; the vine lines, check levels, comment out fmtc lines, check levels etc...
Vine didn't do anything significant to levels in my test (beyond the expected slight changes in edges)
Cary Knoop
16th January 2018, 04:59
Tested this again, and well, I can't reproduce the situation.
I think we have to call it a user error (that's me).
I am sorry.
By the way, Vine works great!
I was wondering how much change it would take to restrict the adjustments to horizontal adjustments only (i.e. reducing vertical stripes while keeping horizontal stripes alone)?
zerowalker
31st December 2019, 10:18
How do you use the Dehalo filter?
I can't make it out:(
Cary Knoop
27th August 2020, 05:25
Vine works great but the fmtc_args dictionary settings change the levels for float32 processing, emptying the fmtc_args dictionary solves the problem for me.
WaxCyl
28th May 2023, 13:13
Does anyone know if there is an update for Vine to work with the latest version of Vapoursynth? I have been unable to find one.
I have had an attempt to do this myself, but with no luck. Def NLmeans brings an error message.
Here is my version of Vine so far:
WaxCyl
28th May 2023, 13:17
import vapoursynth as vs
import math
fmtc_args = dict(fulls=True, fulld=True)
msuper_args = dict(hpad=0, vpad=0, sharp=2, levels=0, chroma=False)
manalyze_args = dict(search=3, truemotion=False, trymany=True, levels=0, badrange=-24, divide=0, dct=0, chroma=False)
mrecalculate_args = dict(truemotion=False, search=3, smooth=1, divide=0, dct=0, chroma=False)
mdegrain_args = dict(plane=0, thscd1=16711680.0, thscd2=255.0)
canny_args = dict(mode=1, op=0)
nnedi_args = dict(field=1, dh=True, nns=4, qual=2, etype=1, nsize=0)
class get_core:
def __init__(self):
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.KNLMeansCL = self.core.haf.KNLMeansCL
self.Canny = self.core.tcanny.TCanny
self.NNEDI = self.core.nnedi3.nnedi3
self.RGB2OPP = self.core.bm3d.RGB2OPP
self.OPP2RGB = self.core.bm3d.OPP2RGB
self.Resample = self.core.fmtc.resample
self.Maximum = self.core.std.Maximum
self.Minimum = self.core.std.Minimum
self.Expr = self.core.std.Expr
self.Merge = self.core.std.Merge
self.MakeDiff = self.core.std.MakeDiff
self.MergeDiff = self.core.std.MergeDiff
self.Crop = self.core.std.CropRel
self.AddBorders = self.core.std.AddBorders
self.Transpose = self.core.std.Transpose
self.Inflate = self.core.std.Inflate
self.MaskedMerge = self.core.std.MaskedMerge
self.ShufflePlanes = self.core.std.ShufflePlanes
self.SetFieldBased = self.core.std.SetFieldBased
def CutOff(self, low, hi, p):
def inline(src):
upsmp = self.Resample(src, src.width*2, src.height*2, kernel="gauss", a1=100, **fmtc_args)
clip = self.Resample(upsmp, src.width, src.height, kernel="gauss", a1=p, **fmtc_args)
return clip
hif = self.MakeDiff(hi, inline(hi))
clip = self.MergeDiff(inline(low), 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):
pad = self.AddBorders(src, a+s, a+s, a+s, a+s)
rclip = self.AddBorders(rclip, a+s, a+s, a+s, a+s) if rclip is not None else None
nlm = self.KNLMeansCL(pad, d=0, a=a, s=s, h=h, rclip=rclip)
clip = self.Crop(nlm, a+s, a+s, a+s, a+s)
return clip
def XYClosest(self, src1, src2, ref):
clip = self.Expr([src1, src2, ref], "x z - abs y z - abs > y x ?")
return clip
class internal:
def dilation(core, src, radius):
for i in range(radius):
src = core.Maximum(src)
return src
def erosion(core, src, radius):
for i in range(radius):
src = core.Minimum(src)
return src
def closing(core, src, radius):
clip = internal.dilation(core, src, radius)
clip = internal.erosion(core, clip, radius)
return clip
def opening(core, src, radius):
clip = internal.erosion(core, src, radius)
clip = internal.dilation(core, clip, radius)
return clip
def gradient(core, src, radius):
erosion = internal.erosion(core, src, radius)
dilation = internal.dilation(core, src, radius)
clip = core.Expr([dilation, erosion], "x y -")
return clip
def tophat(core, src, radius):
opening = internal.opening(core, src, radius)
clip = core.Expr([src, opening], "x y -")
return clip
def blackhat(core, src, radius):
closing = internal.closing(core, src, radius)
clip = core.Expr([src, closing], "y x -")
return clip
def super(core, src, pel):
src = core.Pad(src, 128, 128, 128, 128)
clip = core.std.transpose(core.nnedi3.nnedi3(core.std.transpose(core.nnedi3.nnedi3(src, **nnedi_args)), **nnedi_args))
if pel == 4:
clip = core.std.transpose(core.nnedi3.nnedi3(core.std.transpose(core.nnedi3.nnedi3(clip, **nnedi_args)), **nnedi_args))
return clip
def basic(core, src, a, h, sharp, cutoff):
c1 = 0.3926327792690057290863679493724
c2 = 18.880334973195822973214959957208
c3 = 0.5862453661304626725671053478676
weight = c1 * sharp * math.log(1.0 + 1.0 / (c1 * sharp))
h_refine = c2 * math.pow(h / c2, c3)
upsampled = core.std.Transpose(core.nnedi3.nnedi3(core.std.Transpose(core.nnedi3.nnedi3(src, **nnedi_args)), **nnedi_args))
upsampled = core.NLmeans(upsampled, a, 0, h, None)
resampled = core.Resample(upsampled, src.width, src.height, sx=-0.5, sy=-0.5, kernel="cubic", a1=-sharp, a2=0)
clean = core.NLmeans(src, a, 0, h, None)
clean = core.Merge(resampled, clean, weight)
clean = core.CutOff(src, clean, cutoff)
dif = core.MakeDiff(src, clean)
dif = core.NLmeans(dif, a, 1, h_refine, clean)
clip = core.MergeDiff(clean, dif)
return clip
def final(core, src, super, radius, pel, sad, sigma, alpha, beta, masking, show):
constant = 0.0009948813682897925944723492342
me_sad = constant * math.pow(sad, 2.0) * math.log(1.0 + 1.0 / (constant * sad))
if masking:
mask = core.Canny(src[1], sigma=sigma, **canny_args)
mask = core.Expr(mask, "x {alpha} + {beta} pow {gamma} - 0.0 max 1.0 min".format(alpha=alpha, beta=beta, gamma=math.pow(alpha, beta)))
expanded = internal.dilation(core, mask, radius[1])
closed = internal.closing(core, mask, radius[1])
mask = core.Expr([expanded, closed, mask], "x y - z +")
for i in range(radius[2]):
mask = core.Inflate(mask)
if show:
return mask
for i in range(2):
src[i] = core.Pad(src[i], 128, 128, 128, 128)
src[1] = core.MakeDiff(src[1], src[0])
super[1] = core.MakeDiff(super[1], super[0]) if super[0] is not None and super[1] is not None else None
blankdif = core.Expr(src[0], "0.0")
supersearch = core.MSuper(src[0], pelclip=super[0], rfilter=4, pel=pel, **msuper_args)
superdif = core.MSuper(src[1], pelclip=super[1], rfilter=2, pel=pel, **msuper_args)
vmulti = core.MAnalyze(supersearch, radius=radius[0], overlap=64, blksize=128, **manalyze_args)
vmulti = core.MRecalculate(supersearch, vmulti, overlap=32, blksize=64, thsad=me_sad, **mrecalculate_args)
vmulti = core.MRecalculate(supersearch, vmulti, overlap=16, blksize=32, thsad=me_sad, **mrecalculate_args)
vmulti = core.MRecalculate(supersearch, vmulti, overlap=8, blksize=16, thsad=me_sad, **mrecalculate_args)
vmulti = core.MRecalculate(supersearch, vmulti, overlap=4, blksize=8, thsad=me_sad, **mrecalculate_args)
vmulti = core.MRecalculate(supersearch, vmulti, overlap=2, blksize=4, thsad=me_sad, **mrecalculate_args)
vmulti = core.MRecalculate(supersearch, vmulti, overlap=1, blksize=2, thsad=me_sad, **mrecalculate_args)
averaged_dif = core.MDegrain(src[1], superdif, vmulti, thsad=sad, **mdegrain_args)
averaged_dif = core.XYClosest(averaged_dif, src[1], blankdif)
averaged_dif = core.Crop(averaged_dif, 128, 128, 128, 128)
src[0] = core.Crop(src[0], 128, 128, 128, 128)
clean = core.MergeDiff(src[0], averaged_dif)
clip = core.MaskedMerge(src[0], clean, mask) if masking else clean
return clip
def Super(src, pel=4):
if not isinstance(src, vs.VideoNode):
raise TypeError("Vine.Super: src has to be a video clip!")
elif src.format.sample_type != vs.FLOAT or src.format.bits_per_sample < 32:
raise TypeError("Vine.Super: the sample type of src has to be single precision!")
if not isinstance(pel, int):
raise TypeError("Vine.Super: pel has to be an integer!")
elif pel != 2 and pel != 4:
raise RuntimeError("Vine.Super: pel has to be 2 or 4!")
core = core
src = core.SetFieldBased(src, 0)
colorspace = src.format.color_family
if colorspace == vs.RGB:
src = core.RGB2OPP(src, 1)
if colorspace != vs.GRAY:
src = core.ShufflePlanes(src, 0, vs.GRAY)
clip = internal.super(core, src, pel)
del core
return clip
def Basic(src, a=32, h=6.4, sharp=1.0, cutoff=4):
if not isinstance(src, vs.VideoNode):
raise TypeError("Vine.Basic: src has to be a video clip!")
elif src.format.sample_type != vs.FLOAT or src.format.bits_per_sample < 32:
raise TypeError("Vine.Basic: the sample type of src has to be single precision!")
if not isinstance(a, int):
raise TypeError("Vine.Basic: a has to be an integer!")
elif a < 1:
raise RuntimeError("Vine.Basic: a has to be greater than 0!")
if not isinstance(h, float) and not isinstance(h, int):
raise TypeError("Vine.Basic: h has to be a real number!")
elif h <= 0:
raise RuntimeError("Vine.Basic: h has to be greater than 0!")
if not isinstance(sharp, float) and not isinstance(sharp, int):
raise TypeError("Vine.Basic: sharp has to be a real number!")
elif sharp <= 0.0:
raise RuntimeError("Vine.Basic: sharp has to be greater than 0!")
if not isinstance(cutoff, int):
raise TypeError("Vine.Basic: cutoff has to be an integer!")
elif cutoff < 1 or cutoff > 100:
raise RuntimeError("Vine.Basic: cutoff must fall in (0, 100]!")
core =vs. core
src = core.std.SetFieldBased(src, 0)
colorspace = src.format.color_family
if colorspace == vs.RGB:
src = core.RGB2OPP(src, 1)
if colorspace != vs.GRAY:
src = core.std. ShufflePlanes(src, 0, vs.GRAY)
clip = internal.basic(core, src, a, h, sharp, cutoff)
del core
return clip
continued next post
WaxCyl
28th May 2023, 13:23
def Final(src, super=[None, None], radius=[6, 1, None], pel=4, sad=400.0, sigma=0.6, alpha=0.36, beta=32.0, masking=True, show=False):
if not isinstance(src, list):
raise TypeError("Vine.Final: src has to be an array!")
elif len(src) != 2:
raise RuntimeError("Vine.Final: src has to contain 2 elements exactly!")
elif not isinstance(src[0], vs.VideoNode) or not isinstance(src[1], vs.VideoNode):
raise TypeError("Vine.Final: elements in src must be video clips!")
elif src[0].format.sample_type != vs.FLOAT or src[0].format.bits_per_sample < 32:
raise TypeError("Vine.Final: the sample type of src[0] has to be single precision!")
elif src[1].format.id != vs.GRAYS:
raise RuntimeError("Vine.Final: corrupted basic estimation!")
if not isinstance(super, list):
raise TypeError("Vine.Final: super has to be an array!")
elif len(super) != 2:
raise RuntimeError("Vine.Final: super has to contain 2 elements exactly!")
for i in range(2):
if not isinstance(super[i], vs.VideoNode) and super[i] is not None:
raise TypeError("Vine.Final: elements in super must be video clips or None!")
elif super[i] is not None:
if super[i].format.id != vs.GRAYS:
raise RuntimeError("Vine.Final: corrupted super clips!")
if not isinstance(radius, list):
raise TypeError("Vine.Final: radius parameter has to be an array!")
elif len(radius) != 3:
raise RuntimeError("Vine.Final: radius parameter has to contain 3 elements exactly!")
for i in range(2):
if not isinstance(radius[i], int):
raise TypeError("Vine.Final: radius[" + str(i) + "] has to be an integer!")
if radius[0] <= 0:
raise RuntimeError("Vine.Final: radius[0] has to be greater than 0!")
if radius[1] < 0:
raise RuntimeError("Vine.Final: radius[1] has to be no less than 0!")
if not isinstance(radius[2], int) and radius[2] is not None:
raise TypeError("Vine.Final: radius[2] has to be an integer or None!")
elif radius[2] is not None:
if radius[2] < 0:
raise RuntimeError("Vine.Final: radius[2] has to be no less than 0!")
if not isinstance(pel, int):
raise TypeError("Vine.Final: pel has to be an integer!")
elif pel != 1 and pel != 2 and pel != 4:
raise RuntimeError("Vine.Final: pel has to be 1, 2 or 4!")
if not isinstance(sad, float) and not isinstance(sad, int):
raise TypeError("Vine.Final: sad has to be a real number!")
elif sad <= 0:
raise RuntimeError("Vine.Final: sad has to be greater than 0!")
if not isinstance(alpha, float) and not isinstance(alpha, int):
raise TypeError("Vine.Final: alpha has to be a real number!")
elif alpha < 0.0 or alpha > 1.0:
raise RuntimeError("Vine.Final: alpha must fall in [0.0, 1.0]!")
if not isinstance(beta, float) and not isinstance(beta, int):
raise TypeError("Vine.Final: beta has to be a real number!")
elif beta <= 1.0:
raise RuntimeError("Vine.Final: beta has to be greater than 1.0!")
if not isinstance(masking, bool):
raise TypeError("Vine.Final: masking has to be boolean!")
if not isinstance(show, bool):
raise TypeError("Vine.Final: show has to be boolean!")
if not masking and show:
raise RuntimeError("Vine.Final: masking has been disabled, set masking True to show the halo mask!")
radius[2] = math.ceil(radius[1] / 2) if radius[2] is None else radius[2]
core = core
for i in range(2):
src[i] = core.SetFieldBased(src[i], 0)
super[i] = core.SetFieldBased(super[i], 0) if super[i] is not None else None
colorspace = src[0].format.color_family
if colorspace == vs.RGB:
src[0] = core.RGB2OPP(src[0], 1)
if colorspace != vs.GRAY:
src_color = src[0]
src[0] = core.ShufflePlanes(src[0], 0, vs.GRAY)
clip = internal.final(core, src, super, radius, pel, sad, sigma, alpha, beta, masking, show)
if colorspace != vs.GRAY:
clip = core.ShufflePlanes([clip, src_color], [0, 1, 2], vs.YUV)
if colorspace == vs.RGB:
clip = core.OPP2RGB(clip, 1)
del core
return clip
def Dilation(src, radius=1):
if not isinstance(src, vs.VideoNode):
raise TypeError("Vine.Dilation: src has to be a video clip!")
if not isinstance(radius, int):
raise TypeError("Vine.Dilation: radius has to be an integer!")
elif radius < 1:
raise RuntimeError("Vine.Dilation: radius has to be greater than 0!")
core = core
src = core.SetFieldBased(src, 0)
clip = internal.dilation(core, src, radius)
del core
return clip
def Erosion(src, radius=1):
if not isinstance(src, vs.VideoNode):
raise TypeError("Vine.Erosion: src has to be a video clip!")
if not isinstance(radius, int):
raise TypeError("Vine.Erosion: radius has to be an integer!")
elif radius < 1:
raise RuntimeError("Vine.Erosion: radius has to be greater than 0!")
core = core
src = core.SetFieldBased(src, 0)
clip = internal.erosion(core, src, radius)
del core
return clip
def Closing(src, radius=1):
if not isinstance(src, vs.VideoNode):
raise TypeError("Vine.Closing: src has to be a video clip!")
if not isinstance(radius, int):
raise TypeError("Vine.Closing: radius has to be an integer!")
elif radius < 1:
raise RuntimeError("Vine.Closing: radius has to be greater than 0!")
core = core
src = core.SetFieldBased(src, 0)
clip = internal.closing(core, src, radius)
del core
return clip
def Opening(src, radius=1):
if not isinstance(src, vs.VideoNode):
raise TypeError("Vine.Opening: src has to be a video clip!")
if not isinstance(radius, int):
raise TypeError("Vine.Opening: radius has to be an integer!")
elif radius < 1:
raise RuntimeError("Vine.Opening: radius has to be greater than 0!")
core = core
src = core.SetFieldBased(src, 0)
clip = internal.opening(core, src, radius)
del core
return clip
def Gradient(src, radius=1):
if not isinstance(src, vs.VideoNode):
raise TypeError("Vine.Gradient: src has to be a video clip!")
if not isinstance(radius, int):
raise TypeError("Vine.Gradient: radius has to be an integer!")
elif radius < 1:
raise RuntimeError("Vine.Gradient: radius has to be greater than 0!")
core = core
src = core.SetFieldBased(src, 0)
clip = internal.gradient(core, src, radius)
del core
return clip
def TopHat(src, radius=1):
if not isinstance(src, vs.VideoNode):
raise TypeError("Vine.TopHat: src has to be a video clip!")
if not isinstance(radius, int):
raise TypeError("Vine.TopHat: radius has to be an integer!")
elif radius < 1:
raise RuntimeError("Vine.TopHat: radius has to be greater than 0!")
core = core
src = core.SetFieldBased(src, 0)
clip = internal.tophat(core, src, radius)
del core
return clip
def BlackHat(src, radius=1):
if not isinstance(src, vs.VideoNode):
raise TypeError("Vine.BlackHat: src has to be a video clip!")
if not isinstance(radius, int):
raise TypeError("Vine.BlackHat: radius has to be an integer!")
elif radius < 1:
raise RuntimeError("Vine.BlackHat: radius has to be greater than 0!")
core = core
src = core.SetFieldBased(src, 0)
clip = internal.blackhat(core, src, radius)
del core
return clip
See the error message next page:
WaxCyl
28th May 2023, 13:29
Here is the error message:
2023-05-28 22:03:32.061
Failed to evaluate the script:
Python exception: No attribute with the name NLmeans exists. Did you mistype a plugin namespace?
Traceback (most recent call last):
File "src\cython\vapoursynth.pyx", line 3115, in vapoursynth._vpy_evaluate
File "src\cython\vapoursynth.pyx", line 3116, in vapoursynth._vpy_evaluate
File "E:/VapourProject.vpy", line 30, in
ref = Vine.Basic(clip, h=31.18, sharp=0.48)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Program Files\Python311\Lib\site-packages\Vine.py", line 208, in Basic
clip = internal.basic(core, src, a, h, sharp, cutoff)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Program Files\Python311\Lib\site-packages\Vine.py", line 115, in basic
upsampled = core.NLmeans(upsampled, a, 0, h, None)
^^^^^^^^^^^^
File "src\cython\vapoursynth.pyx", line 2628, in vapoursynth._CoreProxy.__getattr__
File "src\cython\vapoursynth.pyx", line 2483, in vapoursynth.Core.__getattr__
AttributeError: No attribute with the name NLmeans exists. Did you mistype a plugin namespace?
I will be very appreciative of any assistance
richardpl
29th May 2023, 10:31
Am I only one to spot that those morphological filters in here are using extremely inefficient algorithm?
WaxCyl
30th May 2023, 03:18
I think it it may be because Feisty2 placed the highest possible priority on image quality, above all else?
richardpl
30th May 2023, 13:15
I get same quality/output if not much better quality with much faster algorithm. Feel free to keep wasting CPU cycles on crappy morphological implementations.
WaxCyl
31st May 2023, 00:15
OK thanks for your thoughts. I have found Vine to be extremely good and found others to be not very effective. Maybe I am not fine tuning them effectively? What other halo remover would you suggest?
richardpl
31st May 2023, 18:11
I havent looked at dehalo quality, but I just noticed part of code use slow algorithms.
WaxCyl
1st June 2023, 10:41
I have noticed that Dogway has updated Feisty2's Plum and Oyster . Hopefully Vine gets updated eventually! :)
vBulletin® v3.8.11, Copyright ©2000-2025, vBulletin Solutions Inc.