PDA

View Full Version : Equivalent to CCE's low pass filter in AviSynth?


FlimsyFeet
30th September 2008, 14:10
From the CCE manual:
"It is a low pass filter to cut out the higher frequency components at specific frequencies. It tends to make the image blur or smooth."

http://img339.imageshack.us/img339/8255/ccenw5.png (http://imageshack.us)

Firstly, I'm not sure why the deafult is 4.5MHz when DVDs have an equivalent "analogue" resolution of ~ 6.75MHz?

But let's say I have a capture from an analogue format such as VHS (3MHz) or laserdisc (5MHz). Anything above these frequencies would be random noise and not real detail? So you could in theory run the video through a low pass filter which will smooth the image withou actually removing detail?

Is there anything in Avisytnh that can do this? The closest I could find is Defreq, but that seems to be designed for something different.

hanfrunz
30th September 2008, 16:59
Low and Highpass filtering is normaly done with a FIR-filter (http://en.wikipedia.org/wiki/Finite_impulse_response).
Here (http://cnx.org/content/m13115/latest/) you can find a Online Tool for IIR Filter and FIR Filter Design
EDIT: And here (http://www.cellsoft.de/windows/winfirsupport.htm) you can find a windows FIR Filter Designer

in avisynth you can use mt_convolution (http://avisynth.org/mediawiki/MaskTools2#Filters) or GeneralConvolution (http://avisynth.org/mediawiki/GeneralConvolution) to implement your filter-coefficients.

hanfrunz

FlimsyFeet
1st October 2008, 21:14
Ah, OK. Seems like I will have to do a bit of reading before I can understadn how to use that...

Mug Funky
2nd October 2008, 08:38
the old plugin "unfilter" would probably get you close, though the settings are not analogous. the rolloff on that graph there looks soft enough that a very simple filter should be able to achieve that effect.

Dark Shikari
2nd October 2008, 08:40
fft3dfilter?

blur?

*.mp4 guy
3rd October 2008, 02:01
fft3d won't do it, neither will blur (though technically blur is a lowpass filter, its not good enough). I wrote an adjustable multiband frequency adjuster (which can work very well as a lowpass filter) with a lot of help, especialy from foxyshadis.

Heres a version with full documentation.

#DctFreq_1.0

#foxyshadis : Better code organization, all speed optimizations.
#Didée: Avysinth coding explanations, and bugfixing.
#Many other doom9 residents: Troubleshooting and ideas.
#Original code, and documentation by *.mp4 guy
#Average by mg262
#Original Dctfilter by Tom Barry / trbarry

#
# explanation of usage

# assume 0.5 hz is the nyquist frequency.
# dct2 is responsible for 0.0625-0.125 hz (aprox)
# dct3 is 0.125-0.1875 hz (aprox)
# dct4 is 0.1875-0.25 hz (aprox)
# dct5 is 0.25-0.3125 hz (aprox)
# dct6 is 0.3125-0.375 hz (aprox)
# dct7 is 0.375- 0.4375 hz (aprox)
# dct8 is 0.4375-0.5 hz (aprox)
# dc controls the dc component (brightness) of the entire image (don't change it)
# this filter is effectively limited to a minimum frequency of 0.125 hz, as eliminating the dct2
# frequency bin will cause the filter to perform as a simple "average" filter with a sliding 8*8 window
# The filter is most accurate (sharpest roll off) the higher the frequency bin, because the size of the filter
# window remains constant, this is actually a plus in certain circumstances, as this filter will mimic the
# impulse response behavior of mpeg family condecs (those using an 8*8 dct, so all but avc)

# All float values have limited precision, to 0.125, so valid entries are 0, 1.25, 0.25, 0.375, 0.5 ... etc.
# nonvalid entries will be rounded to the nearest multiple of 0.125
# valid range is -8 to 8, useful range is -1 to 2, a value of 0 eliminates a band, a value of 1 does nothing
# a value of 2 doubles the strength of the band, negative values function as you would expect.

# use8dct/use64dct set the number of dct blocks to be used, 8 is 8 times faster then 64, and indistinguishable from
# 64 to the naked eye, use 64 only when you are doing multiple convolutions, or otherwise need very high accuracy
# 8 is the default. If both are set to false, only 1 dct will be used THIS IS UGLY.

# Required Plugins: Average, foxyshadis' modified dctfilter build
# Aerage: http://forum.doom9.org/showthread.php?t=100626
# Dctfilter: http://forum.doom9.org/showthread.php?p=951432#post951432
# Average filter direct link: http://forum.doom9.org/attachment.php?attachmentid=8355&d=1209332365
# Dctfilter Direct link: http://foxyshadis.slightlydark.com/random/DctFilter.zip

function dctfreq(clip c, float "dct2", float "dct3", float "dct4", float "dct5", float "dct6", float "dct7", float "dct8", float "dc", bool "use8dct", bool "use32dct", bool "use64dct", bool "use4dct"){

dc = default(dc, 1)
dct2 = default(dct2, 1)
dct3 = default(dct3, 1)
dct4 = default(dct4, 1)
dct5 = default(dct5, 0)
dct6 = default(dct6, 0)
dct7 = default(dct7, 0)
dct8 = default(dct8, 0)

use4dct = default(use4dct, false)
use8dct = default(use8dct, true)
use32dct = default(use32dct, false)
use64dct = default(use64dct, false)

w = c.width
h = c.height

sourcey = c
source = sourcey
cropc = sourcey
#crop0 = sourcey.dctfilter(dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8,chroma=-1)

##################################################################-dct16-1
align1 = source.dfilter( 1, 0, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
align2 = source.dfilter( 1, 1, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
align3 = source.dfilter( 1, 2, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
align4 = source.dfilter( 1, 3, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
align5 = source.dfilter( 1, 4, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
align6 = source.dfilter( 1, 5, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
align7 = source.dfilter( 1, 6, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
align8 = source.dfilter( 1, 7, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
align9 = source.dfilter( 2, 0, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
align10 = source.dfilter( 2, 1, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
align11 = source.dfilter( 2, 2, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
align12 = source.dfilter( 2, 3, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
align13 = source.dfilter( 2, 4, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
align14 = source.dfilter( 2, 5, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
align15 = source.dfilter( 2, 6, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
align16 = source.dfilter( 2, 7, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)

################################################################## dct32 2
align17 = source.dfilter( 3, 0, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
align18 = source.dfilter( 3, 1, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
align19 = source.dfilter( 3, 2, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
align20 = source.dfilter( 3, 3, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
align21 = source.dfilter( 3, 4, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
align22 = source.dfilter( 3, 5, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
align23 = source.dfilter( 3, 6, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
align24 = source.dfilter( 3, 7, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
align25 = source.dfilter( 4, 0, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
align26 = source.dfilter( 4, 1, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
align27 = source.dfilter( 4, 2, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
align28 = source.dfilter( 4, 3, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
align29 = source.dfilter( 4, 4, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
align30 = source.dfilter( 4, 5, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
align31 = source.dfilter( 4, 6, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
align32 = source.dfilter( 4, 7, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)

################################################################## dct48 3
align33 = source.dfilter( 5, 0, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
align34 = source.dfilter( 5, 1, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
align35 = source.dfilter( 5, 2, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
align36 = source.dfilter( 5, 3, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
align37 = source.dfilter( 5, 4, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
align38 = source.dfilter( 5, 5, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
align39 = source.dfilter( 5, 6, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
align40 = source.dfilter( 5, 7, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
align41 = source.dfilter( 4, 0, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
align42 = source.dfilter( 6, 1, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
align43 = source.dfilter( 6, 2, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
align44 = source.dfilter( 6, 3, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
align45 = source.dfilter( 6, 4, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
align46 = source.dfilter( 6, 5, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
align47 = source.dfilter( 6, 6, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
align48 = source.dfilter( 6, 7, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)

################################################################## dct64 4
align49 = source.dfilter( 7, 0, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
align50 = source.dfilter( 7, 1, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
align51 = source.dfilter( 7, 2, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
align52 = source.dfilter( 7, 3, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
align53 = source.dfilter( 7, 4, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
align54 = source.dfilter( 7, 5, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
align55 = source.dfilter( 7, 6, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
align56 = source.dfilter( 7, 7, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
align57 = source.dfilter( 0, 0, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
align58 = source.dfilter( 0, 1, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
align59 = source.dfilter( 0, 2, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
align60 = source.dfilter( 0, 3, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
align61 = source.dfilter( 0, 4, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
align62 = source.dfilter( 0, 5, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
align63 = source.dfilter( 0, 6, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
align64 = source.dfilter( 0, 7, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)

dct4_1 = average(align56, 0.25, align38, 0.25, align20, 0.25, align2, 0.25)
dct8_1 = average(align57, 0.125, align56, 0.125, align38, 0.125, align47, 0.125, align20, 0.125, align29, 0.125, align2, 0.125, align11, 0.125)
dct16_1 = average(align1, 0.0625, align2, 0.0625, align3, 0.0625, align4, 0.0625, align5, 0.0625, align6, 0.0625, align7, 0.0625, align8, 0.0625, align9, 0.0625, align10, 0.0625, align11, 0.0625, align12, 0.0625, align13, 0.0625, align14, 0.0625, align15, 0.0625, align16, 0.0625)
dct32_2 = average(align17, 0.0625, align18, 0.0625, align19, 0.0625, align20, 0.0625, align21, 0.0625, align22, 0.0625, align23, 0.0625, align24, 0.0625, align25, 0.0625, align26, 0.0625, align27, 0.0625, align28, 0.0625, align29, 0.0625, align30, 0.0625, align31, 0.0625, align32, 0.0625)
dct48_3 = average(align33, 0.0625, align34, 0.0625, align35, 0.0625, align36, 0.0625, align37, 0.0625, align38, 0.0625, align39, 0.0625, align40, 0.0625, align41, 0.0625, align42, 0.0625, align43, 0.0625, align44, 0.0625, align45, 0.0625, align46, 0.0625, align47, 0.0625, align48, 0.0625)
dct64_4 = average(align49, 0.0625, align50, 0.0625, align51, 0.0625, align52, 0.0625, align53, 0.0625, align54, 0.0625, align55, 0.0625, align56, 0.0625, align57, 0.0625, align58, 0.0625, align59, 0.0625, align60, 0.0625, align61, 0.0625, align62, 0.0625, align63, 0.0625, align64, 0.0625)

align57
use4dct ? dct4_1 : last
use8dct ? dct8_1 : last
use32dct ? average(dct16_1, 0.5, dct32_2, 0.5) : last
use64dct ? average(dct16_1, 0.25, dct48_3, 0.25, dct32_2, 0.25, dct64_4, 0.25) : last
mergechroma(source, 1)

return(last)
}

function dfilter(clip c, int offx, int offy, float dc, float dct2, float dct3, float dct4, float dct5, float dct6, float dct7, float dct8) {
#c.PointResize(c.width,c.height,offx,offy,c.width,c.height).dctfilter(dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8,chroma=0,offx=offx,offy=offy).PointResize(c.width,c.height,-offx,-offy,c.width,c.height)
c.dctfilter(dc, dct2, dct3, dct4, dct5, dct6, dct7, dct8,chroma=0,offx=offx,offy=offy)
}

function m(int r, float x) {return(x<16?16:int(round(x/float(r))*r))}

FlimsyFeet
3rd October 2008, 14:47
Hmm, I think that looks promising, thanks, but I have a question:
# assume 0.5 hz is the nyquist frequency.
If I were to use this to do approximately the same thing as the graph at the top of this thread, I would want the nyquist frequency to be 6MHz, yes? How do I change this in the function? (So dct2 would be controlling 0.75 - 1.5MHz, dct3 would be 1.5 - 2.25MHz, etc.)

45tripp
3rd October 2008, 15:04
Heres a version

i like this
:thanks:

Didée
3rd October 2008, 16:17
@ mp4guy - related note, with a somewhat complex script like that, did you consider that DCTFilter is actually buggy?

Try this, and look closely:
blankclip(color_yuv=$808080,pixel_type="YV12")
AddGrainC(64,0,0,0)

# both variants of DCTFilter are buggy calculating DC :
a = DCTFilter(1.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0)
b = DCTFilterD(14)
interleave(a,b)
return(last)

What *should* come out is frames with nothing but uniquely-colored 8x8 blocks.

But that isn't the case. There are lots of blocks that have a horizontal stripe in the middle. Small example (zoomed 400%):

http://img174.imageshack.us/img174/4995/buggydctfilterdn3.png (http://imageshack.us)

Obviously, that's not correct. If the DC component isn't calculated correctly, everything else coming out of DCTFilter is not correct, too. And subsequently any operation that is based on DCTFilter.

I can't tell if this actually makes a noticeable difference in the end, or if it's neglectable ... but definetly there is a bug in DCTFilter.

It seems like it could be some rounding issue. It's unclear if it's "only" the DC calculation which is affected (with all other DCT's being based on that rather small error), or if all DCT calculations have the same kind of deviation.

*.mp4 guy
3rd October 2008, 17:40
@ mp4guy - related note, with a somewhat complex script like that, did you consider that DCTFilter is actually buggy?
Interesting, that probably explains some of the +-1/2 pixel errors that occur when you set the filter to do nothing (dctfreq, not dctfilter). I've used dctfreq a lot, however, and it doesn't suffer noticibly from those errors.

Hmm, I think that looks promising, thanks, but I have a question:

If I were to use this to do approximately the same thing as the graph at the top of this thread, I would want the nyquist frequency to be 6MHz, yes? How do I change this in the function? (So dct2 would be controlling 0.75 - 1.5MHz, dct3 would be 1.5 - 2.25MHz, etc.)
Thats how it works. If you wanted to aproximate the thing in the graph, you would set it like this DctFreq(dct2=1, dct3=1, dct4=1, dct5=1, dct6=0.25, dct7=0, dct8=0), because dct6=5.0625 mhz, according to the scale that cce is using. Incidently, isnt 4.5mhz the freqhency resolution of analog television?

[edit] fixed incorrect calculations