White balance on skintones

Started by a1ex, December 06, 2013, 07:18:46 AM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

a1ex

From http://www.magiclantern.fm/forum/index.php?topic=7139.msg90883#msg90883 :

Quote from: a1ex on December 06, 2013, 04:31:54 AM
If it's daylight, it's easy (something around 5500 in sunlight, 6500 in shadow). A little magenta boost when shooting grass with older lenses. Indoors, I found balancing on something white a bit too harsh (I prefer to go a little warmer from there). Sometimes I get much better results if I do the white balance directly on skintones.

I have a small modification to ufraw that lets me do spot WB on skintones; if anyone is interested I can share it.

Quote from: budafilms on December 06, 2013, 06:50:31 AM
Share it!

Alright; before doing this, I'd like a little help from you:

1) before reinventing the wheel, let me know how are you doing white balance on skin tones in your favorite image editor.

2) then, upload a few sample pictures with really difficult WB that I can use as test material (of course, the pictures should contain skin tones). If you have an image where you did WB with a grey card, but skin tones look wrong, that's the perfect candidate. Formats accepted: CR2 or DNG. If you have some reference images with the same skin tones in daylight (how they should look like in the final output), upload them too. Formats accepted: CR2/DNG + rendered JPG + white balance info (Kelvin or RGB multipliers).

Basically, my method is a modification to ufraw, where instead of doing white balance on a gray card, I can select a reference color.

Related: https://discussions.apple.com/thread/4705311

Download: http://www.magiclantern.fm/forum/index.php?topic=9597

Luiz Roberto dos Santos

A little while ago I had this problem. Maybe your tests help me A1ex.
Here is the link to download the DNG (60D - dual_iso and ETTR): http://goo.gl/oaziYZ

[dual_iso interpolation performed in "cr2hdr-histmatch3"]

edit: the cr2 non-interp. : http://goo.gl/jT0Rkf

a1ex

My quick try (warning: untrained eye and uncalibrated monitor):

The GUI change on ufraw (for now, the reference skintone is hardcoded, so I just select some skintone and push the button):


Rendering with my script (overall_bias=-2, since it was a bit too noisy with default settings)


Selecting the skin on the face of the main guy resulted in something more green. I prefer WB a little on the magenta side, so I did the WB on the other guy.

Selecting the bright hand on the main guy would result in something around 5500K / green=1.05.

Regular WB on the clock (which I assume it should be gray) results in something around 6000K / green = 1.28. That one looks good to me too, maybe a tiny bit on the green side.

Worth polishing or not?

Luiz Roberto dos Santos

Very interesting results A1ex!
In this work we had a serious problem with WB, so that the final version had invasion of  bluish. We had to force the red so that skin tones were not corrupted.
Sounds promising, indeed.
The "final" version:


2048px http://img35.imageshack.us/img35/2320/g9sq.jpg

This is a buid-in ufraw function, or a change in the GUI by you? How can we try?
Very good, thank you for your advances.



a1ex

This is my rough patch, if anyone wants to try or review it:


diff -r 1541ceae5790 ufraw_preview.c
--- a/ufraw_preview.c Wed May 01 17:25:51 2013 +0300
+++ b/ufraw_preview.c Fri Dec 06 19:21:12 2013 +0200
@@ -1388,6 +1388,7 @@
     guint16 rawChannels[4], linearChannels[3];
     for (c = 0; c < data->UF->colors; c++)
         rawChannels[c] = rawSum[c] / spot.Size;
+
     develop_linear(rawChannels, linearChannels, Developer);
     double yValue = 0.5;
     extern const double xyz_rgb[3][3];
@@ -1398,6 +1399,12 @@
         yValue *= (double)Developer->exposure / 0x10000;
     rgb[3] = yValue;
     rgb[4] = value2zone(yValue);
+   
+    /* show raw spotmeter instead of RGB */
+    rgb[0] = rawChannels[0];
+    rgb[1] = rawChannels[1];
+    rgb[2] = rawChannels[2];
+   
     color_labels_set(data->SpotLabels, rgb);
     char tmp[max_name];
     g_snprintf(tmp, max_name, "<span background='#%02X%02X%02X'>"
@@ -1644,10 +1651,20 @@
             for (c = 0; c < data->UF->colors; c++)
                 rgb[c] += pixie[c];
         }
+   
+    double ref[4] = {data->UF->rgbMax, data->UF->rgbMax, data->UF->rgbMax, data->UF->rgbMax};
+   
+    if (user_data)
+    {
+        ref[0] *= 4686.0 / 6069 * 1.979;
+        ref[2] *= 2817.0 / 6069 * 1.678;
+    }
+   
     for (c = 0; c < 4; c++) rgb[c] = MAX(rgb[c], 1);
     double chanMulArray[4];
     for (c = 0; c < data->UF->colors; c++)
