Log in

View Full Version : Internaly multi-threaded resampling functions


Pages : 1 2 3 4 [5] 6 7 8 9

jpsdr
23rd February 2022, 18:38
Finaly sooner than expected, new version, see first post.

tormento
1st September 2022, 20:05
Finaly sooner than expected, new version, see first post.
Please have a look at descale (https://github.com/Irrational-Encoding-Wizardry/descale/releases/tag/r8).

Is the b & c assignment of any help when downsizing to native resolution?

If positive, would you please add them?

Edit: I tried descale and it’s nice to play with them to have the wanted result.

jpsdr
2nd September 2022, 18:42
I just took a quick look, but... I think... it basicaly does what my Desampling functions are doing. Just he computes a different matrix a different way, maybe producing smaller matrix and so maybe faster.
I'll will not work on this, as i've allready done Desampling functions, which are, from my point of view (after, i may be wrong...), the same thing.

Edit
Ok, looking at the other thread, it's doing the same thing, but with a different method.
But, still not planning to add this to my projects.

jpsdr
20th November 2022, 15:10
New version, see first post.

jpsdr
26th February 2023, 12:33
New version, see first post.

DTL
27th February 2023, 00:03
Same idea as in the https://github.com/AviSynth/AviSynthPlus/issues/337#issuecomment-1443754965 - add also user control for 'support' of UserDefined2ResizeMT as it was found make significant changes to processing result. At least in the range from current 2.0 to 3. So it recommended to add one more control param 'support' or 's' and use it as 'support()' kernel class return value to resampler's program (line https://github.com/jpsdr/ResampleMT/blob/b55cb99a681ad69795c9dbdf678d9a7c601ee697/ResampleMT/resample_functions.h#L311 ). Range from todays 2.0 (or even 1.5 if user like to truncate used in resampler kernel even more) to may be some really 'big' value like 20.
Also the 'UserDefined' will be more flexible controlled by user's params input (no internally fixed 'support' param as today).

Also as AVS looks like allow to put vector of variable length as filter argument - may be make more 'universal' version of UserDefinedNResizeMT() with variable number of kernel members ? Let it be default 2 arguments as today but if user need more precise control and want to provide more kernel members - read from provided text string (count number of provided numbers and set as b,c,d,e,... members of kernel). Or may be separated named resize with kernel members list instead of b and c fixed 2 members ?

DTL
16th March 2023, 21:55
I install MFC to my home VisualStudio2019 as it looks it required now (need include file afxres.h) but still got lots of linker errors like

Error LNK2001 unresolved external symbol "void __cdecl resizer_h_avx2_generic_float<-1,7>(unsigned char *,unsigned char const *,int,int,struct ResamplingProgram *,int,int,int,unsigned char,bool)" (??$resizer_h_avx2_generic_float@$0?0$06@@YAXPEAEPEBEHHPEAUResamplingProgram@@HHHE_N@Z) ResampleMT \ResampleMT-master\ResampleMT\resample.obj 1

What may be wrong ? At work it builds with another install of VisualStudio2019 but may be with different set of components installed. May be some component of VS still missing ?

jpsdr
17th March 2023, 09:38
Ah... Sorry, no idea about the install needed part.
But... just be sure that the avx2 .cpp specific files are effectively build in the project. My .sln on github is a VS2010, so avx2 files are included in the project, but disabled in the build.

DTL
17th March 2023, 11:34
Oh - it works now. Thank you. It looks I forgot it from previous years. I sadly quickly forgot many things.

Now I found I make changes of addition s-param to UserDefined2Resize and make pull-requests to your github and to pinterf's AVS+ but forgot to make pre-build for users to test. It is made and uploaded now - https://github.com/DTL2020/ResampleMT/releases/tag/pre-2.3.8

I understand the accepting new changes may also take many months or many years but it is good to start process of testing by users some day.

The default s-param value is set to 2.2f to better differentiate it from SinPowResize (only 2.0 support by design and unlikely can be significantly changed). The UserDefined2Resize kernel as really infinitely linear can use any support value without additional distortions. Also for best 'linear' processing quality the 'large' support of much more 3 is recommended (though resampler's performance will be lower). But playing with 'low' support values around 1.8..2.5 may give additional benefits in not-true-highend workflows of limited frame sizes giving smaller (thinner) halo around transients.
Currently max s-value is limited to 15 to not allow user to set too slow processing with visually equal output. I hope it is enough with even float precision computing and currently used only 2 kernel members.

pinterf
17th March 2023, 12:55
When the changes seem to be final, I'm going to accept the pull request (along with a short and a long hint which can be put into the documentation), it is a good thing to end users to keep the original and jpsdr's MT variants in sync. To Avisynth+ core UserDefined2 is new and hasn't got history so it is easier for me.

DTL
17th March 2023, 16:49
"When the changes seem to be final"

I hope changes are final. The kernel equation become more simple (and hope more stronger in design). No more condition check with internal 'magic number'. Also the last processing param of 'support' is also user-defined now. The a-member of the kernel is =1 by design and should not be changed. Nothing more to control. It is much more programmer- and user-friendly in compare with 100+ user-controlled params of mvtools degrain now. MDegrainN may soon reach 50+ params count. Heh.

Also to make total resampling_functions.cpp program text shorter - the sinc(x) function may be global for all sinc-based kernels. UserDefined2 do not require any special sinc(). It may be equal for common mathematics of current civilization sin(x)/x (with some protection from division by zero error in practical programming). It may reuse sinc() from 'classic' SincResize() and others.

If sinc() exist in standard C-library it can be directly used.

jpsdr
26th March 2023, 13:55
New version, see first post.

jpsdr
20th November 2023, 21:54
New version, see first post, but nothing big...

tormento
30th September 2024, 14:25
I've made a plugin of the resampling functions, with internal multi-threading.
I need some clarifications about how they compare with AVS+ internal filters.

I am using SinPowerResize(720,540) to downsample Y plane in a 2:1 anime downscale:

Y = ConvertToY(matrix="Rec709").SinPowerResize(720,540)
U = UToY()
V = VToY()
YToUV(U, V, Y)

What is the difference between SinPowerResize and your SinPowResizeMT? How many taps do they apply by default? Higher is better?

And, what is the inverse function of it? DeSincResizeMT, DeSinSqrResizeMT or DeSincLin2ResizeMT?

jpsdr
30th September 2024, 19:31
What is the difference between SinPowerResize and your SinPowResizeMT?
Normaly, none. I mean, unless of a bug, the functions are identical in ouput.

But... I'm not sure, as it was a while ago, but if i remember properly, it's DLT who asked me to add these functions, so it's possible that they were first implemented in my plugin, and then afterward implemented in avs.
If that's the case, it wasn't possible for me to compare my functions with the ones in avs core (to be sure of identical output) as they didn't exist, so, in that case, maybe output is not identical...

The description is in the Readme, default p=2.5.


And, what is the inverse function of it?
The reverse of a function is the same name with "De", so reverse of SinPowResizeMT is DeSinPowResizeMT.

tormento
30th September 2024, 20:12
If that's the case, it wasn't possible for me to compare my functions with the ones in avs core
They are not, at least SinPow. AVS+ is sharper.
The reverse of a function is the same name with "De"
Why you created the "De" variant? Aren't them identical, once you use the same downscaled resolution? What does change?

jpsdr
30th September 2024, 20:43
They are not, at least SinPow. AVS+ is sharper.

In that case, it was probably like i vaguely remember. DLT asked me these functions, with some default settings.
Then, later, asked for them to be implemented in avs+ core. Either with different default settings, either with a different parameter in the function.
Code should be compared.
Or... Default settings in avs+ changed since i made the code, but i doubt... More likely the first explanation.



Why you created the "De" variant? Aren't them identical, once you use the same downscaled resolution? What does change?
IF you have an original size of X0,Y0.
If you do
xxxxResize(X1,Y1)
xxxxResize(X0,Y0)
It will not revert exactly to your orignal X0,Y0 picture.
But this:
xxxxResize(X1,Y1)
(or xxxxResizeMT(X1,Y1))
DexxxxResizeMT(X0,Y0)
will revert exactly to your orignal X0,Y0 picture.

hello_hello
30th September 2024, 21:04
They are not, at least SinPow. AVS+ is sharper.

Are you sure?

https://imgur.com/rMAST0R.png

tormento
30th September 2024, 22:15
Are you sure?
I am talking about downsizing not upsizing.

hello_hello
1st October 2024, 00:01
I am talking about downsizing not upsizing.

I did try it both ways.

https://imgur.com/itrILx0.png

tormento
1st October 2024, 16:20
I did try it both ways.
I was actually wrong. I forgot a 'c' in the function name.

They are eventually equal in image output but jpsdr's SinPowResizeMT is faster, with threads=1 in a Prefetch (2,6) script.

I have tried DeSinPowResizeMT to downsize an image but the results is awful.

FranceBB
1st October 2024, 17:39
DeSinPowResizeMT to downsize an image but the results is awful.

Each "De" version of resampling kernels is used to invert such a kernel. If the content was upscaled with Bilinear, then DeBilinear inverts it, if the content was upscaled with Bicubic, then DeBicubic inverts it and so on.
In other words, only if an image was upscaled with SinPowerResize, then you can reverse it using the "De" variant.

A few catches, though:

1) SinPower is only really used to downscale, so it's very unlikely to ever find a source that has been upscaled with such a kernel

2) Inverting a kernel isn't a normal downscale, you have to not only be sure that a content was upscaled with that resizing kernel, but also that the resolution you're bringing it back to was the one you started with.



