View Full Version : madVR - high quality video renderer (GPU assisted)
AndreaMG
9th October 2012, 15:14
Thanks, but unfortunately it doesn't work for me.
Strange, have you AnydvdHD enabled? It should remove macrovision...
digitech
9th October 2012, 15:22
Chroma upscaling: Jinc 8 taps
Image upscaling: Jinc 8 taps
Image downscaling: Lanczos 8 taps
(I have the anti-ringing option enabled on everyone of them.
All work great on the NVIDIA GTX 570M without dropped/delayed frames. The image and colours of 1080p, 720p and below are magnificent. And the display modes option also works really well for me.
Keep up the good work Madshi.
Sunnah im interested about your HTPC, can you give me details about processor type, speeed, amount of ram etc, etc, pls? im about to build a new htpc just for the main use of playing movies with madvr, any info about your htpc details will be very apprecciated, thanks!
NicolasRobidoux
9th October 2012, 16:04
... Generally I think movies are softer than photos. ...This is very important information.
NicolasRobidoux
9th October 2012, 16:25
I've added (tensor) Ginseng, Lanczos, Lanczos4, and EWA QuadraticJinc, produced similarly to the earlier ones, to http://web.cs.laurentian.ca/nrobidoux/misc/madVR/glyphs/
-----
Mathias:
Ginseng is very often within JND of Lanczos, so much so that you probably could substitute it for Lanczos, and nobody would know better. (Sorry: I should have mentioned this earlier.) This being said, it does have measurably less halo, and it is slightly less jaggy, although the difference is only noticeable with sharp high contrast features. Although the difference is small, it is (on my brash Samsung monitor), noticeable on the "glyph" enlargements.
Tensor Lanczos is definitely too sharpening when enlarging. Ginseng backs the dial down from 11, just a nudge.
NicolasRobidoux
9th October 2012, 16:51
Mathias:
Indeed, the one advantage of QuadraticJinc (which I am oh! so tempted to christen the "Kaching" filter even though it is oh! so tacky) over LanczosSharp is that it has much reduced halo, without this costing too much in terms of jaggies, sharpness etc (as it does with Keys cubics, which are the best cubics).
So, if you manage to fix the anti-ringing filter for Jinc (or you go with sigmoidization, which does work better with the EWA Lanczoses than the tensor ones anyway), I would guess there is no need for it. Otherwise, use it for chroma when using Jinc for luma?
madshi
9th October 2012, 17:03
Thanks, Nicolas.
Do you have any pointers where I can find information about how the "full" sigmoidization works? I suppose it's higher quality than the fast "trick" you mentioned, right? If I start doing funny stuff with color space to improve scaling, I can just as well go the full mile and implement full sigmoidization (if it's not too complicated/slow).
Xaurus
9th October 2012, 17:09
Well, I would much rather implement a *real* sharpening algorithm, to be honest. That's why I'm also reluctant offering so many more tweaks: It costs many hours of my time which I could instead spend on doing the "real thing". Personally, I don't like Darbee pop at all. I much prefer something like Didee's FineSharp. So if you ask me to add this and that, and a couple of other tweaks in between, basically you're keeping me busy with so-so stuff, instead of allowing me to move on to bigger and greater things. I've said it so many times before: Let me first add all the missing features, before spending my time by twiddling with 1% improvements. I'm feeling held back at the moment, by all the constant requests for small tweaks and changes everywhere. Aren't you guys interested in getting things like custom shader support, 3D support etc?
I fully agree with you, now that you added Jinc I think the algorithm-people should be satisfied.
For me I think 3D-support would be my nr. 1 on the wishlist. :)
Xaurus
9th October 2012, 17:14
For LAV I check off all of the output formats and leave RBG output levels as untouched.
To check your colorspace, what I've found works best is downloading the mp4 version of these test videos:
http://www.avsforum.com/t/948496/avs-hd-709-blu-ray-mp4-calibration
Use the APL clipping (Basic Settings #2) to make sure your colors are correct. Nvidia cards notoriously will output 16-235 over HDMI unless you hack the monitor INF or use Madshi's madnvlevelstweaker (I haven't tested it but I assume it works).
You want to be able to see blinking in the white area up to at least 234 (And black down to 17 or so ideally). If the whole screen is blinking your card is probably converting down to 16-235 and you should try using madshi's tweak.
I have to try that. I have only checked NV12 since I am certain nevcairiel (or was it madshi?) said that was the smartest thing to do.
I am already using the inf-hack for a time, and it works. The APL-test behaves like you describe.
NicolasRobidoux
9th October 2012, 17:24
Mathias:
I'm the one who invented sigmoidization, and when I program stuff into ImageMagick, there are certain things I can't do because I have to fit whatever I do into the existing structure.
-----
Can you point me to an original of your parkmeter image and what size enlargements you like to look at?
-----
You can see examples of sigmoidization at the following various places. Everywhere, it's used on all three channels, but I think that it may be better to only use it on luma or luminance.
If you try it yourself with ImageMagick, please use a very recent version, ideally of ImageMagick 7, because there was a bug in the IM sigmoidal-contrast code that was introduced, I think, in February, that I had to fix before I could use something else than the "sRGB pretend hack". I fixed it in ImageMagick 7 in August, and in ImageMagick 6 in September.
Look at this stuff with the suspicious eyes of someone who is presented the most beautiful baby in the world by his father.
http://www.imagemagick.org/Usage/resize/#nicolas_upsampling
http://www.imagemagick.org/Usage/resize/#resize_sigmoidal
http://www.imagemagick.org/discourse-server/viewtopic.php?f=22&t=21804
http://www.imagemagick.org/discourse-server/viewtopic.php?f=1&t=21695
http://www.imagemagick.org/discourse-server/viewtopic.php?f=22&t=21933
http://www.imagemagick.org/discourse-server/viewtopic.php?f=1&t=21850
http://www.imagemagick.org/discourse-server/viewtopic.php?f=22&t=21415
nevcairiel
9th October 2012, 17:35
I have to try that. I have only checked NV12 since I am certain nevcairiel (or was it madshi?) said that was the smartest thing to do.
With madVR, the smartest thing to do is keep everything checked. Defaults, use them. :p
NicolasRobidoux
9th October 2012, 17:36
Mathias:
What is your "anchor" colorspace?
Actually, what is your "anchor" luma/luminance channel.
What I most care about is whether it is a linear light channel, or whether it belongs to a perceptual color space.
-----
It's cheaper to do something like a "colorspace transformation" just to luma/luminance, yes? Does it cost a lot to convert to linear light, or is it one of these things that are basically free? Are colorspace transformations implemented as LUTs or with computational code?
-----
This is the key code in ImageMagick (actually, the IM6 code computes a LUT; what I'm showing is the IM7 code). This is way too complicated for all sorts of reasons. But it gives the idea, hopefully.
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% EEEEE N N H H AAA N N CCCC EEEEE %
% E NN N H H A A NN N C E %
% EEE N N N HHHHH AAAAA N N N C EEE %
% E N NN H H A A N NN C E %
% EEEEE N N H H A A N N CCCC EEEEE %
% %
% %
% MagickCore Image Enhancement Methods %
% %
% Software Design %
% John Cristy %
% July 1992 %
% %
% %
% Copyright 1999-2012 ImageMagick Studio LLC, a non-profit organization %
% dedicated to making software imaging solutions freely available. %
% %
% You may not use this file except in compliance with the License. You may %
% obtain a copy of the License at %
% %
% http://www.imagemagick.org/script/license.php %
% %
% Unless required by applicable law or agreed to in writing, software %
% distributed under the License is distributed on an "AS IS" BASIS, %
% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %
% See the License for the specific language governing permissions and %
% limitations under the License. %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% S i g m o i d a l C o n t r a s t I m a g e %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% SigmoidalContrastImage() adjusts the contrast of an image with a non-linear
% sigmoidal contrast algorithm. Increase the contrast of the image using a
% sigmoidal transfer function without saturating highlights or shadows.
% Contrast indicates how much to increase the contrast (0 is none; 3 is
% typical; 20 is pushing it); mid-point indicates where midtones fall in the
% resultant image (0 is white; 50% is middle-gray; 100% is black). Set
% sharpen to MagickTrue to increase the image contrast otherwise the contrast
% is reduced.
%
% The format of the SigmoidalContrastImage method is:
%
% MagickBooleanType SigmoidalContrastImage(Image *image,
% const MagickBooleanType sharpen,const char *levels,
% ExceptionInfo *exception)
%
% A description of each parameter follows:
%
% o image: the image.
%
% o sharpen: Increase or decrease image contrast.
%
% o contrast: strength of the contrast, the larger the number the more
% 'threshold-like' it becomes.
%
% o midpoint: midpoint of the function as a color value 0 to QuantumRange.
%
% o exception: return any errors or warnings in this structure.
%
*/
/*
ImageMagick 6 has a version of this function which uses LUTs.
*/
/*
Sigmoidal function Sigmoidal with inflexion point moved to b and "slope
constant" set to a.
The first version, based on the hyperbolic tangent tanh, when combined with
the scaling step, is an exact arithmetic clone of the the sigmoid function
based on the logistic curve. The equivalence is based on the identity
1/(1+exp(-t)) = (1+tanh(t/2))/2
(http://de.wikipedia.org/wiki/Sigmoidfunktion) and the fact that the
scaled sigmoidal derivation is invariant under affine transformations of
the ordinate.
The tanh version is almost certainly more accurate and cheaper. The 0.5
factor in the argument is to clone the legacy ImageMagick behavior. The
reason for making the define depend on atanh even though it only uses tanh
has to do with the construction of the inverse of the scaled sigmoidal.
*/
#if defined(MAGICKCORE_HAVE_ATANH)
#define Sigmoidal(a,b,x) ( tanh((0.5*(a))*((x)-(b))) )
#else
#define Sigmoidal(a,b,x) ( 1.0/(1.0+exp((a)*((b)-(x)))) )
#endif
/*
Scaled sigmoidal function:
( Sigmoidal(a,b,x) - Sigmoidal(a,b,0) ) /
( Sigmoidal(a,b,1) - Sigmoidal(a,b,0) )
See http://osdir.com/ml/video.image-magick.devel/2005-04/msg00006.html and
http://www.cs.dartmouth.edu/farid/downloads/tutorials/fip.pdf. The limit
of ScaledSigmoidal as a->0 is the identity, but a=0 gives a division by
zero. This is fixed below by exiting immediately when contrast is small,
leaving the image (or colormap) unmodified. This appears to be safe because
the series expansion of the logistic sigmoidal function around x=b is
1/2-a*(b-x)/4+...
so that the key denominator s(1)-s(0) is about a/4 (a/2 with tanh).
*/
#define ScaledSigmoidal(a,b,x) ( \
(Sigmoidal((a),(b),(x))-Sigmoidal((a),(b),0.0)) / \
(Sigmoidal((a),(b),1.0)-Sigmoidal((a),(b),0.0)) )
/*
Inverse of ScaledSigmoidal, used for +sigmoidal-contrast. Because b
may be 0 or 1, the argument of the hyperbolic tangent (resp. logistic
sigmoidal) may be outside of the interval (-1,1) (resp. (0,1)), even
when creating a LUT from in gamut values, hence the branching. In
addition, HDRI may have out of gamut values.
InverseScaledSigmoidal is not a two-sided inverse of ScaledSigmoidal:
It is only a right inverse. This is unavoidable.
*/
static inline double InverseScaledSigmoidal(const double a,const double b,
const double x)
{
const double sig0=Sigmoidal(a,b,0.0);
const double sig1=Sigmoidal(a,b,1.0);
const double argument=(sig1-sig0)*x+sig0;
const double clamped=
(
#if defined(MAGICKCORE_HAVE_ATANH)
argument < -1+MagickEpsilon
?
-1+MagickEpsilon
:
( argument > 1-MagickEpsilon ? 1-MagickEpsilon : argument )
);
return(b+(2.0/a)*atanh(clamped));
#else
argument < MagickEpsilon
?
MagickEpsilon
:
( argument > 1-MagickEpsilon ? 1-MagickEpsilon : argument )
);
return(b-log(1.0/clamped-1.0)/a);
#endif
}
MagickExport MagickBooleanType SigmoidalContrastImage(Image *image,
const MagickBooleanType sharpen,const double contrast,const double midpoint,
ExceptionInfo *exception)
{
#define SigmoidalContrastImageTag "SigmoidalContrast/Image"
#define ScaledSig(x) ( ClampToQuantum(QuantumRange* \
ScaledSigmoidal(contrast,QuantumScale*midpoint,QuantumScale*(x))) )
#define InverseScaledSig(x) ( ClampToQuantum(QuantumRange* \
InverseScaledSigmoidal(contrast,QuantumScale*midpoint,QuantumScale*(x))) )
CacheView
*image_view;
MagickBooleanType
status;
MagickOffsetType
progress;
ssize_t
y;
/*
Convenience macros.
*/
assert(image != (Image *) NULL);
assert(image->signature == MagickSignature);
if (image->debug != MagickFalse)
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
/*
Side effect: may clamp values unless contrast<MagickEpsilon, in which
case nothing is done.
*/
if (contrast < MagickEpsilon)
return(MagickTrue);
/*
Sigmoidal-contrast enhance colormap.
*/
if (image->storage_class == PseudoClass)
{
register ssize_t
i;
if (sharpen != MagickFalse)
for (i=0; i < (ssize_t) image->colors; i++)
{
if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
image->colormap[i].red=ScaledSig(image->colormap[i].red);
if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
image->colormap[i].green=ScaledSig(image->colormap[i].green);
if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
image->colormap[i].blue=ScaledSig(image->colormap[i].blue);
if ((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0)
image->colormap[i].alpha=ScaledSig(image->colormap[i].alpha);
}
else
for (i=0; i < (ssize_t) image->colors; i++)
{
if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
image->colormap[i].red=InverseScaledSig(image->colormap[i].red);
if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
image->colormap[i].green=InverseScaledSig(image->colormap[i].green);
if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
image->colormap[i].blue=InverseScaledSig(image->colormap[i].blue);
if ((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0)
image->colormap[i].alpha=InverseScaledSig(image->colormap[i].alpha);
}
}
/*
Sigmoidal-contrast enhance image.
*/
status=MagickTrue;
progress=0;
image_view=AcquireAuthenticCacheView(image,exception);
#if defined(MAGICKCORE_OPENMP_SUPPORT)
#pragma omp parallel for schedule(static,4) shared(progress,status) \
dynamic_number_threads(image,image->columns,image->rows,1)
#endif
for (y=0; y < (ssize_t) image->rows; y++)
{
register Quantum
*restrict q;
register ssize_t
x;
if (status == MagickFalse)
continue;
q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
if (q == (Quantum *) NULL)
{
status=MagickFalse;
continue;
}
for (x=0; x < (ssize_t) image->columns; x++)
{
register ssize_t
i;
if (GetPixelMask(image,q) != 0)
{
q+=GetPixelChannels(image);
continue;
}
for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
{
PixelChannel
channel;
PixelTrait
traits;
channel=GetPixelChannelChannel(image,i);
traits=GetPixelChannelTraits(image,channel);
if ((traits & UpdatePixelTrait) == 0)
continue;
if (sharpen != MagickFalse)
q[i]=ScaledSig(q[i]);
else
q[i]=InverseScaledSig(q[i]);
}
q+=GetPixelChannels(image);
}
if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
status=MagickFalse;
if (image->progress_monitor != (MagickProgressMonitor) NULL)
{
MagickBooleanType
proceed;
#if defined(MAGICKCORE_OPENMP_SUPPORT)
#pragma omp critical (MagickCore_SigmoidalContrastImage)
#endif
proceed=SetImageProgress(image,SigmoidalContrastImageTag,progress++,
image->rows);
if (proceed == MagickFalse)
status=MagickFalse;
}
}
image_view=DestroyCacheView(image_view);
return(status);
}
TheLion
9th October 2012, 17:41
I've added (tensor) Ginseng, Lanczos, Lanczos4, and EWA QuadraticJinc, produced similarly to the earlier ones, to http://web.cs.laurentian.ca/nrobidoux/misc/madVR/glyphs/
-----
Mathias:
Ginseng is very often within JND of Lanczos, so much so that you probably could substitute it for Lanczos, and nobody would know better. (Sorry: I should have mentioned this earlier.) This being said, it does have measurably less halo, and it is slightly less jaggy, although the difference is only noticeable with sharp high contrast features. Although the difference is small, it is (on my brash Samsung monitor), noticeable on the "glyph" enlargements.
Tensor Lanczos is definitely too sharpening when enlarging. Ginseng backs the dial down from 11, just a nudge.
In my opinion the basic issue is that people use "sharp" resampling methods like Lanczos4 to actually sharpen the image. But this shouldn't be the prime function of a resampling algorithm. When Mathias implements a high quality "sharpening filter" I expect people will start to prefer resampling algorithms with the least artifacts (ringing, aliasing) and not so much the one with the most "perceived sharpness".
Availability of a special purpose sharpness filter will definitely shift resampling preferences.
NicolasRobidoux
9th October 2012, 17:45
Mathias:
Sorry. I was not clear.
What I invented was using sigmoidal-contrast to do better upsampling. Another way to put it is that I invented a parameterized family of color spaces which help get better results when enlarging (upsampling, actually: does not need to be orthogonal).
The code I show above was mostly written by me. It's based on earlier version written by, I believe, Anthony Thyssen and Cristy with some help from others who I can't all list without digging (Fred Weinhaus is one of them, and there is a textbook involved).
To give you the most optimal code, I need to know a few things about how you do things. As I mentioned, the ImageMagick code is way too complicated because it is mostly used to do other things than what I call "sigmoidizing".
-----
Makes more sense?
Xaurus
9th October 2012, 17:46
With madVR, the smartest thing to do is keep everything checked. Defaults, use them. :p
Haha thanks nev, I can't even remember what the defaults are. I guess there's no "reset to defaults" button within LAV Video.
So everything checked, including 10-bit and 16-bit formats as well as RGB 32 & 24?
madshi
9th October 2012, 17:53
Yes, that makes a lot of sense, thanks!
What is your "anchor" colorspace?
Actually, what is your "anchor" luma/luminance channel.
What I most care about is whether it is a linear light channel, or whether it belongs to a perceptual color space.
-----
It's cheaper to do something like a "colorspace transformation" just to luma/luminance, yes? Does it cost a lot to convert to linear light, or is it one of these things that are basically free? Are colorspace transformations implemented as LUTs or with computational code?
I usually get Y'CbCr 4:2:0 from the decoder. I convert that to R'G'B', meaning gamma corrected RGB, usually with BT.601 or BT.709 primaries. I can convert that to linear light. Conversion to linear light is not free, but it's fast enough to not have to worry about it too much. I usually scale in R'G'B', usually with BT.709 primaries. Colorspace transformations? I don't convert to XYZ or things like that. I only convert from Y'CbCr to R'G'B' which is done by using simple matrix math.
This is the key code in ImageMagick (actually, the IM6 code computes a LUT; what I'm showing is the IM7 code). This is way too complicated for all sorts of reasons. But it gives the idea, hopefully.
Thanks. So this seems to be the key formula?
#define Sigmoidal(a,b,x) ( tanh((0.5*(a))*((x)-(b))) )
#define Sigmoidal(a,b,x) ( 1.0/(1.0+exp((a)*((b)-(x)))) )
I suppose "x" is the image data, probably in the range 0.0 (black) to 1.0 (white), correct? But which parameters are used for "a" and "b" when you tell ImageMagick to do e.g. "+sigmoidal-contrast 7.5"? Basically all I need is the exact formula to use for your sigmoidization trick. Thanks a lot!!
madshi
9th October 2012, 18:03
P.S: Here's the parking meter image in full/original size:
http://madshi.net/parking-big.png
I usually upscale by 400% to check upscaling algorithms.
NicolasRobidoux
9th October 2012, 19:21
Mathias:
==================
Sigmoidization HOW TO
==================
Let me explain things thus, and we can sort out the nitty gritty later.
I've always done sigmoidization separately on each channel of a
physically linear color space which in ImageMagick is linear RGB
with sRGB primaries.
So, let's suppose that we have one channel of image data x which is
strongly constrained to the interval [0,1] and which can reasonably be
interpreted as one component of linear light. I understand that in
general there may be mild over- or undershoots, resulting from color space
conversion (it has to do with negative coefficients in transformation
matrices when things are properly normalized). If there may be over
and undershoots, let me know and I'll tell you how to fix things.
First, choose a contrast. Like in the ImageMagick code, let's call the
contrast "a". a should be a float > 0. As a approaches 0,
sigmoidization has less and less effect, so you may as well skip it.
I generally like values between 7 and 12.
If tanh is in your math library, it should compute faster than the
formula that uses exponentials, because tanh is a very easy function
to approximate. I can also provide fast approximations (given a bit of
time). Or I can give you the formulation in terms of the exp function.
Ideally, though, you have access to both tanh and atanh (the
hyperbolic tangent and its inverse).
Have the following constant set:
s = tanh(0.25*a)
(This is equal to Sigmoidal(a,1) = -Sigmoidal(a,0) because tanh is odd.)
Step 1: Convert your input to the "sigmoidal color space", that is,
"replace" every x by the value y computed as follows:
y = 0.5 + (2.0/a) * atanh(-s+(2.0*s)*x) <- friendly to multiply-add
Now, we are in the "sigmoidal color space". You don't need to clamp:
If your original x was in [0,1], y is in [0,1] too.
(Again: I know how to fix things if there may be over and undershoots
in the x data.)
Step 2:
Upsample as usual, using the y values. Let's say that we get a pixel
value of w.
Step 3: Convert w back to "linear color space":
z = tanh((0.5*a)*(w-0.5)) = tanh((-0.25*a)+(0.5*a)*w) <- friendly to multiply-add
final value = (z+s)/2s = 0.5+(0.5/s)*z
Only clamp if you want to. Step 3 does not care about what interval w is in.
-----
That's it!
madshi
9th October 2012, 19:35
Thank you, that looks easy enough!! :)
Two problems:
(1) Pixel shaders can do "atan", "tanh" and "exp", but not "atanh", unfortunately.
(2) Black is 0.0 and white is 1.0, correct? In that case: Yes, there may be values outside of [0,1]. Not only from YCbCr -> RGB conversion, but some movies also contain BTB (black than black) and WTW data. How can I solve that?
Thanks!!
NicolasRobidoux
9th October 2012, 19:46
(2) Black is 0.0 and white is 1.0, correct? In that case: Yes, there may be values outside of [0,1]. Not only from YCbCr -> RGB conversion, but some movies also contain BTB (black than black) and WTW data. How can I solve that?
Yes, 0 is black and 1 is white.
Can you determine ahead of time an (ideally reasonably tight) interval which each channel cannot overshoot (after conversion to linear light or what resembles it)?
(I'm sure computing the min and max in each channel for the whole movie is not an option.)
-----
The atanh issue is not a big deal. Just need to sit down and do algebra. Atanh is often not included because it's so easy to reconstruct.
NicolasRobidoux
9th October 2012, 19:54
Mathias:
No need to do algebra: http://mathworld.wolfram.com/InverseHyperbolicTangent.html.
atanh(x) = 0.5 * log((1+x)/(1-x))
NicolasRobidoux
9th October 2012, 20:03
P.S: Here's the parking meter image in full/original size:
http://madshi.net/parking-big.png
I usually upscale by 400% to check upscaling algorithms.It's actually the small version I'd like, so I can re-enlarge by 400% like you do.
madshi
9th October 2012, 20:03
Can you determine ahead of time an (ideally reasonably tight) interval which each channel cannot overshoot (after conversion to linear light or what resembles it)?
If my math is correct, the possible value range for all 3 channels in *linear light* should be:
[-0.0029842504073062995363224069370219,1.2143440435408780674380747705496]
Mathias:
No need to do algebra: http://mathworld.wolfram.com/InverseHyperbolicTangent.html.
atanh(x) = 0.5 * log((1+x)/(1-x))
Cool. One problem solved.
madshi
9th October 2012, 20:05
It's actually the small version I'd like, so I can re-enlarge by 400% like you do.
small parking meter (http://madshi.net/parking-org.png)
Luv
9th October 2012, 20:56
XP32
Catalyst 12.4,HD 4770
ZP 5.02
Hello,Madshi
everything is fine here but I just can't select the Intel MPEG2 decoder (While the libav can be without any pb).ZP uses the Cyberlink decoder (Wich ouputs 4:2:2...).
Is it a question of priority ?
Thank you.
madshi
9th October 2012, 20:57
Ok, I've implemented the Sigmoidal contrast stuff and it seems to work pretty well. I like the results better compared to the "pretend linear" hack. Here they are for comparison:
jinc3 normal (http://madshi.net/parking3-jinc3.png) -|- jinc3 hack (http://madshi.net/parking3-jinc3hacked.png) -|- jinc3 sigmoidal (http://madshi.net/parking3-jinc3sigmoidal.png)
To my eyes the "sigmoidal" image clearly looks best. I've still left the anti-ringing filter enabled, though. Although the "sigmoidal" stuff does reduce the ringing artifacts, it doesn't completely remove them. So image quality is still noticeably better with the added anti-ringing filter on top.
So, only 2 questions remaining:
(1) Which is the "best" sigmoidal contrast? I've seen 7.5 (named with "safe") and 11.5. The image from above is with 11.5, which I prefer with this test image. Should I always use 11.5? Or would that be a bad idea?
(2) Still need to handle those out of [0,1] values somehow.
Thanks a lot, Nicolas, with your help upscaling quality just made another step forward in madVR... :)
madshi
9th October 2012, 20:58
@Luv, you need the Intel decoder DLL, see first page of this thread for a download link. Personally, I prefer libav, though.
sunnah
9th October 2012, 21:06
Sunnah im interested about your HTPC, can you give me details about processor type, speeed, amount of ram etc, etc, pls? im about to build a new htpc just for the main use of playing movies with madvr, any info about your htpc details will be very apprecciated, thanks!
Well I bought a game laptop, mainly because of the high-end specs overall.
I watch my Korean tv shows always 1080p quality, on the laptop's full hd screen or by hdmi on a full hd led tv.
The laptop also has an overclock button on it, so that if it ever stutters(never happened), then I just push it then the processor speed will increase plus the graphic processing speed.
This is the laptop, http://nl.msi.com/product/nb/GT683.html
Cheers.
Don't forget to enable the "Hardware acceleration: LAV CUVID"
Luv
9th October 2012, 21:11
@Luv, you need the Intel decoder DLL, see first page of this thread for a download link. Personally, I prefer libav, though.
:D
I forgot (again) to add it.Thanks,Madshi.
I'm going to test the libav this evening.Could you say why it is to be preferred?
madshi
9th October 2012, 21:15
It's much faster, decodes 4:2:2 etc etc...
NicolasRobidoux
9th October 2012, 21:18
Mathias:
Here's the fix (or, more precisely, here is "a" fix, since I am not
enforcing symmetry w.r.t black (0) and white (1) and I'm not 100% sure
this is the best choice): The constant s of my HOW TO is strictly
between 0 and 1. (In the interval (0,1), which I think some Europeans
write ]0,1[.)
Let's assume that the interval in which every single channel belongs
to is contained in (A,B). Note that I don't want the bounds to be
attained. In the case of
[-0.0029842504073062995363224069370219,1.2143440435408780674380747705496],
I'd use something like A=-0.00298426 and B=1.214345. That is, I'd
enlarge the interval by some epsilon on each side to make sure that
the bounds cannot be reached. If I was in double precision, I'd use
something tighter, of course.
What you are going to do is that you are going to fix things so that
(A,B) is mapped to (-1,1) by the transformation
x -> -s+(2.0*s)*(b+m*x)
A little bit of algebra says that this is accomplished by choosing
m = (1/L)/s
and
b = 0.5 + (D/L)/s
where L = B-A and D = -0.5*(B+A)
-----
So, all you have to do is add a preliminary step that replaces x by
b+m*x, and add a final step that replaces "final value" by
(-b/m)+(final value)/m.
So, it adds two multiply-adds: one at the beginning, and one at the
end.
madshi
9th October 2012, 21:28
That's quite interesting. Won't that change the look of the image a bit, though?
What happens if I simple ignore that some values may lie outside of the [0,1] range? Will I get wildly inaccurate results, like division by zero, infinity or something like that?
NicolasRobidoux
9th October 2012, 21:29
Question: Wouldn't it be better to simple "linearize" the Y channel and only sigmoidize that?
(I need to reread these various definitions. Is Y' physically a linear light channel (luminance) or a gamma-encoded light channel (luma)?
P.S. Just reread. So, you normally work and enlarge in a perceptual space (R'G'B').
The formulas I gave assumed that I was working with physically linear light channels. Apparently you can convert to some form of linear light (light RGB with something-something-something primaries). But maybe this is a waste.
-----
Need to think.
Maybe some form of the dirty hack would turn out better in the end?
P.S.
Something like:
Y'CbCr -> R'G'B' -> negate -> pretend it's RGB -> R'G'B' -> resample -> RGB -> negate -> "retag" as R'G'B' -> Y'CbCr
?
P.S.2 How does gamma correction handle negative values? By clamping?
NicolasRobidoux
9th October 2012, 21:42
That's quite interesting. Won't that change the look of the image a bit, though?
Not really: If you scheme is interpolatory, it will still be interpolatory using the "old" version of sigmoidization or this "fixed" one. Does not matter.
For example, assuming no rounding error, nearest neighbour would give the same result with all variants.
However, it changes somewhat how sigmoidization affects the result, just like going through linear light or La*b* to upsample would affect the result. But someone could argue that it's an as good, or better, sigmoidization.
I don't really know.
What happens if I simple ignore that some values may lie outside of the [0,1] range? Will I get wildly inaccurate results, like division by zero, infinity or something like that?
You can go out of the [0,1] range "a little bit" without feeding values outside of (-1,1) to atanh (no matter how it's computed) because "s", which characterizes where 0 and 1 go, provides some headroom within (-1,1). But once you hit -1 or 1 or go past, all hell breaks loose.
-----
In ImageMagick, this is fixed by clamping the argument of atanh to [-1+MagickEpsilon,1-MagickEpsilon]. You would not lose all the blacker than black and whiter than white, esp. when the contrast is low. But with high contrast, you may lose a chunk of whiter than white.
The solution works within ImageMagick because we're mostly concerned about sRGB and it converts to and from linear RGB with sRGB primaries without over- and undershoots.
madshi
9th October 2012, 21:42
P.S. Just reread. So, you normally work and enlarge in a perceptual space (R'G'B').
The formulas I gave assumed that I was working with physically linear light channels. Apparently you can convert to some form of linear light (light RGB with something-something-something primaries). But maybe this is a waste.
-----
Need to think.
Maybe some form of the dirty hack would turn out better in the end?
It's not as complicated as it seems. After all the conversions I end up with R'G'B', usually with BT.709 primaries, which happen to be identical to sRGB primaries, IIRC. So basically I end up with the very same thing you get when you load a BMP file. The formulas you gave me are for linear light, I understood that. Of course when I implementing all this in madVR, an hour ago, I've first converted R'G'B' to RGB and then applied your sigmoidization formulas. And it's working well! So no problem here. The only thing I'm worried about are those values outside of [0,1].
madshi
9th October 2012, 21:45
P.S: Although I do end up with similar data to a BMP file, there's one small difference: The values can go outside of the [0,1] range, as discussed before.
madshi
9th October 2012, 21:46
Not really: If you scheme is interpolatory, it will still be interpolatory using the "old" version of sigmoidization or this "fixed" one. Does not matter.
For example, assuming no rounding error, nearest neighbour would give the same result with all variants.
However, it changes somewhat how sigmoidization affects the result, just like going through linear light or La*b* to upsample would affect the result. But someone could argue that it's an as good, or better, sigmoidization.
I don't really know.
Ok, I'll give this a try tomorrow, thanks so much for your help!!
NicolasRobidoux
9th October 2012, 22:00
Mathias:
This is exciting.
And I think that we both understand and agree that the issue is how to handle values that go "out of nominal gamut" without diminishing the ability of sigmoidization to enhance what's within the nominal gamut.
NicolasRobidoux
9th October 2012, 22:10
Mathias:
I just clicked on something: It should be easy to compute a maximum allowable contrast ("a") that guarantees that things don't go to hell.
The maximum allowable contrast would depend on A and B in an elegant way.
Then, sigmoidization would be "intact". There just would be "less of it" when there is a possibility of large overshoots.
-----
The simplest fix is simply to clamp like in ImageMagick. If the clamping messes things up, we should be able to see it.
I'm a bit concerned that we are messing up sigmoidization by trying hard to preserve outliers (very large whiter than white, for example).
NicolasRobidoux
9th October 2012, 23:55
Mathias: I think that my "one multiply-add at the beginning, one at the end" is probably a pretty good solution, in part because giving more intense sigmoidization near darks (which is the case since A apparently is generally quite close to zero) may match what's best given the HVS: We're less sensitive to light halo because our eyes are more sensitive to darks.
-----
Otherwise, I think that the clampling solution built into ImageMagick would be both good and simple. All it is is clamping -s+(2.0*s)*x to the interval [-1+fudgeEpsilon,1-fudgeEpsilon] before feeding to atanh. No more and no less.
Part of why I think this may work well is that even for the huge overshoot you estimated, namely 1.2143440435408780674380747705496, you'd need contrast > 3.468 before any clamping occurs.
Sure, I like something like 7.5. But we are not talking orders of magnitude.
This being said, with contrast=7.5, clamping will start at 1.024 or so.
-----
I have a third solution, but I'll leave it out until I know better whether the above two work or fail.
aufkrawall
10th October 2012, 00:05
I have a little problem:
I created a custom resolution with 59,94 Hertz and added it and the native 60 Hertz resolution to the madVR display modes list (both 1280x1024).
It works well with 720p59,94 and 1080p60 videos but for a 1080p59,94 it refuses to choose 59,94 Hertz. :(
What's going wrong?
NicolasRobidoux
10th October 2012, 00:09
One comment to all of you out there:
When enlarging, it may be that you like the results obtained with sigmoidization better than those obtained by explicitly sharpening.
NicolasRobidoux
10th October 2012, 00:40
...
To my eyes the "sigmoidal" image clearly looks best. I've still left the anti-ringing filter enabled, though. Although the "sigmoidal" stuff does reduce the ringing artifacts, it doesn't completely remove them. So image quality is still noticeably better with the added anti-ringing filter on top.
So, only 2 questions remaining:
(1) Which is the "best" sigmoidal contrast? I've seen 7.5 (named with "safe") and 11.5. The image from above is with 11.5, which I prefer with this test image. Should I always use 11.5? Or would that be a bad idea?
...
I had missed this post, so busy I was fixing the "out of gamut" issue.
Now:
Sigmoidization is a method that I invented less than 3 months ago. So I don't know everything there is to know.
Let's assume that you use the "clamp the argument of atanh" like it's done in ImageMagick. Otherwise contrast values are not really comparable.
My hunch is this:
Given that:
1) You actually "come from" Y'CbCr, not sRGB
2) Your luminance channel is better resolved. (Is it?)
3) Your video images are generally somewhat "soft" (by DSLR standards)
I would say that it is quite likely that contrast 11.5 is almost always safe. Maybe even 12.
I'd consider, however, using the slightly larger LanczosSharp deblur I discuss earlier in this thread and in my new ImageMagick recommendations: Let sigmoidization take care of "tightening things" and let EWA Lanczos take care of "smoothing things".
If people start complaining about something, it will be this:
They will notice that sometimes a colour that has a very high component (say R=255) mixed in with more midtone-like values in the G and B channels will "bleed" near sharp interfaces. Same if you have R=0.
What's happening is that the extreme colour values are "sharpened" differently by the low pass filter than the midtones, and mixed extreme/midtone interfaces thus are "rolled up" differently in the three channels.
Fixing this would be hugely complicated...
sRGB does this too. All the perceptual color spaces, actually, to the best of my understanding.
But then enlarging through linear light sucks!
-----
If you use the [A,B] gamut control "system", I'd say you may want even higher sigmoidization.
Does my answer make sense?
(You understand that I'm the one who invented EWA LanczosSharp in all its mutliple variants, yes? Was kind of an obvious extension of what people had done before, and Anthony Thyssen and Fred Weinhaus, as well as publications by Gustafson and deForest, were strongly pointing in the right direction, but still. I'm the one who finally put all the pieces together, and then added "optimizing the deblur" to the mix, mostly in response to Anthony Thyssen's knowledgeable list of shortcomings of the earlier ImageMagick implementation.)
P.S. TTBOMK I'm the one who finally got is just right. If anybody knows of predecessors I should acknowledge, by all means, please point me to them. "As usual," Paul Heckbert and associates got this going.
At some point I may take the time to carefully track down everybody who had pieces of this lying around.
blackjack12
10th October 2012, 02:14
But when using the official v0.84.2 build, the problems with 6000 series are not specific to deinterlacing, correct? They also occur with progressive content, correct? Could you please double check, just to be safe? It's important to know.
So the special test build I created for you makes everything progressive work just fine, and the only problems left are when using deinterlacing? Is that correct? How about the official v0.84.2 then? Could you please double check if maybe the official v0.84.2 also plays progressive content fine? I'm asking because the only difference between the official v0.84.2 and your special test build is deinterlacing. So for progressive content v0.84.2 and your test build should behave identical.
I'm sorry that fixing this problem takes so long. If only I could reproduce it on my PC !!!
Okay ... re-test results.
AMD Radeon 6570/1GB DDR3
Driver ver. 12.8
MPC-HC or MPC-BE (latest versions)
LAV Filters: 51.3-120
Windows 7 and Windows 8 test – identical systems (64 bit)
Official 0.84.2
Windowed Mode
Interlaced: BAD
Progressive: BAD
FSE Mode
Interlaced: GOOD
Progressive: GOOD
0.84.2 – special madVRblackjack test build
Windowed Mode
Interlaced: CRASH
Progressive: BAD (4 plus jumps = dropped frames and buffers don’t fill)
FSE Mode
Interlaced: CRASH
Progressive: GOOD
Go back to 0.82.5 and all is GOOD... :confused:
turbojet
10th October 2012, 06:02
Well, I would much rather implement a *real* sharpening algorithm, to be honest. That's why I'm also reluctant offering so many more tweaks: It costs many hours of my time which I could instead spend on doing the "real thing". Personally, I don't like Darbee pop at all. I much prefer something like Didee's FineSharp. So if you ask me to add this and that, and a couple of other tweaks in between, basically you're keeping me busy with so-so stuff, instead of allowing me to move on to bigger and greater things. I've said it so many times before: Let me first add all the missing features, before spending my time by twiddling with 1% improvements. I'm feeling held back at the moment, by all the constant requests for small tweaks and changes everywhere. Aren't you guys interested in getting things like custom shader support, 3D support etc?
Interesting, never heard of vapoursynth yet.
I'm not trying to change your priorities but didn't think it would take hours to implement. Create a dropdown, label, changing blur parameter to a variable, set variable based on dropdown state. Without variables some copy/paste and changing one number but no clue how the code is. The first place I saw negative blur suggested was in the finesharp thread by the finesharp author. I think the reasoning is finesharp should give/take as much information as possible, blurring is counter-intuitive.
Shader support sounds exciting but my experience is avisynth can do everything shaders can do and often better, except madvr's anti-ringing, you did a great job on it! Sharpen complex is bested by simple avisynth sharpen() imo and deband shaders aren't effective at all. Shaders shift cpu load to gpu which is a plus but kind of irrelevant with madvr loading the gpu more than cpu.
3D support sounds nice for those that have 3DTV's are you talking SBS, Top/Bottom, both can be done via avisynth, or is it something else?
Here's parking meter 4x upsize test with -1 and 0 blur (http://180upload.com/4nnu7kisd46j) if you want to take a look, it's more of a difference then the pic's I posted earlier. Here's hoping you haven't given up on it.
Vapoursynth is cross platfrom and requires avisynth plugins to be rewritten.
madshi
10th October 2012, 08:07
I have a little problem:
I created a custom resolution with 59,94 Hertz and added it and the native 60 Hertz resolution to the madVR display modes list (both 1280x1024).
It works well with 720p59,94 and 1080p60 videos but for a 1080p59,94 it refuses to choose 59,94 Hertz. :(
What's going wrong?
If you create a madVR debug log, I can tell you for sure.
Okay ... re-test results.
Official 0.84.2
Windowed Mode
Interlaced: BAD
Progressive: BAD
FSE Mode
Interlaced: GOOD
Progressive: GOOD
0.84.2 – special madVRblackjack test build
Windowed Mode
Interlaced: CRASH
Progressive: BAD (4 plus jumps = dropped frames and buffers don’t fill)
FSE Mode
Interlaced: CRASH
Progressive: GOOD
Go back to 0.82.5 and all is GOOD... :confused:
So in other words: The test build didn't help at all, correct? Oh well, this is going to be difficult to fix. There's one thing remaining for you to test, though: When going back to v0.82.5, are you using any of the tweak settings that I removed in v0.83.0 (and higher)? You can test this by simply resetting v0.82.5 to default settings. If it still works fine, and if v0.84.2 does not work fine with default settings then the tweak settings are not the problem.
If the tweak settings are not the problem, would you mind creating another debug log or 2 or 3? Please seek until you get those frame drops, then let it run for ca. 10-20 seconds, then close the media player. Please don't reseek after you achieved the frame drop situation. That will make it easier for me to find the right location in the monster sized log files. Please also use a progressive source, that makes the logs a bit easier because no deinterlacing is performed. Thanks!
I'm not trying to change your priorities but didn't think it would take hours to implement. Create a dropdown, label, changing blur parameter to a variable, set variable based on dropdown state. Without variables some copy/paste and changing one number but no clue how the code is.
Creating a different advanced/simple user interface would take hours, days even. Just adding a blur parameter would not take that long, of course. But just adding a dropdown and label etc isn't all there is to it: I'd have to:
(1) Extend the settings records.
(2) Modify madVR to read, write, understand and use the new setting.
(3) Probably add a toggle keyboard shortcut.
(4) Make sure the setting is only available for cubic algorithms.
(5) Change my resampling weight calculator to support custom blur.
(6) Think about how to make the dropdown work with Bicubic, SoftCubic, CatmullRom and Mitchell. Using the same blur value for all wouldn't work because they have different blur values on their own. Of course it would be possible to limit negative blur capability to Bicubic, only.
All added up it might easily take 2-3 hours. More if I'm stupid and introduce bugs. Add to that that the user interface gets more complicated again, which means that new users will ask not only "which is the best algorithm" but also "which blur factor should I use" etc.
I prefer the idea to offer a fully configurable cubic resampler, which could replace all the other cubic based algorithms (Mitchell, Bicubic, Catmull-Rom, SoftCubic). But then, that would definitely be a settings for experts, only, and will have to wait until I have separate beginner/expert settings.
Shader support sounds exciting but my experience is avisynth can do everything shaders can do and often better, except madvr's anti-ringing, you did a great job on it! Sharpen complex is bested by simple avisynth sharpen() imo and deband shaders aren't effective at all. Shaders shift cpu load to gpu which is a plus but kind of irrelevant with madvr loading the gpu more than cpu.
I somewhat agree, but you can't run avisynth scripts *after* scaling, when using madVR, so shaders have their use. Also GPUs get much faster every year, while CPUs get only slightly faster. So I think in the long run it makes sense to run these kind of algorithms all on the GPU. Furthermore: If you have a good GPU, you can run algorithms on it which avisynth scripts couldn't do in realtime on a CPU. Whether it is easily possible to convert such complex avisynth scripts to a GPU shader is another question, though.
3D support sounds nice for those that have 3DTV's are you talking SBS, Top/Bottom, both can be done via avisynth, or is it something else?
I was mainly thinking about HDMI 1.4 frame packed output. That will not be easy because all ATI, Nvidia and Intel have custom development solutions for that. But this should be the ultimate goal. Doing SBS or Top/Bottom is kind of yesterday.
Here's parking meter 4x upsize test with -1 and 0 blur (http://180upload.com/4nnu7kisd46j) if you want to take a look, it's more of a difference then the pic's I posted earlier. Here's hoping you haven't given up on it.
It is not uninteresting, but I much prefer Lanczos or Jinc over Bicubic with negative blur. Bicubic has too much aliasing for my taste.
Look, if I knew a way to support negative blur without making the settings dialog more complicated, I would consider it. Maybe I will add it in the future when I find the time to do separate settings dialogs for noobs and experts. But for now I don't want to implement it because I don't want to spend that time and because I don't want to make the settings dialog more complicated. Just have a bit of patience.
I had missed this post, so busy I was fixing the "out of gamut" issue.
I've had another idea on how to fix the "out of gamut" issue: For values outside the valid range I could practically mirror the sigmoidization S curve. Meaning e.g. for values "> 1" I would do "2 - value" before *and* after sigmoidization. And for values "< 0" I could do "abs" before sigmoidization and then simply restore the "-" sign after sigmoidization. What do you think?
My hunch is this:
Given that:
1) You actually "come from" Y'CbCr, not sRGB
2) Your luminance channel is better resolved. (Is it?)
3) Your video images are generally somewhat "soft" (by DSLR standards)
I would say that it is quite likely that contrast 11.5 is almost always safe. Maybe even 12.
I think I'll stick with 11.5. In one of your threads I found "11.6933", but that was for Ginseng. I guess you used some formula to end up with exactly "11.6933", right? But I guess that only applies to Ginseng? Is it alright to use exactly "11.50000" for 2D Jinc and 1D Lanczos? Or is there some math reason to choose slightly different values?
I'd consider, however, using the slightly larger LanczosSharp deblur I discuss earlier in this thread
Will do. You mean 0.9891028367558475, right?
sRGB does this too. All the perceptual color spaces, actually, to the best of my understanding.
But then enlarging through linear light sucks!
Agreed. But sigmoidization is not perceptual, is it? I mean it's linear light + S curve. That's not really perceptual, I think.
You understand that I'm the one who invented EWA LanczosSharp in all its mutliple variants, yes? Was kind of an obvious extension of what people had done before, and Anthony Thyssen and Fred Weinhaus, as well as publications by Gustafson and deForest, were pointing in the right direction, but still.)
Yes, and I very much appreciate the invention you did there. Funny enough, in my own experiments I thought that 2D resampling should be better than scaling X and Y separately, because looking at a circle of source pixels to find a target pixel seems so much more intuitive, but I never got it to work right in my experiments. Well, I tried Sinc-Sinc (Lanczos) with the real 2D distance (Sqrt(xDist^2 + yDist^2)), but the results were pretty bad. So I gave up on that, my math skills were simply not good enough to understand why it didn't work. So I was quite happy when I understood that basically the key thing about your EWA resamplers is that they work in 2D instead of 1D, using a circle of source pixels... :D I will add a paragraph to madVR's readme to thank you for your contributions!
bugmen0t
10th October 2012, 08:28
Not sure what you guys want to achieve but you could modify the atanh to fit every range (a, b): atanh_mod(x) = log((a + x)/(b - x))/2. If a and b are known this is really cheap.
Neeto
10th October 2012, 11:35
Yes, and I very much appreciate the invention you did there. Funny enough, in my own experiments I thought that 2D resampling should be better than scaling X and Y separately, because looking at a circle of source pixels to find a target pixel seems so much more intuitive, but I never got it to work right in my experiments. Well, I tried Sinc-Sinc (Lanczos) with the real 2D distance (Sqrt(xDist^2 + yDist^2)), but the results were pretty bad. So I gave up on that, my math skills were simply not good enough to understand why it didn't work. So I was quite happy when I understood that basically the key thing about your EWA resamplers is that they work in 2D instead of 1D, using a circle of source pixels... :D I will add a paragraph to madVR's readme to thank you for your contributions!
NicolasRobidoux & Mashi I only understand about 10th of what you're discussing but you two seriously rock - brilliant maths/understanding & implementation - brilliant combination!!
NicolasRobidoux
10th October 2012, 11:56
... I prefer the idea to offer a fully configurable cubic resampler, which could replace all the other cubic based algorithms (Mitchell, Bicubic, Catmull-Rom, SoftCubic). But then, that would definitely be a settings for experts, only, and will have to wait until I have separate beginner/expert settings.You are aware that there is a discussion of exactly this in "The Recommendations", yes?
It is not uninteresting, but I much prefer Lanczos or Jinc over Bicubic with negative blur. Bicubic has too much aliasing for my taste.
Agreed: The bicubics don't compete. (See "The Recommendations", which unfortunately don't make this point strongly enough, partly become some commercial clients of mine really really like the Robidoux cubic EWA filter for downsampling, and consequently I'm wondering if there is something I'm missing (I try not to argue with panels of top web designers). The runner-up was EWA LanczosSharp (the "older" one; the new one did not exist then). I'll give another try at making them change, but speed matters and they're using an 8-bit toolchain, and they are processing sRGB values directly with lots of sky lines, and sRGB is bad with "light" haloing...)
This can be done with a "knob" that changes the deblur of the filter, like actually used with Jinc right now, except hardwired to .98...
P.S. (I realize that you probably have this figured out already.)
Actually, some DSLR people have gotten acceptable results doing this with tensor Lanczos as well (Lanczos 3 with roots spaced tighter than 1 by scaling the support of the filter), which will make some people shudder in horror big time, when downsampling.
But it appears that careful USM or other sharpening is better, at least when downsampling. (The jury is still out.)
I've had another idea on how to fix the "out of gamut" issue: For values outside the valid range I could practically mirror the sigmoidization S curve. Meaning e.g. for values "> 1" I would do "2 - value" before *and* after sigmoidization. And for values "< 0" I could do "abs" before sigmoidization and then simply restore the "-" sign after sigmoidization. What do you think?Here is a better idea, inspired by yours (and somewhat reminiscent of the sRGB handling of the gamma curve's slope singularity at 0): Extend the curves past 0 and 1 with straight lines (which I feel like an idiot not having thought of before).
What do you think?
I think I'll stick with 11.5. In one of your threads I found "11.6933", but that was for Ginseng. I guess you used some formula to end up with exactly "11.6933", right? But I guess that only applies to Ginseng? Is it alright to use exactly "11.50000" for 2D Jinc and 1D Lanczos? Or is there some math reason to choose slightly different values?These fancy values were obtained by applying uniformly an exact method of determining the contrast values for each filter that used an numerical approach based on ... vaguely determined parameters (based on usually accepted values for JND, namely 2.3 in Lab = 8 in 8-bit sRGB).
Honest advice: Use your eyes, and the eyes of your users. There is a possibility that BluRay people ask you to back this down. Or that some people ask for more of this "strange halo free sharpening". Or that some people will want less of it even when enlarging somewhat blurry images.
11.5 is a good, solid, pretty strong value. Maybe a little too strong? Probably not with enlargements of slightly blurry images that can't be scrutinized because they go by at 30fps.
But remember that sigmoidization, as a resampling technique, is not even 3 months old. You're in terra incognita.
Will do. You mean 0.9891028367558475, right?Yes.
Agreed. But sigmoidization is not perceptual, is it? I mean it's linear light + S curve. That's not really perceptual, I think.
Even though it was not meant to be perceptual, there is a not totally explained connection with Weber's law, which is an approximation of the HVS that gamma correction itself approximates, at the dark end.
So, I could explain sigmoidization purely "physically", but actually I think it works well partly because it connects to the perceptual: "Midtone" halos don't offend us. "Extreme" ones do.
This is why I can fake sigmoidization with linear RGB -> sRGB -> linear RGB conversions + inversions (going "through the photo negative").
What I'm doing, in a sense, is symmetrizing the perceptual spaces so that white does not creep too much into the darker end, in other words, I'm symmetrizing w.r.t. black <-> white interchange.
Will read the rest after making coffee for my wife!
-----
My earlier LUT advice was backward. Will fix in a later post.
NicolasRobidoux
10th October 2012, 13:13
Not sure what you guys want to achieve but you could modify the atanh to fit every range (a, b): atanh_mod(x) = log((a + x)/(b - x))/2. If a and b are known this is really cheap.Thank you! (My complex variables teacher would hit me with a ruler if he knew I overlooked this.)
Will need to think of the consequences. I think it may be equivalent to the "two multiply-add" suggestion, saving flops.
Basically, it's like simplifying the fraction (I think).
NicolasRobidoux
10th October 2012, 13:40
Mathias:
RE: "Is sigmoidization perceptual?"
Near the dark end, the lightly truncated logistic curve (same as tanh, really) approximates a gamma correction curve (or it's inverse: depends how you define forward/backward).
vBulletin® v3.8.11, Copyright ©2000-2026, vBulletin Solutions Inc.