-        chanMulArray[c] = (double)spot.Size * data->UF->rgbMax / rgb[c];
+        chanMulArray[c] = (double)spot.Size * ref[c] / rgb[c];
+   
     if (data->UF->colors < 4) chanMulArray[3] = chanMulArray[1];
     UFObject *chanMul = ufgroup_element(CFG->ufobject,
                                         ufChannelMultipliers);
@@ -4377,9 +4394,13 @@
                               0, 1, _("Green"), _("Green component"));
     // Spot WB button:
     button = stock_icon_button(GTK_STOCK_COLOR_PICKER,
-                               _("Select a spot on the preview image to apply spot white balance"),
+                               _("Spot white balance"),
                                G_CALLBACK(spot_wb_event), NULL);
-    gtk_table_attach(subTable, button, 7, 8, 0, 2, 0, 0, 0, 0);
+    gtk_table_attach(subTable, button, 7, 8, 0, 1, 0, 0, 0, 0);
+    button = stock_icon_button(GTK_STOCK_COLOR_PICKER,
+                               _("Skin white balance"),
+                               G_CALLBACK(spot_wb_event), (void*)1);
+    gtk_table_attach(subTable, button, 7, 8, 1, 2, 0, 0, 0, 0);

     box = GTK_BOX(gtk_hbox_new(0, 0));
     gtk_table_attach(table, GTK_WIDGET(box), 0, 1, 2, 3, 0, 0, 0, 0);


I'm not yet sure how to compile it for Windows (need to dig deep in their instructions). On Linux it was straightforward, probably on Mac too.

Andy600

What a great (but disturbing) image!
Colorist working with Davinci Resolve, Baselight, Nuke, After Effects & Premier Pro. Occasional Sunday afternoon DOP. Developer of Cinelog-C Colorspace Management and LUTs - www.cinelogdcp.com

Luiz Roberto dos Santos

Quote from: a1ex on December 06, 2013, 06:32:52 PM
This is my rough patch, if anyone wants to try or review it:


diff -r 1541ceae5790 ufraw_preview.c
--- a/ufraw_preview.c Wed May 01 17:25:51 2013 +0300
+++ b/ufraw_preview.c Fri Dec 06 19:21:12 2013 +0200
@@ -1388,6 +1388,7 @@
     guint16 rawChannels[4], linearChannels[3];
     for (c = 0; c < data->UF->colors; c++)
         rawChannels[c] = rawSum[c] / spot.Size;
+
     develop_linear(rawChannels, linearChannels, Developer);
     double yValue = 0.5;
     extern const double xyz_rgb[3][3];
@@ -1398,6 +1399,12 @@
         yValue *= (double)Developer->exposure / 0x10000;
     rgb[3] = yValue;
     rgb[4] = value2zone(yValue);
+   
+    /* show raw spotmeter instead of RGB */
+    rgb[0] = rawChannels[0];
+    rgb[1] = rawChannels[1];
+    rgb[2] = rawChannels[2];
+   
     color_labels_set(data->SpotLabels, rgb);
     char tmp[max_name];
     g_snprintf(tmp, max_name, "<span background='#%02X%02X%02X'>"
@@ -1644,10 +1651,20 @@
             for (c = 0; c < data->UF->colors; c++)
                 rgb[c] += pixie[c];
         }
+   
+    double ref[4] = {data->UF->rgbMax, data->UF->rgbMax, data->UF->rgbMax, data->UF->rgbMax};
+   
+    if (user_data)
+    {
+        ref[0] *= 4686.0 / 6069 * 1.979;
+        ref[2] *= 2817.0 / 6069 * 1.678;
+    }
+   
     for (c = 0; c < 4; c++) rgb[c] = MAX(rgb[c], 1);
     double chanMulArray[4];
     for (c = 0; c < data->UF->colors; c++)
-        chanMulArray[c] = (double)spot.Size * data->UF->rgbMax / rgb[c];
+        chanMulArray[c] = (double)spot.Size * ref[c] / rgb[c];
+   
     if (data->UF->colors < 4) chanMulArray[3] = chanMulArray[1];
     UFObject *chanMul = ufgroup_element(CFG->ufobject,
                                         ufChannelMultipliers);
