PDA

View Full Version : which filter to remove that effect of "old"


magilvia
5th July 2004, 00:24
I've an anime encoded from old films with a slight Sepia(yellow) tint from old. This is how it looks:
http://www.ecompoint.com/members/magilvia/temp/original.jpg
I would like to remove this effect. Something like this:
http://www.ecompoint.com/members/magilvia/temp/best.jpg
Could you suggest a filter combination to do this?
Thanks

toysoldier
5th July 2004, 09:14
try to use whitebalance.vdf in virtualdub,
it can set picture white balance and change color hue,
but I think it cant just change one part color in picture,
as you showed second picture's windows sky.

toysoldier
5th July 2004, 09:18
sorry ,I am too careless ,forget give your address:
neuron2.net
you will find it in "Hosted".

Mug Funky
5th July 2004, 10:19
if you don't mind working in RGB, RGBadjust will do what you need. yellow/orange tint is fixed by having a higher gain on the blue (and slightly higher on green).

it's explained in the avisynth docs, but it's pretty simple:

RGBadjust(1,1.1,1.4,0) for example, to leave red untouched, and boost green and blue (and turn alpha to 0). that is RGBadjust(red, green, blue, alpha). if you use photoshop's levels, then converting to multipliers is pretty easy. simply 256/level will give you the right number to plug in, if you only do white point adjustment in Photoshop.

colorYUV and Tweak will also give you some control over colours without having to convert to RGB, but tweaking YUV can be counter-intuitive, so i'd have a play with it first.

magilvia
5th July 2004, 14:30
I've tryed whitebalance.vdf. That filter has a really great potential but also a big problem. When you configure the filter you must choose a frame to use as a "sample". The filter calculates what RGB value is supposed to be white in that frame and modifies the frame accordingly. It does a really good job! The problem is that the filter uses this fixed RGB value as reference for the entire movie, which is not correct. For example dark indoor scenes requires stronger settings rather than bright outdoor ones. Instead the filter should be modified to resample a new RGB value for every scene change.
Using it like it is now do not make much sense because a fixed color tweak could be attained whith a combination of avysinth filter like this:
Tweak(bright=-9, cont=1.05).converttorgb().rgbadjust(1, 1.08, 1.16, 0)
as Mug Funky suggests.
It's a pity because whitebalance could potentially do a really good job.
Also it lacks a setting to modify the strenght of the filter: 1 = full strenght, 0 = no modification.

I'll try to contact the author.

Corran
5th July 2004, 19:33
Try adding this to your script:

RGBadjust(1,1,1.18,0)
Levels(4, 1.1, 220, 0, 240)

