View Full Version : Dark noise reduction ... ?
Sagittaire
13th August 2007, 11:56
There are a filter/script to reduce noise/grain only in dark area? Perhaps a script with masking tools? Filter with progressive filtering level with dark level will be perfect.
Didée
13th August 2007, 12:35
Do you mean like this?
a = source
b = source.denoise()
th_low = 20
th_high = 32
dmask = b.levels(th_low,1.0,th_high,255,0,false)
a.mt_merge(b,dmask,U=3,V=3,luma=true)
Quickest & easiest solution I can think of atm.
If that's basically what you want, it can be sped up, too ... the levels+maskedmerge can be replaced with one single lutxy.
Edit:
Argh, stupid me. Since there's no Y->U/V linking, in this case it can *not* be replaced by a single lutxy. At least not if chroma denoising shall be handled accordingly.
So, above script stays as it is. Same principle & almost same fast as foxy's script below, but tweakable.
foxyshadis
13th August 2007, 17:04
For quick and dirty I like
b=denoised()
mt_merge(last,b,b.mt_invert,luma=true,chroma="process")
But it obviously not very tweakable =p
Sagittaire
18th August 2007, 23:39
thx ... work very well.
Nikos
23rd February 2008, 01:02
If i want stronger denoise in dark areas, the right script is this:
source=last
Bright = source.FFT3dgpu(sigma=1.0)
Dark = source.FFT3dgpu(sigma=4)
th_low = 0
th_high = 40
dmask = Bright.levels(th_low, 1.0, th_high, 255, 0, false)
Bright.mt_merge(Dark, dmask, U=3, V=3, luma=true)
or this:
source=last
Bright = source.FFT3dgpu(sigma=1.0)
Dark = source.FFT3dgpu(sigma=4)
th_low = 0
th_high = 40
dmask = Dark.levels(th_low, 1.0, th_high, 255, 0, false)
Bright.mt_merge(Dark, dmask, U=3, V=3, luma=true)
Please help, i am a little confused. From two above i take same results.
If i want and a third area (th_low = 41, th_high = 80) with medium denoise which is the right script?
:thanks:
Didée
23rd February 2008, 03:29
From two above i take same results.
That's because it doesn't matter if you use a red or a blue screwdriver to screw a screw.
To use an additional intermediate range:
source=last
weak = source.FFT3dgpu(sigma=1.0)
medium = source.FFT3dgpu(sigma=2.5)
strong = source.FFT3dgpu(sigma=4)
th_low = 20
th_med = 40
th_high = 80
mmask = medium.levels(th_med, 1.0, th_high, 255, 0, false)
dmask = medium.levels(th_low, 1.0, th_med, 255, 0, false)
weak.mt_merge(medium, mmask, U=3, V=3, luma=true)
\ .mt_merge(strong, dmask, U=3, V=3, luma=true)
Nikos
23rd February 2008, 05:19
Many thanks Didée for the explanation and the script.
Now i want to apply your Contra-sharpening function to the week range only. The script below is right?
source=last
weak = source.FFT3dgpu(sigma=1.0).contra(source, last)
medium = source.FFT3dgpu(sigma=2.5)
strong = source.FFT3dgpu(sigma=4)
th_low = 20
th_med = 40
th_high = 80
mmask = medium.levels(th_med, 1.0, th_high, 255, 0, false)
dmask = medium.levels(th_low, 1.0, th_med, 255, 0, false)
weak.mt_merge(medium, mmask, U=3, V=3, luma=true)
\ .mt_merge(strong, dmask, U=3, V=3, luma=true)
# Contra-sharpening: sharpen the denoised clip, but don't add more than what was removed previously.
# Here: A simple area-based version with relaxed restriction. The full version is more complicated.
#
function contra (clip clip1, clip clip2)
{
s = clip2.minblur(1,1) # Damp down remaining spots of the denoised clip.
allD = mt_makediff(clip1,clip2) # The difference achieved by the denoising.
ssD = mt_makediff(s,s.removegrain(11,-1)) # The difference of a simple kernel blur.
ssDD = ssD.repair(allD,1) # Limit the difference to the max of what the denoising removed locally.
ssDD = SSDD.mt_lutxy(ssD,"x 128 - abs y 128 - abs < x y ?") # abs(diff) after limiting may not be bigger than before.
clip2.mt_adddiff(ssDD,U=2,V=2) # Apply the limited difference. (Sharpening is just inverse blurring.)
output = last
return(output)
}
# From Didee's MCBob script
function MinBlur(clip clp, int r, int "uv")
{
uv = default(uv,3)
uv2 = (uv==2) ? 1 : uv
rg4 = (uv==3) ? 4 : -1
rg11 = (uv==3) ? 11 : -1
rg20 = (uv==3) ? 20 : -1
medf = (uv==3) ? 1 : -200
RG11D = (r==1) ? mt_makediff(clp,clp.removegrain(11,rg11),U=uv2,V=uv2)
\ : (r==2) ? mt_makediff(clp,clp.removegrain(11,rg11).removegrain(20,rg20),U=uv2,V=uv2)
\ : mt_makediff(clp,clp.removegrain(11,rg11).removegrain(20,rg20).removegrain(20,rg20),U=uv2,V=uv2)
RG4D = (r==1) ? mt_makediff(clp,clp.removegrain(4,rg4),U=uv2,V=uv2)
\ : (r==2) ? mt_makediff(clp,clp.medianblur(2,2*medf,2*medf),U=uv2,V=uv2)
\ : mt_makediff(clp,clp.medianblur(3,3*medf,3*medf),U=uv2,V=uv2)
DD = mt_lutxy(RG11D,RG4D,"x 128 - y 128 - * 0 < 128 x 128 - abs y 128 - abs < x y ? ?",U=uv2,V=uv2)
clp.mt_makediff(DD,U=uv,V=uv)
return(last)
}
If you want post the more complicated version of Contra-sharpening.
Thanks again for your support.
Didée
23rd February 2008, 14:16
Almost right, but not quite. With the code
source = last
weak = source.FFT3dgpu(sigma=1.0).contra(source, last)
you'll nuke out that FFT3dgpu call. "last" cannot refer to previous operations in the same line. Hence, in this code the contra call is the same as "contra(source,source)", which is obviously not what you want. You have to write it like
source = last
weak = source.FFT3dgpu(sigma=1.0)
weak = contra(source, weak)
...
On another note, the function contra is structured inappropriate, since the clip arguments are ordered backwards. (Is that your version, or Sagekilla's, or even Spud's?) The "logical" order would be "contra(denoised,original)". Not the other way round.
The function contra() should look like this:
function contra (clip denoised, clip original)
{
s = denoised.minblur(1,1) # Damp down remaining spots of the denoised clip.
allD = mt_makediff(original,denoised) # The difference achieved by the denoising.
ssD = mt_makediff(s,s.removegrain(11,-1)) # The difference of a simple kernel blur.
ssDD = ssD.repair(allD,1) # Limit the difference to the max of what the denoising removed locally.
ssDD = SSDD.mt_lutxy(ssD,"x 128 - abs y 128 - abs < x y ?") # abs(diff) after limiting may not be bigger than before.
denoised.mt_adddiff(ssDD,U=2,V=2) # Apply the limited difference. (Sharpening is just inverse blurring.)
return( last )
}
Well, confusion ahead: with this version of contra(), the usage code posted further above is no more correct. :)
Now, one would use
source = last
weak = source.FFT3dgpu(sigma=1.0)
weak = contra(weak, source)
...
The point is that now dot-chaining can be used:
source = last
weak = source.FFT3dgpu(sigma=1.0).contra(source)
which was not possible with the wrong-ordered version of contra.
Nikos
23rd February 2008, 18:01
Thanks Didée for the valuable informations, you are a generous man!!!
Yes the mistake in contra sharpening was mine, sorry for this.
Now it's all correct.
Which values are reasonable for the th_low, th_med and th_high parameters in the below script?
I don't want to destroy the details in bright areas.
source=last
weak = source.FFT3dgpu(sigma=1.0)
medium = source.FFT3dgpu(sigma=2.5)
strong = source.FFT3dgpu(sigma=4)
th_low = 20 # ???
th_med = 32 # ???
th_high = 64 # ??? This is important
mmask = medium.levels(th_med, 1.0, th_high, 255, 0, false)
dmask = medium.levels(th_low, 1.0, th_med, 255, 0, false)
weak.mt_merge(medium, mmask, U=3, V=3, luma=true)
\ .mt_merge(strong, dmask, U=3, V=3, luma=true)
If you want post the more complicated version of Contra-sharpening. Now with the High Definition movies i think that the Contra-sharpening is enough (almost).
Didée
23rd February 2008, 18:21
Which thresholds are suited you have to figure for yourself. The whole method is arbitrary, and so are the possible thresholds.
The mentioned "more complicated" version of contra-sharpening uses explicit motion compensation to determine local min/max values for limiting. For scripts without MC it is too elaborate (too little improvement to justify the effort of doing ME+MC solely for that purpose). It's better suited for scripts that use MC anyway, since the costly action of doing a motion search has already been done for the purpose of denoising.
A simple example:
(edit: corrected copy/paste error in the MVCompensate() section) o = last
vbw2 = o.MVAnalyse(isb=true, delta=2, pel=2, blksize=16, overlap=8, idx=1)
vbw1 = o.MVAnalyse(isb=true, delta=1, pel=2, blksize=16, overlap=8, idx=1)
vfw1 = o.MVAnalyse(isb=false, delta=1, pel=2, blksize=16, overlap=8, idx=1)
vfw2 = o.MVAnalyse(isb=false, delta=2, pel=2, blksize=16, overlap=8, idx=1)
comp_bw2 = o.MVCompensate(vbw2, idx=1)
comp_bw1 = o.MVCompensate(vbw1, idx=1)
comp_fw1 = o.MVCompensate(vfw1, idx=1)
comp_fw2 = o.MVCompensate(vfw2, idx=1)
pmax = o.mt_logic(comp_bw1,"max").mt_logic(comp_fw1,"max")
# \ .mt_logic(comp_bw2,"max").mt_logic(comp_fw2,"max")
pmin = o.mt_logic(comp_bw1,"min").mt_logic(comp_fw1,"min")
# \ .mt_logic(comp_bw2,"min").mt_logic(comp_fw2,"min")
interleave(comp_fw2,comp_fw1,o,comp_bw1,comp_bw2)
FFT3DFilter(sigma=5,bt=5) # simple denoiser example
SelectEvery(5,2)
denoised = last
sharp = denoised.sharpen(x) # very simple sharpening
sharp.mt_clamp(pmax,pmin,0,0,U=2,V=2)
Note that scriptlet uses (overly) simple filtering, just to show the general method.
It's mostly suited for sources with strong grain, when using strong mocomp'ed filtering to eliminate the grain. In those cases, the information of "what the denoiser has removed locally" in the current frame might not be sufficient to guide /or limit a sharpening operation. Additionally using the minima and maxima from adjacent frames often seems to work out better.
Nikos
23rd February 2008, 19:04
Just a question, the sharpen(x) is mandatory or optional?
Didée
23rd February 2008, 19:22
It's a basic example. The matter as a whole is complex, and what is suited when and what not and/or when not depends on many different things. So I use basic filters, sort of a placeholder, to give the general idea.
Full dissertations are lengthy, take months or years to write, and can't buy you something to eat.
Terranigma
23rd February 2008, 23:04
Didée, :P
Would you know of a way to use mvdegrain in the same way you have listed here in place of fft3d, or would mvdegrain need to be a standalone function for that to be possible?
If so, i'll try fiddling around with the code to try and make that possible, though i'm not skilled with this stuff.
Never hurts to try though. :D
Didée
24th February 2008, 00:36
That's easy enough. No need for a special version of MVDegrain.
[...]
# interleave(comp_fw2,comp_fw1,o,comp_bw1,comp_bw2)
# FFT3DFilter(sigma=5,bt=5) # simple denoiser example
# SelectEvery(5,2)
o.MVDegrain2(vbw1,vfw1,vbw2,vfw2,idx=1)
denoised = last
[...]
Hint: Required changes are in blue. :p
But methinks now we've drifted far enough from the topic: noise reduction in dark areas.
*sealed*
Nikos
24th February 2008, 15:41
One more question about noise reduction in dark areas.
If i want to see the areas with strong denoise i use the following script:
a = source
b = source.strong_denoise()
th_low = 20
th_high = 32
dmask = b.levels(th_low,1.0,th_high,255,0,false)
# a.mt_merge(b,dmask,U=3,V=3,luma=true)
dmask.greyscale()
The areas with strong denoise are the white. I am correct or not?
Didée
24th February 2008, 16:26
Yes, that's correct. This way of merging can be done in two different ways:
a) make the mask bright for dark areas, then copy the "dark-processed" onto the "normal-processed", using that mask.
b) make the mask bright for bright areas, then copy the "normal-processed" onto the "dark-processed" using that mask.
Both ways are equally feasable, and I had chosen to go by route a).
Nikos
24th February 2008, 17:02
Is this the other way?
a = source
b = source.strong_denoise()
th_low = 20
th_high = 32
dmask = b.levels(th_low,1.0,th_high,0,255,false)
b.mt_merge(a,dmask,U=3,V=3,luma=true)
Sorry for my questions, i try to learn mask tools and without your help it's impossible althought i am physicist :rolleyes:
:thanks:
Didée
24th February 2008, 17:25
Yes, exactly. You see, it's quite easy ... even for physicists. :p
Nikos
2nd March 2008, 01:58
Didée in your post #10 i noticed the two #
pmax = o.mt_logic(comp_bw1,"max").mt_logic(comp_fw1,"max")
# \ .mt_logic(comp_bw2,"max").mt_logic(comp_fw2,"max")
pmin = o.mt_logic(comp_bw1,"min").mt_logic(comp_fw1,"min")
# \ .mt_logic(comp_bw2,"min").mt_logic(comp_fw2,"min")
I suppose without the two # we have more accurate pmin and pmax.
If you want explain the meaning.
Didée
2nd March 2008, 16:18
Yes. "more accurate pmin & pmax" is not a bad description.
Small survey ahead:
The basic idea is, not surprisingly, this: Through strong denoising the signal amplitude of detail may have been flattened more than wanted. The loss of signal amplitude should be recovered by sharpening.
Now, using faint sharpening, that recovery usually is not enough. Using strong sharpening, the recovery is better, but will result in oversharpening in those places where the denoising did not reduce signal amplitude. That's the usual problem of "free" or "unrestricted" sharpening. Therefore, the sharpening should be restricetd in some way. There are several more or less simple methods of limiting:
1) Limiting to the min/max of the spatial neighborhood
That's the way LimitedSharpen works. Drawbacks are: a) this kind of limiting can produce edge aliasing, it requires supersampling or blurring-the-difference to avoid this. b) the local signal amplitude isn't enhanced
2) Limiting according to denoiser's removal
That's the way shown in the script that became TemporalDegrain. Shortly: the difference achieved by the sharpening is limited so that the sharpener may not add more to a pixel than the denoiser previously removed. (practically: ... than the denoiser removed from any pixel in a 3x3 neighborhood.)
Works pretty good for the most part, but has (at least) one weak point: imagine the sharpener is processing a pixel. This very pixel wasn't changed much by the denoiser, but some pixel in the neighborhood have been changed much. Thus, the actual pixel shouldn't get much sharpening, but does because of the neighborhood. That's an issue.
3) Sampling of current pixel's extrema over several frames
That's the method shown here. By using motion compensation, we figure the minimum & maximum values of each pixel over some consecutive frames. The result of the sharpening process is limited to not exceed this temporal [min,max] span.
Keep in mind I'm talking about footage that contains rather strong grain. Processing of rather clean sources with only some minor noise is a much different thing.
One important fact with grainy sources is: the actual value of one pixel doesn't mean anything, or at least not much. A pixel's value may be close to what it should be, or it may be distorted by the grain. Values of single pixels are shady.
That's the reason why method (2) shouldn't be reduced to work with single pixel's difference, and the 3x3-neighborhood-thingy works better, despite the mentioned weakness. When using method (2) with single pixel's difference, too much fluctuations of the initial grain might get re-introduced.
The intend behind method (3) is this: we don't know if a pixel's original value is to be taken serious or not. But we can be pretty sure that the pixel's "real" value is amongst those values that the pixel takes in a sequence of several frames. Therefore, limiting to the mentioned temporal min/max interval is feasable.
A side-effect that can be achieved by (3) at best is: keeping more "energy" in the picture. After strong grain removal, the result often seems to appear "too flat", even if you had used an ideal grain filter. That's because the grain, although being unwanted, still is "something" to the eye. After removing the grain, a good amount of signal energy is taken out of the source, and this energy often is missed then. Using suited sharpening routines, method (3) is the most suited (to my experience) to re-introduce a sufficient amount of that lost energy, without the result appearing too noisy again.
Hopefully, the correlation now becomes clear:
The example script uses 3 frames for figuring the temporal min/max span of a pixel: current, current-1, and current+1. This should be sufficient for many sources with "strong" grain -- however, some sources with "even stronger" grain may benefit from additionally using current-2 and current+2.
Another point then is which kind of sharpening to use ... to give an idea, something in the range of 3x3-kernel sharpening most times is not fully sufficient. The strong filtering required for strong grain removal will remove signal amplitude at several frequency ranges, so ideally you'll need sharpening on serveral frequency ranges too, not just a simple 3x3 kernel or similar.
Sorry for being lengthy. :o
Nikos
2nd March 2008, 23:59
Didée i love your long explanations, they are crystal clear ;)
Tomorrow i will post the results from my tests on one HD-rip with your functions.
:thanks:
Didée
3rd March 2008, 02:10
Have happy playing, it's fun!
After putting together not all, but a good part of the needed procedures, there were things like this:
feeding a grainy DVD (PAL) source ...
http://img507.imageshack.us/img507/1706/grainydvdsourcekn9.th.png (http://img507.imageshack.us/my.php?image=grainydvdsourcekn9.png)
... and ...
http://img507.imageshack.us/img507/2030/grainfiltersurpriseas9.th.png (http://img507.imageshack.us/my.php?image=grainfiltersurpriseas9.png) ... thus quoth the grain filter.
Oops. :D
Arriving at that point, you may sign with 'q.e.d.', probably.
Nikos
3rd March 2008, 17:32
improper results because wrong idx's values in mvtools.
Please, delete this post.
Thanks
Didée
3rd March 2008, 19:01
Please post the script that you used. From the look and from the bitrates of the results, I'm pretty sure that there's one certain mistake in the script, related to pre-filter usage.
BTW, looking at after-scenechange I-frames is not the most useful place to look at. At those frames, mocomp'ed denoisers reach only 50% of their full potential.
Nikos
3rd March 2008, 19:20
I will do the tests again and i will post the results and the scripts.
Didée
3rd March 2008, 20:06
Edit: hey, what happened. A few minutes ago, there were scripts in the post above, and they contained the mistake that I suspected!
Ah, there we are. It seemed suspicious that the bitrate dropped by *such* an additional amount only because of pre-filtering. Also, those screenshots where pre-filtering was used don't look exactly brilliant - too much loss of facial textures.
The mistake is in the idx usage. As a consequence, the pre-filter goes into the end result by 66.6% (with MVdegrain1), where it should not at all.
For a quick fix, in the MVDegrain1 call replaxe "idx1" with "idx1 + 1".
The rest I'll try to put briefly.
The grain seems to have a peak-peak amplitude of roughly 16. That's already on the strong side, and MVDegrain1 is way, way to weak for that. Especially if you follow the grain filter with contra sharpening. If the grain filter is too weak, it will not cancel the grain out, but only flatten it down a bit. But, if the grain is not removed completely, then the contra-sharpening will re-introduce much of the grain that you just tried to remove. And here we come into answering your points ...
re (a): The bitrate went up so strongly again because the grain removal wasn't sufficient. If a grainy sequence looks like 50-57-46-51-58-44-50, and the grain filter produces thereof 50-52-49-50-52-48-50, then the remaining signal is enough that contra-sharpening will amplify it again.
re (b) - impossible is nothing. But in this case too, there's no such thing as "THE" method. There are different possible methods, and some will fit better than others to the actual source in progress. Not a big deal if you're used to look at a source and quickly have an idea what it needs. But a big deal for those that want all-in-wonder functions. :p
re (c): for one, as already mentioned, use stronger degraining like MVDegrain2 or -3. If that's not enough, try TemporalDegrain.
Also, have a look at the start of this thread. After all, that's what this thread is about. ;)
re (d): how comes that lowpass protection into play, all of a sudden? The posted code I once made for protection of simple, not-compensated temporal filters. It doesn't fit that well into the motion-compensated strategies. (Well, it's an issue for those, too ... but I won't open that can of worms now.)
Nikos
3rd March 2008, 21:04
Didée thanks for the support.
I will open a new thread for the correct idx values in mvtools with or without SetMTMode().
Didée
3rd March 2008, 22:20
Last christmas, no shiny new PC was lying under my christmas tree. It's been several years since.
First you need to eat, so I'm still stuck with my two old single core rigs, and thus I can't tell you much about correct usage of MVTools with MT-something.
In any case, the idx in your "Edit Here:" - script is wrong, too. :D
There, you need "idx1 + 1" also in the MVCompensate() lines.
It's not that hard, really. You just need to think a bit about what is happening.
When vectors are computed with pel=2 (or pel=4), the subpel interpolation is done by enlargening the supplied clip by 2x (or 4x).
Now, the point is that these enlarged clips often can be re-used by other filters, to reduce memory usage. (Note that you can always escape the idx-confusion by not specifying idx at all. In that case, every filter will compute its own subpel interpolation, which is safe. But ... scripts like TemporalDegrain would need several GB of RAM then, i.e. could easily exceed the 2GB process limit of 32bit Windows.)
Therefore it's better to understand idx, and use it correctly. There's no sense in using fifteen different interpolations when only one or two are needed.
Let's try with some easy examples.
vector1 = clip1.MVAnalyse( pel=2, idx=5)
This computes motion vectors on the clip "clip1". Because of pel=2, a subpel interpolated clip ("pelclip") is computed: clip1 gets resized to 200%. This resized clip ("pelclip") can be addressed anywhere, anytime in the actual script by using the idx number that was used when the pelclip was created.
clip1.MVCompensate(vector1)
This will correctly compensate clip1 with the vectors of vector1. Since no idx has been specified, MVCompensate will internally make another subpel interpolation of clip1.
It works, but is inefficient. clip1 once has been subsampled, there's not really a point in subsampling it again. Therefore:
clip1.MVCompensate(vectors1, idx=5)
This will correctly compensate clip1. MVCompensate is told to use idx=5, therefore it will look up if idx=5 is already existent. Well yes: idx=5 was used during the MVAnalyse call. Therefore, MVCompensate will compensate clip1 by re-using the subpel interpolation of clip1, made at the time of MVAnalyse.
Now, danger:
clip2.MVCompensate( vectors1, idx=5)
This is NOT correct. We did the motion search on clip1, but we want to compensate clip2 with those vectors. But since pel=2 is used (this info is stored in the vector clips), a subpel interpolation is needed. Well, MVCompensate is told to use idx=5. But idx=5 refers to the pelclip that was made from clip1! Therefore, the last line will not give a compensation of clip2. Instead it will give a compensation of clip1, since that's the corresponding pelclip that MVCompensate was told to use.
To make a correct compensation of clip2, here one needs to use a different idx:
clip2.MVCompensate( vectors1, idx=6)
Here too, MVCompensate will look up if a pelclip of idx=6 already exists. But it doesn't exist yet, and so MVCompensate will create a subpel interpolation of clip2.
And that's the way the story goes, over and over again. When writing a MVTools' script, you need to keep track which idx value corresponds to which clip, and you need to realize when you can re-use already existent idx values (namely when processing the same source clip on which that idx value initially has been introduced), and when you need to use a different idx value (namely when you process a different clip than that on which the idx value initially has been introduced.)
So, this was written pretty quickly from the guts. Perhaps it helps, perhaps it introduces even more confusion. Who knows.
Nikos
3rd March 2008, 23:13
Before a month i obtained my new C2Q, till now i had a good old Pentium 4 and i had not problems with MT modes :)
I understand very well your explanation. I confuse :( with the IanB and Fizick post about mvtools and SetMTMode() or MT().
With SetMTMode() the two or four or six MVAnalyse (bw & fw) need different idx's or not?
With MT() the two or four or six MVAnalyse (bw & fw) need different idx's or not?
IanB:
Code:
global idx = 123
mt("""
global idx = idx + 1
backward_vec1 = MVAnalyse(isb = true, delta = 1, pel = 2, overlap=4, sharp=1, idx = idx)
forward_vec1 = MVAnalyse(isb = false, delta = 1, pel = 2, overlap=4, sharp=1, idx = idx)
last.MVDegrain1(backward_vec1,forward_vec1,thSAD=400,idx=idx)
""", overlap=8)
As MT "Eval"'s the command with a different input clip for each thread this should work as the Rand()
version does without the indeterminacy. Also this probably wants a good amount of overlap so any
motion vectors near the join won't get truncated.
IanB:
Gees guys, take a minute and think about this.
If you are going to use the IDX option in Mvtools with multithreading then you need a scheme
to ensure that every thread has a unique IDX value.
It is easy to test if your current idea is working as expected by putting a SubTitle(String(IDX))
in appropriate places in your script. None of the SetMtMode's are going to allow this.
Fizick:
IanB,
No, every thread should not to have a unique IDX value,
with proper locking.
IanB:
@Fizick,
Well we don't have any Script level locking syntax. And if you put locking in your filter,
then you will probably end up single tasking it. The real problem is the whole IDX concept,
it is unAvisynth. All comunication between modules in MV should be thru the IClip interface
with the Avisynth CACHE providing all the buffering needed, backdoor hacks like private
buffers and IDX numbers make the whole design fragile
Fizick:
IanB, i say about SetMtMode(), not about MT().
if idx is unique for every thread, we will have duplicate caclulation
Two ways:
1. If we preserve indx syntax, I (we or somebody) can implement internal three-state indicator of "interpolated idx frame":
- not-exist (may be calculated and written right now by current thread),
- ready to read (may be read by current thread),
- currently updated by other thread (current thread must wait to read).
2. Yes, it is better to remove idx. It is my dream too. But is need in more work (and some tricks again).
I need to send some parameters about vectors. Avisynth still does not have normal way
to trasfer additional parameters (metadata). When it will be implemented? I do not see it even
in Avisynth 2.6. Currently I consider to use audio parameters as metadata. I will try analyse
and formulate suggestions in MVTools thread.
Final notes.
I (and you) do not have dual-core anyway, but probably you can add some part of AvisynthMT to
version 2.5.8? I say about minimal changes to support MT (and MTi ?) filter only (it is rather stable) as a first step.
How big chages are need?
SetMTmode may be added later, in v2.6.0.
May be tsp can comment this.
IanB:
MVTools stores internal state so when accessed in a normal sequential manner it can reuse
previous calculations to save time. Using the IDX parameter allows different MVAnalyse()
instances to share the same calcs if available.
If you don't set IDX then you cannot share the calc so there can be no speed up but then they cannot be stuffed up.
If the accesses are not sequential then the state is again useless and a full recalc happens. No stuff ups here.
Things go wrong when the shared calculations are not appropriate. Even without an IDX hitting the same
MVAnalyse instance twice at just the right time can confuse things.
g-force
7th March 2008, 18:56
Have happy playing, it's fun!
After putting together not all, but a good part of the needed procedures, there were things like this:
Oops. :D
Arriving at that point, you may sign with 'q.e.d.', probably.
q.e.d. is right! That looks amazing. AND, I'm getting similar results (on my video anyway) with an even simpler filter chain. Nice work!
-G
Nikos
7th March 2008, 19:37
What's the q.e.d?
Edit
Thanks g-force for q.e.d. explain.
g-force
7th March 2008, 20:22
What's the q.e.d?
A latin abbreviation that comes at the end of proofs meaning "That which was to be shown".
-G
Nikos
10th March 2008, 00:52
With this:
source = last
denoise = source.FFT3Dfilter(sigma=8, sigma2=6, sigma3=4, sigma4=3, plane=0, wintype=1, bw=48, bh=48, ow=16, oh=16)
prefilter = mt_lut(denoise,"x 32 < 0 x ?", Y=3, U=3, V=3)
b2_vec=prefilter.MVAnalyse..... idx=1
.....
source.MVDegrain2..... idx=2
i eliminate completly the nasty dancing noise (luma and chroma) in dark areas for the prefilter stage in mvtools. All pixels under 32 now are pure black. But i don't know if this is the correct way.
The right place for mt_lut is before or after fft3dfilter?
Didée help please :confused:
This is my first try in MaskTools, even for me it's was very simple and easy :p
Didée
10th March 2008, 01:02
Well, why not use
prefilter = denoise.blackness()
This will remove even more noise and dancing grain. Okay, it also removes the actual content ... but hey, that's what your line already does for all content with luminance<32, so it's just more consequent.
Nikos
10th March 2008, 01:42
Thanks Didée. The masktools it's very funny :)
By the way the addgrain in MC Noice i think that it's wrong
take a look here (http://forum.doom9.org/showpost.php?p=1110478&postcount=117)
legionator2
21st March 2008, 18:47
a = source
b = source.denoise()
th_low = 20
th_high = 32
dmask = b.levels(th_low,1.0,th_high,255,0,false)
a.mt_merge(b,dmask,U=3,V=3,luma=true)
It's kinda stupid to ask, but I'm still a newbie and I haven't understood all of the script. If I want to apply filters to only the bright area, do you have a suggestion of which values should be given to th_low and th_high parameters?
Nikos
21st March 2008, 19:51
It's simple.
a = source.your_bright__filter()
b = source.your_dark__filter()
th_low = 0
th_high = 32 # change this....
dmask = b.levels(th_low,1.0,th_high,255,0,false)
# or dmask = a.levels(th_low,1.0,th_high,255,0,false)
# same results
a.mt_merge(b,dmask,U=3,V=3,luma=true)
0 - 32 --> "dark" area
32 - 255 --> "bright" area
We make the mask bright for dark areas, then we copy the "dark-processed" onto the "bright-processed", using that mask.
Edit:
Sorry, halfway wrong :) information, see bellow!!!
legionator2
21st March 2008, 20:19
Thanks for the explanation. I understand now :)
Didée
21st March 2008, 21:18
It's simple.
0 - 32 --> "dark" area
32 - 255 --> "bright" area
That's only halfway correct (ergo it's halfway wrong) ...
0 ........... th_low --> "dark area"
th_low ... th_high --> transition from "dark area" to "bright area"
th_high ....... 255 --> "bright area"
With Nikos' example of low=0 / high=32, there will be a 50:50 mix of both clips at luma = 16, meaning that (with standard YUV input) the darkest parts will get only 50% strength of whatever dark_filter does.
My original suggestion was th_low=20, giving full filter strength for the darkest parts.
Nikos
21st March 2008, 23:46
Sorry for the misinterpret :confused:
I read again the levels doc carefully and now the right way and explanation:
source=last
a = source.bright_filter()
b = source.dark_filter()
th_low = 20 # change this if you want
th_high = 32 # change this if you want
dmask = b.levels(th_low,1.0,th_high,255,0,false)
# or dmask = a.levels(th_low,1.0,th_high,255,0,false)
# or dmask = source.levels(th_low,1.0,th_high,255,0,false)
# The mask it's same
a.mt_merge(b,dmask,U=3,V=3,luma=true)
1. 0 ........ th_low --> "dark area", the darkest parts will get full strengh (100%) of dark_filter.
2. th_high ... 255 --> "bright area", the brightest parts will get full strengh (100%) of bright_filter.
3. th_low ...th_high --> linear transition from "dark area" to "bright area", we apply mix of bright_filter and dark_filter. The area near "th_low" will get more dark_filter, the area near "th_high" will get more bright_filter and the area (th_low + th_high) / 2 will get 50% of dark_filter and 50% bright_filter.
Didee thanks again for your support and if i am wrong, please correct me :rolleyes:
Comatose
22nd March 2008, 06:42
Have happy playing, it's fun!
After putting together not all, but a good part of the needed procedures, there were things like this:
feeding a grainy DVD (PAL) source ...
Poke! Can you share this script with us? I'd really like to see what you did to remove all that grain and restore so much detail that's already weak in the input clip.
Learning from examples is easier than learning from the documentation ;)
vBulletin® v3.8.11, Copyright ©2000-2026, vBulletin Solutions Inc.