Welcome to Doom9's Forum, THE in-place to be for everyone interested in DVD conversion.

Before you start posting please read the forum rules. By posting to this forum you agree to abide by the rules.

 

Go Back   Doom9's Forum > Capturing and Editing Video > Avisynth Development

Reply
 
Thread Tools Search this Thread Display Modes
Old 7th February 2007, 01:59   #1  |  Link
*.mp4 guy
Registered User
 
*.mp4 guy's Avatar
 
Join Date: Feb 2004
Posts: 1,350
overlapped dct, proof of concept frequency lowpass and interpolator function

I made a dct based frequency limiter/expander. The function has variable precision, using 4, 8, 32, or 64 overlapped dct's specified by the "useXdct=true/false" parameters, the highest specified accuracy will be used, if no accuracy is specified 8X accuracy will be used, if all are set to false the lowest accuracy will be used. frequency weighting is by default a sinc function, different frequency weighting can be specified with the dct2-8 parameters, dct2 being the lowest frequncies, dct4 and dct5 being the middle, and dct8 being the highest.

Also included is a simple 4x enlargement function with variable sharpness, and a non-functioning downsizing function.

frequency limiter usage:
dctlimit(dc=1, dct2=1, dct3=1, dct4=1.2, dct5=-0.2, dct6=0, dct7=0, dct8=0, use8dct=true)
dctlimit does not process chroma

upsizer usage:
dctus(sharpness=2)

upsizer2 usage:
wdresize(sharpness=1.95, warp=4, u64dct=false)

The second upsizer function is just a wrapper for the first with some usefull additions, its separated so the other function can be used as a regular interpolater.

Required plugins are dctfilter and average

The upsizer performs about aswell as lanczos, but with less aliasing.

Code:
see later post for the function, it almost exceeds the char limit

Last edited by *.mp4 guy; 9th February 2007 at 04:23.
*.mp4 guy is offline   Reply With Quote
Old 8th February 2007, 13:05   #2  |  Link
708145
Professional Lemming
 
708145's Avatar
 
Join Date: Dec 2003
Location: Stuttgart, Germany
Posts: 359
Do I get it right: Is this like a DCTfilter on steroids?

If so then it's very nice. I was looking for that for a long time.

bis besser,
T0B1A5
__________________
projects page: ELDER, SmoothD, etc.
708145 is offline   Reply With Quote
Old 8th February 2007, 15:08   #3  |  Link
*.mp4 guy
Registered User
 
*.mp4 guy's Avatar
 
Join Date: Feb 2004
Posts: 1,350
Yep thats exactly what it is, high precision modes are S L O W.
*.mp4 guy is offline   Reply With Quote
Old 8th February 2007, 15:11   #4  |  Link
foxyshadis
ангел смерти
 
foxyshadis's Avatar
 
Join Date: Nov 2004
Location: Lost
Posts: 9,175
Needs to come with a warning, "Requires 4 gigs of memory", though. Creating a simplified plugin out of it is probably necessary to work with HD resolutions.

Possible idea - what about creating a massively overlapped 8x8 DCT this way, and then doing a 16x16 IDCT on the coefficients, in order to perform the upsizing, instead of all of these machinations with pointresize? It probably wouldn't be too hard to create a filter to do that, along with an offset parameter to get overlapped versions. (Without actually performing the averaging in the filter.)
__________________
There are four boxes to be used in defense of liberty: soap, ballot, jury, and ammo. Please use in that order. ~ Ed Howdershelt
foxyshadis is offline   Reply With Quote
Old 9th February 2007, 04:18   #5  |  Link
*.mp4 guy
Registered User
 
*.mp4 guy's Avatar
 
Join Date: Feb 2004
Posts: 1,350
Quote:
Originally Posted by foxyshadis View Post
Possible idea - what about creating a massively overlapped 8x8 DCT this way, and then doing a 16x16 IDCT on the coefficients, in order to perform the upsizing, instead of all of these machinations with pointresize?
All of the pointresize calls in the dctlimit function are just used to shift the image without interpolating data, but you were probably refering to the pointresize calls used in the interpolation function?

Quote:
Originally Posted by foxyshadis View Post
Needs to come with a warning, "Requires 4 gigs of memory", though. Creating a simplified plugin out of it is probably necessary to work with HD resolutions.

Possible idea - what about creating a massively overlapped 8x8 DCT this way, and then doing a 16x16 IDCT on the coefficients, in order to perform the upsizing, instead of all of these machinations with pointresize? It probably wouldn't be too hard to create a filter to do that, along with an offset parameter to get overlapped versions. (Without actually performing the averaging in the filter.)
That would be the "non-half-assed" way to go about this type of resizing . It would be much more memory efficient if each independant instance of dct filter ulnoaded its memory after it processed its data aswell. Another possible speedup would be using the hct instead of the dct, but I don't know how that would impact quality.

