View Full Version : Script to increase compressibility
Malcolm
16th October 2002, 10:50
This thread (see (http://forum.doom9.org/showthread.php?s=&threadid=35493)) is about blurring chroma-values in dark areas to increase compressibility of video.
i wrote a script that does just that (see below).
Currently, i'm unable to test, how this script affects compressibility. Is there someone who's interested enough to do that? :rolleyes: :) Would be very nice! I think a lot of people would like to see the results too.
Maybe testing different methods (spatialBlur, TemporalBlur, greying out). Testing different luma-ranges (16-32, 16-48, ...). Compressing to MPEG2 (SVCD).
Here's the script:
# The Source
AviSource("T:\Temp\test.AVI")
# slowest, time heavily depends on parameter 'radius'
#overlay = SpatialSoften(5,255,255).ConvertToRGB32()
# second fastest
#overlay = TemporalSoften(5,255,255).ConvertToRGB32()
# fastest, but sometimes leads to visible desaturation
# in areas, that are not dark enough (lower the current
# value '32' inside the levels() function)
overlay = BlankClip(last, $888888).ConvertToRGB32()
overlay = resetmask(overlay)
base = ConvertToRGB32(last)
# areas where luma is between 16 (and below) and 32 will
# be replaced. You can use the gamma-parameter
# to adjust the linearity of the mask
mask_clip = levels(base,16,1,32,255,0)
# the following lines doesn't need to be changed
overlay_clip = Mask(overlay, mask_clip)
final = layer(base,overlay_clip,"add",255,0,0,0)
# finally, only the chroma-channels are replaced
MergeChroma(ConvertToYUY2(base), ConvertToYUY2(final))
bye, Malcolm
iago
16th October 2002, 17:05
@Malcolm
I'm really interested in trying your script and I've been following the related thread you pointed to for a while. Currently I'm doing some constant quant tests (using XviD) with your script regarding compressibility. I'll report back the results and my impressions when I finish and compare the results of several tests.
thanks for the nice work
and best regards,
iago
Malcolm
16th October 2002, 18:05
@iago
super! :) I just want to add some tips:
i changed this post; changes are marked red
- use a filter (vdub or avisynth) to show only the chroma-channels. Just to check how the values in the script affect the image
- method 3 (greying out the image in dark areas) works very strong. this can lead to a good compressability. but the 'input_high' value of the Levels() function mustn't be too high, or you will see desaturation. so because you can't go high with that value, it will maybe limit the compressibility.
- all methods that do blurring doesn't change the color. so i think you can rise the 'input_high' higher than with method 3. i used values up to 128.
- feel free to use other filters.
- Use the following line to do a very quick blur. I think (at least i hope) that this is the best and fastest method!overlay = BicubicResize(8,6).BicubicResize(last.width, last.height).ConvertToRGB32()
- Use a very dark clip, a normal clip (mixed) and a bright clip to test.
bye, Malcolm
iago
17th October 2002, 15:48
Malcolm,
Below are some initial test results:
DVD2AVI 1.76 (Color Space: YUV / YUV->RGB: PC Scale)
Avisynth 2.06
MPEG2Dec3.dll (beta 6)
VirtualDub 1.4.10 (Fast recompress)
XviD / Koepi's 04102002-1 build / 1-pass constant quantizer 2 / 6.Ultra High / MPEG quantization type / no lumi masking
(A very dark part of the movie with occasional morning sky views)
script 1 (normal encode)
------------------------
LoadPlugin("C:\PROGRA~1\GORDIA~1\mpeg2dec3.dll")
mpeg2source("D:\GHOSTDOG\GHOSTDOG.d2v")
crop(4,8,712,464)
Trim(500,5500)
#overlay = BicubicResize(8,6).BicubicResize(last.width, last.height).ConvertToRGB32()
#overlay = resetmask(overlay)
#base = ConvertToRGB32(last)
#mask_clip = levels(base,16,1,32,255,0)
#overlay_clip = Mask(overlay, mask_clip)
#final = layer(base,overlay_clip,"add",255,0,0,0)
#MergeChroma(ConvertToYUY2(base), ConvertToYUY2(final))
LanczosResize(640,352)
script 2 (Malcolm's script)
---------------------------
LoadPlugin("C:\PROGRA~1\GORDIA~1\mpeg2dec3.dll")
mpeg2source("D:\GHOSTDOG\GHOSTDOG.d2v")
crop(4,8,712,464)
Trim(500,5500)
overlay = BicubicResize(8,6).BicubicResize(last.width, last.height).ConvertToRGB32()
overlay = resetmask(overlay)
base = ConvertToRGB32(last)
mask_clip = levels(base,16,1,32,255,0)
overlay_clip = Mask(overlay, mask_clip)
final = layer(base,overlay_clip,"add",255,0,0,0)
MergeChroma(ConvertToYUY2(base), ConvertToYUY2(final))
LanczosResize(640,352)
Results:
--------
Compressibility
---------------
Script 1 file size: 51726 kb
Script 2 file size: 48824 kb
Script 2 increased compressibility by 5.6% in this test.
Speed
-----
Script 2 decreased encoding speed by ~ 60% in this test.
Visuals
-------
Quality pretty good with both scripts; however, the black-blocking issue remains unsolved with both scripts even with quantizer 2 -> highest possible quality
Malcolm,
Please post your comments and any possible modifications to the script especially regarding the "blockiness-in-dark/black-areas" issue. (lumoff=-2 parameter with Marc FD's MPEG2Dec3.dll still seems to me the only possible way to get rid of this problem, as discussed widely in "lumi-masking" thread in the XviD forum, on which I would like to hear about your opinion too. (Also, my constant quant tests with quantizer 3 and h263 quantization resulted in a compressibility increase of ~ 3% with your script using the same other parameters)
best regards,
iago
Malcolm
17th October 2002, 17:30
@iago
hello and thank you very much! just to give you a quick answer (i hope i can do some tests this weekend):
1. 'Ghost Dog'. Good Choice! :p
2. 5.6% seems o.k. to me but could be better. (see below)
3. 60% speed-drop is a lot but if you look at what's done (multiple colorspace conversions, resizing, layering, ...) it's still pretty fast! Maybe this can only get significantly faster if someone combines all the stuff inside one filter...
4. i'm not into XviD, nor the 'blockiness-in-dark/black-areas' issue. So i can't comment on this atm. i'll search the forum for that topic and i hope i can help you with that. :)
Here are my tips:
DVD2AVI 1.76 (Color Space: YUV / YUV->RGB: PC Scale) Don't change the colorspace to RGB. the 2 Resizings at the start of the avisynth-script will then be done in YUV. That's a tick faster.
LanczosResize(640,352) You can safely do the Resize directly behind your crop() command. This won't affect my script, but makes it faster.
mask_clip = levels(base,16,1,32,255,0) Try values like '64' or '96' or even '128' instead of '32' inside levels(). I guess this will _heavily_ affect the compressibility!
That's all i can say right now (i'm at work you know) :rolleyes:
Thank you again
bye, Malcolm
iago
17th October 2002, 18:05
@Malcolm,
Originally posted by Malcolm
Don't change the colorspace to RGB. the 2 Resizings at the start of the avisynth-script will then be done in YUV. That's a tick faster.The color space selected in DVD2AVI in my above settings is already YUV, not RGB. Maybe it would be better to write it like that:
DVD2AVI 1.76
Color Space: YUV
YUV->RGB: PC Scale
So there is nothing to be modified in the DVD2AVI settings I guess ;).
Originally posted by Malcolm
You can safely do the Resize directly behind your crop() command. This won't affect my script, but makes it faster..That's really nice! :)
Originally posted by Malcolm
Try values like '64' or '96' or even '128' instead of '32' inside levels(). I guess this will _heavily_ affect the compressibility!..Yeah, I'll give it a go tweaking these values and report back the results :).
BTW, if you are using MPEG2Dec3.dll it's always possible to gain even more compressibility (though I agree with you that ~ 5% is really OK ;)) by setting some pre-processing value with the "cpu" parameter (i.e. cpu=4 or cpu=6, etc.) like in the following script, where some pre-deblocking/pre-processing is also applied to the source:
----------------------------------------------------------
LoadPlugin("C:\PROGRA~1\GORDIA~1\mpeg2dec3.dll")
mpeg2source("D:\GHOSTDOG\GHOSTDOG.d2v",cpu=4)
Trim(500,5500)
crop(4,8,712,464)
LanczosResize(640,352)
overlay = BicubicResize(8,6).BicubicResize(last.width, last.height).ConvertToRGB32()
overlay = resetmask(overlay)
base = ConvertToRGB32(last)
mask_clip = levels(base,16,1,32,255,0)
overlay_clip = Mask(overlay, mask_clip)
final = layer(base,overlay_clip,"add",255,0,0,0)
MergeChroma(ConvertToYUY2(base), ConvertToYUY2(final))
----------------------------------------------------------
thanks again for this very promising effort/script and
best regards,
iago
SILICON
17th October 2002, 19:35
For increase the compressibility I suggested one similar way.
The idea is high blurring the croma in dark pixels, but blurring lees in bright pixels.
Make one filter for this purpose can speed up a lot, with best permormance.
I suggest this algoritm: (can anybody code it?)
int threshhold = 64;
pixel32 newPix;
int w = 640;
int h = 304;
int TempFrameY[720,576]; // I don't know how make it dinamic size.
int TempFrameCb[720,576];
int TempFrameCr[720,576];
int x, y;
int BlurCb, BlurCr
// Change all pixels to YUV
for (x=0, x<w, x++)
for (y=0, y<h, y++)
{
TempFrameCb(x,y)=((-43 * src[x, y].r - 85 * src[x, y].g + 128 * src[x, y].b) >> 8) + 128;
TempFrameCr(x,y)=((128 * src[x, y].r - 107 * src[x, y].g - 21 * src[x, y].b) >> 8) + 128;
TempFrameY(x,y)=((77 * src[x, y].r + 150 * src[x, y].g + 29 * src[x, y].b) >> 8) + 16;
if( TempFrameY(x,y) == 0) TempFrameY(x,y)++; // for not have "error, divided by 0"
}
// make the blur
for (x=1, x<w-1, x++) //skip the borders!!
for (y=1, y<h-1, y++)
{ //make the average in Cb and Cr
BlurCb=TempFrameCb[x-1,y-1]+TempFrameCb[x-1,y]
+TempFrameCb[x-1,y+1]+TempFrameCb[x,y-1]
+TempFrameCb[x,y+1]+TempFrameCb[x+1,y-1]
+TempFrameCb[x+1,y]+TempFrameCb[x+1,y+1];
BlurCb>>=3; //sum all neigbour pixels and divide for 8
BlurCr=TempFrameCr[x-1,y-1]+TempFrameCr[x-1,y]
+TempFrameCr[x-1,y+1]+TempFrameCr[x,y-1]
+TempFrameCr[x,y+1]+TempFrameCr[x+1,y-1]
+TempFrameCr[x+1,y]+TempFrameCr[x+1,y+1];
BlurCr>>=3; //sum all neigbour pixels and divide for 8
// for more Y, more influence of Original Pixel
// For more threshhold, less influence of Original Pixel
// linnear funtion
finalCb = (TempFrameCb[x,y] * TempFrameY[x,y] / threshhold)
+ (BlurCb * threshhold / TempFrameY[x,y]);
finalCr = (TempFrameCr[x,y] * TempFrameY[x,y] / threshhold))
+ (BlurCr * threshhold / TempFrameY[x,y]);
//Now change the pixel to RGB
red = (Y - 16)*298/256 + (finalCr-128)*516/256;
green = (Y - 16)*298/256 - (finalCr-128)*208/256 - (finalCb-128)*100/256;
blue = (Y - 16)*298/256 + (finalCb-128)*409/256;
if (red < 0) red = 0;
else if (red > 255) red = 255;
if (green < 0) green = 0;
else if (green > 255) green = 255;
if (blue < 0) blue = 0;
else if (blue > 255) blue = 255;
newPix.r = red;
newPix.g = green;
newPix.b = blue;
dst[x, y] = newPix;
}
// The end :-)
For gauss funtion (I think best metod) change:
finalCb = (TempFrameCb[x,y] * TempFrameY[x,y]^GAUSS / threshhold)
+ (BlurCb * threshhold / TempFrameY[x,y]^GAUSS);
finalCr = (TempFrameCr[x,y] * TempFrameY[x,y]^GAUSS / threshhold))
+ (BlurCr * threshhold / TempFrameY[x,y]^GAUSS);
Them: higger blur in Y low values, same blur than linnear funtion in the midle blur values and less blur in Y high values.
I have not sure about Gauss funtion (test it!!)
You can code it? Thanks
vBulletin® v3.8.5, Copyright ©2000-2012, Jelsoft Enterprises Ltd.