@@ -4377,9 +4394,13 @@
                               0, 1, _("Green"), _("Green component"));
     // Spot WB button:
     button = stock_icon_button(GTK_STOCK_COLOR_PICKER,
-                               _("Select a spot on the preview image to apply spot white balance"),
+                               _("Spot white balance"),
                                G_CALLBACK(spot_wb_event), NULL);
-    gtk_table_attach(subTable, button, 7, 8, 0, 2, 0, 0, 0, 0);
+    gtk_table_attach(subTable, button, 7, 8, 0, 1, 0, 0, 0, 0);
+    button = stock_icon_button(GTK_STOCK_COLOR_PICKER,
+                               _("Skin white balance"),
+                               G_CALLBACK(spot_wb_event), (void*)1);
+    gtk_table_attach(subTable, button, 7, 8, 1, 2, 0, 0, 0, 0);

     box = GTK_BOX(gtk_hbox_new(0, 0));
     gtk_table_attach(table, GTK_WIDGET(box), 0, 1, 2, 3, 0, 0, 0, 0);


I'm not yet sure how to compile it for Windows (need to dig deep in their instructions). On Linux it was straightforward, probably on Mac too.


Thanks A1ex, I will try this as soon as possible!


Quote from: Andy600 on December 06, 2013, 06:45:06 PM
What a great (but disturbing) image!


Thank you Andy! This is a project called "Allegory of Ignorance", whose concept criticize our eating habits, eating garbage (literally, in this case) and not knowing how they even make us sick (the clock indicates that our time is running out).
Thanks to the team: Eduardo da Rocha, Leonardo Henrique, Fernanda, Ednilson Jr. and Jalil Damus.

budafilms

Quote from: a1ex on December 06, 2013, 07:18:46 AM
From http://www.magiclantern.fm/forum/index.php?topic=7139.msg90883#msg90883 :

Alright; before doing this, I'd like a little help from you:

1) before reinventing the wheel, let me know how are you doing white balance on skin tones in your favorite image editor.

2) then, upload a few sample pictures with really difficult WB that I can use as test material (of course, the pictures should contain skin tones). If you have an image where you did WB with a grey card, but skin tones look wrong, that's the perfect candidate. Formats accepted: CR2 or DNG. If you have some reference images with the same skin tones in daylight (how they should look like in the final output), upload them too. Formats accepted: CR2/DNG + rendered JPG + white balance info (Kelvin or RGB multipliers).

Basically, my method is a modification to ufraw, where instead of doing white balance on a gray card, I can select a reference color.

Related: https://discussions.apple.com/thread/4705311

1) I use DaVinci Resolve Lite.
- In Master Setting I put:
- Decode Using: Clip.
- Withe Balance: Custom
- Color Space: BMD Film
- Gamma: BMD FILM
- Hightlight Recovery: On

Clip Decoder Settings:
- Color Temp: 4217
- Tint: 17.14

After That I work with Color Wheels, Primary Corrections. Always Start with raise the blacks with scopes. After up the highlight. And after that the mid tones that affect skin tones directly. I always touch the red to down and the blue to up. I never touch the green. For greener or Magenta its just touch the shadows very little. I prefer very little dark greener.

2)  Atached examples in DNG and after: https://www.dropbox.com/s/yb0et512jjq33pt/Skin%20Tones%20for%20A1ex.zip

For everybody: This is the TRAILER of the movie (1 hr 50 Min) of a movie did it completely with ML RAW!



a1ex

My quick try (if you look close, you can see the spot where I've metered WB on each shot):



I didn't use the reference JPEGs, only my hardcoded values.

budafilms

Amaizing work! Should I use Ufraw too? I will copy your values. Wich is the process you recommend to do this?

Audionut

Quote from: a1ex on December 06, 2013, 05:53:10 PM
My quick try (warning: untrained eye and uncalibrated monitor):

If their is some spare donation money you should buy one of these.

I'd recommend to calibrate with this, and if you want a GUI.

Either that or you can borrow mine.

Audionut

Quote from: a1ex on December 06, 2013, 07:18:46 AM
1) before reinventing the wheel, let me know how are you doing white balance on skin tones in your favorite image editor.

By eye unless I've used a grey card.  Grey card is great when the lighting doesn't change, but it quickly becomes cumbersome at the park with the kids. 

Quote from: a1ex on December 06, 2013, 07:18:46 AM
If you have an image where you did WB with a grey card, but skin tones look wrong, that's the perfect candidate.

A grey card doesn't lie.  It needs to be in the light you want to white balance too!

l_d_allan

Quote from: budafilms on December 07, 2013, 07:17:22 AM
Amazing work!

Agree. Looks VERY promising.

Quote
Should I use Ufraw too?