For your use-case which is downscaling, you can go with SinPowerResize and call it a day.

tormento
6th October 2024, 10:44
@jpsdr

Can your resampling functions deal with fractional resolutions? If positive, have I to converto to floating before your resizing filter or the output is floating already?

jpsdr
7th October 2024, 18:04
They are exactly the same as the core functions. Parameters target are interger, src are float.
I don't realy understand the question about the ouput. The data depth is the same as the input, if picture data input is float, picture data output is float.

FranceBB
7th October 2024, 20:46
Can your resampling functions deal with fractional resolutions?


You can't convert to fractional resolutions, they have to be integers. If you work in yv12 then they can only be even and if you work in yv16, yv24 or rgb24 then they can also be odd.

For instance:

ColorBars(848, 480, pixel_type="yv12")

Spline64Resize(848, 478)

because you can only resize to even resolutions, but if you go to yv16, yv24 or rgb24 then you can resize to odd resolutions, so this works:

ColorBars(848, 480, pixel_type="yv16")

Spline64Resize(848, 479)

same goes for this:

ColorBars(848, 480, pixel_type="yv24")

Spline64Resize(848, 479)

and of course this:

ColorBars(848, 480, pixel_type="RGB24")

Spline64Resize(848, 479)

Note the "479" here being odd, yet working.
Anyway, encoding files with an odd resolution is a very bad behavior and I know a person or two who would try to find you and scold you if they were to get in touch with a similarly encoded file hahahahahahha



