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 1st September 2017, 11:54   #1  |  Link
jpsdr
Registered User
 
Join Date: Oct 2002
Location: France
Posts: 2,309
Internaly multi-threaded desampling functions (DeBilinear, DeBicubic,...)

I've created a specific thread even if it will be implemented inside the ResampleMT dll, because i've thought it would be more appropriate. And if i didn't create a specific dll, it's because it's exactly the same thing, and just adding around 1% of code add the functions.

Download is on the ResampleMT dll page here.

The new functions are :
DeBilinearResizeMT
DeBicubicResizeMT
DeLanczosResizeMT
DeLanczos4ResizeMT
DeBlackmanResizeMT
DeSpline16ResizeMT
DeSpline36ResizeMT
DeSpline64ResizeMT
DeGaussResizeMT
DeSincResizeMT
DeSinSqrResizeMT
(same parameters than DeGauss)
DeSincLin2ResizeMT (same parameters than Sinc, default param 15)
DeUserDefined2ResizeMT (Same parameters as BicubicResize)

Parameters are identicals to the resampling functions, except there is two others parameters at the end.

accuracy -
Will specify the accuracy used for the desampling.
0 : Average
1 : A little less than 0.
2 : A little better than 0.

Default: 0 (int)

order -
Will specify in what order the desampling will be done (process horizontal or vertical first).
0 : Automatic, will choose according the same method implemented in the core filters.
1 : Process vertical first.
2 : Process horizontal first.

Default: 0 (int)

So, syntax is :
DesampleFunction([parameters of ResampleMT],int accuracy,int order)

The usage is the following : You have to enter in the parameters exactly the same that have been
used for the original resampling, except the size of course, where you specify the original size you want back.

For exemple, if the source file is an 720x480 video :

Code:
Spline36ResizeMT(1280,720,src_left=17.2,src_width=680,src_top=-8.7,src_height=440)
# or Spline36Resize(1280,720,src_left=17.2,src_width=680,src_top=-8.7,src_height=440)
# To revert :
DeSpline36ResizeMT(720,480,src_left=17.2,src_width=680,src_top=-8.7,src_height=440,accuracy=0,order=0)
This is intended to be a new version of the actual DeBilinear, working with all data formats of avs+, and having an x64 version. There is no intended link between the parameters of this new version and the old original. If some parameters happen to be identical, it's pure coincidence.


Now, a little explaination of how it works.

