10

I'm trying to set a custom value for the White Balance & temperature color in my camera app. I'm using camera2 API and I'm trying different ways to set this value. I found a method from a excel file to get the right RGB Temperature matrix [Red,Green,Blue] from the White Balance Value between 100 and 100.000.

I attached this method to a Seekbar and its working fine, my problem appear when I try to focus something white, then it becomes pink. Any kind of light looks like a pink torch in the screen.

enter image description here

I'm setting the values in this way:

mPreviewRequestBuilder.set(CaptureRequest.COLOR_CORRECTION_MODE, CaptureRequest.COLOR_CORRECTION_MODE_TRANSFORM_MATRIX);

RggbChannelVector rggb = getTemperatureVector(seekBackSelectedTemperature);

mPreviewRequestBuilder.set(CaptureRequest.COLOR_CORRECTION_GAINS, myRggbChannelVector);

In other way, my method to get the matrix is this one:

 public static RggbChannelVector getTemperatureVector (int WhiteBalanceValue){


    float InsertTemperature = WhiteBalanceValue;
    float temperature = InsertTemperature / 100;
    float red;
    float green;
    float blue;

    //Calculate red

    if (temperature <= 66)
        red = 255;
    else {
        red = temperature - 60;
        red = (float) (329.698727446 * (Math.pow((double) red, -0.1332047592)));
        if (red < 0)
            red = 0;
        if (red > 255)
            red = 255;
    }


    //Calculate green
    if (temperature <= 66) {
        green = temperature;
        green = (float) (99.4708025861 * Math.log(green) - 161.1195681661);
        if (green < 0)
            green = 0;
        if (green > 255)
            green = 255;
    } else
        green = temperature - 60;
    green = (float) (288.1221695283 * (Math.pow((double) red, -0.0755148492)));
    if (green < 0)
        green = 0;
    if (green > 255)
        green = 255;


    //calculate blue
    if (temperature >= 66)
        blue = 255;
    else if (temperature <= 19)
        blue = 0;
    else {
        blue = temperature - 10;
        blue = (float) (138.5177312231 * Math.log(blue) - 305.0447927307);
        if (blue < 0)
            blue = 0;
        if (blue > 255)
            blue = 255;
    }
    RggbChannelVector finalTemperatureValue = new RggbChannelVector(red/255,(green/255)/2,(green/255)/2,blue/255);
    return finalTemperatureValue;
}

Maybe it's because the method of my CaptureRequest is not correct, but I don't find a way to fix it.

halfer
  • 19,824
  • 17
  • 99
  • 186
Francisco Durdin Garcia
  • 12,540
  • 9
  • 53
  • 95
  • 2
    It would be nice to point the link to this algorithm: [link](http://www.tannerhelland.com/4435/convert-temperature-rgb-algorithm-code/) – Dimas Crocco May 16 '18 at 15:15

2 Answers2

22

It worked after change the template to Still_capture or Manual Template and use the next method:

 captureBuilder.set(CaptureRequest.CONTROL_AWB_MODE, CaptureRequest.CONTROL_AWB_MODE_OFF);
        // adjust color correction using seekbar's params
        captureBuilder.set(CaptureRequest.COLOR_CORRECTION_MODE, CaptureRequest.COLOR_CORRECTION_MODE_TRANSFORM_MATRIX);
        captureBuilder.set(CaptureRequest.COLOR_CORRECTION_GAINS, CameraCapabilities.colorTemperature(Integer.parseInt(awbMode)));

public static RggbChannelVector colorTemperature(int whiteBalance) {
    float temperature = whiteBalance / 100;
    float red;
    float green;
    float blue;

    //Calculate red
    if (temperature <= 66)
        red = 255;
    else {
        red = temperature - 60;
        red = (float) (329.698727446 * (Math.pow((double) red, -0.1332047592)));
        if (red < 0)
            red = 0;
        if (red > 255)
            red = 255;
    }


    //Calculate green
    if (temperature <= 66) {
        green = temperature;
        green = (float) (99.4708025861 * Math.log(green) - 161.1195681661);
        if (green < 0)
            green = 0;
        if (green > 255)
            green = 255;
    } else {
        green = temperature - 60;
        green = (float) (288.1221695283 * (Math.pow((double) green, -0.0755148492)));
        if (green < 0)
            green = 0;
        if (green > 255)
            green = 255;
    }

    //calculate blue
    if (temperature >= 66)
        blue = 255;
    else if (temperature <= 19)
        blue = 0;
    else {
        blue = temperature - 10;
        blue = (float) (138.5177312231 * Math.log(blue) - 305.0447927307);
        if (blue < 0)
            blue = 0;
        if (blue > 255)
            blue = 255;
    }

    Log.v(TAG, "red=" + red + ", green=" + green + ", blue=" + blue);
    return new RggbChannelVector((red / 255) * 2, (green / 255), (green / 255), (blue / 255) * 2);
}
Francisco Durdin Garcia
  • 12,540
  • 9
  • 53
  • 95
4

Another possible and more simpler solution; factor must be between 0 and 100:

private static RggbChannelVector computeTemperature(final int factor)
{
    return new RggbChannelVector(0.635f + (0.0208333f * factor), 1.0f, 1.0f, 3.7420394f + (-0.0287829f * factor));
}
PerracoLabs
  • 16,449
  • 15
  • 74
  • 127
  • 1
    If this could be modified to take a kelvin temperature rather than a factor it would be perfect. Or alternatively what are 0 and 100 in kelvin? – Pete May 29 '22 at 14:20
  • @Pete Then pass your desired kelvin factor, but before calling RggbChannelVector convert the factor to the 0 - 100 range. For example: MathUtils.clamp(((factor - minKelvinFactor) / (maxKelvinFactor - minKelvinFactor)) * 100, 0, 100). Search in stackoverflow how to convert between numeric ranges. – PerracoLabs Jun 03 '22 at 07:52
  • @PerracoLabs - that does not make sense. The [0, 100] in this formula is already based on some kelvin values. If we take an arbitrary kelvin range and map it to [0-100], I dont think it will result in accurate colors. – JGS Dec 07 '22 at 02:46
  • @PerracoLabs Can you explain the logic behind this formula? – Uriel Frankel May 23 '23 at 12:25