DeepDVD
2nd August 2004, 03:51
In this thread (http://forum.doom9.org/showthread.php?threadid=40056&highlight=whitebalance) you'll see this:


OK - I'm back.

I did get to work on some features in the weekend. 2.5 beta is close.

Changes:
* Added: ColorYUV parameter "analyze" can be true or false. This will print out frame color and luma statistics.
* Added: ColorYUV parameter "autowhite" can be true or false. This will automatically adjust U/V offsets for each frame, so that color will be normalized for each frame. This is useful for recorded material, where whitebalance has been set wrong.
* Added ColorYUV parameter: "autogain". This will adjust luma to have maximum luma range for each frame. This function is also known as "autolevels" in some programs. This can be useful for recordings with bad light conditions, but it might make images flicker.
* MMX/ISSE optimized BitBlt function. This gives a reallife performance increase of ~15%.
* Added dissolve YV12. This also corrects FadeIn/Out.
* Separatefields now seems to work.
* MMX optimized YV12 merge functions.


An build-in filter i guess.

In case you got that version installed on your system, just put into your script:

ColorYUV(autowhite=true,autogain=true)


You also can use just one of those options, just test what give better results... I've tested it onto an old VHS-Rip an got very good results.

Mug Funky
12th August 2004, 12:17
DO NOT USE AUTOGAIN!

sorry for the all-caps, but autogain is a disaster on fade ins/outs.

it works per-frame, so passing objects, explosions, fan blades in front of lights (a more common effect than you'd think) will pump the brightness of the whole frame over time. blackness is completely bad with autogain - all you'll see is mid-grey DCT noise, greatly varying in intensity.

i've got a gain-control script that works rather like a dynamics compressor, but it's not perfect at the moment. i'll test it to see if i haven't broken it, then post it in a sec :)

[edit]

hmm... can't seem to make it behave properly (the brightness adapts 1 frame late), but FWIW here it is:


global gl_lum=1

function AGC (clip c, int "mode",float "multiplier", float "gamma", int "radius",int "scenechange", bool "luma")
{
global gl_radius = default(radius,4)
global gl_scenechange = default(scenechange,20)
global gl_multiplier = default(multiplier,.96)
gl_c = c
global gl_gamma = default(gamma,1)
mode= default(mode, 2)
luma = default(luma,true)

global gl_multiplier = (mode==2)? float(gl_multiplier*2) :
\ float(gl_multiplier)

global gl_method = (mode==1)? "averageluma(filterme)" :
\ (mode==2)? "YplaneMax(filterme)" : "YplaneMedian(filterme)"

filterme = gl_c.reduceby2().reduceby2().reduceby2().
\ temporalsoften(gl_radius,255,255,gl_scenechange,2).
\ levels(0,gl_gamma,255,0,255,coring=false)

gl_c=gl_c.frameevaluate("global gl_lum = gl_multiplier*128 / (" + string(gl_method + ")")
\ ,after_frame=false)

(luma==true)? gl_c.scriptclip("coloryuv(gain_y=round(gl_lum * 256)-256)") :
\ gl_c.scriptclip("converttorgb32().RGBadjust(gl_lum,gl_lum,gl_lum,0).converttoyv12()")

}



[edit edit]

added the recalcitrant first line that was breaking the script... sorry guys.

DeepDVD
13th August 2004, 09:58
I've recognized similiar problems. In my TV-Rip, autogain put a flicker onto some scenes. Autowhite is catastrophe for every Anime, some scenes were turn from megenta-blue to magenta-green!

Cannot understand, why those functions work in a such inproper way. Maybe those two were added for natural things, a VHS-Rip of a Camcorder-Record was better with autowhite and autogain than before.

EDIT:

The Gain-Control you've posted before does have a problem. In the streamed and gain-controled video i've got the message

I don't know what "gl_lum" means
([ScriptClip],line 1)

Didée
13th August 2004, 10:49
It's safer to do an initial initialzing at the script/function beginning for variables that are used inside the conditional environment *only*. (It's still a mystery to me why it's sometimes needed, and sometimes it works without ... I simply always intitialize everything, and then have one potential problem less to care about.)

Simply add "global gl_lum = 128" to the beginning of the function, and it should work.

- Didée

DeepDVD
13th August 2004, 11:09
If I add "global gl_lum = 128" to the function to explain the function the variable is good for, the whole video would be shown so bright nobody can see anything except some bright colors. The rest appear white.

EDIT:

"global gl_lum=128" just works, if you take a floating value among 2... e.g. 1.1 ... but it's too bright yet.

Now Avisynth doesn't understand the value "(filterme)" in the function, the same error like in my earlier post.

Didée
13th August 2004, 12:19
Hrmpfh. I currently can't test anything here on this machine. Better wait for Mug Funky to return, or me coming home. Doesn't make much sense if we stumble around in the blue now.
It seems like the whole frameevaluate() thingie gets not correctly evaluated on your side. But for Mug Funky it seemed to work ...

What's the exact AviSynth version you'r running, DeepDVD? What's "version()" reporting? Perhaps even the date of the DLL in your system32 directory?

Oh, wait!

"filterme" of course is also evaluated inside the conditionalEnv, through "gl_method". Therefore, the assignment "filterme = gl_c.deleteframe(..." should also read "global filterme = gl_c...", shouldn't it.

Heh, I've become a li'l rusty with ScriptClip'ing & Co. ... :o


- Didée

DeepDVD
13th August 2004, 13:09
Maybe my version is buggy. I don't know but somehow I see the streamed video and get on the top that little error message.

Avisynth Version: 2.5.5 Beta from July 29th

Also my knowledge in avisynth-programscripting (not just the scripting of some resizes, using filters and so on) isn't very advanced. Although I understand the error shouldn't be there. Perhaps there are some other bugs opening the message? I've never seen an error-message in an AVS-video by watching the video on the screen before.

Further I see you're from Germany, too. Could be easier to discuss any further thing in german but it wouldn't be fair for the other readers, so go on in english *sigh* ;)

Didée
13th August 2004, 14:06
No, your Avisynth is perfectly up to date.

Try setting the "global" tag in front of the "filterme = etc.etc." like I said earlier, and see if it runs correctly then. If not, wait for Mug Funky's return to whine against his shoulder :sly: - I won't return before somewhen tomorrow.

BTW, as far as digital video matters are concerned, I myself am astounded to find that I can express myself much easier in English than in my own language :eek: - its just the surrounding sentences in which the technical details must be embedded, that sometimes are difficult to build ;)

- Didée

DeepDVD
13th August 2004, 14:52
Wow, I took the global tag into the script before filterme and... guess what happened... it works... but I don't completely understand what mug funky means with not perfect. It already looks very pleasent for my noob-eyes ;)

I hope we could get the script perfect so I can begin push the quality of my TV-Rips for DVD.

Wilbert
13th August 2004, 15:18
I think it doesn't work properly, because the script contains errors (for example the last two lines which should be switched). What happens now is that gl_lum = 128 is applied to the first frame (and the calculated one is applied to the next frame, I think).

The following works