I'll note 'A the transpose matrix of A.
If X is your input line to resample, you can write the resampling method like this : Y=A*X.
Using the less square method, you can revert by the following method :
'A*Y='A*A*X
B = inverse_matrix ('A*A)
C = B*'A
We have X=C*Y.
So applying the matrix C, we can revert the resampling process.

Now, if in the A matrix, around 95% are 0.0 value (size of rif resampler is only around 3 or 4), it's absolutely not the same for the C matrix.

For exemple, in a case of reverting a 720 -> 1080 upscale, with an upscale rif filter of 4.
The scan in the lines of resulting matrix C showed that it will produce a rif size filter of 311.

This this where the accuracy parameter is used.

For the default value, 0, it will use what i would call "integer" precision.
In the filter, the integer values of the filter are converted with the following formula : int(0.5+f*16384).
So, if this result in 0, the coefficient in the C matrix is set to 0.0.
In our example, it will produce a rif filter of size 30.

With the value of 1, it will keep a 0.1% of precision. On each line of C, the max(abs(f)) is scanned, and any value lower than 0.1% of this max is set to 0. In our example, it will produce a rif filter of size 20.

With the value of 2, any value within C which abs()<1e-6 is set to 0. In our example case, it will produce a rif filter of size 41.

So, for a 720 data vector input [0, 1, 2, ..., 719] inside, "upscaled" to 1080 values, and then reduce back to 720 values, the results are the following :

accuracy 0 :
[-0.000209 1.000103 1.999724 3.000118 3.999680 5.000134
.... 714.983521 716.005859 716.983643 718.006226 718.985046]

accuracy 1 :
[-0.000512 1.003681 1.999033 3.004512 3.998633 5.005422
... 714.856384 716.323120 716.855835 718.331421 718.868530]
Rounded it's still good.

accuracy 2 :
[-0.000005 1.000017 1.999993 3.000018 3.999994 5.000021
... 714.999573 716.000732 716.999756 718.000977 718.999634]

Now, the order parameter.
This will set if the image of the video will be processed horizontaly first, or verticaly first.
If the value is 0, in automatic mode, the filter will figure out, according the internal avisynth core filter algorithm, in what order the image would have been processed by the original resampling, to do the oposite.
For example, if the original resampling would result in resampling horizontal first, then vertical, the filter in that case will do vertical, then horizontal.
Of course, if original resampling is not done by avisynth, you can't know for sure, this is why you can set the order to the filter, to check what produce the best result.

Quality improvement tip
There is the accuracy parameter, but another way to eventualy improve the quality is to increase the bit depth if you're using avs+. If you are in 8 bits, the resampler compute using integer rif parameters converted from the float rif parameters. But, if you are in bit depth>8, the resampler uses the float coefficients. In desampling cases, where rif size can easely be of 40 or 50, if you're trying to be the most accurate, i would advise to increase the bitdepth to 16 (or even to float if you're searching for ultra accuracy) just for the desampling filter.

WARNING !!!!
The init phase of the filter is very slow, it can take easely several seconds, and the bigger the picture is, the more it will take. If you don't even have SSE2 instructions, it may take several dozen of seconds !

So, in a standard filter chain doing :
Create,Constructor,getframe(n=0),getframe(n=1),getframe(n=2),...destructor, there will be no issue.
Now, if you are using something like ScriptClip, which works like this :
Create,Constructor,getframe(n=0),Destructor,Create,Constructor,getframe(n=1),Destructor,Create,Constructor, getframe(n=2),Destructor,...
It will be slow as hell !!! Avoid absolutely using it in this case.

Last edited by jpsdr; 29th April 2021 at 17:40.
jpsdr is offline   Reply With Quote
Old 6th September 2017, 03:52   #2  |  Link
FranceBB
Broadcast Encoder
 
FranceBB's Avatar
 
Join Date: Nov 2013
Location: Royal Borough of Kensington & Chelsea, UK
Posts: 2,883
Works.
Quality-wise it does its job and, although it doesn't use all my cores and threads at 100%, it's really fast (10fps in a 1080 -> 720 reverse upscale using debilinear is quite good).



Code:
FFMpegSource2("GTO (2014) - 02 [1080p].mkv", fpsnum=30000, fpsden=1001, atrack=-1)

DeBilinearResizeMT(1280, 720, threads=8, logicalCores=true, MaxPhysCore=true, SetAffinity=true)

TextSub("GTO_2014_ep2.ass")

ResampleAudio(48000)

Normalize(0.89, show=false)

video=last

FFMpegSource2("logo_finaleGTO.avi", fpsnum=30000, fpsden=1001, atrack=-1)

Converttoyv12()
ResampleAudio(48000)
TextSub("Onizuka Credits.ass")

logo=last

logo++video++logo
The screen of Task Manager Windows is of when it already passed the initial logo part and is encoding the mkv video using debilinear, of course.

Last edited by FranceBB; 6th September 2017 at 03:58.
FranceBB is offline   Reply With Quote
Old 6th September 2017, 08:52   #3  |  Link
jpsdr
Registered User
 
Join Date: Oct 2002
Location: France
Posts: 2,309
For now it works if fabs(shift)<1 and no cropping. Working on to make it works even with things like this (source 720x480) :
Code:
Spline36ResizeMT(a,1280,720,src_left=17.2,src_width=680,src_top=-8.7,src_height=440)
DeSpline36ResizeMT(720,480,src_left=17.2,src_width=680,src_top=-8.7,src_height=440)
Expect a new release soon.

Last edited by jpsdr; 6th September 2017 at 08:54.
jpsdr is offline   Reply With Quote
Old 7th September 2017, 19:02   #4  |  Link
jpsdr
Registered User
 
Join Date: Oct 2002
Location: France
Posts: 2,309
New release, now Desample works with high shift value and/or croped on origin.
jpsdr is offline   Reply With Quote
Old 3rd November 2017, 05:25   #5  |  Link
real.finder
Registered User
 
Join Date: Jan 2012
Location: Mesopotamia
Posts: 2,587
tried to play with it but I think there are some bug!

Code:
some SD source here
w=Width
h=Height
IResize(1080,1440,resifilter="BilinearResizeMT")
IResize(w,h,resifilter="DeBilinearResizeMT")
you may see this strange but there are many sources that resized in interlaced (like FAIRY TAIL S1 anime TV)

even some interlaced bluray (seen in some movie of detective conan for example)

edit: tried with dither_resize16

Code:
w=Width
h=Height
IResize(1080,1440,resifilter="resizex",res_params=""",lsb=true,kernel="Bilinear"""")
IResize(w,h,resifilter="resizex",res_params=""",lsb=true,kernel="Bilinear",dither_params=",invks=true"""")
and it work fine, Debilinear by Prunedtree work too, but it need to run the script in avs2.5 since Debilinear support only yv12 and rgb, so the problem in Desample

edit: now it work with Desample, forget about old resizex and IResize above

and even with resizex (Important if you work with 422 and 411 sources cuz there are some chroma shift, but don't worry when you work with 420 and 444 of even Y*)

Code:
IResize(720,480,resifilter="resizex",res_params=""",desampling=true,kernel="Bilinear"""")
__________________
See My Avisynth Stuff

Last edited by real.finder; 29th January 2022 at 14:22.
real.finder is offline   Reply With Quote
Old 3rd November 2017, 10:58   #6  |  Link
jpsdr
Registered User
 
Join Date: Oct 2002
Location: France
Posts: 2,309
I think the issue comes from the fact the it resizes splitting planes and shifting chroma according resize size.
As i said in the 1rst post :
Code:
The usage is the following : You have to enter in the parameters exactly the same that have been
used for the original resampling, except the size of course, where you specify the original size you want back.
And your IResize is messing this requirement, putting different src_left on resampling and desampling phase.
See the example to look how exactly how it has to be done.
I've never said the filter behave exactly like "old/original" desampler, because i don't have the code and the author gave me only the global description of the algorithm, and i don't know how it handles shift parameters, but i will not change what i've done in my filter.
The way IResize works, or you use it, is not compatible with the way my desample works. You have either to change adapt the IResize, or manualy set the shift parameters, or use it differently. I don't look deep enough to say what exactly is the correct answer.

My desample will try to retreive the original before resampling, it will not do any shift, if you want to to shift, you have to do it afterward. For a desample to do shift, it would need "2" shift parameters instead of "1". One for the shift used in original resampling, one for the shift you want to produce afterward. "Original" desampler didn't have the shift paramaters doubled, neither mine. I choose to consider that the shift parameter you put is the one you've put in the original resampler, and not a shift you want to produce afterward, otherwise, it means you'll be unable to desample a resampling with shift, if you're unable to provide the original shift information to your desample.

Last edited by jpsdr; 3rd November 2017 at 11:05.
jpsdr is offline   Reply With Quote
Old 3rd November 2017, 18:36   #7  |  Link
real.finder
Registered User
 
Join Date: Jan 2012
Location: Mesopotamia
Posts: 2,587
Quote:
Originally Posted by jpsdr View Post
My desample will try to retreive the original before resampling, it will not do any shift, if you want to to shift, you have to do it afterward. For a desample to do shift, it would need "2" shift parameters instead of "1". One for the shift used in original resampling, one for the shift you want to produce afterward. "Original" desampler didn't have the shift paramaters doubled, neither mine. I choose to consider that the shift parameter you put is the one you've put in the original resampler, and not a shift you want to produce afterward, otherwise, it means you'll be unable to desample a resampling with shift, if you're unable to provide the original shift information to your desample.
yes, the "it will not do any shift" is why it not work correctly

anyway IResize do the shift in fields, it needed for resize interlaced sources, without shift the output will be wrong
__________________
See My Avisynth Stuff
real.finder is offline   Reply With Quote
Old 6th November 2017, 10:45   #8  |  Link
jpsdr
Registered User
 
Join Date: Oct 2002
Location: France
Posts: 2,309
So, if "original" version can do shift, it means it's not able to properly desample shifted resampled video. Because the shift parameter is used like the shift parameter in the original resample to shift the video, and not as an information of the shift value in the original resampler.
So, even if with the "original" desampler the little 2 lines script seems to work, i think it's not also working realy properly, because the desampling phase doesn't know the shift value used in the sampling phase.

Honestly, i don't think you can use IResize for both sampling and desampling with real proper result. You need to create a specific IDesize, where you'll add another shift parameter which is the shift value used in the resampling phase, or, automaticaly compute what you think the shift value in the previous resampling phase may have been to properly desample, and then, after desampling and retrieve the real proper original picture, before the shift&resample, add another shift if you want.

All i can say, it's if you're doing this :
Code:
a=SD Video
w=a.Width()
h=a.Height()
b=BilinearResize(a,1080,1440,src_left=0.5) (or MT, whatever)
c=DeBilinearResizeMT(b,w,h,src_left=0.5)
You'll have c=a.
If you change the value of src_left, you'll have improper result.

If you want after to shift the result, you'll have to do :
Code:
a=SD Video
w=a.Width()
h=a.Height()
b=BilinearResize(a,1080,1440,src_left=0.5) (or MT, whatever)
c=DeBilinearResizeMT(b,w,h,src_left=0.5)
BilinearResize(c,c.Width(),c.Height(),src_left="the shift you want")
Warning : If in the resample phase, you'll have high (>1) src_left shift value for exemple, you'll get c.Witdh()<w ! Because i can't do magic and retreive the croped/discarded pixels.

Last edited by jpsdr; 6th November 2017 at 11:05.
jpsdr is offline   Reply With Quote
Old 6th November 2017, 15:08   #9  |  Link
real.finder
Registered User
 
Join Date: Jan 2012
Location: Mesopotamia
Posts: 2,587
well, I already did some edit for that, even did support resizex case, the result is better now but not perfect
__________________
See My Avisynth Stuff
real.finder is offline   Reply With Quote
Old 6th November 2017, 15:54   #10  |  Link
jpsdr
Registered User
 
Join Date: Oct 2002
Location: France
Posts: 2,309
Can you tell/describe me what you want to do exactly, with a precise specific exemple ?
(Like : I have a 1080i upsample video i want do desample to 520i, assuming the resampling have been done using xxxx).
I think you use IResize for the chroma resize shift adjustment, but, just assume for one moment, we ignore this, and don't try to correct/this issue, and don't split planes.
With just Bilinear and Debilinear, what would be your script ? (But maybe before doing the script, the description would be enough...).

Maybe with the description, i could be able to make a script (even if specific) which will do what you want to do ?
jpsdr is offline   Reply With Quote
Old 6th November 2017, 20:50   #11  |  Link
real.finder
Registered User
 
Join Date: Jan 2012
Location: Mesopotamia
Posts: 2,587
here the original post by IanB https://forum.doom9.org/showpost.php...7&postcount=35

and here Gavino one https://forum.doom9.org/showpost.php...0&postcount=51

yes, lets say we have 1080i but the original of it was in SD (480i or 520i) and they did upscale (resize) it to 1080i without deinterlacing (VirtualDub has an option for that for example)
__________________
See My Avisynth Stuff
real.finder is offline   Reply With Quote
Old 7th November 2017, 09:58   #12  |  Link
jpsdr
Registered User
 
Join Date: Oct 2002
Location: France
Posts: 2,309
By resize without deinterlacing, you mean they resize each field separetely. It's at my request that Avery Lee added the option on VDub, but he "refused" to make it work on YV12, because he "stuck" on the fact that YV12 is only progressive by format definition/specification, so if you check the interlaced box in resize filter on YV12 video, it automaticaly converts to YV16...
I'll think/work on something later during my lunch break for a script.
jpsdr is offline   Reply With Quote
Old 7th November 2017, 13:43   #13  |  Link
jpsdr
Registered User
 
Join Date: Oct 2002
Location: France
Posts: 2,309
Ok, if i didn't make any mistakes and understood properly :
Code:
function IBilinearYV12(clip c,int NewWidth,int NewHeight)
{
  Wr=Float(NewWidth)
  Hr=Float(NewHeight)/2.0
  v=SeparateFields(c)
  W0=Float(v.Width())
  H0=Float(v.Height())	
  C_Shift=0.25*(1.0-W0/Wr)
  V_Shift=(GetParity(v) ? -0.25 : 0.25)*((H0/Hr)-1.0)
	
  Video=SelectEven(v)
  Ye=ConvertToY8(Video).BilinearResizeMT(NewWidth,NewHeight/2,src_top=V_Shift)
  Ue=UToY8(Video).BilinearResizeMT(NewWidth/2,NewHeight/4,src_top=V_Shift,src_left=C_Shift)
  Ve=VToY8(Video).BilinearResizeMT(NewWidth/2,NewHeight/4,src_top=V_Shift,src_left=C_Shift)
	
  Video=SelectOdd(v)
  Yo=ConvertToY8(Video).BilinearResizeMT(NewWidth,NewHeight/2,src_top=-V_Shift)
  Uo=UToY8(Video).BilinearResizeMT(NewWidth/2,NewHeight/4,src_top=-V_Shift,src_left=C_Shift)
  Vo=VToY8(Video).BilinearResizeMT(NewWidth/2,NewHeight/4,src_top=-V_Shift,src_left=C_Shift)
	
  Y=Interleave(Ye,Yo)
  U=Interleave(Ue,Uo)
  V=Interleave(Ve,Vo)
	
  YToUV(U,V,Y).Weave()
}


function IDeBilinearYV12(clip c,int OriginalWidth,int OriginalHeight,int "order")
{
  order=default(order,0)

  W0=Float(OriginalWidth)
  H0=Float(OriginalHeight)/2.0
  v=SeparateFields(c)
  Wr=Float(v.Width())
  Hr=Float(v.Height())	
  Original_C_Shift=0.25*(1.0-W0/Wr)
  Original_V_Shift=(GetParity(v) ? -0.25 : 0.25)*((H0/Hr)-1.0)
	
  Video=SelectEven(v)
  Ye=ConvertToY8(Video).DeBilinearResizeMT(OriginalWidth,OriginalHeight/2,src_top=Original_V_Shift,order=order)
  Ue=UToY8(Video).DeBilinearResizeMT(OriginalWidth/2,OriginalHeight/4,src_top=Original_V_Shift,src_left=Original_C_Shift,order=order)
  Ve=VToY8(Video).DeBilinearResizeMT(OriginalWidth/2,OriginalHeight/4,src_top=Original_V_Shift,src_left=Original_C_Shift,order=order)
	
  Video=SelectOdd(v)
  Yo=ConvertToY8(Video).DeBilinearResizeMT(OriginalWidth,OriginalHeight/2,src_top=-Original_V_Shift)
  Uo=UToY8(Video).DeBilinearResizeMT(OriginalWidth/2,OriginalHeight/4,src_top=-Original_V_Shift,src_left=Original_C_Shift,order=order)
  Vo=VToY8(Video).DeBilinearResizeMT(OriginalWidth/2,OriginalHeight/4,src_top=-Original_V_Shift,src_left=Original_C_Shift,order=order)
	
  Y=Interleave(Ye,Yo)
  U=Interleave(Ue,Uo)
  V=Interleave(Ve,Vo)
	
  YToUV(U,V,Y).Weave()
}


a=AVISource("Your_720x480i_video.avi",FALSE,"YV12")
b=IBilinearYV12(a,1920,1080)
IDeBilinearYV12(b,720,480)
Warning : You're assuming that the video has been upscaling using a specific method, a specific resizer and from YV12.
I don't know what format professionnals use as master and work with. Theres is also possibility that master was 4:4:4 or 4:2:2, upscaled, and ther afterward converted to YV12.

So to figure out the best desampling option, a lot of tests and investigations has to be done, considering a lot of possibility of "upscaling method" (with and without shift when upscaling, play with the order parameter of Debilinear, upscale was done on 4:4:4 and then converted to YV12, etc...)

Last edited by jpsdr; 7th November 2017 at 13:46.
jpsdr is offline   Reply With Quote
Old 7th November 2017, 16:03   #14  |  Link
real.finder
Registered User
 
Join Date: Jan 2012
Location: Mesopotamia
Posts: 2,587
yes, it work now, I was think of I must did some reverse in shift, thanks to your editions of IResize give me the incentive after test your script

and now it even successfully work with FAIRY TAIL S1 anime TV sample I have

Code:
IResize(720,480,resifilter="resizex",res_params=""",desampling=true,kernel="Bilinear"""")
the links of new edit in the bottom part of same post https://forum.doom9.org/showpost.php...45&postcount=5
__________________
See My Avisynth Stuff
real.finder is offline   Reply With Quote
Old 3rd May 2018, 01:22   #15  |  Link
real.finder
Registered User
 
Join Date: Jan 2012
Location: Mesopotamia
Posts: 2,587
can these desampling functions used in undownscale nowdays DVD anime OVA/OAD that has halos? Of course we can't get the details back, but I ask for this to dehalo these sources in more details and more clean output than old dehalo methods
__________________
See My Avisynth Stuff
real.finder is offline   Reply With Quote
Old 3rd May 2018, 11:46   #16  |  Link
jpsdr
Registered User
 
Join Date: Oct 2002
Location: France
Posts: 2,309
I don't know if it will work.
You can reverse upscale, because mathematicaly, in a certain way, you kept all the informations. Basicaly, you added pixels, so you can say that you've "only" added information, and all the original information may still be retrieved.
Downscale, basicaly you remove pixels, so information is loss.
I was even thinking of forbid reverse downscale, but it wasn't realy easy to make accurate test, because of possible akward croping cases. I thought i add, but a quick look on the code, it seems i didn't.
You still can try, but you may encounter cases of matrix not being reversible, and i don't know what it can produce (well case of matrix not reversible should theoricaly be handled and produce an error message). But if by any luck it produces good result...
__________________
My github.
jpsdr is offline   Reply With Quote
Old 24th March 2021, 23:36   #17  |  Link
real.finder
Registered User
 
Join Date: Jan 2012
Location: Mesopotamia
Posts: 2,587
Quote:
Originally Posted by jpsdr View Post
You still can try, but you may encounter cases of matrix not being reversible, and i don't know what it can produce (well case of matrix not reversible should theoricaly be handled and produce an error message). But if by any luck it produces good result...
it give


I did some test with this




yahr2




Code:
Dither_convert_8_to_16()
Dither_resize16(854,Height()/2,invksh=true, kernel="spline36")
Dither_resize16(720,480, kernel="bilinear")
Ditherpost()


it seems do something
__________________
See My Avisynth Stuff

Last edited by real.finder; 25th March 2021 at 02:11.
real.finder 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 16:29.


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