If positive, have I to converto to floating before your resizing filter or the output is floating already?

Nope, ConvertBits(32) won't save you, you can't resize with non integer values, so sticking a "ConvertBits(32)" before Spline64ResizeMT() won't automagically allow you to do something like Spline64Resize(848, 479.5).


TL;DR just resize to even pixels and encode it. ;)

DTL
8th October 2024, 18:05
@jpsdr

Can your resampling functions deal with fractional resolutions? If positive, have I to converto to floating before your resizing filter or the output is floating already?

First you need to understand the difference between:
1. Frame/canvas size
2. Image size
3. Resolution

1. Frame or digital canvas size always integer (simply number of samples)

2. Image size can be any real number in size (also the position too) and in the beast case Image size < Frame size. For example at ADC of Analog TV line (ITU Rec.601 and later) it takes 702 samples of 720 frame size. Outer samples help to encode transients from edge of line to the 'known level' and it is black level. With your fractional V image size it is better to add some padding to digital frame size to keep these transients (also you need to shape/prepare/condition these transients in a good way so any upscale resizer at display will create nice image borders without Gibbs ringing).
The 'pure digital' standards like DV and many more others with 'all-samples active image') are not completely defined at the image edges and require some hacking at the image processing to handle image edges of 'special case' (typically as some extension of last sample to half kernel size or other ways to fix edge issues).

3. Resolution is property of image data and can be from zero to max (soft of Nyquist and Gibbs limited).

Here is some simple drawing how Image can be positioned inside Frame
https://ibb.co/d23F04C
https://i.ibb.co/ncV9sMd/2024-10-08-201305.png (https://ibb.co/d23F04C)

