View Full Version : How to calculate saturation?
zee944
13th March 2009, 20:48
Does anybody know how to calculate out the saturation level of a frame? I need it for comparsion with another frame.
I assume it is possible with some RGBDifference/GreyScale trick. Anyone know such trick?
hanfrunz
16th March 2009, 10:15
You can only compare saturation differences of colors. So you have to pick the color of a pixel in frame 1 and the color of the same pixel in frame 2. You can of course average values from many pixels.
Look here for more information about saturation (http://forum.doom9.org/showthread.php?t=108348)
regards,
hanfrunz
Mug Funky
19th March 2009, 10:32
couldn't distance-from-128 in the U and V planes work as a measure of saturation?
possibly:
[code]u=last.utoy()
v=last.vtoy()
global sat=mt_lutxy(u,v,expr="x 128 - abs y 128 - abs > x 128 - abs y 128 - abs ?")
scriptclip(""" subtitle(string(sat.averageluma()/2.55)+"%") """)
gives a little number from 0 to 128 in the top left, the only film i tried it on averaged about 4% saturation
not sure if my maths is ideal here, but i figured average of the greatest absolute distance from grey would be fair. possibly the 2 planes should be added rather than the max found, but this could bias neutral scenes against warmer or cooler scenes.
[edit]
you might find for comparing frames, the vectorscope function of histogram() is far more useful... this will not only tell you how saturated (how wide the blob is), but where the colours are with respect to each other. this makes matching easier.
zee944
27th March 2009, 17:33
You can only compare saturation differences of colors. So you have to pick the color of a pixel in frame 1 and the color of the same pixel in frame 2. You can of course average values from many pixels.
Look here for more information about saturation (http://forum.doom9.org/showthread.php?t=108348)
regards,
hanfrunz
Ah, thanks. I've seen this thread before, I've just skimmed through the second expression.
So the correct expression is sat=(max(r,g,b)-min(r,g,b))/max(r,g,b)
zee944
29th March 2009, 19:03
Here are two pictures:
http://i179.photobucket.com/albums/w286/zee944/TD_less_saturated.jpghttp://i179.photobucket.com/albums/w286/zee944/TD_more_saturated.jpg
They're from two different prints from the same movie. Going by the formula in my previous post, the first image is 58.3%, the second is 58.2% saturated. Despite the result, the second seems a lot more saturated.
Without changing contrast or color balance (I have to leave them intact) how can I calculate out how much less saturation needed for the second to match the first?
I've tried out manually, and 10% less saturation (Tweak(sat=0.90)) makes it fine. But I need to find out it mathematically, with some kind of formula. I can go pixel by pixel if needed, I don't have to do it in AviSynth. Any ideas? :)
Wilbert
29th March 2009, 20:35
I would take the average of the saturation of the pixel, and not the saturation of the average pixels.
JohnnyMalaria
29th March 2009, 22:40
sqrt(U*U + V*V)
And since you are comparing two frames, you can skip the computationally-expensive sqrt function.
zee944
31st March 2009, 20:53
I would take the average of the saturation of the pixel, and not the saturation of the average pixels.
If you mean calculating saturation of each pixels separatedly then averaging in the end, there's not much difference: 65.02% and 66.22%. The difference is nowhere close to ~10%.
sqrt(U*U + V*V)
Calculating from the average U and V plane provided by ColorYUV: 184.356 and 184.345. Practically the same.
Anything else? :( I've thought I should use some smart weighting, but simply weighting for luma (brighter pixel -> higher weighting) still wasn't good.
JohnnyMalaria
1st April 2009, 13:13
Create a saturation histogram for each frame and then optimize an adjustable parameter to minimize the difference between them (least squares). You could do this on a frame-by-frame basis or calculate the parameter based upon a few frames and apply it to the whole frame set.
It may help to look at the histograms of such things in a program designed for that kind of thing to see where the differences lie. See if your proposed parameter(s) have side effects w.r.t. contrast/balance etc.
JohnnyMalaria
1st April 2009, 14:32
I've been looking at the histograms and they reveal that your problem is non-linear - which you probably know. The saturation levels in the 50-75% region have been boosted while the lowest have been almost fully removed.
I took the saturation channel for each of the two images (cropped to remove the text) and converted one into a pure red and the other into a pure green image. Combining them gives an image that should be pure yellow where the saturations are the same and either more green or more red where the saturations differ. The histogram clearly shows where differences lie.
It seems to me that you should determine the differences between the histograms collected over multiple frames and then correct each pixel in each frame using that information. I think you'll will end up reversing whatever color correction was done to the material in the first place. One thing to notice, too, is that the saturation histogram for the 'better' image is very quantized where the adjustment has been made.
zee944
1st April 2009, 20:12
I've been looking at the histograms and they reveal that your problem is non-linear - which you probably know. The saturation levels in the 50-75% region have been boosted while the lowest have been almost fully removed.
Thanks for devoting time to my problem, but it's becoming too complicated. ;) These two pictures are not even from the same print, so it probably doesn't worth to "reverse engineer" it... I don't expect them to be the same pixel-by-pixel, I just want to find a better method for measuring the saturation level.
JohnnyMalaria
1st April 2009, 21:48
You stated earlier:
Without changing contrast or color balance (I have to leave them intact) how can I calculate out how much less saturation needed for the second to match the first?
That's what I was looking at in my previous reply. i.e., comparing the saturation levels in one image with those in the other. A single average value won't help because the amount needed to make the images match is dependent on the saturation level - there's a notable difference in the upper mid range. Comparing histograms is actually very straightforward. The images I made with the red, green etc serve to just illustrate the principle. Computationally, there's little difference between calculating the average for the whole frame and creating a histogram. The latter retains a lot more information (256 times!)
Can you explain a bit more about what you are trying to do? e.g., make a bad print look more like the original (perhaps because not all of the original exists).
morsa
2nd April 2009, 00:12
What about converting to HSI and checking the intensity of the S channel?
Am I nuts?
zee944
2nd April 2009, 18:52
Computationally, there's little difference between calculating the average for the whole frame and creating a histogram. The latter retains a lot more information (256 times!)
I understand your theory, I just don't understand how would it help me to auto-compute the needed adjustment. The saturation can be set manually, I just wanted a mathematical way.
e.g., make a bad print look more like the original (perhaps because not all of the original exists).
That's exactly what I'm doing. The second (oversaturated) image is actually already heavily adjusted.
Here's an example. First image: bad print unprocessed. Second image: bad print processed. Third image: good (reference) print. Only setting the saturation remained, but in this case below, it seems fine.
http://i179.photobucket.com/albums/w286/zee944/DONE09_before.jpg
http://i179.photobucket.com/albums/w286/zee944/DONE09_modified.jpg
http://i179.photobucket.com/albums/w286/zee944/DONE09_reference.jpg
What about converting to HSI and checking the intensity of the S channel?
Could you show a script for that?
JohnnyMalaria
2nd April 2009, 20:25
I'm confused. The histogram method *is* mathematical - there's nothing manual involved. But it can't be done unless you have a least one known good and bad frame. Once you have compared those two to see what correction is needed then you just apply it to all the frames.
Create a 256-channel array. Scan the known good image and count each saturation level. Do the same with the bad image. This gives you a correction factor for each saturation level. Armed with this info, correct every frame. But to be more robust, create the correction factor array with a few known good/bad pairs of frames instead of one. The entire process is automatic and deterministic.
I don't understand the HSI thing since you have already been calculating S (be it from RGB or YUV).
zee944
3rd April 2009, 03:08
Create a 256-channel array. Scan the known good image and count each saturation level. Do the same with the bad image. This gives you a correction factor for each saturation level. Armed with this info, correct every frame.
Then maybe I don't understand. I count how many pixels each saturation level has... and if it turns out 50 pixels has the saturation level of 120 in the bad image, and 150 pixels in the good image, then what do I do in AviSynth?
JohnnyMalaria
3rd April 2009, 18:33
Ooops - no wonder you are confused - I've been talking out of my bottom somewhat :o What I should have been saying is...
Scan through both frames and build an array that maps the saturation values on your source (bad) frame to those on your target (good) frame. Effectively, you will be creating a 256-point transfer function that will specify how much to shift particular saturation values to new values. But you also need to take into account that, for example, 125 won't always map to 129. It may be spread about 129. So, for each target value, create the average source saturation value. i.e., suppose 125 -> 129 for one pixel and then 125 -> 132 for another and then 125 -> 126 etc, you would simply add 129 + 132 + 126... for each pixel in the image. You also keep a count of how many values were added. Once the frame has been scanned, divide the sum by the number to get the average. Now you have an array that should give you a decent mapping. You would repeat the process a few times throughout the video to see that the mapping is reasonable constant. Once done, apply the mapping to each frame.
I'm not particularly familiar with Avisynth's programming syntax but I'm pretty sure the above can be done.
It's actually a lot easier to code the algorithm than describe it!
zee944
3rd April 2009, 19:22
Oh, I get it - but that was what I was afraid of... it can't really be done in AviSynth. Not without writing a plugin, or it'll be very, very complicated, and I don't have the ability to do that. And the geometries of the two frames are not identical! Remember they're from different sources. So you can't just do the averages, you have to drop values above a threshold etc.
The whole thing is like... I don't know the right English phrase for that, but it's like shooting a bird with a cannon :D So I'll have to set the saturation manually instead. Thanks anyway. :)
Sagekilla
3rd April 2009, 19:48
You can still resize one image to the same dimensions of the other, and get a very good approximation of what it would be like if both were the same dimensions though.
It'd be probably easy to implement the algorithm JohnnyMalaria describe in a plugin, thoiugh.
JohnnyMalaria
3rd April 2009, 21:10
The whole thing is like... I don't know the right English phrase for that, but it's like shooting a bird with a cannon :D So I'll have to set the saturation manually instead. Thanks anyway. :)
Good luck :)
The English equivalent to your saying is "using a sledgehammer to crack a nut" - but I think yours is much better.
vBulletin® v3.8.5, Copyright ©2000-2012, Jelsoft Enterprises Ltd.