Overlapped 8x8dct to overlapped 16*16 IDCT processing would have less overlapping during idct then during the dct, which might cause artifacts. The way things are now it is either a 2-tap function overlapped to 4 taps (all the benefits of a 4tap function, but no ringing) or a 4 tap function averlapped to 8 taps, using a 16X16 idct would turn it into an 8tap function overlapped to 16taps, which could introduce an unpleasant amount of ringing, but would have amaizing high frequency accuracy.

I can't program myself or I would have started on a plugin already, this method definately looks like it will need some real code to work properly.

[edit] function code has been updated, quality of upsizing improved.

Last edited by *.mp4 guy; 9th February 2007 at 04:21.
*.mp4 guy is offline   Reply With Quote
Old 9th February 2007, 04:23   #6  |  Link
*.mp4 guy
Registered User
 
*.mp4 guy's Avatar
 
Join Date: Feb 2004
Posts: 1,350
Code:
see later posts for new versions

Last edited by *.mp4 guy; 9th February 2007 at 23:53. Reason: removed an out of date script
*.mp4 guy is offline   Reply With Quote
Old 9th February 2007, 06:00   #7  |  Link
Fizick
AviSynth plugger
 
Fizick's Avatar
 
Join Date: Nov 2003
Location: Russia
Posts: 2,183
I do not know any fast (MMX) DCT 16x16 code.
But I develop dct3dfilter (not finished).
__________________
My Avisynth plugins are now at http://avisynth.org.ru and mirror at http://avisynth.nl/users/fizick
I usually do not provide a technical support in private messages.
Fizick is offline   Reply With Quote
Old 9th February 2007, 08:44   #8  |  Link
*.mp4 guy
Registered User
 
*.mp4 guy's Avatar
 
Join Date: Feb 2004
Posts: 1,350
More info please.

Does dct3dfilter do an 8x8x8 3d dct across the horizontal vertical and temporal axis?

Is it a non standard size like 8x8x4?

Hows the speed?

How accurate are the dct and idct algorithms you are using?

How does it deal with improperly temporally lowpassed content?
*.mp4 guy is offline   Reply With Quote
Old 9th February 2007, 17:29   #9  |  Link
Fizick
AviSynth plugger
 
Fizick's Avatar
 
Join Date: Nov 2003
Location: Russia
Posts: 2,183
1. Now I partially implement mode bt=0, bt=1, bt=3, for size 8x8,
overlap=0, 2, 4.
2.Speed is about twice fft3d.
3.Not very accurate dct,
4.I do not know.
It is under development. Please wait.

IMO Soulhunter and tritical have similar filters
__________________
My Avisynth plugins are now at http://avisynth.org.ru and mirror at http://avisynth.nl/users/fizick
I usually do not provide a technical support in private messages.
Fizick is offline   Reply With Quote
Old 9th February 2007, 19:25   #10  |  Link
foxyshadis
ангел смерти
 
foxyshadis's Avatar
 
Join Date: Nov 2004
Location: Lost
Posts: 9,175
Quote:
Originally Posted by *.mp4 guy View Post
It would be much more memory efficient if each independant instance of dct filter ulnoaded its memory after it processed its data aswell.
That makes an enormous difference. Enjoy.

I also added a chroma=-1 parameter so that it won't bother doing all that, since it's grey-only currently. 0 also works, but I'm reserving that for "copy" eventually (current behavior is "trash it"). Also enabled the dormant SSE2 fdct; it hasn't crashed on me so far, though the idct was buggy.

btw, you could put the mergechroma immediately before the return, instead of multiple times after each average; not much of a speedup but something. And I think you mixed up the rep logic.

Prettied up version:
Code:
# DCTlimit, by *.mp4 guy
#