After you prepare an Image inside Frame (Digital) you can perform a non-integer scale (and shift) to fine tune your image in digital form on digital canvas. If resizer filters do not support real number direct scale - you can use upsize to N and downsize to M integers so output will have N/M real numbered size. Any avisynth resizer should support integer-sized resize (also see chroma subsampling limitations if used).

So with AVS resizers you operate with Frame/canvas integer sized objects all the time but your Image inside this Frame can be real numbered in size and position (relative to sampling grid). Similar to any real object in the image. You can treat Image as largest possible object in the digital Frame.

If you set Image size = Frame size you lost about half samples to proper encode Image size and position in real numbers space. And force display scaling to work in harder way to make some more or less nice scaling at the edges if image. For N.x Image size you anyway need to use Frame size at least of N+1 or more integer. For less scaling aftifacts it is recommended to pad source frame enough before scaling and make scaling to output Frame size and try to Crop as many Frame samples around Image as you decide (also test with your display scalers how they will handle such prepared Image edges - simple scalers can make more halo or even ringing at poorly conditioned Image edges). In a 'perfect digital world' we need to have some 'safe area' around Image in the Frame and auto-overscan in the display device to cut-off this transient area to show only Image area limited by hardware frame of display device. Like emulating physical overscan at CRT display device. If user set zero overscan at display device it will cause some issues like black border at white areas near frame edge (or any other level of Frame edge defined). If display device also black frame over Image area it may be minor issue.

tormento
8th October 2024, 19:10
Thank you all! :)

tormento
20th October 2024, 19:50
I am going thru a very strange bug with SinPowResizeMT and lineart.

It produces really jagged lines with halo "sparks" (please, zoom the image).

