View Full Version : How would I remove grains from a video ?
Batman007
24th February 2015, 15:12
Hi guys
I got a movie of 1987 having grains in it .... How do I remove those grains ?
Please give me plugins and filters for DeGraining ....
Thank you .......
StainlessS
24th February 2015, 15:19
http://avisynth.nl/index.php/External_filters#Denoisers
I like (others will differ)
Spatial: VagueDenoise().
SpatioTemporal: FFT3DFilter(), HqDN3D() [fast], MCDegrain script.
MCDegrain by Didee (requires MVTools v2.0, heavy duty grain removal)
Function MCDegrain(clip c, int "frames")
{ # By Didee, http://forum.doom9.org/showthread.php?p=1508289#post1508289
frames = default(frames, 2)
bs = (c.width>960) ? 16 : 8
super = c.MSuper(pel=2, sharp=1)
backward_vec3 = MAnalyse(super, isb = true, delta = 3, blksize=bs, overlap=bs/2)
backward_vec2 = MAnalyse(super, isb = true, delta = 2, blksize=bs, overlap=bs/2)
backward_vec1 = MAnalyse(super, isb = true, delta = 1, blksize=bs, overlap=bs/2)
forward_vec1 = MAnalyse(super, isb = false, delta = 1, blksize=bs, overlap=bs/2)
forward_vec2 = MAnalyse(super, isb = false, delta = 2, blksize=bs, overlap=bs/2)
forward_vec3 = MAnalyse(super, isb = false, delta = 3, blksize=bs, overlap=bs/2)
(frames<=0) ? c :\
(frames==1) ? c.MDegrain1(super, backward_vec1,forward_vec1,thSAD=400) :\
(frames==2) ? c.MDegrain2(super, backward_vec1,forward_vec1,backward_vec2,forward_vec2,thSAD=400) :\
c.MDegrain3(super, backward_vec1,forward_vec1,backward_vec2,forward_vec2,backward_vec3,forward_vec3,thSAD=400)
return(last)
}
Function MCDegrainSharp(clip c, int "frames", float "bblur", float "csharp", bool "bsrch")
{ # Based on MCDegrain By Didee, http://forum.doom9.org/showthread.php?t=161594
# Also based on DiDee observations in this thread: http://forum.doom9.org/showthread.php?t=161580
# "Denoise with MDegrainX, do slight sharpening where motionmatch is good, do slight blurring where motionmatch is bad"
# In areas where MAnalyse cannot find good matches, the blur() will be dominant.
# In areas where good matches are found, the sharpen()'ed pixels will overweight the blur()'ed pixels
# when the pixel averaging is performed.
frames = default(frames, 2)
bblur = default(bblur, 0.6)
csharp = default(csharp, 0.6)
bsrch = default(bsrch, true)
bs = (c.width>960) ? 16 : 8
c2 = c.blur(bblur)
super = bsrch ? c2.MSuper(pel=2, sharp=1) : c.MSuper(pel=2, sharp=1)
super_rend = c.sharpen(csharp).MSuper(pel=2, sharp=1,levels=1)
backward_vec3 = MAnalyse(super, isb = true, delta = 3, blksize=bs, overlap=bs/2)
backward_vec2 = MAnalyse(super, isb = true, delta = 2, blksize=bs, overlap=bs/2)
backward_vec1 = MAnalyse(super, isb = true, delta = 1, blksize=bs, overlap=bs/2)
forward_vec1 = MAnalyse(super, isb = false, delta = 1, blksize=bs, overlap=bs/2)
forward_vec2 = MAnalyse(super, isb = false, delta = 2, blksize=bs, overlap=bs/2)
forward_vec3 = MAnalyse(super, isb = false, delta = 3, blksize=bs, overlap=bs/2)
(frames<=0) ? c :\
(frames==1) ? c2.MDegrain1(super_rend, backward_vec1,forward_vec1,thSAD=400) :\
(frames==2) ? c2.MDegrain2(super_rend, backward_vec1,forward_vec1,backward_vec2,forward_vec2,thSAD=400) :\
c2.MDegrain3(super_rend, backward_vec1,forward_vec1,backward_vec2,forward_vec2,backward_vec3,forward_vec3,thSAD=400)
return(last)
}
Witzig
24th February 2015, 16:06
I second StainlessS.
On a side note: grain is detail. In my opinion, especially with old movies, the movies look better with the grain preserved. Just some food for thought.
johnmeyer
24th February 2015, 19:52
Completely removing grain can make the film look artificial and odd. I suggest that your goal should be grain reduction, and not removal.
There are several threads about restoring old film, and several excellent scripts for not only reducing grain, but also removing dirt, removing gate weave, improving color, correcting gamma, etc. Here is a link to one of those threads:
The power of Avisynth: restoring old 8mm films (http://forum.doom9.org/showthread.php?p=1711026)
Stormborec
24th February 2015, 19:58
Removing grain = removing details.
Fast, but destroying: removegrain(1) / (2) / (3) / (4)
Compromise: fft3dfilter(sigma=x) /Fastdegrain(x) /Edgecleaner(x)
Slow - just experimental: MCtemporaldegrain/ Dfttest
Sparktank
25th February 2015, 02:22
I also agree grain should be touched ever so lightly or not at all.
A prime example, funnily enough, is a 1987 film of Predator.
I read so many reviews when the "Ultimate Hunter Edition" came out only to find out it's heavily DNR'ed and looked like wax to so many people.
I went store to store to look for the first release of the movie, with the grain.
It was significantly cheaper since the UHE was available.
I've personally never dealt with grain removal, but I would go with any of the above for their experience.
EDIT: Assuming the source is progressive:
You can add this right after the source filter so you can trim the video down to 5 minutes or less for test encoding with the various degraining filters:
### NTSC VALUES # (24000 / 1001 = 23.97602397602398)
## 30s=719 | 1min=1438 | 2min=2877 | 3min=4315 | 4min=5754 | 5min=7192 | 10min=14385 ########
SelectRangeEvery(every=1500, length=71, offset=0, audio=false).Trim(0, 7192)
The number sign (#) is a comment sign that gets ignored in scripts.
71 seconds will give you over a minute of video frames, which should do well to judge a scene long enough.
I luck out during scene changes.
The Trim at the end you can change from 7192 (5min) to any thing else, as long as it's equal to the source frame rate (23.976, 24, 25; all after deinterlacing/detelecining).
You'll get 5min of a test encode using each variation of degraining and you can judge yourself what suits your own needs, as grain is a highly subjective nature rather than an objective nature.
It would look like this really...
degrain.avs
SetMemoryMax(512)
LoadPlugin(whatever)
FFVideoSource("source.mkv", cachefile="source.mkv.ffindex")
## TFM order | -1 auto | 0 BFF | 1 TFF #
#tfm(order=0, mode=5, slow=2, pp=7, field=0).TDecimate(mode=1, hybrid=1).Vinverse()
#remove comment for above line if it needs detelecine for 1080i film.
### NTSC VALUES # (24000 / 1001 = 23.97602397602398)
## 30s=719 | 1min=1438 | 2min=2877 | 3min=4315 | 4min=5754 | 5min=7192 | 10min=14385 ########
SelectRangeEvery(every=1500, length=71, offset=0, audio=false).Trim(0, 7192)
DeRingFiler()
Change "DeRingFilter()" to whatever filter the others have suggested.
If you want to use SetMTMode() with it, you'll have to make sure any dependancy plugins are updated for whatever version of Avisnynth you are using (assuming you are using most current AviSynth 2.6.0 RC1 [Jan 14th, 2015] (http://forum.doom9.org/showthread.php?t=171668)).
Alternatively, for a speed boost, you can also try out ThreadRequest() (http://forum.doom9.org/showthread.php?p=1404556#post1404556) and add it to the end most lines after the source line (FFVideoSource, DirectShowSource, DGsource, etc) as ".ThreadRequest()".
But, ThreadRequest is more stable without SetMTMode, but some have experimented with the combination of the two, I have yet to see a difference myself, so it's largely dependent on what filters are used and how...
TMI.
SelectRangeEvery(every=1500, length=71, offset=0, audio=false).Trim(0, 7192).ThreadRequest()
Batman007
27th February 2015, 17:20
See how much grains are in the video http://prntscr.com/69n99z... and its BD ..... Please tell me perfect filter so I can encode within less time possible and which will make grains invisible or less ..
johnmeyer
27th February 2015, 20:11
See how much grains are in the video http://prntscr.com/69n99z... and its BD ..... Please tell me perfect filter so I can encode within less time possible and which will make grains invisible or less ..
1. There is no "perfect" filter.
2. All filters take a lot of time to do their work.
3. Nothing will make the grain completely invisible without also introducing new artifacts that will be more objectionable than the grain.
Your expectations are completely unrealistic.
Sparktank
28th February 2015, 03:07
http://prntscr.com/69n99z
Looks pretty old. Removing a lot of grain would probably destroy the quality/details.
Today, we're spoiled with films switching over to digital cameras for filming movies.
I would leave it as it is.
Depending on your PC specs, you're probably looking at a 48hr+ encode time.
I've got 28 Days Later (the first movie) and it was filmed on a very low budget. The grain and noise in it is severe. I've decided to leave it on the disc and bare with it.
Batman007
1st March 2015, 16:20
Looks pretty old. Removing a lot of grain would probably destroy the quality/details.
Today, we're spoiled with films switching over to digital cameras for filming movies.
I would leave it as it is.
Depending on your PC specs, you're probably looking at a 48hr+ encode time.
I've got 28 Days Later (the first movie) and it was filmed on a very low budget. The grain and noise in it is severe. I've decided to leave it on the disc and bare with it.
Yeah ... Movie is of 1987 .... I would keep the grains as they're ...
feisty2
1st March 2015, 16:42
TNLMeans (ax=32, ay=32, az=6, bx=0, by=0, sx=16, sy=16)
Stereodude
1st March 2015, 16:52
See how much grains are in the video http://prntscr.com/69n99z... and its BD ..... Please tell me perfect filter so I can encode within less time possible and which will make grains invisible or less ..
MCTD (http://forum.doom9.org/showthread.php?t=139766) is probably your best bet at minimizing the grain. It's quite slow and is hard to multithread. So, generally if I'm going to process a BD I break the movie up into 4 equal sized pieces with trim() and process all 4 pieces to a lossless intermediate file at the same time with 2 pieces each on 2 different computers. Then I combine the 4 lossless pieces with an AVIsynth script to feed to x264. If you cut it up into pieces you'll probably want to overlap a few frames on the ends of the clips because it's a temporal filter.
So as an example, if I had a 40000 frame clip to MCTD I will do 0-10010, 9990-20010, 19990-30010, 29990-40000 as the 4 pieces. Then I cut 10 frames off the start and end of the 2 middle clips and 10 off the end of the first / 10 off the start of the last when combining them.
feisty2
1st March 2015, 16:59
MCTD (http://forum.doom9.org/showthread.php?t=139766) is probably your best bet at minimizing the grain.
TNLMeans is even better theoretically, it's not popular only because it's slow like hell, but if you got a fancy computer or whatever, replace MCTD with it.
feisty2
1st March 2015, 17:45
theoretical quality compare of some common video denoise filters
BM4D > NLMeans > Motion Compensate > Frequency Filters (FFT/DFT..) > Bilateral > Median Filter > simple linear filters (Gaussian Filter, Wiener Filter...)
Overdrive80
1st March 2015, 17:52
I hope that this script you like it:
You can fit this paremeters for decreasing or increasing denoise (thSAD=250, thSAD2=120,sbright=3.5, smedium=0.38, sdark=0,tr = 4)
original=last
pre=original.BrightDfttestMod(sbright=3.5, smedium=0.38, sdark=0,th_low=20, th_med=40, th_high=100, tbsize=1,lsb=true,mode=6)
mascara=original.mt_edge("hprewitt",thY1=8, thY2=255,thc1=0,thc2=255)
prefiltrado=mt_merge(pre, original, mascara,u=2,v=2)
#Temporal degrain
tr = 4 #Stepping
super= MSuper(prefiltrado,mt=true)
multi_vec = MAnalyse (super, multi=true, delta=tr, blksize=8, overlap=4,search=4, searchparam=3,dct=10)
last=prefiltrado.MDegrainN (super, multi_vec, tr, thSAD=250, thSAD2=120,plane=4,lsb=true,thSCD1=500,thSCD2=160).ditherpost(mode=6)
gradfun3(mode=6,lsb_in=true, lsb=false)
BrightDfttestMod:
function BrightDfttestMod(clip input, float "sbright", float "smedium", float "sdark",
\ int "th_low", int "th_med", int "th_high", int "tbsize", bool "lsb", bool "lsb_in", int "mode")
{
sbright = default( sbright, 0 )
smedium = default( smedium, 0 )
sdark = default( sdark, 0 )
th_low = default( th_low, 20 )
th_med = default( th_med, 40 )
th_high = default( th_high, 100 )
lsb = default( lsb, false )
lsb_in = default( lsb_in, false )
mode = default( mode, 0 )
#It isn't correct to use lsb_in&&lsb==true at the same time
Assert(!(lsb==true && lsb_in==true), "This function not return lsb clip, if lsb_in=true then set lsb=false")
bright = (sbright > 0 && lsb==true && lsb_in==false) ? input.dfttest(sigma = sbright,tbsize=tbsize,sbsize=18,sosize=9,lsb=lsb,lsb_in=lsb_in).ditherpost(mode=mode):\
(sbright > 0 && lsb==false && lsb_in==true) ? input.dfttest(sigma = sbright,tbsize=tbsize,sbsize=18,sosize=9,lsb=lsb,lsb_in=lsb_in):\
(sbright > 0 && lsb==false && lsb_in==false) ? input.dfttest(sigma = sbright,tbsize=tbsize,sbsize=18,sosize=9,lsb=lsb,lsb_in=lsb_in):input
medium = (smedium > 0 && lsb==true && lsb_in==false) ? input.dfttest(sigma = smedium,tbsize=tbsize,sbsize=18,sosize=9,lsb=lsb,lsb_in=lsb_in).ditherpost(mode=mode):\
(smedium > 0 && lsb==false && lsb_in==true) ? input.dfttest(sigma = smedium,tbsize=tbsize,sbsize=18,sosize=9,lsb=lsb,lsb_in=lsb_in):\
(smedium > 0 && lsb==false && lsb_in==false) ? input.dfttest(sigma = smedium,tbsize=tbsize,sbsize=18,sosize=9,lsb=lsb,lsb_in=lsb_in):input
dark = (sdark > 0 && lsb==true && lsb_in==false) ? input.dfttest(sigma = sdark,tbsize=tbsize,sbsize=18,sosize=9,lsb=lsb,lsb_in=lsb_in).ditherpost(mode=mode):\
(sdark > 0 && lsb==false && lsb_in==true) ? input.dfttest(sigma = sdark,tbsize=tbsize,sbsize=18,sosize=9,lsb=lsb,lsb_in=lsb_in):\
(sdark > 0 && lsb==false && lsb_in==false) ? input.dfttest(sigma = sdark,tbsize=tbsize,sbsize=18,sosize=9,lsb=lsb,lsb_in=lsb_in):input
mmask = medium.levels(th_med, 1.0, th_high, 255, 0, false)
dmask = medium.levels(th_low, 1.0, th_med, 255, 0, false)
output = bright.mt_merge(medium, mmask, U=3, V=3, luma=true)
\ .mt_merge(dark, dmask, U=3, V=3, luma=true)
return output
}
papcom
18th March 2015, 20:16
http://avisynth.nl/index.php/External_filters#Denoisers
I like (others will differ)
Spatial: VagueDenoise().
SpatioTemporal: FFT3DFilter(), HqDN3D() [fast], MCDegrain script.
MCDegrain by Didee (requires MVTools v2.0, heavy duty grain removal)
@stainless - I would like to try Your script but I still am not successful. I do not know where to put the Video. I have read on the mvtools guide and on other threads ...but I do not yet understand the principle with the function call.
Where do I put "myavi.avi" in order that it will be processed by Your script?
StainlessS
18th March 2015, 20:49
Import("MCDegrain.avs") # assumes that Didee's script saved as MCDegrain.avs
AviSource("myavi.avi")
MCDegrain(frames=3) # 1 to 3, 3 heaviest
#MCDegrainSharp(frames=3)
papcom
18th March 2015, 23:02
Import("MCDegrain.avs") # assumes that Didee's script saved as MCDegrain.avs
AviSource("myavi.avi")
MCDegrain(frames=3) # 1 to 3, 3 heaviest
#MCDegrainSharp(frames=3)
thank You @stainlesss - Your script consists of two functions (MCDegrain and MCDegrainSharp). Is it correct that I save these both functions in one script as MCDegrain.avs?
Is there another way which works without the import avs? ...e.g. to put the videofile at the beginning or the end of the function(s). I saw in the documentation an example where the avi source it inserted after the function...like:
fields.MDegrain2(super, backward_vec2,forward_vec2,backward_vec4,forward_vec4,thSAD=400)
Weave()
}
AVISource("video.avi")
mdegrain2i2(4,0)
StainlessS
18th March 2015, 23:09
If you want, the MCDegrainSharp was an additional suggestion (by myself) and changed a little by Didee.
If you dont want that one then just delete from avs.
There is nothing wrong in having multiple functions in a single script.
EDIT: Yes, you can just add the script functions instead of import, import is convenient if you want to keep the
script for use at any time. I use a 'BANK' folder to hold multiple avs scripts that I often use.
And you can put functions anywhere in script, either before or after eg AVISource(), it does not matter where they are.
papcom
19th March 2015, 00:15
thanks @stainlesss - I understand the avs Import but still I don't understand the position and manner where to place the avisource command.
In Your example I put it just before the function script or behind... it shows the avi but it is not processed (as far as I see). How do I relate the function to the video? ...how is the function assigned to the video?
In my sample from the documentation of MVTools the avisource is somehow at the end after the function? Why? How does this work?
Sorry for the simplicity of my question, but I must understand something before I can use it. Perhaps You can show me a small example? Thanks a lot.
StainlessS
19th March 2015, 00:25
Import("D:\avs\Bank\MCDegrain.avs") # Import is exactly the same as Pasting the script function HERE.
Avisource("D:\avs\test.avi") # Clip in special Last variable as not assigned to anything
MCDegrain(3) # Calls MCDegrain using implicit Last clip variable, as not explicitly supplied.
Return Last
Avisource("D:\avs\test.avi") # Clip in special Last variable as not assigned to anything
MCDegrain(3) # Calls MCDegrain using implicit Last clip variable, as not explicitly supplied.
Return Last
Function MCDegrain(clip c, int "frames")
{ # By Didee, http://forum.doom9.org/showthread.php?p=1508289#post1508289
frames = default(frames, 2)
bs = (c.width>960) ? 16 : 8
super = c.MSuper(pel=2, sharp=1)
backward_vec3 = MAnalyse(super, isb = true, delta = 3, blksize=bs, overlap=bs/2)
backward_vec2 = MAnalyse(super, isb = true, delta = 2, blksize=bs, overlap=bs/2)
backward_vec1 = MAnalyse(super, isb = true, delta = 1, blksize=bs, overlap=bs/2)
forward_vec1 = MAnalyse(super, isb = false, delta = 1, blksize=bs, overlap=bs/2)
forward_vec2 = MAnalyse(super, isb = false, delta = 2, blksize=bs, overlap=bs/2)
forward_vec3 = MAnalyse(super, isb = false, delta = 3, blksize=bs, overlap=bs/2)
(frames<=0) ? c :\
(frames==1) ? c.MDegrain1(super, backward_vec1,forward_vec1,thSAD=400) :\
(frames==2) ? c.MDegrain2(super, backward_vec1,forward_vec1,backward_vec2,forward_vec2,thSAD=400) :\
c.MDegrain3(super, backward_vec1,forward_vec1,backward_vec2,forward_vec2,backward_vec3,forward_vec3,thSAD=400)
return(last)
}
Function MCDegrain(clip c, int "frames")
{ # By Didee, http://forum.doom9.org/showthread.php?p=1508289#post1508289
frames = default(frames, 2)
bs = (c.width>960) ? 16 : 8
super = c.MSuper(pel=2, sharp=1)
backward_vec3 = MAnalyse(super, isb = true, delta = 3, blksize=bs, overlap=bs/2)
backward_vec2 = MAnalyse(super, isb = true, delta = 2, blksize=bs, overlap=bs/2)
backward_vec1 = MAnalyse(super, isb = true, delta = 1, blksize=bs, overlap=bs/2)
forward_vec1 = MAnalyse(super, isb = false, delta = 1, blksize=bs, overlap=bs/2)
forward_vec2 = MAnalyse(super, isb = false, delta = 2, blksize=bs, overlap=bs/2)
forward_vec3 = MAnalyse(super, isb = false, delta = 3, blksize=bs, overlap=bs/2)
(frames<=0) ? c :\
(frames==1) ? c.MDegrain1(super, backward_vec1,forward_vec1,thSAD=400) :\
(frames==2) ? c.MDegrain2(super, backward_vec1,forward_vec1,backward_vec2,forward_vec2,thSAD=400) :\
c.MDegrain3(super, backward_vec1,forward_vec1,backward_vec2,forward_vec2,backward_vec3,forward_vec3,thSAD=400)
return(last)
}
Video = Avisource("D:\avs\test.avi") # assigned to Video
Video2 = MCDegrain(Video,3) # Calls MCDegrain using Video clip variable
Return Video2
papcom
19th March 2015, 00:31
thank You so much @stainlesss , that's very kind. I will study Your samples.
papcom
19th March 2015, 15:06
@stainlesss - principally I was successful with Your scriptsamples. The result is good and improves my noisy Hi8 sources nicely.
I am mostly working with 720x576i ProRes files. I think therefore I have some fields issues with the interlaced material. My actual Adaptation of Your script Looks like this:
SetMemoryMax(1024)
SetMTMode(5,6)
#~ AVISource("c:\videodaten\intensitytest8mm.avi").ConvertToYV12.AssumeTFF().waveform().SeparateFields() # Clip in special Last variable as not assigned to anything
qtinput("C:\myvideo.mov", color=2, audio=1).ConvertToYV12.AssumeTFF()
SetMTMode(2)
MCDegrain(3) # Calls MCDegrain using implicit Last clip variable, as not explicitly supplied. (1=light/3=full)
return last
Function MCDegrain(clip c, int "frames")
{ # By Didee, http://forum.doom9.org/showthread.php?p=1508289#post1508289
frames = default(frames, 2)
bs = (c.width>960) ? 16 : 8
super = c.MSuper(pel=2, sharp=1)
backward_vec3 = MAnalyse(super, isb = true, delta = 3, blksize=bs, overlap=bs/2)
backward_vec2 = MAnalyse(super, isb = true, delta = 2, blksize=bs, overlap=bs/2)
backward_vec1 = MAnalyse(super, isb = true, delta = 1, blksize=bs, overlap=bs/2)
forward_vec1 = MAnalyse(super, isb = false, delta = 1, blksize=bs, overlap=bs/2)
forward_vec2 = MAnalyse(super, isb = false, delta = 2, blksize=bs, overlap=bs/2)
forward_vec3 = MAnalyse(super, isb = false, delta = 3, blksize=bs, overlap=bs/2)
(frames<=0) ? c :\
(frames==1) ? c.MDegrain1(super, backward_vec1,forward_vec1,thSAD=400) :\
(frames==2) ? c.MDegrain2(super, backward_vec1,forward_vec1,backward_vec2,forward_vec2,thSAD=400) :\
c.MDegrain3(super, backward_vec1,forward_vec1,backward_vec2,forward_vec2,backward_vec3,forward_vec3,thSAD=400)
# Crops xx pixels L,T,R,B and resizes to 720x576:
Crop(10, 4, -14, -10).LanczosResize(720, 288)
Weave()
return(last)
}
How do I adapt Your script for interlaced material... especially if I need to crop the source (blanking reasons)?
Where do I insert the crop and resize arguments?
StainlessS
19th March 2015, 18:31
# Crops xx pixels L,T,R,B and resizes to 720x576:
Crop(10, 4, -14, -10).LanczosResize(720, 288)
Weave()
Dont put extra code inside the function, if you must, then slip it in after the function call ie after MCDegrain(3).
I think there is a script function called McDegrain2i2() (or something like that), I rarely keep interlacing, dont like it and
pretty much always get rid for either computer or hand held display.
I see JohnMeyer on-line, perhaps he can advise on the interlaced version of MCDegrain (I looked at wiki and did not spot it).
EDIT: And you cannot just resize interlaced material, that would screw it up (others would be better placed than I to advise on that).
johnmeyer
19th March 2015, 18:57
I see JohnMeyer on-line, perhaps he can advise on the interlaced version of MCDegrain (I looked at wiki and did not spot it).
EDIT: And you cannot just resize interlaced material, that would screw it up.I created a test script for you that uses MDegrain to denoise interlaced footage, and which also includes a call to a re-size function designed for interlaced footage. I've used variations of this script to denoise hundreds of hours of VHS transfers.
I seldom use the re-size function. It was created by someone in these forums, and seemed to work pretty well, but I make no claims beyond that.
Block size of 8 is usually good for VHS. You get better quality in the shadows and in flat areas if you use an overlap of 2 or 4 (overlap must be mod2, I think). However, using larger overlap values will slow down the script. Use the commented out stackhorizontal line to view the before/after side-by-side to see if you get better results with different overlaps. You can also experiment with block sizes of 4 (slower) or 16 (faster) to see if the quality is better or worse. Smaller block sizes do not always result in better quality and are therefore not worth the considerable performance penalty.
Most important, play around with the strength parameter. This may have to be adjusted when you change block size.
I also have another version that uses MRecalculate in the motion estimation which sometimes (although not always) produces better results, in less time.
As always, even if you don't change the script, you will need to tune the block size, overlap and strength to fit your particular needs. There is no "one size fits all" approach.
SetMemoryMax(768)
Loadplugin("C:\Program Files\AviSynth 2.5\plugins\MVTools\mvtools2.dll")
SetMTMode(5,6)
source=AVISource("E:\fs.avi").killaudio().AssumeBFF()
SetMTMode(2)
output=MDegrain2i2(source,8,2,400,0)
#output=IResize(output,720,480)
#stackhorizontal(source,output)
return output
#-------------------------------
function MDegrain2i2(clip source, int "blksize", int "overlap", int "strength", int "dct")
{
fields=source.SeparateFields() # separate by fields
super = fields.MSuper(pel=2, sharp=1)
backward_vec2 = super.MAnalyse(isb = true, delta = 2, blksize=blksize, overlap=overlap, dct=dct)
forward_vec2 = super.MAnalyse(isb = false, delta = 2, blksize=blksize, overlap=overlap, dct=dct)
backward_vec4 = super.MAnalyse(isb = true, delta = 4, blksize=blksize, overlap=overlap, dct=dct)
forward_vec4 = super.MAnalyse(isb = false, delta = 4, blksize=blksize, overlap=overlap, dct=dct)
MDegrain2(fields,super, backward_vec2,forward_vec2,backward_vec4,forward_vec4,thSAD=strength)
Weave()
}
function IResize(clip Clip, int NewWidth, int NewHeight)
{
Clip
SeparateFields()
Shift=(GetParity() ? -0.25 : 0.25) * (Height()/Float(NewHeight/2)-1.0)
E = SelectEven().Spline36resize(NewWidth, NewHeight/2, 0, Shift)
O = SelectOdd( ).Spline36resize(NewWidth, NewHeight/2, 0, -Shift)
Ec = SelectEven().Spline36Resize(NewWidth, NewHeight/2, 0, 2*Shift)
Oc = SelectOdd( ).Spline36Resize(NewWidth, NewHeight/2, 0, -2*shift)
Interleave(E, O)
IsYV12() ? MergeChroma(Interleave(Ec, Oc)) : Last
Weave()
}
papcom
19th March 2015, 18:59
thanks @stainlesss for your hints.
Yes there is MDegrain2i2 . I used it already in a script-sample of Johnmeyer, which gives also a good result.
I just wanted to try Your (or Didee's) script, but I wasn't aware that interlacing and crop/resize could make difficulties.
EDIT:
@johnmeyer, thank you - I just tried Your above script Proposition. It's fast and neat. I would Need resize because I am always cropping on the sides, as well as top and bottom. Where in Your script would You suggest to insert the cropping?
StainlessS
19th March 2015, 19:08
Thanks for posting the functions John, I've snatched a copy of both. :)
StainlessS
19th March 2015, 19:17
@johnmeyer, thank you - I just tried Your above script Proposition. It's fast and neat. I would Need resize because I am always cropping on the sides, as well as top and bottom. Where in Your script would You suggest to insert the cropping?
Perhaps crop immediately before resize.
Make sure top and bottom crop by multiple of 4 (else damage interlacing).
feisty2
19th March 2015, 19:20
That Iresize ain't no nice solution somehow
U need to resize the interlaced crap progressively where there ain't no motion
And do what "iresize" does where there're moving objects
Then merge'em with a motion mask
StainlessS
19th March 2015, 19:22
That Iresize ain't no nice solution somehow
U need to resize the interlaced crap progressively where there ain't no motion
And do what "iresize" does where there're moving objects
Then merge'em with a motion mask
And do you have a spoon fed recipe for such ?
feisty2
19th March 2015, 19:25
If some parts of the interlaced image like backgrounds stand still, those parts are actually progressive
Trust me, u don't wanna know how screwed up the progressive image could be when resized field based
StainlessS
19th March 2015, 19:28
Is that a 'no' then ? :)
feisty2
19th March 2015, 19:34
And do you have a spoon fed recipe for such ?
We got tmm, tcombmask and things similar, just "iresize" the clip, resize the clip directly like its progressive and resize the mask and merge them together, I'm on cell now, couldn't help for scripts
papcom
19th March 2015, 19:42
Perhaps crop immediately before resize.
Make sure top and bottom crop by multiple of 4 (else damage interlacing).
tried "crop" before function IResize(clip Clip, int NewWidth, int NewHeight) , did not work... and tried "crop" before the line: output=IResize(output,720,576)... get invalid arguments error.
I put the crop into the function MDegrain2i2, just before Weave() ...this crops the Video, but I am unsure.
Where is the correct place for the "crop" of interlaced video
johnmeyer
19th March 2015, 19:50
I direct all those critical of the IResize function to read the long thread where it was developed:
Deinterlace should preserve original pixels? (http://forum.doom9.org/showthread.php?t=140233&page=2)
Much of the discussion was between Gavino and IanB. This particular post, within the thread, provides the first step towards code I used:
IResize (http://forum.doom9.org/showthread.php?p=1173977#post1173977)
The actual IResize function appears a few posts after this one.
I think the argument being made here is that one should use a smart bobber instead of separatefields. However, the point of all the extra code in the IResize function is to provide the re-alignment of a bobber, but with extra adjustments to provide correct shifting for the chroma.
As I said in my original post above, I don't use this function much, and I made no claim about the quality of its results. However, when I did use it, I noticed no problems, and the people who developed it have shown, over the years, that they know what they are doing.
Perhaps someone should try it, and post the results?
feisty2
19th March 2015, 20:04
@johnmeyer
You could try to iresize any progressive clip and the artifacts should pop out any moment
I know it's wrong to iresize progressive clips for sure, but there's no 100% interlaced clip, if the interlaced clip contains any still motionless scene, it would suffer the same
johnmeyer
19th March 2015, 20:05
Taking my own advice, I just resized some 1440x1080 HDV interlaced ballet footage. I looked at fast moving sections where the dancers were leaping and saw absolutely no "ugliness." In fact, I would be hard-pressed to spot any artifacts. I'd post the results, but it would be a case of "nothing to see here, keep on moving ..."
I think I understand the concept of using motion estimation in order to be able to temporarily align each frame's two fields in time so that the resolution (spatial data) from the odd field can be used when resizing the even field (and vice versa). However, since motion estimation also introduces errors, using it may or may not produce a better result. This technique has at least one advantage in that its results are consistent from frame to frame.
By at least doing a separatefields (or a bob), you avoid the huge problem of resizing both fields of interlaced footage at once, i.e., resizing at a frame rather than a field level. That produces completely unusable footage. You must resize at a field level when dealing with interlaced footage.
johnmeyer
19th March 2015, 20:13
@johnmeyer
You could try to iresize any progressive clip and the artifacts should pop out any moment
I know it's wrong to iresize progressive clips for sure, but there's no 100% interlaced clip, if the interlaced clip contains any still motionless scene, it would suffer the sameI understand the concept that an interlaced clip with no movement is identical to progressive.
However, I just went back to my ballet footage, which I took on a tripod. There are sections where the camera is not panning, and the background is absolutely still. I see absolutely nothing "bad" going on. This is true whether I look at the result field-by-field, or frame-by-frame.
Here is the result of resizing to 720x480 from 1440x1080:
Re-sized Test Clip (https://www.mediafire.com/?1ys27f2dlyk61fv)
[edit]Here's the HDV source for that "re-sized test clip":
Source Clip (https://www.mediafire.com/?176rkufe2pplm8s)
feisty2
19th March 2015, 20:16
Sure, will check it out when I got home
Edit: tried upscale? Last time I checked, the artifacts appeared when I tried to upscale some interlaced clips
johnmeyer
19th March 2015, 20:29
Last time I checked, the artifacts appeared when I tried to upscale some interlaced clipsNo, I didn't try that. I've run out of time for now, so I'll have to get back to this later. Thanks for making me think about this again.
edwin_r
30th March 2021, 03:30
Dear StainlessS. Sorry to revive such an old thread. I need to ask if can you give me please an example of MCDegrain to denoising an interlaced source, but with a prefiltered clip for more reliable motion estimation. I need to make some DVD's
Thank you.
StainlessS
30th March 2021, 15:38
I totally dislike Interlaced stuff and always deinterlace, others would likely be better source of advise here.
If was me, then deinterlace using least denoise (whatever args give least denoise for eg QTGMT), to doublerate.
Apply McDegrain to result and then re-interlace.
Boulder gave good args for little denoising something like this [excluding Preset, and NoisePreset,
QTGMC(Preset="Medium",NoisePreset="Faster",SourceMatch=2, Lossless=2, EZKeepGrain=0.4, Sharpness=0.1, tr2=0) # After Presets, from Boulder
And to re-interlace its something like
Deint.SeparateFields.SelectEvery(4,0,3).Weave # Singlerate Re-Interlacing : EDIT: BFF maybe SelectEvery(4,1,2).Weave
johnmeyer
30th March 2021, 15:52
There is always this old chestnut. You'll find it on the AVISynth Wiki:
ApplyInterlacedFilter (http://avisynth.nl/index.php/ApplyInterlacedFilter)
#This applies any filter to an interlaced source. The filter can be used for both spatial filters, like Blur and temporal filters like TemporalSoften.
#Example of usage
#AviSource("file.avi")
#ApplyInterlacedFilter(last, "blur(1.5)")
function ApplyInterlacedFilter(clip v1, string filter)
{
v2 = separatefields(v1)
selecteven(v2)
even = Eval(filter)
selectodd(v2)
odd = Eval(filter)
interleave(even,odd)
return weave()
}
edwin_r
30th March 2021, 19:27
There is always this old chestnut. You'll find it on the AVISynth Wiki:
ApplyInterlacedFilter (http://avisynth.nl/index.php/ApplyInterlacedFilter)
#This applies any filter to an interlaced source. The filter can be used for both spatial filters, like Blur and temporal filters like TemporalSoften.
#Example of usage
#AviSource("file.avi")
#ApplyInterlacedFilter(last, "blur(1.5)")
function ApplyInterlacedFilter(clip v1, string filter)
{
v2 = separatefields(v1)
selecteven(v2)
even = Eval(filter)
selectodd(v2)
odd = Eval(filter)
interleave(even,odd)
return weave()
}
Thanks. I tried this yesterday, but it only access internal commands. You can't cast external ones like LSF, Awarpsharp2, etc. Thank you anyway :)
edwin_r
30th March 2021, 19:32
I totally dislike Interlaced stuff and always deinterlace, others would likely be better source of advise here.
If was me, then deinterlace using least denoise (whatever args give least denoise for eg QTGMT), to doublerate.
Apply McDegrain to result and then re-interlace.
Question: if it gets doublerated, will a temporal denoiser work fine just after that?. Thanks
DTL
30th March 2021, 20:00
For interlaced HDTV (currently produced) I use mvtools with high enough tr :
tr=12
fields=AssumeTFF().SeparateFields()
super=MSuper(fields,pel=1)
multi_vec=MAnalyse (super, multi=true, delta=tr, overlap=4)
MDegrainN(fields,super, multi_vec, tr, thSAD=250, thSAD2=180)
Weave()
where tr - the half num of frames (fields ?) to process for each output field. The more the better noise suppression but also lower speed.
thSAD and thSAD2 - to be adjusted for the noise amount in the input. Too low do not touch noise, too high start to smooth low-contrast details. For newer HDTV cams it is about 250, for old more noisy it may be 400 and more. thSAD2 typically 1/2..2/3 of thSAD I think.
With finally coded MDegrainN() function it starts to be very good and easy to use tool.
DTL
30th March 2021, 20:06
Question: if it gets doublerated, will a temporal denoiser work fine just after that?. Thanks
I think for perfectionists it must be deinterlaced to doublerate (full frame height output) - process and re-interlace. Very slow processing. Because high-quality HDTV deinterlace is also slow. Also perfectionists-level re-interlace is also not very easy task and must be aligned with previous deinterlacing stage.
At least after non-linear deint, the process of interlacing like
SeparateFields.SelectEvery(4,0,3).Weave
Must be preceded by vertical (and possibly also some horizontal) low-pass filter. Because advanced end-only deinterlacer like QTGMC may significally changes spectrum and add new high frequency content that will cause aliasing after simple weaving (it is equal to PointResize(height/2)). And user of pointresize is responsible for spectrum-shaping (conditioning) before downscaling. And spectrum-shaping may be also motion-dependent for not blur static areas etc.
If interlaced content was conditioned by high$$$$ pro/broadcast-graded video camera it is not easy to do same quality level 'interlaced-progressive-interlaced' conversion with freeware tools.
Simple processing of separated fields as frames give acceptable result though may be a bit degrade vertical resolution.
StainlessS
30th March 2021, 20:11
EDIT:
Question: if it gets doublerated, will a temporal denoiser work fine just after that?. Thanks
Yes, should do.
Here latest McDegrain() on-line ver$:- https://forum.doom9.org/showthread.php?p=1926403#post1926403
Can call McDegrain(bblur=0.6) [default=0.0, as Didee original] to use same pre-filter blur as McDegrainSharp().
EDIT: If you change tm=false [truemotion], then also set Glob=true [default is currently same as tm, maybe it should always be true].
EDIT: Might also like to play with one of these experimental funcs:- https://forum.doom9.org/showthread.php?p=1932874#post1932874
edwin_r
2nd April 2021, 04:16
For interlaced HDTV (currently produced) I use mvtools with high enough tr :
tr=12
fields=AssumeTFF().SeparateFields()
super=MSuper(fields,pel=1)
multi_vec=MAnalyse (super, multi=true, delta=tr, overlap=4)
MDegrainN(fields,super, multi_vec, tr, thSAD=250, thSAD2=180)
Weave()
where tr - the half num of frames (fields ?) to process for each output field.
@DTL. I was looking the mvtools2 docs, and saw an example for Mdegrain in case of interlaced stuff.
Obviously, when fields=AssumeTFF().SeparateFields(), deltas becomes evens:
backward_vec2 = super.MAnalyse(isb = true, delta = 2, overlap=overlap, dct=dct)
forward_vec2 = super.MAnalyse(isb = false, delta = 2, overlap=overlap, dct=dct)
backward_vec4 = super.MAnalyse(isb = true, delta = 4, overlap=overlap, dct=dct)
forward_vec4 = super.MAnalyse(isb = false, delta = 4, overlap=overlap, dct=dct)
I'm not sure if MdegrainN's delta parameter gets evens values too i have the doubt, since many scripts i've seen are not made for interlaced. Thus, i modified directly Mdegain2i2, and set
specifically those values for delta, and added a prefilter. It seems to work ok, results are better now (thsad lowered to 200, before prefilter was 300, and even denoises better)
Sorry, i didn't mention before that i don't want to deinterlace.
Now, my question is, if you have a better recomendation for a prefilter than "pre=fluxsmootht(3).removegrain(11)", (this is the example for smdegrain, but i don't use smdegrain anymore, since it stops working randomly in my system and some black blotchers appear, but classic Mdegrain works flawlessly, so i tend to prefer the original scripts)
Thank you :)
" an example for Mdegrain in case of interlaced stuff.
Obviously, when fields=AssumeTFF().SeparateFields(), deltas becomes evens:
backward_vec2 = super.MAnalyse(isb = true, delta = 2, overlap=overlap, dct=dct)"
It is old very large and not user-friendly syntax for initial degarin2/3/4/5/6 functions. Later the lovely MDegrainN function was coded finally in mvtools and you no more need to type awful number of strings for every tr-param value. Also looks MAnalyse was modified to use
multi=true
and gives required multi-frames vec data for MDegrainN.
MAnalyse->multi
When set to true, MAnalyse generates the motion vectors for all the reference frames −delta…−1 and +1…+delta. The resulting clip is made of single MAnalyse results interleaved in the delta order −1, +1, −2, +2, …, −delta, +delta, where negative values indicate backward searchs. This order is similar to the motion vector parameters in MDegrain3. The output clip is intended to be used directly in MDegrainN.
"Mdegain2i2"
tr=2 is too few for great results I think. I usually use something like 10..20+. And above script is for interlaced processing - in and out.
vBulletin® v3.8.11, Copyright ©2000-2026, vBulletin Solutions Inc.