function AGC (clip c, int "mode", float "multiplier", float "gamma", int "radius", int "scenechange", bool "luma")
{
global gl_lum = 0
global gl_multiplier = default(multiplier, .96)
global gl_method = 0

global av = 0
global yma = 0
global yme = 0

global gl_radius = default(radius, 4)
global gl_scenechange = default(scenechange, 20)
global gl_gamma = default(gamma, 1)

mode = default(mode, 2)
luma = default(luma, true)

global gl_multiplier = (mode==2)? float(gl_multiplier*2) :
\ float(gl_multiplier)


filterme = c.reduceby2().reduceby2().reduceby2().
\ temporalsoften(gl_radius,255,255,gl_scenechange,2).
\ levels(0,gl_gamma,255,0,255,coring=false)

global filterme = filterme

global gl_method = (mode==1) ? av : (mode==2) ? yma : yme

c = c.frameevaluate("global av = averageluma(filterme)")
c = c.frameevaluate("global yma = YplaneMax(filterme)")
c = c.frameevaluate("global yme = YplaneMedian(filterme)")

c = (luma==true) ? c.scriptclip("coloryuv(gain_y=round(gl_lum * 256)-256)") :
\ c.scriptclip("converttorgb32().RGBadjust(gl_lum,gl_lum,gl_lum,0).converttoyv12()")

c = c.frameevaluate("global gl_lum = gl_multiplier*128 / gl_method")

return c

}

mpeg2source("F:\From_hell\from_hell.d2v")
agc

However, it makes my pc crash when scrolling through the clip (latest binaries).

Mug Funky
13th August 2004, 17:24
ACH! sorry, all.

cut and paste error.. i forgot about the initializing thing.

put this outside the function (like jus before the "function AGC(..." line)

global gl_lum=1

hehe...

and it does work, but it runs 1 frame behind. you'll notice it on scene-changes.

[edit]

btw, anyone who knows avisynth's frameevaluate, scriptclip, etc a little better is free to bugfix it :) it's a bit enigmatic to me, and i don't use this enough to be bothered :)

i should really document my stuff.. you know how it is. i write the script between "f5"'s in VirtualDub, and once it works i hardly ever touch it again. so it's all very ad hoc.

the principle is (for anyone who codes more elegantly than me) to do a strong temporal filter on a downscaled video to get the average luma over a short period of time. think of it as a compressor with attack and release both set to temporalsoften's radius value. after grabbing the average luminance the input clip is multiplied.

there are 3 different strategies for scaling - YplaneMax (default) which is like a normalization without clipping (there'll be a little from the fact that the clip used to determine this is downscaled a lot), YplaneMedian, and AverageLuma. i'm not sure if they all work, but the latter two strategies require a rescaling, or the average luma of input (mid grey) will be scaled to white on output...

[edit edit]

this is something that would work better as a plugin i think... then you could specify attack and release separately, and have some more elegant (and fast) ways of getting metrics.

Didée
13th August 2004, 17:43
BTW, what exactly does "YPlaneMedian()" calculate? I've a hard time in imagining that it returns the _true median_ of the a frame's Y levels, i.e. the value of that pixel out of all pixels that has 49.999% brighter and 49.999% darker neighbors, over the whole frame. This requires sorting all pixels by brightness, and then taking the middle one from the sorted list (AFAIK, unless there's no other neat coding trick), which would be way too slow. In practice, PlaneMedian is working much too fast for that.
?

- Didée

DeepDVD
13th August 2004, 18:18
@ Wilbert

The Script does work on my machine... but the result is a black screen.

global gl_lum = 0

Maybe here's the error?
________________________________________________________________

@ Mug Funky

I've corrected the script and it works good now... it would be very nice, if someone could correct the 1-frame-behind-bug and recorrect the code for TV-output... if i look at the results, i could imagine the tv-output should be too bright, shouldn't it?

Leak
13th August 2004, 18:18
Originally posted by Didée
This requires sorting all pixels by brightness, and then taking the middle one from the sorted list (AFAIK, unless there's no other neat coding trick), which would be way too slow.

No, it doesn't.

It just requires to count how often each of the 256 possible values occurs (i.e. building a luma histogram, which is something I've actually implemented in my BlendBob plugin if you're looking for a code example) and then sum up the number of occurrences of each value starting from 0 until you pass half the number of all pixels, which means the current value is the median. It's quite fast, but it's not something you can speed up a lot by using MMX or SSE.

np: Dntel - Your Hill ((This Is) The Dream Of Evan & Chan)

Wilbert
13th August 2004, 18:30
global gl_lum = 0
Maybe here's the error?

I don't see why (cause it's only initialization).

I saw image in WMP6.4. But it remained black in VDubMOd, and my whole PC crashes after scrolling through a bunch of frames. Maybe I will try it with v2.54.

But, like I said: I think here's your 1-frame-behind bug:


What happens now is that gl_lum = 128 is applied to the first frame (and the calculated one is applied to the next frame).