Here (https://www.mediafire.com/file/cmrixa6u6rmlsno/Shangri-La+01+11151-11228.mkv/file) you can find a sample of the video.

SinPowResizeMT script:

SetMemoryMax()
SetCacheMode(0)
SetFilterMTMode("DEFAULT_MT_MODE", 2)
LoadPlugin("D:\Eseguibili\Media\DGDecNV\DGDecodeNV.dll")
DGSource("M:\Out\Shangri-La 01 11151-11228.dgi")
SinPowResizeMT(1656,932,threads=1)
Prefetch(2,6)

Frame 33:

https://i.ibb.co/JF8Q57w/Shangri-La-01-11151-11228-Sin-Pow-Resize-MT-33.png (https://ibb.co/sJcHywd)

Spline64ResizeMT script:

SetMemoryMax()
SetCacheMode(0)
SetFilterMTMode("DEFAULT_MT_MODE", 2)
LoadPlugin("D:\Eseguibili\Media\DGDecNV\DGDecodeNV.dll")
DGSource("M:\Out\Shangri-La 01 11151-11228.dgi")
Spline64ResizeMT(1656,932,threads=1)
Prefetch(2,6)

Frame 33:

https://i.ibb.co/YTMf6Dd/Shangri-La-01-11151-11228-Spline64-Resize-MT-33.png (https://ibb.co/vvGLbsd)

Any idea?

DTL
20th October 2024, 22:37
Some downsizers are not 'universal' with default control params. Try to set a higher p-param value if your source is too sharp. Like p=2.6 or even 2.7 or higher. With p > 3.0..3.2 it will be close to gauss and may be too soft. Default p may be about 2.5 and it may be too 'sharp' for very sharp sources (and low downscale ratio).

Also SinPow resize is not completely perfect and only more simple to control by the average user with simply 1 control param. If it does not work nice with your source it is recommended to try more 'linear' and somehow more complex to control UserDefined2Resize(MT) . The b and c initial params you can see at table https://forum.doom9.org/showthread.php?p=1951250#post1951250 and s-param may be about 2.0..2.2 for better 'sharp/crisp' result but if your source already too sharp you may set s to 3.0 or more to allow filter to be more 'linear'.

Downsizing is a complex task and requires user control to get better results. Also required 'look/makeup' about balance between flat/sharp/ringing or other distortions.

tormento
21st October 2024, 11:07
Some downsizers are not 'universal' with default control params.
I hoped that SinPower could be a general purpose filter and I expected haloing but not line distortion, that's why I reported.

Is it normal that a resize filter deforms lines so much?

Please notice that your link to the table is broken.

If you have some values to start with this kind of scenario, you are welcome.

DTL
21st October 2024, 13:07
The link is to post #179 in this thread. Will try to fix it.

The image hosting looks still working -
https://i2.imageban.ru/out/2021/09/03/2942e09c366b65e4c5e123385e62e340.png

It may be enough good for 'natural' sources like broadcast cameras and film scans. But some sources may cause issues. If it do not work for you with your sources and default params - you can either tweak params or try different resizer.

I still not able to download your source - will try later from different provider and at different machine. My home machine is currently bugged with some issues with browser updates and I do not have time to fix it.

tormento
21st October 2024, 14:30
The link is to post #179 in this thread. Will try to fix it.
Nice!

Are the c,d,e values the result of a formula or determined by some kind of trials and errors?

It would be nice to have a .avsi capable, given b, to ask for how much sharpness/softness we want and give the correct parameters to the other values.

DTL
21st October 2024, 15:37
They are adjusted manually via sinc-summing web-scripting application. They are recommended values but only expected to be mostly valid with infinity downscaling ratio (or at least > 10:1). With a low downscaling ratio best b and c (or c for some given b value) may be somehow different.
Possible adjusting workflow: set b value for some expected sharpness/peaking and adjust c for lowest possible ringing. Currently only the b and c 2 members version is implemented (so name is UserDefined2). If 2 members are not enough for some precise adjustment - the d and e (and any more) may be easily added. In general form it may be UserDefinedN if someone will program any number of input arguments (like string with , separated or any other separation of float numbers). But easy enough was to program 2 members as separated b and c params.

"It would be nice to have a .avsi capable, given b, to ask for how much sharpness/softness we want and give the correct parameters to the other values."

I had the same idea. But for any given source the best c (d,e,..) combination with any given b-member may be different (depending on both source and downscale ratio). Some way to adjust c (and possible other members) - feed output to waveform monitor and find some sharp enough transient and adjust c (and other members if present) to get lowest possible ringing (or some balance between sharpness and ringing). Where first b-member mostly control overall shape of transient (soft/flat/peaked).

Addition: I got your source and made tests - the Spline64Resize works about very good with this footage. About close to this is UserDefined2Resize(1656,932,b=80, c=-20, s=2.0). Differences with SincLin2Resize(width*2, height*2) testing:
1. Spline64Resize on most lines sharper (thinner lines), very few places with some ringing.
2. UserDefined2Resize - on most lines softer (thicker lines and some peaking), looks about no ringing, still some jagginess on lines present. More softer version with less residual distortions is UserDefined2Resize(1656,932,b=90, c=-12, s=3.0) (larger support and longer peaking/halo around transients).

More simple and hacky short support SinPowResize is completely looser at this specially peaked anime source - with default p=2.5 too many distortions and with p=3.2 it going into too soft.

I think users like to use more simple and sharper Spline64Resize and may be very few can see some ringing (at some places at some displays with long sinc kernel scaler). Though the real viewing experience may significantly depends also on display size and viewing distance - too thin 'peaking/halo' may going out of viewer's resolution and image with some more thicker peaking/halo may look visibly sharper (typical 'video' look/makeup). So you can test different production scalers with your own displays (and its sharpen settings) and your typical viewing distance.

DTL
21st October 2024, 21:24
For your use-case which is downscaling, you can go with SinPowerResize and call it a day.

As you see at some real use cases the more simple and short kernel of SinPowerResize may be not any good. So for broadcast purposes it may be recommended to switch from SinPowerResize to UserDefined2Resize in FFASTrans application. The UserDefined2Resize may be more 'fail safe' in such possible use cases as this anime sample. The best defaults values for b,c,s params are subject of big testing with many real footages (including such anime cases) may be with some weighting to different footages classes (real broadcast/ENG/EFP cameras, film scans, such anime if possible and may be others). As some small enough testing shows typical values may be around b=80 c=-20 s=3.0 (may be tested range of 2.0..3.0 with initial close to 2.5..3.0).

FranceBB
21st October 2024, 23:34
I think that line art as those in anime are a very edge case. Before putting SinPowerResize() in production via FFAStrans I've been testing it on a lot of footages and I manually checked several different real life footage without ever finding any issues, from penguins in ice to otters chilling on a stone on the side of a river to urban areas with buildings to trees and grass in a park to people and their faces etc. I was looking for ringing and aliasing and it never created anything as weird as the images posted above. I think that with natural footage we're fine and that's the predominant use case, but yeah, now that I know that for things like anime it doesn't work, I'll go back to using LanczosResize() or BlackmanResize() when I'll come across that kind of content. After all, they're windowed Sinc so they should be fine. I'm not gonna go with things like GaussResize() unless it's a last resort as it's far too soft. At the same time, I'll never gonna use Spline based resizers to downscale as they're known to be introducing ringing and I've seen it with my eyes back in 2013 in my first job at Crunchyroll. Anyway, I've been working for Sky for almost 9 years now, so I haven't really been encoding anime for a really long time. It's almost exclusively natural footage. As for FFAStrans, you have now given me a bit of an headache, but I guess I'm gonna have to revert to either Lanczos or Blackman by default 'cause if something like that comes up without anyone checking it and it's performing the downscale automatically in production bad things are gonna happen and there won't be anyone QCing it given that most stuff nowadays are all handled automatically. :(

DTL
22nd October 2024, 04:58
they're windowed Sinc so they should be fine.

For downscaling single windowed sinc is not enough (too narrow). So UserDefined2 is a weighted sum of several (standard sampling interval 1 sample shifted) sincs. And it is enough self-windowed with that set of weighting coefficients from table.

The kernels of Gauss, SinPow and UserDefined2 are of special 'family' of 'wide kernels' with some low-pass filtering effect required for supress Gibbs ringing. Also with adjustable width of the main lobe. Many others of single windowed sincs (Lanczos or Blackman or many many other window-named) are not so only good for upscale.

About Spline I not sure but if the graph of http://avisynth.nl/index.php/File:Spline.jpg is correct - it also have first zero at x=1 (+-1) as standard sinc so too narrow for downsize.

"it never created anything as weird as the images posted above."

The distortions may be increased in case of 1. Too sharp/peaked source + 2. Too small downscale ratio (below 2:1) + 3. Non-integer scale ratio (about 1.159:1). If you test something like UHD to FHD downscale or lower it may perform with less distortions.

You may add some more auto-logic into FFASTrans like special case of downsizing with very small ratio range like from 1.001:1 to about 1.4:1 (subject to test) and recommend some other downsize engine instead of SinPow with default p-param (also depends on input source sharpness). Or at least note (warning) to user to check output in this case.

tormento
22nd October 2024, 12:10
I can't understand the sensitivity of p parameter in SinPow: p=1-2 are the sharpest but with lot of artefacts.

In the 1-100 range of p parameter, even 4 makes the picture softer than Spline.

tormento
22nd October 2024, 13:53
Every day I understand how much I ignore.

Such as in 420 chroma is half the resolution of luma, isn't better to downscale like

Y = ConvertToY(matrix="Rec709").Spline64ResizeMT(resX,res,threads=1)
U = UToY().Spline64ResizeMT(resX*2, resY*2 ,threads=1)
V = VToY().Spline64ResizeMT(resX*2, resY*2 ,threads=1)
YToUV(U, V, Y)

And if positive, how much should I move chroma in the ConvertY line?

Another option could be

AiUpscale(Factor=1, CResample="KrigBilateral", Mode="LineArt", OutDepth=16)

but I'd like to keep things as simple and fast as possible.

DTL
22nd October 2024, 15:07
I can't understand the sensitivity of p parameter in SinPow: p=1-2 are the sharpest but with lot of artefacts.

In the 1-100 range of p parameter, even 4 makes the picture softer than Spline.

It is not aligned to 0..100 range and only usable range is very narrow float - from about 2.5 to 3.0. Where 2.5 is about max sharp and about 3.2 and more is close to Gauss.

FranceBB
22nd October 2024, 15:46
If you test something like UHD to FHD downscale or lower it may perform with less distortions.


Yeah that's probably the case. Most of the times the use cases were either UHD SDR to FULL HD SDR or FULL HD SDR to SD SDR as I have to create all the versions of the files starting from the same main asset.


You may add some more auto-logic into FFASTrans like special case of downsizing with very small ratio range like from 1.001:1 to about 1.4:1 (subject to test)


Yeah, I've been thinking about this as I was in bed, trying to sleep, and I came up with a similar approach. I actually like this and I feel like this is gonna be the way to go. :)



Or at least note (warning) to user to check output in this case.

Yep, I will definitely write something under the "?" button and in the documentation, that's for sure.

tormento
23rd October 2024, 08:04
It is not aligned to 0..100 range and only usable range is very narrow float - from about 2.5 to 3.0. Where 2.5 is about max sharp and about 3.2 and more is close to Gauss.
Ok, perhaps it's better to clarify this in the Wiki.

What about my idea of different scaling for luma/chroma?

DTL
23rd October 2024, 16:45
I do not understand your variables (also no values) and no input-output sizes. Better post example with all numbers filled and also input clip size.

I see no one is updating Wiki after new releases today. So I need to register and attempt to make edits to Resize page about 3 new resize filters added. I made registration on Wiki but still not got confirmation e-mail so can not edit Resize page. Will try to wait several days.

tormento
23rd October 2024, 18:32
I do not understand your variables (also no values) and no input-output sizes. Better post example with all numbers filled and also input clip size.

I know the syntax is not exact, it is just a fuzzy idea in my mind.



Resizing from 1920*1080 to 540p, I can go full chroma with:



Y = ConvertToY(matrix="Rec709").Spline64ResizeMT(960,540,threads=1)

U = UToY()

V = VToY()

YToUV(U, V, Y)



Let's say that I have a 1920*1080 4:2:0 source and I want to resize it to 1280*720.



Would be correct to do like this?



Y = ConvertToY(matrix="Rec709").Spline64ResizeMT(1280,720,threads=1)

U = UToY().Spline64ResizeMT(1280, 720 ,threads=1)

V = VToY().Spline64ResizeMT(1280, 720 ,threads=1)

YToUV(U, V, Y)



I'd like to avoid chroma being resized from 540p to 360p, such as in a a simple resize filter. Why to waste all the bits in the 540p chroma that I already have?



And, if correct, would I have a 444 video? Do I need to shift chroma too?

Selur
23rd October 2024, 19:25
Y = ConvertToY(matrix="Rec709").Spline64ResizeMT(720,540,threads=1)
U = UToY()
V = VToY()
YToUV(U, V, Y)
Does this work?!? This seems wrong to me.
Y = ConvertToY(matrix="Rec709").Spline64ResizeMT(720,540,threads=1) should return a 720x540 plane, this looks fine, but
U = UToY() should return 960x540, same for
V = VToY()
with 4:2:0 U and V should be half the clips width and height.
So:

Y = ConvertToY(matrix="Rec709").Spline64ResizeMT(960,540,threads=1)
U = UToY()
V = VToY()
YToUV(U, V, Y)
should work, but using 720 instead of 960 seems wrong to me.

Cu Selur

tormento
23rd October 2024, 19:42
I wrote for 1440x1080, sorry. Fixed.

DTL
23rd October 2024, 22:54
"Let's say that I have a 1920*1080 4:2:0 source and I want to resize it to 1280*720.
Would be correct to do like this?
Y = ConvertToY(matrix="Rec709").Spline64ResizeMT(1280,720,threads=1)
U = UToY().Spline64ResizeMT(1280, 720 ,threads=1)
V = VToY().Spline64ResizeMT(1280, 720 ,threads=1)
YToUV(U, V, Y)"

"would I have a 444 video?"

I think you need to set current clip to 444 format first. So the YtoUV filter can collect planes to required 4:4:4 format. Expected better:
Y = ConvertToY(matrix="Rec709").Spline64ResizeMT(1280,720,threads=1)
U = UToY().Spline64ResizeMT(1280, 720 ,threads=1)
V = VToY().Spline64ResizeMT(1280, 720 ,threads=1)
ConvertToYUV444()
YToUV(U, V, Y)

And you will get 4:4:4 sampling format but still not full possible bandwidth UV because it is only 960x540 at 4:2:0 FullHD. But it is still some better in comparison with 4:2:0 downscaling.

"Do I need to shift chroma too?"

It may depend on your input chroma assumed position. So you can check 4:4:4 result for possible chroma offset and correct it with chroma sub-shifting if required.

hello_hello
24th October 2024, 01:14
Do the ConvertToY() and ExtractY() functions give you identical output when you want the untouched Y plane from a YUV source?

ConvertToY(matrix="Rec709")
To the best of my knowledge the matrix argument does nothing unless you're converting RGB to YUV, or converting YUV to RGB.

I don't think there'd be any chroma shift if you're only resizing the Y plane, but I did find myself wondering how to correct the chroma shift when resizing from 1920x1080 to 1280x720, or to any resolution that isn't half the original width and height, and you want to resize the chroma for YUV444. Would it make more sense to convert the source to YUV444 before resizing, or would it be better to resize the luma down from 1920x1080 to 1280x720 and the chroma up from 960x540 to 1280x720?

Clip = last

Luma = Clip.Resize8(1280, 720, kernel="Spline36", kernel_c="Bicubic", chroma=false)

Chroma = Clip.Resize8(2560, 1440, kernel="Spline36", kernel_c="Bicubic", y=false)

CombinePlanes(Luma, Chroma, planes="YUV", source_planes="YUV", pixel_type="YUV444P8")

Resize8 is chroma placement aware and shouldn't cause a shift when resizing "normally", but I can't quite get my head around whether the shift would be any different when up-scaling the chroma for YUV444 using the method above.

tormento
24th October 2024, 11:56
I can't quite get my head around whether the shift would be
And that's secondo reason for my question.

The first one is: the result is different enough (i.e. resize chroma separately) to justify the few extra cpu cycles or a normal resize is more than enough? If positive, perhaps chroma "adaptation" should be hardcoded in the resize filters.

DTL
24th October 2024, 17:08
"but I did find myself wondering how to correct the chroma shift when resizing from 1920x1080 to 1280x720, or to any resolution that isn't half the original width and height, and you want to resize the chroma for YUV444. "

I think typical plane shift in integer number of samples is Crop+AddBorders and sub-sample shift is applying some resize kernel (Sinc/SincLin2 may be recommended or any Lanczos-like with enough taps) with no-integer resize and only float src_left/src_top arguments.

Though AddBorders is not very nice (in most cases where edge sample of the frame are not conditioned to some fixed code value so it can be safely repeated) and better to use some edge sample-repeating filter.

hello_hello
24th October 2024, 19:45
My understanding of how much the chroma is shifted by Avisynth's resizers for YUV420 is as follows, assuming the chroma placement is "left"....

For a 2x upscale it's a shift of one quarter of a luma pixel to the right.
For a 2x downscale it's half a luma pixel to the left.

As YUV420 chroma has half the luma resolution, shifting the chroma to the left by half a chroma pixel would shift it a full pixel left relative to the luma. That's how Resize8 calculates it. For a 2x upscale it shifts the chroma half of one quarter of a luma pixel to the left (an 8th of a chroma pixel) to compensate for the resizer shifting it to the right.

https://i.imgur.com/maVfpXK.png

Which gets me to my question....
To match what ConvertToYUV444 does, I have to shift the chroma by twice the amount I mentioned above. I can't seem to get my head around the reason though, given it's just being resized. Is ConvertToYUV444 shifting it too much?

separate=true for Resize8 bypasses the normal chroma shift correction and lets you specify the same shift for all planes, even when the chroma is sub-sampled.

What I assumed would be correct.

Clip = last # 1280x720
Luma = Clip.Resize8(1280,720, kernel="Spline36", kernel_c="bicubic", chroma=false)
Chroma = Clip.Resize8(2560,1440, 0.125,0,1280,720, kernel="Spline36", kernel_c="bicubic", y=false, separate=true)
A = CombinePlanes(Luma, Chroma, planes="YUV", source_planes="YUV", pixel_type="YUV444P8")
B = Clip.ConvertToYUV444(ChromaInPlacement="left", chromaresample="bicubic")
Compare(A.ExtractU(), B.ExtractU())

https://imgur.com/74iQphM.png

But to match ConvertToYUV444.

Clip = last # 1280x720
Luma = Clip.Resize8(1280,720, kernel="Spline36", kernel_c="bicubic", chroma=false)
Chroma = Clip.Resize8(2560,1440, 0.25,0,1280,720, kernel="Spline36", kernel_c="bicubic", y=false, separate=true)
A = CombinePlanes(Luma, Chroma, planes="YUV", source_planes="YUV", pixel_type="YUV444P8")
B = Clip.ConvertToYUV444(ChromaInPlacement="left", chromaresample="bicubic")
Compare(A.ExtractU(), B.ExtractU())

https://i.imgur.com/sgUdAi7.png