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. |
![]() |
#1 | Link |
Soul Architect
Join Date: Apr 2014
Posts: 2,559
|
AviSynthShader + SuperRes
Shiandow wrote a scaling algorithm called SuperRes that greatly enhances upscaling. Unfortunately, it wasn't possible to use this code in AviSynth and I really wanted to use it. So, I wrote an AviSynth plugin that allows running any HLSL pixel shaders through DirectX9.
Download the latest release here (v1.6.4, September 20th 2017) https://github.com/mysteryx93/AviSynthShader/releases Source code available on GitHub https://github.com/mysteryx93/AviSynthShader This plugin allows running HLSL pixel shaders within AviSynth. This gives access to various HLSL filters that haven't been programmed in AviSynth. Note: Shiandow's SuperRes is not what is typically being called SuperRes; it's something else. It does not "create" any details like traditional SuperRes or Sharpening algorithms do. It doesn't have any temporal effect either, it works with frames one by one. Here's the way it works. It wraps around other resizers. After doubling the image size (with NNEDI3 for example), it resizes it back down with Bicubic and compares it with the original, producing a diff map representing details that were lost while upscaling. Then, it does its magic from that diff map. How? Well... with this code. Results speak for themselves. I found it to work best with NNEDI3(nns=4) Syntax information on GitHub Special thanks to Shiandow for writing such amazing code, and especially to make it open source! Special thanks to Madshi for taking the time to give very valuable pointers when nobody else was able to help! Here are comparison images ImageSource("Lighthouse.png").ConvertToRGB24() Note: Since uploading these comparison, SuperRes has slightly changed. The newer version has less ringing and softer images. 1. Original 2. Spline16 3. nnedi3_rpow2(4, nns=4, cshift="Spline16Resize") 4. SuperXBR(edgeStrength=.6, weight=.6), twice 5. SuperRes(2, .43, 0, """edi_rpow2(2, nns=4, cshift="Spline16Resize")"""), twice 6. SuperResXBR(2, .6, xbrEdgeStrength=2.3, xbrSharpness=1.2), twice 7. SuperResXBR(1, .7, xbrEdgeStrength=.1, xbrSharpness=.7), twice Lighthouse ![]() ![]() ![]() ![]() ![]() ![]() ![]() Clown ![]() ![]() ![]() ![]() ![]() ![]() ![]() Eclipse (x2) ![]() ![]() ![]() ![]() ![]() ![]()
__________________
FrameRateConverter | AvisynthShader | AvsFilterNet | Natural Grounding Player with Yin Media Encoder, 432hz Player, Powerliminals Player and Audio Video Muxer Last edited by tebasuna51; 14th October 2019 at 11:00. Reason: postimg.cc |
![]() |
![]() |
![]() |
#2 | Link |
Soul Architect
Join Date: Apr 2014
Posts: 2,559
|
SuperRes is one of may shaders that can be run with AviSynthShader. This particular shader greatly enhances upscaling quality and runs on top of any other algorithm you're already using such as NNEDI3.
SuperRes(input, passes, strength, softness, hqdownscaling, upscalecommand) In Shaders\SuperRes\SuperRes.avsi. Thanks to Shiandow for writing this great code! Arguments: passes: How many SuperRes passes to run. Default=1. strength: How agressively we want to run SuperRes, between 0 and 1. Default=1. softness: How much smoothness we want to add, between 0 and 1. Default=0. hqdownscaling: True to downscale using Bicubic, false to downscale using Bilinear. upscalecommand: An upscaling command that must contain offset-correction. Ex: """nnedi3_rpow2(2, cshift="Spline16Resize")""" Shiandow provides many other HLSL shaders available here that can be integrated into AviSynth. https://github.com/zachsaw/MPDN_Exte.../RenderScripts Here's a comparison of NNEDI3 with and without SuperRes. Original ![]() NNEDI3 ![]() NNEDI3 + SuperRes (passes=1, strength=1, softness=0) ![]()
__________________
FrameRateConverter | AvisynthShader | AvsFilterNet | Natural Grounding Player with Yin Media Encoder, 432hz Player, Powerliminals Player and Audio Video Muxer Last edited by tebasuna51; 14th October 2019 at 11:02. |
![]() |
![]() |
![]() |
#3 | Link |
Soul Architect
Join Date: Apr 2014
Posts: 2,559
|
As of right now, ConvertFromFloat isn't working towards RGB32. By fixing this, it would allow avoiding an unnecessary RGB-YUV conversion within SuperRes and may increase quality and performance.
The conversion code is here, could someone familiar with RGB32 help me on this one? https://github.com/mysteryx93/AviSyn...mFloat.cpp#L54 Then, we could also avoid an unnecessary conversion by doing the SuperRes downscaling via a Shader; I don't have any such code right now, and I don't know if the DLL code will have to be tweaked to allow HLSL resizing. Another limitation is that although the library contains a HLSL YUV-RGB conversion and converting back and forth works fine, I get weird distortion after running any other shaders. When using CPU conversion, it works fine. However, the CPU conversion code is Rec601 instead of Rec709. Since it gets converted back using the same algorithm, it doesn't distort the output, but it may cause a slight distort on the shader processing.
__________________
FrameRateConverter | AvisynthShader | AvsFilterNet | Natural Grounding Player with Yin Media Encoder, 432hz Player, Powerliminals Player and Audio Video Muxer Last edited by MysteryX; 2nd October 2015 at 22:48. |
![]() |
![]() |
![]() |
#4 | Link |
ангел смерти
![]() Join Date: Nov 2004
Location: Lost
Posts: 9,555
|
You're officially my hero.
Edit: You're not incrementing dst properly. Since it's char, you're writing to it like: 00000000 ABC00000 ADEF0000 ADGHI000 etc. A simple fix is swapping &dst[x],&dst[x+1],&dst[x+2] with &dst[(x*4)+2],&dst[(x*4)+1],&dst[x*4]. Note that I swapped the order because RGB32 is actually BGRA in memory. The way the function's designed now isn't the greatest, but at least it'll work, that's most important. Last edited by foxyshadis; 3rd October 2015 at 01:48. |
![]() |
![]() |
![]() |
#5 | Link |
Soul Architect
Join Date: Apr 2014
Posts: 2,559
|
|
![]() |
![]() |
![]() |
#6 | Link |
ангел смерти
![]() Join Date: Nov 2004
Location: Lost
Posts: 9,555
|
Is dst memsetted to 0? Could be garbage in the alpha bit. Actually, it's only happening on white, so it's probably not clamping. Should move the clamping outside of the if yuv/rgb block, along with memsetting (or just manually setting alpha to 0 each pixel).
|
![]() |
![]() |
![]() |
#7 | Link |
Soul Architect
Join Date: Apr 2014
Posts: 2,559
|
Great, it now supports converting to/from RGB32. SuperRes's downscaling is now done in RGB32, avoiding unnecessary RGB-YUV conversion. It considerably further increases quality.
![]() 2 areas that still need improvement: 1. Find a Bicubic HLSL shader to avoid unnecessary conversion for downscaling. 2. Convert YUV-RGB in Rec709 colorspace. Because it is currently converting in the Rec601 colorspace, the sharpening effect may slightly pull towards certain colors. Contributions or suggestions are welcomed on those. And then, of course, there are all kinds of performance optimizations that could be implemented. Here are some performance numbers. CPU-Z isn't reading my GPU usage properly so I can't measure what's happening on the GPU. nnedi3_rpow2(2, cshift="Spline16Resize") 60fps @ 55% CPU SuperRes(1, 1, 0, true, """nnedi3_rpow2(2, cshift="Spline16Resize")""") 4.5fps @ 12% CPU MT=8 nnedi3_rpow2(2, cshift="Spline16Resize", Threads=2) 80fps @ 83% CPU SuperRes(1, 1, 0, true, """nnedi3_rpow2(2, cshift="Spline16Resize", Threads=2)""") 15fps @ 85% CPU
__________________
FrameRateConverter | AvisynthShader | AvsFilterNet | Natural Grounding Player with Yin Media Encoder, 432hz Player, Powerliminals Player and Audio Video Muxer Last edited by MysteryX; 3rd October 2015 at 19:32. |
![]() |
![]() |
![]() |
#8 | Link |
Registered User
Join Date: Nov 2014
Posts: 440
|
I have not had yet the opportunity to see the workings of Shiandow's SuperRes. Maybe is Farsiu or Mitzel. Really I have no idea.
I could make it a plugin like KNLMeansCL. If ever I have time.
__________________
github.com |
![]() |
![]() |
![]() |
#9 | Link |
Soul Architect
Join Date: Apr 2014
Posts: 2,559
|
SuperRes doesn't work like typical resize algorithms. It runs around other resizers. So let's say you want to use NNEDI3, it takes the larger image and the original image, does a Bicubic resize on the enlarged image to size it back down to the original, and then creates a difference map between the two, showing the details that were lost during the upsizing. From that diff map, it restores details and edges that were lost. Brilliant idea. It makes even basic resizers like Bilinear look decent.
Originally he was working on the Lab colorspace that definitely requires half-float data, and lately he dropped that to use Linear RGB colorspace. Perhaps I could try running with 8-bit-per-channel to see if there is a significant quality penalty. |
![]() |
![]() |
![]() |
#10 | Link |
Soul Architect
Join Date: Apr 2014
Posts: 2,559
|
I have added support for processing standard 8-bit-per-channel instead of 16-bit-per-channel. Simply add parameter "precision=1" to each conversion and shader calls. Quality is considerably lowered.
![]() With MT=8 SuperRes(1, 1, 0, true, """nnedi3_rpow2(2, cshift="Spline16Resize", Threads=2)""") I get 24fps @ 78% CPU |
![]() |
![]() |
![]() |
#11 | Link | |
Registered User
Join Date: Nov 2014
Posts: 440
|
Quote:
Mitzel: pdf. That's what I was talking about. Like me or tritical, we did not invent NLMeans, but we simply implement a well known algorithm ![]()
__________________
github.com |
|
![]() |
![]() |
![]() |
#12 | Link |
Soul Architect
Join Date: Apr 2014
Posts: 2,559
|
When using SuperRes, NNEDI3 and EEDI3 give almost identical output. Which means I can get rid of the ridiculously-expensive EEDI3.
1 pass with strength=.85 gives almost the same result as 2 passes with strength=.425, and 2 passes looks slightly better. 2 passes with NNEDI3 is faster than 1 pass with EEDI3. Splitting in 3 or more passes gives the exact same thing as 2 passes. |
![]() |
![]() |
![]() |
#13 | Link | |
Soul Architect
Join Date: Apr 2014
Posts: 2,559
|
Quote:
I'm seeing a weird bug when using 2 passes with strength=0.425, sometimes I get Access Violation, and it's random. Sometimes it starts anyway, and then fails unexpectedly. Now I'm running it with 1 pass with strength=0.85 and it's been running for half an hour without any issue. I really don't see why running a second pass could cause any such issue...
__________________
FrameRateConverter | AvisynthShader | AvsFilterNet | Natural Grounding Player with Yin Media Encoder, 432hz Player, Powerliminals Player and Audio Video Muxer Last edited by MysteryX; 4th October 2015 at 00:50. |
|
![]() |
![]() |
![]() |
#14 | Link |
/人 ◕ ‿‿ ◕ 人\
Join Date: May 2011
Location: Russia
Posts: 643
|
One thing that should be noted is that Shiandow's SuperRes is not a Super Resolution algorithm. I'd call it a "reverse downscaler" - it modifies upscaled image so that downscaled upscaled image is closer to the original image.
|
![]() |
![]() |
![]() |
#15 | Link | |
Registered User
Join Date: Dec 2013
Posts: 753
|
Quote:
|
|
![]() |
![]() |
![]() |
#16 | Link |
Soul Architect
Join Date: Apr 2014
Posts: 2,559
|
I fixed a crash when the DX9 device was lost.
I also replaced the code to copy the data in and out of DX9 with AviSynth's BitBlt, and it considerably increases performance by itself. input.ConvertToFloat().ConvertFromFloat() renders 38fps @ 12% CPU, and if I disable YUV-RGB conversion, 42fps. Could someone look at how this short code could be optimized? |
![]() |
![]() |
![]() |
#17 | Link |
Soul Architect
Join Date: Apr 2014
Posts: 2,559
|
The Access Violation error seems to be an out of memory error, plain and simple.
After playing some more with the settings, softness is actually working pretty well when using Strength=1 and 2 or 3 passes. This is the best result I got with Passes=3, Strength=1, Softness=.25 ![]() There should be further increase in quality once I get to do Bicubic downscaling via shader, as it will avoid clamping on the diff map. |
![]() |
![]() |
![]() |
#18 | Link |
Soul Architect
Join Date: Apr 2014
Posts: 2,559
|
One thing I love about SuperRes is that before, to get the best quality upscaling, I would have to combine EEDI3 and NNEDI3 in the right order and add just the right amount of sharpening at 3 different stages.
With SuperRes, I get better quality with only NNEDI3 and no artificial sharpening. No fine-tuning is necessary per video, standard NNEDI3 frame doubling with SuperRes(Passes=2, Strength=1, Softness=.3) is working perfect for all the videos I tried so far. For the media encoder I was working on, it will make it much simpler. |
![]() |
![]() |
![]() |
#20 | Link |
Soul Architect
Join Date: Apr 2014
Posts: 2,559
|
Fixed float-byte rounding to be more accurate by adding .5f before rounding. Slight performance improvement.
This results in the colors being slightly brighter, and the SuperRes Diff map to be more accurate which slightly improve its effectiveness. As far as writing a native AviSynth version, I don't know if that would work. Originally, Shiandow was using the Lab colorspace which definitely requires half-float processing. He finally dropped it to use RGB Linear (not Gamma) colorspace. I doubt the YUV-RGB conversion could be avoided, and from my tests processing it with non-float data, the quality is considerably lower. This algorithm is very sensitive to details and must be processed with half-float precision. In that sense, perhaps native approaches wouldn't even be better than this. The GPU is much better at processing float data than the CPU.
__________________
FrameRateConverter | AvisynthShader | AvsFilterNet | Natural Grounding Player with Yin Media Encoder, 432hz Player, Powerliminals Player and Audio Video Muxer Last edited by MysteryX; 8th October 2015 at 07:15. |
![]() |
![]() |
![]() |
Thread Tools | Search this Thread |
Display Modes | |
|
|