function dctlimit(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
	crop1 =  source.dfilter(-1,  0, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
	crop2 =  source.dfilter(-1, -1, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
	crop3 =  source.dfilter(-1, -2, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
	crop4 =  source.dfilter(-1, -3, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
	crop5 =  source.dfilter(-1, -4, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
	crop6 =  source.dfilter(-1, -5, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
	crop7 =  source.dfilter(-1, -6, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
	crop8 =  source.dfilter(-1, -7, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
	crop9 =  source.dfilter(-2, -0, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
	crop10 = source.dfilter(-2, -1, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
	crop11 = source.dfilter(-2, -2, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
	crop12 = source.dfilter(-2, -3, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
	crop13 = source.dfilter(-2, -4, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
	crop14 = source.dfilter(-2, -5, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
	crop15 = source.dfilter(-2, -6, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
	crop16 = source.dfilter(-2, -7, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)

	##################################################################-dct32-2
	crop17 = source.dfilter(-3,  0, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
	crop18 = source.dfilter(-3, -1, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
	crop19 = source.dfilter(-3, -2, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
	crop20 = source.dfilter(-3, -3, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
	crop21 = source.dfilter(-3, -4, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
	crop22 = source.dfilter(-3, -5, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
	crop23 = source.dfilter(-3, -6, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
	crop24 = source.dfilter(-3, -7, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
	crop25 = source.dfilter(-4, -0, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
	crop26 = source.dfilter(-4, -1, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
	crop27 = source.dfilter(-4, -2, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
	crop28 = source.dfilter(-4, -3, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
	crop29 = source.dfilter(-4, -4, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
	crop30 = source.dfilter(-4, -5, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
	crop31 = source.dfilter(-4, -6, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
	crop32 = source.dfilter(-4, -7, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)

	##################################################################-dct48-3
	crop33 = source.dfilter(-5,  0, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
	crop34 = source.dfilter(-5, -1, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
	crop35 = source.dfilter(-5, -2, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
	crop36 = source.dfilter(-5, -3, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
	crop37 = source.dfilter(-5, -4, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
	crop38 = source.dfilter(-5, -5, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
	crop39 = source.dfilter(-5, -6, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
	crop40 = source.dfilter(-5, -7, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
	crop41 = source.dfilter(-4, -0, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
	crop42 = source.dfilter(-6, -1, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
	crop43 = source.dfilter(-6, -2, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
	crop44 = source.dfilter(-6, -3, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
	crop45 = source.dfilter(-6, -4, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
	crop46 = source.dfilter(-6, -5, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
	crop47 = source.dfilter(-6, -6, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
	crop48 = source.dfilter(-6, -7, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)

	##################################################################-dct64-4
	crop49 = source.dfilter(-7,  0, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
	crop50 = source.dfilter(-7, -1, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
	crop51 = source.dfilter(-7, -2, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
	crop52 = source.dfilter(-7, -3, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
	crop53 = source.dfilter(-7, -4, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
	crop54 = source.dfilter(-7, -5, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
	crop55 = source.dfilter(-7, -6, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
	crop56 = source.dfilter(-7, -7, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
	crop57 = source.dfilter(-0,  0, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
	crop58 = source.dfilter(-0, -1, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
	crop59 = source.dfilter(-0, -2, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
	crop60 = source.dfilter(-0, -3, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
	crop61 = source.dfilter(-0, -4, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
	crop62 = source.dfilter(-0, -5, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
	crop63 = source.dfilter(-0, -6, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)
	crop64 = source.dfilter(-0, -7, dc,dct2,dct3,dct4,dct5,dct6,dct7,dct8)

	###################################
	alignc = cropc
	###################################


	##################################################################-align16-1
	align1 =  crop1 .pointResize(W, H, 1, 0, W, H)
	align2 =  crop2 .pointResize(W, H, 1, 1, W, H)
	align3 =  crop3 .pointResize(W, H, 1, 2, W, H)
	align4 =  crop4 .pointResize(W, H, 1, 3, W, H)
	align5 =  crop5 .pointResize(W, H, 1, 4, W, H)
	align6 =  crop6 .pointResize(W, H, 1, 5, W, H)
	align7 =  crop7 .pointResize(W, H, 1, 6, W, H)
	align8 =  crop8 .pointResize(W, H, 1, 7, W, H)
	align9 =  crop9 .pointResize(W, H, 2, 0, W, H)
	align10 = crop10.pointResize(W, H, 2, 1, W, H)
	align11 = crop11.pointResize(W, H, 2, 2, W, H)
	align12 = crop12.pointResize(W, H, 2, 3, W, H)
	align13 = crop13.pointResize(W, H, 2, 4, W, H)
	align14 = crop14.pointResize(W, H, 2, 5, W, H)
	align15 = crop15.pointResize(W, H, 2, 6, W, H)
	align16 = crop16.pointResize(W, H, 2, 7, W, H)

	##################################################################-align32-2
	align17 = crop17.pointResize(W, H, 3, 0, W, H)
	align18 = crop18.pointResize(W, H, 3, 1, W, H)
	align19 = crop19.pointResize(W, H, 3, 2, W, H)
	align20 = crop20.pointResize(W, H, 3, 3, W, H)
	align21 = crop21.pointResize(W, H, 3, 4, W, H)
	align22 = crop22.pointResize(W, H, 3, 5, W, H)
	align23 = crop23.pointResize(W, H, 3, 6, W, H)
	align24 = crop24.pointResize(W, H, 3, 7, W, H)
	align25 = crop25.pointResize(W, H, 4, 0, W, H)
	align26 = crop26.pointResize(W, H, 4, 1, W, H)
	align27 = crop27.pointResize(W, H, 4, 2, W, H)
	align28 = crop28.pointResize(W, H, 4, 3, W, H)
	align29 = crop29.pointResize(W, H, 4, 4, W, H)
	align30 = crop30.pointResize(W, H, 4, 5, W, H)
	align31 = crop31.pointResize(W, H, 4, 6, W, H)
	align32 = crop32.pointResize(W, H, 4, 7, W, H)

	##################################################################-align48-3
	align33 = crop33.pointResize(W, H, 5, 0, W, H)
	align34 = crop34.pointResize(W, H, 5, 1, W, H)
	align35 = crop35.pointResize(W, H, 5, 2, W, H)
	align36 = crop36.pointResize(W, H, 5, 3, W, H)
	align37 = crop37.pointResize(W, H, 5, 4, W, H)
	align38 = crop38.pointResize(W, H, 5, 5, W, H)
	align39 = crop39.pointResize(W, H, 5, 6, W, H)
	align40 = crop40.pointResize(W, H, 5, 7, W, H)
	align41 = crop41.pointResize(W, H, 6, 0, W, H)
	align42 = crop42.pointResize(W, H, 6, 1, W, H)
	align43 = crop43.pointResize(W, H, 6, 2, W, H)
	align44 = crop44.pointResize(W, H, 6, 3, W, H)
	align45 = crop45.pointResize(W, H, 6, 4, W, H)
	align46 = crop46.pointResize(W, H, 6, 5, W, H)
	align47 = crop47.pointResize(W, H, 6, 6, W, H)
	align48 = crop48.pointResize(W, H, 6, 7, W, H)

	##################################################################-align64-4
	align49 = crop49.pointResize(W, H, 7, 0, W, H)
	align50 = crop50.pointResize(W, H, 7, 1, W, H)
	align51 = crop51.pointResize(W, H, 7, 2, W, H)
	align52 = crop52.pointResize(W, H, 7, 3, W, H)
	align53 = crop53.pointResize(W, H, 7, 4, W, H)
	align54 = crop54.pointResize(W, H, 7, 5, W, H)
	align55 = crop55.pointResize(W, H, 7, 6, W, H)
	align56 = crop56.pointResize(W, H, 7, 7, W, H)
	align57 = crop57#.pointResize(W, H, 0, 0, W, H)
	align58 = crop58.pointResize(W, H, 0, 1, W, H)
	align59 = crop59.pointResize(W, H, 0, 2, W, H)
	align60 = crop60.pointResize(W, H, 0, 3, W, H)
	align61 = crop61.pointResize(W, H, 0, 4, W, H)
	align62 = crop62.pointResize(W, H, 0, 5, W, H)
	align63 = crop63.pointResize(W, H, 0, 6, W, H)
	align64 = crop64.pointResize(W, H, 0, 7, W, H)

	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(alignc, 1)

	return(last)
}

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



Function DCTus(clip clp, float "sharpness", bool "u64dct"){
	OX = m(16,Clp.Width)
	OY = m(16,Clp.Height)
	dx = ox - clp.width
	dy = oy - clp.height
	sharpness = default(sharpness, 2)
	u64dct = default(u64dct, false)
	luma = clp.pointresize(Clp.Width*4,Clp.Height*4).addborders(dx*4, dy*4, 0, 0).dctlimit(dct2=sharpness, dct3=0, dct4=0, dct5=0, \
            use64dct=u64dct, use8dct=true).crop(dx*4, dy*4, 0, 0)
	luma.mergechroma(lanczosresize(clp,Clp.Width*4 ,Clp.Height*4), 1)
	return(last)
}

Function DCTds(clip clp,int destx, int desty, float "sharpness"){
	sharpness = default(sharpness,1)
	OX = m(16,Clp.Width)
	OY = m(16,Clp.Height)
	dx = ox - clp.width
	dy = oy - clp.height
	(clp.width < destx*2) ? dx*2 : dx
	(clp.width < destx*2) ? dy*2 : dy
	clp
	(width < destx*2) ? dctus(sharpness) : last
	(width < destx*2) ? dctds(destx=destx, desty=desty, sharpness=sharpness) : \
            bilinearresize(destx,desty).addborders(dx, dy, 0, 0).dctlimit(dct3=0.75+(sharpness/4),dct4=sharpness, dct5=0).crop(dx, dy, 0, 0).pointresize(destx,desty)
	return last
}

function wdresize(clip clp, float "sharpness", bool "u64dct", int "warp", int "thresh", int "rep"){
	sharpness = default(sharpness, 2)
	u64dct = default(u64dct, false)
	warp = default(warp, 4)
	thresh = default(thresh, 50)
	rep = default(rep, 1)

	clp.dctus(sharpness=sharpness, u64dct=u64dct).DeHalo_alpha(ss=1, lowsens=30, highsens=30, rx=2, ry=2)

	w = last.width
	h = last.height
	pointresize(w/2, h/2)
	(rep>= 2) ? last.dctlimit(use64dct=u64dct, dct2=1, dct3=1, dct4=sharpness, dct5=0) : last
	(rep>= 2) ? last.DeHalo_alpha(ss=1, lowsens=15, highsens=15, rx=2, ry=2) : last

	(rep>= 3) ? last.dctlimit(use64dct=u64dct, dct2=1, dct3=1, dct4=0.5, dct5=sharpness).dctlimit(use64dct=u64dct, dct2=1, dct3=1, dct4=sharpness, dct5=0) : last
	(rep>= 3) ? last.DeHalo_alpha(ss=1, lowsens=20, highsens=20, rx=2, ry=2) : last

	awarpsharp(depth=warp, cm=0, blurlevel=1)
	awarpsharp(depth=warp, cm=0, blurlevel=1)
	awarpsharp(depth=warp, cm=0, blurlevel=1)
	awarpsharp(depth=warp, cm=0, blurlevel=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=-1)
}
__________________
There are four boxes to be used in defense of liberty: soap, ballot, jury, and ammo. Please use in that order. ~ Ed Howdershelt

Last edited by foxyshadis; 22nd December 2014 at 00:16. Reason: fixed link
foxyshadis is offline   Reply With Quote
Old 9th February 2007, 21:08   #11  |  Link
*.mp4 guy
Registered User
 
*.mp4 guy's Avatar
 
Join Date: Feb 2004
Posts: 1,350
Thanks for the help (!) dctfilter doesn't crash avisynth on frames larger then 352*192 now .

The script cleanup is quite nice aswell. One question though, how do you set which dct dctfilter uses?

Minor update to resizing function, defaults improved, it is now possible to set the initial taps, non mod 16 imput resolutions now work, rep code had a minor cleanup and halo removal strength is now a variable:
Code:
function wdresize(clip clp, float "sharpness", bool "u64dct", int "warp", int "thresh", int "rep", int "antihalo", int "taps", int "dehalo"){
	sharpness = default(sharpness, 2)
	u64dct = default(u64dct, true)
	warp = default(warp, 4)
	thresh = default(thresh, 50)
	rep = default(rep, 1)
	antihalo = default(antihalo, 150)
	taps = default(taps, 4)
    dehalo = default(dehalo, rep)

	cw = clp.width
	ch = clp.height

	(taps <=3) ? clp.dctus(sharpness=sharpness, u64dct=u64dct).DeHalo_alpha(ss=1, lowsens=antihalo, highsens=antihalo, rx=2, ry=2) : last

	(taps >=3) ? clp.pointresize(cw*2, ch*2).dctlimit(use64dct=u64dct, dct2=1, dct3=1, dct4=sharpness, dct5=0) : last
	
    (dehalo >=1) ? last.DeHalo_alpha(ss=1, lowsens=round((antihalo/2)*3), highsens=round((antihalo/2)*3), rx=2, ry=2) : last

	w = last.width
	h = last.height

	(taps <=3) ? pointresize(w/2, h/2) : last

	OX = m(16,Clp.Width)
	OY = m(16,Clp.Height)
	dx = ox - clp.width
	dy = oy - clp.height

	addborders(dx, dy, 0, 0)

	(rep>=2) ? last.dctlimit(use64dct=u64dct, dct2=1, dct3=1, dct4=0.5, dct5=sharpness).dctlimit(use64dct=u64dct, dct2=1, dct3=1, dct4=sharpness, dct5=0) : last
    (dehalo >=2) ? last.DeHalo_alpha(ss=1, lowsens=antihalo, highsens=antihalo, rx=2, ry=2) : last

	(rep>=3) ? last.dctlimit(use64dct=u64dct, dct2=1, dct3=1, dct4=0.5, dct5=sharpness).dctlimit(use64dct=u64dct, dct2=1, dct3=1, dct4=sharpness, dct5=0) : last
    (dehalo >=3) ? last.DeHalo_alpha(ss=1, lowsens=round((antihalo/2)*3), highsens=round((antihalo/2)*3), rx=2, ry=2) : last

	(rep>=4) ? last.dctlimit(use64dct=u64dct, dct2=1, dct3=1, dct4=0.5, dct5=sharpness).dctlimit(use64dct=u64dct, dct2=1, dct3=1, dct4=sharpness, dct5=0) : last
    (dehalo >=4) ? last.DeHalo_alpha(ss=1, lowsens=round((antihalo/2)*3), highsens=round((antihalo/2)*3), rx=2, ry=2) : last

	(rep>=5) ? last.dctlimit(use64dct=u64dct, dct2=1, dct3=1, dct4=0.5, dct5=sharpness).dctlimit(use64dct=u64dct, dct2=1, dct3=1, dct4=sharpness, dct5=0) : last
    (dehalo >=5) ? last.DeHalo_alpha(ss=1, lowsens=round((antihalo/2)*3), highsens=round((antihalo/2)*3), rx=2, ry=2) : last

	(rep>=6) ? last.dctlimit(use64dct=u64dct, dct2=1, dct3=1, dct4=0.5, dct5=sharpness).dctlimit(use64dct=u64dct, dct2=1, dct3=1, dct4=sharpness, dct5=0) : last
    (dehalo >=6) ? last.DeHalo_alpha(ss=1, lowsens=round((antihalo/2)*3), highsens=round((antihalo/2)*3), rx=2, ry=2) : last
    
    (rep>=7) ? last.dctlimit(use64dct=u64dct, dct2=1, dct3=1, dct4=0.5, dct5=sharpness).dctlimit(use64dct=u64dct, dct2=1, dct3=1, dct4=sharpness, dct5=0) : last
    (dehalo >=7) ? last.DeHalo_alpha(ss=1, lowsens=round((antihalo/2)*3), highsens=round((antihalo/2)*3), rx=2, ry=2) : last
    
    (rep>=8) ? last.dctlimit(use64dct=u64dct, dct2=1, dct3=1, dct4=0.5, dct5=sharpness).dctlimit(use64dct=u64dct, dct2=1, dct3=1, dct4=sharpness, dct5=0) : last
    (dehalo >=8) ? last.DeHalo_alpha(ss=1, lowsens=round((antihalo/2)*3), highsens=round((antihalo/2)*3), rx=2, ry=2) : last


	crop(dx, dy, 0, 0)

	awarpsharp(depth=warp, cm=0, blurlevel=1)
	awarpsharp(depth=warp, cm=0, blurlevel=1)
	awarpsharp(depth=warp, cm=0, blurlevel=1)
	awarpsharp(depth=warp, cm=0, blurlevel=1)

	mergechroma(lanczosresize(clp,clp.Width*2 ,clp.Height*2), 1)

	return(last)}
on the todo list -
-intelligent masking to tone down halos and ringing (this is going to be really hard, but worth it if I figure something out)
-chroma processing
-investigate the effects of dct-idct precision on visible artifacts after multiple frequency seperation repetitions
-tone down the flattening caused by dehaloing. (see 1)
-look into 16*16 idct speed versus 8*8 idct speed.


[edit] upsizing function updated again, now suppots up to 8 reps (which very surprisingly actually looks good on some images, though I'm beginning to suspect that the reason lenna image is used so frequently in digital image processing is that it is perfectly lowpassed... it makes every image processing algorithm look like a miracle worker)

Last edited by *.mp4 guy; 10th February 2007 at 17:45.
*.mp4 guy is offline   Reply With Quote
Old 9th February 2007, 22:35   #12  |  Link
foxyshadis
ангел смерти
 
foxyshadis's Avatar
 
Join Date: Nov 2004
Location: Lost
Posts: 9,175
Quote:
Originally Posted by *.mp4 guy View Post
Thanks for the help (!) dctfilter doesn't crash avisynth on frames larger then 352*192 now .
Cool!

Quote:
The script cleanup is quite nice aswell. One question though, how do you set which dct dctfilter uses?
It sets it by the processor it detects right now. There isn't any floating-point dct, only mmx/sse2 dct and mmx/isse idct, so they all have the same (lousy) precision. If I can find a way to get a float in there (like mplayer's) I'll make it selectable.
__________________
There are four boxes to be used in defense of liberty: soap, ballot, jury, and ammo. Please use in that order. ~ Ed Howdershelt
foxyshadis is offline   Reply With Quote
Old 9th February 2007, 22:39   #13  |  Link
Si
Simply me
 
Si's Avatar
 
Join Date: Aug 2002
Location: Lancashire, England
Posts: 610
Someones got to ask and it may as well be me
Quote:
I made a dct based frequency limiter/expander. The function has variable precision, using 4, 8, 32, or 64 overlapped dct's specified by the "useXdct=true/false" parameters, the highest specified accuracy will be used, if no accuracy is specified 8X accuracy will be used, if all are set.....
And what's one of them then ?

regards

Simon
Si is offline   Reply With Quote
Old 9th February 2007, 23:09   #14  |  Link
*.mp4 guy
Registered User
 
*.mp4 guy's Avatar
 
Join Date: Feb 2004
Posts: 1,350
Quote:
Originally Posted by Si View Post
Someones got to ask and it may as well be me


And what's one of them then ?

regards

Simon
It's a highly precise bluring/sharpening/line detection algorithm that can be used to remove artifacts when upsizing and downsizing by correctly removing frequencies that cause aliasing ringing and haloing, without removing frequencies that are actually detail.

Quote:
Originally Posted by foxyshadis View Post
It sets it by the processor it detects right now. There isn't any floating-point dct, only mmx/sse2 dct and mmx/isse idct, so they all have the same (lousy) precision. If I can find a way to get a float in there (like mplayer's) I'll make it selectable.
That might explain something, is the mmx sse2 dct more precise then the mmx isse one? I thought the results I got were uncharacteristically low on ringing after I updated dctfilter and a difference in precision would explain it.

[RAMBLE=sampling theory]
I've been thinking about sampling theory, and the theoretically impossible sinc function, and I realised that not only would you need an infinitely precise sinc function to get perfect frequency elimination, you would also need an infinitely precise colorspace and sampling depth, IE you would need an infinte resolution image with an infinite colorspace just to store the results of the perfect sinc function. So given that it is both impossible to create a perfect sinc function and to adequately sample its results, shouldn't it then be possible to use a sufficiently precise sinc function so that the error it produces is lower then the accuracy loss of your destination resolution and colorspace, thereby giving you results that are as good as the perfect sinc functions results would be had they been subsampled to the resolution and colorspace you are using. Of couse in all likely hood such a sufficiently precise sinc function would be so slow that it would be completely useless. Given that a perfect dct transform is impossible, I think its possible that a sufficiently precise dct could impersonate the perfect sinc function with an adequately imprecise output resolution and colorspace.[/RAMBLE]

Last edited by *.mp4 guy; 9th February 2007 at 23:17.
*.mp4 guy is offline   Reply With Quote
Old 10th February 2007, 01:03   #15  |  Link
Didée
Registered User
 
Join Date: Apr 2002
Location: Germany
Posts: 5,390
The concept sounds interesting. But somehow I have some issues ... perhaps I'm missing something?

1. In whichever way I juggle around with true/false for all the useXdct, the result is always exactly the same?

2. Looking at what a dctlimit() call does to a sample frame:

original:

dctlimit:


Well, there's definetly an effect, but I see no use for what it's giving to me ...

Is the function really doing what it's supposed to do? Am I missing something obvious?
__________________
- We´re at the beginning of the end of mankind´s childhood -

My little flickr gallery. (Yes indeed, I do have hobbies other than digital video!)
Didée is offline   Reply With Quote
Old 10th February 2007, 10:56   #16  |  Link
*.mp4 guy
Registered User
 
*.mp4 guy's Avatar
 
Join Date: Feb 2004
Posts: 1,350
Quote:
Originally Posted by Didée View Post
The concept sounds interesting. But somehow I have some issues ... perhaps I'm missing something?

1. In whichever way I juggle around with true/false for all the useXdct, the result is always exactly the same?

2. Looking at what a dctlimit() call does to a sample frame:

original:

dctlimit:


Well, there's definetly an effect, but I see no use for what it's giving to me ...

Is the function really doing what it's supposed to do? Am I missing something obvious?
Are you
1-trying to resize the image
2-trying to lowpass
3-trying to enhance detail

If you are trying to do 1 you need to use the wdresize() function instead of dctlimit, wdresize is SLOW.

If you are trying to do #2, you just have, but you need to remove more frequencoes above the nyquist limit, try

dctlimit(use64dct=true, dct2=1, dct3=2, dct4=2, dct5=0)
dctlimit(use64dct=true, dct2=1, dct3=2, dct4=0.5, dct5=2)

dctlimit(use64dct=true, dct2=1, dct3=2, dct4=2, dct5=0)
dctlimit(use64dct=true, dct2=1, dct3=2, dct4=0.5, dct5=2)

repetition refines the frequency seperation, giving more accurate results, but also causes errors by the dct-idct algorithms to be amplified.

if you are trying to do # 3 you would call dctlimit like this

dctlimit(use64dct=true, dct2=1, dct3=1, dct4=1, dct5=1, dct6=1.5, dct7=2, dct8=2)

I havent extensively tested using dctlimit for accurate frequency sharpening.


the "usxdct" parameter adds accuracy, when all you are doing is running a single operation of dctlimit the difference between use8dct and use64dct will be impossible to see without enhancement of the image.

Last edited by *.mp4 guy; 10th February 2007 at 11:02.
*.mp4 guy is offline   Reply With Quote
Old 10th February 2007, 11:55   #17  |  Link
CAFxX
Stray Developer
 
CAFxX's Avatar
 
Join Date: Mar 2003
Location: Italy
Posts: 82
A little ago I did something similar, i.e. performing a fft on the whole image and then padding/cropping to reach the desired size.
I used the FFTW library and I got this (video is the second bravia commercial, 1280x720 downsized to 320x180 via spline36 and then upconverted with my filter (and spline36 as a reference); luma only atm; spline first, fft second):
frame 370:


frame 817:


I suppose the ringing effect near the borders is due to the limited precision but I actually can't guarantee that my code is bugless.
atm it can't do downsizing, but in matlab downsizing using this method proved interesting.
the filter is quite slow (15-20fps on my athlon64 3200), and it takes a while to load (fftw needs some time to prepare the ffts).
obviously (granted that the above mentioned ringing effect is due to limited precision) a overlapping window approach should resolve the issue. (and prove faster: fftw works in double precision... a highly tuned costant size integer/fixed-point algorithm will surely go much faster: btw, if anyone can point me towards an integer fft i may try to use that instead)

edit: found IPPs: will try them later
__________________
CAFxXcrossway, a collection of my projects
CAFxX@strayorange, my blog

Last edited by CAFxX; 10th February 2007 at 15:26.
CAFxX is offline   Reply With Quote
Old 10th February 2007, 15:31   #18  |  Link
*.mp4 guy
Registered User
 
*.mp4 guy's Avatar
 
Join Date: Feb 2004
Posts: 1,350
Overlapping should always increase precision for frequency transforms that are not odd, that is overlapping will always improve precision when used with a dct or an fft (they only work on even blocks of data) however the optimal way to avoid problems with any frequency transform is to only use the center pixel, as the center pixel has the least error, so for the most precise 8x8 dct-idct data you would need to perform 9 dct transforms per group of four pixels, avergaing the results and using only the center four pixels of the average after idct, using a different group of 9 transforms for each group of four pixels in the entire image, each group sharing 8 transforms with its neighbors (1 left, 1 up, 1 uperleft, etc.), this would give the most precise reconstruction (better then 64x overlapping). The same aplies to the fft, so the best ways to improve results are to 1-increase transform size, 2-use sufficient overlapping and pixel binning 3-use a precise transform and inverse transform.

After some additional research it turns out that the optimal frequency domain transform is the KLT(Karhunen-Loève transform), which is better then the dct, which is better then the fft. The klt is the most optimal linear transform, for the same reason the dct is better then the fft, that is it keeps the most important data only at the lowest frequencies, whereas with the dct and fft some important information is kept at higher frequencies then unimportant information, the fft has low frequency seperation, whereas the dct has high frequency seperation, and the klt has perfect frequency seperation. A perfectly resmapled image could be made using a sufficiently precise aproximation of a klt and a sufficiently imprecise colorspace and destination resolution, the klt would have to use variable transform sizes, the interior of the image would use a transform the size of the entire image, as the transform moved twards the borders of the image the transform size would have to be reduced to stay within the image boundaries.

Last edited by *.mp4 guy; 10th February 2007 at 17:16.
*.mp4 guy is offline   Reply With Quote
Old 10th February 2007, 18:06   #19  |  Link
Didée
Registered User
 
Join Date: Apr 2002
Location: Germany
Posts: 5,390
@ *.mp4 guy

Thanks for all the explanations, but I already know the drill.

You didn't get my point ... I was wondering if the function is working correctly.
Answer is: it does, and it does not.
And if you would have looked at the sample, you should have noted that something is definetly going wrong there ...

Solution:
Like it is posted, dctlimit() will work correctly only with Avisynth v2.57.
But when used with Avisynth v2.56, the result is a joke ... because of the resizer bug of AS 2.56.

I added the needed workaround, & put up the modified script here.
It's not needed for v.257, but it doesn't hurt, either.

(No need to discuss the "why still use 2.56???" question ... it is still used, and there the original function "silently" gives a b0rked result. Quite sneaky if one don't know about that ... it seems to work, but the result is crap, and people might wonder what it is all about ...
Better to play safe, for the time being.)
__________________
- We´re at the beginning of the end of mankind´s childhood -

My little flickr gallery. (Yes indeed, I do have hobbies other than digital video!)
Didée is offline   Reply With Quote
Old 10th February 2007, 18:38   #20  |  Link
*.mp4 guy
Registered User
 
*.mp4 guy's Avatar
 
Join Date: Feb 2004
Posts: 1,350
The results were bad on that sample, but I wasn't sure why, I figured it was just bad settings/ a tough source, thanks for the fix/workaround.

Also, does anyone know where I can get more information on the KLT/PCA transform? Wikipedias explanation was nice, but I would like more information about practical uses.

Last edited by *.mp4 guy; 10th February 2007 at 19:00.
*.mp4 guy is offline   Reply With Quote
Reply

Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT +1. The time now is 15:26.


Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2017, vBulletin Solutions Inc.