I'm unfamiliar with ufraw. My speculation is that instead of having a typical eye-dropper that sets the WB so the selected pixel(s) become gray (red=green=blue), it instead causes the equivalent to result in a reasonable skin tone. Or not?

a1ex

Quote from: l_d_allan on December 08, 2013, 06:19:27 AM
My speculation is that instead of having a typical eye-dropper that sets the WB so the selected pixel(s) become gray (red=green=blue), it instead causes the equivalent to result in a reasonable skin tone.

Exactly. Is there a similar tool in other image editors?

QuoteI'm unfamiliar with ufraw.
I like it because I find it easy to script and hack, and the GUI does what I need without standing in the way. I've also tried RawTherapee, but I can spend half an hour dragging sliders and still can't get the same look that I get with ufraw and enfuse. The downside is poor highlight handling (also a probem in dcraw), and I'll probably fix it at some point. I also have DxO and Lightroom demos, but they didn't convince me. I liked DxO PRIME and LR highlight recovery, but not the GUIs.

Back to the topic, the todo list would be:
- use robust statistics for the spotmeter
- implement a GUI to choose the reference skintone color (a little hard, need to learn some GTK basics and figure out where to save these values)
- submit the patch to ufraw
- compile a Windows binary so you can try it

engardeknave

QuoteI liked DxO PRIME and LR highlight recovery, but not the GUIs

You should try Adobe Camera Raw.

a1ex

Update: now you can download a modified UFRaw that includes this patch:

http://www.magiclantern.fm/forum/index.php?topic=9597

l_d_allan

Quote from: Audionut on December 07, 2013, 03:30:51 PM
A grey card doesn't lie.  It needs to be in the light you want to white balance too!


  • mostly agree, but ...
  • obviously, I often don't have a gray card taken in the same lighting
  • even with a gray card in the same lighting, I've certainly found it difficult to get satisfactory skin tones with many images. ymmv
  • I try to take a "by the numbers" approach to WB and DR, but "easier said than done"

a1ex

Can you upload some of the most difficult shots, if you still have the raw files?

(yes, I'm still looking for test images)

Also, take a look at this: http://en.wikipedia.org/wiki/Metamerism_%28color%29

(in a nutshell, a gray card can lie).

l_d_allan

Quote from: a1ex on December 20, 2013, 05:43:14 PM
(in a nutshell, a gray card can lie).

A problem is that a gray card typically faces the camera, and gets frontal lighting. However, a face is 3d, and the left and right side can very much be getting different lighting.

Another issue is when multiple people are in the same picture. I can recall situations with a group shot of 200+ people at a "Kids Camp" with some in sunshine, and others in the shade, and others under trees with "mottled shade". Nearly impossible.

BTW: I have been using a SpyderCube from Datacolor, which I've found useful, especially since it was bundled with something else (pricey otherwise). I've asked Datacolor to consider improving it by having a "forward facing facet".

Also, the SpyderCube is helpful with very contrasty Dual_ISO situations ... with one SpyderCube and a DIY black trap:
http://berean.zenfolio.com/misc/hC87E705#hc87e705

I'll make it a point to look for difficult flesh tones.

You may be aware of this, but my understanding is that, according to Dan Margulis (PS and L*a*b guru), Caucasian skin tends to follow a certain formula when viewed with CMYK ... don't recall the specifics ... Magenta and Yellow will be about the same, and Cyan about 1/3rd of M and Y?  Or not?




a1ex

I don't know, my approach simply reads a reference color from some skintone (R-G and B-G ratios, currently hardcoded) and attempts to match it.

Audionut

Quote from: l_d_allan on December 20, 2013, 09:51:32 PM
A problem is that a gray card typically faces the camera, and gets frontal lighting. However, a face is 3d, and the left and right side can very much be getting different lighting.

Another issue is when multiple people are in the same picture. I can recall situations with a group shot of 200+ people at a "Kids Camp" with some in sunshine, and others in the shade, and others under trees with "mottled shade". Nearly impossible.

These are all outside the bounds of a grey card.  An object in sunshine and an object in shade are under different lighting conditions ;)

Quote from: a1ex on December 20, 2013, 05:43:14 PM
(yes, I'm still looking for test images)

The most difficult shot I can think of for mine is this one.
The light source on camera right had a green tinge.

a1ex

Indeed, WB on the background result in slight green tint.

My spotmeter chose this:



Can you also upload a reference JPG?

Audionut



WB off background left (matches known flash characteristics) with selective editing.

edit:  And with a preferred warmer tone (+1.3K).


engardeknave

http://we.tl/jaO31Dmjrh

Some samples I recall being particularly traumatizing to white balance.