Change the intensity of an image by comparing intensity of another image - OpenTK

孤街浪徒 提交于 2019-12-23 18:09:40

问题


I have two images. I have to found the points of first image which have intensity greater than 0.8. At the same time I have to found the intensity of second image on same points and need to adjust the light on second image on same points with a threshold/slider value(ranges from 0 to 1). I have done like below. Getting black or dark area on points have intensity greater than 0.8.  I'm trying with z value of HSV.
But instead of this black area I should be able to adjust the light on image2. How can I achieve this? 

public void CreateShaders()
{
    /***********Vert Shader********************/
    vertShader = GL.CreateShader(ShaderType.VertexShader);
    GL.ShaderSource(vertShader, @"
        attribute vec3 a_position;
        varying vec2 vTexCoordIn; 
        void main() {
            vTexCoordIn=( a_position.xy+1)/2 ;
            gl_Position = vec4(a_position,1);
        }");
    GL.CompileShader(vertShader);

    /***********Frag Shader ****************/
    fragShader = GL.CreateShader(ShaderType.FragmentShader);
    GL.ShaderSource(fragShader, @"
        precision highp float;

        uniform sampler2D sTexture1;
        uniform sampler2D sTexture2;  
        varying vec2 vTexCoordIn;
        const float Epsilon = 1e-10;
        uniform float sSelectedIntensity1;//slider value 0 to 1
        void main ()
        {
            vec2 vTexCoord=vec2(vTexCoordIn.x,vTexCoordIn.y);    
            vec4  color1 = texture2D (sTexture1, vTexCoord);
            vec4  color2= texture2D (sTexture2, vTexCoord);
            vec3  col1_hsv = RGBtoHSV(color1.rgb);
            float col1_intensity =col1_hsv.z;
            float ConstVal=0.8;

            if(col1_intensity>ConstVal)
            { 
                vec3 col_hsv = RGBtoHSV(color2.rgb);
                col_hsv.z *= sSelectedIntensity1;//slider value 0 to 1 
                vec3 col_rgb = HSVtoRGB(col_hsv.rgb);
                gl_FragColor = vec4(col_rgb.rgb, color2.a);
            }
            else
            {  
                gl_FragColor = color2;
            }
        }");
    GL.CompileShader(fragShader);
}

Practically, if image1 and image2 are frames coming from two adjusent cameras cam1 and cam2 respectively. And if I put a flash light infront of cam1, i should be able to dim/remove this light effect on frames of camera 2.


回答1:


If you want to modify the lightness of the color, the you've to multiply with a value in range [0, 2] rather than a value in range [0, 1]. If you multiply with a value in range [0, 1] the result will at maximum be as bright as the source:

col_hsv.z *= sSelectedIntensity1 * 2.0;

If you want to enlighten the image dependent dependent on the "bright" parts of the other image then you've to add a term to the lightness, which depends on the lightness (of the other image) and the slider. e.g.:

col_hsl2.z += (col1_intensity-constVal)*sSelectedIntensity1/(1.0-constVal);

If you want to change the lightness the I recommend to use the HSL (hue, saturation, lightness) color range rather than the HSV (hue, saturation, value.
In compare to HSV, at HSL the 3rd value represents the lightness of the color:

const float Epsilon = 1e-10;

vec3 RGBtoHSL(in vec3 RGB)
{
    vec4  P   = (RGB.g < RGB.b) ? vec4(RGB.bg, -1.0, 2.0/3.0) : vec4(RGB.gb, 0.0, -1.0/3.0);
    vec4  Q   = (RGB.r < P.x) ? vec4(P.xyw, RGB.r) : vec4(RGB.r, P.yzx);
    float C   = Q.x - min(Q.w, Q.y);
    float H   = abs((Q.w - Q.y) / (6.0 * C + Epsilon) + Q.z);
    vec3  HCV = vec3(H, C, Q.x);
    float L   = HCV.z - HCV.y * 0.5;
    float S   = HCV.y / (1.0 - abs(L * 2.0 - 1.0) + Epsilon);
    return vec3(HCV.x, S, L);
}

vec3 HSLtoRGB(in vec3 HSL)
{
    float H   = HSL.x;
    float R   = abs(H * 6.0 - 3.0) - 1.0;
    float G   = 2.0 - abs(H * 6.0 - 2.0);
    float B   = 2.0 - abs(H * 6.0 - 4.0);
    vec3  RGB = clamp( vec3(R,G,B), 0.0, 1.0 );
    float C   = (1.0 - abs(2.0 * HSL.z - 1.0)) * HSL.y;
    return (RGB - 0.5) * C + HSL.z;
}

Use the functions like this:

void main ()
{
    vec2  vTexCoord = vec2(vTexCoordIn.x,vTexCoordIn.y);
    vec4  color1    = texture2D (sTexture1, vTexCoord);
    vec4  color2    = texture2D (sTexture2, vTexCoord);

    vec3  col1_hsl1 = RGBtoHSL(color1.rgb);
    float col1_intensity = col1_hsl1.z;

    float constVal = 0.8;
    if (col1_intensity > constVal)
    {
        vec3 col_hsl2 = RGBtoHSL(color2.rgb);
        col_hsl2.z   += (col1_intensity-constVal)*sSelectedIntensity1/(1.0-constVal);
        vec3 col_rgb  = HSLtoRGB(col_hsl2.rgb);
        color2        = vec4(col_rgb.rgb, color2.a);
    }

    gl_FragColor = color2;
}

An other option would be to modify the lightness of the entire image dependent on the lightness of the other image. In this case there is no need of the factor 0.8:

void main ()
{
    vec2  vTexCoord = vec2(vTexCoordIn.x,vTexCoordIn.y);
    vec4  color1    = texture2D (sTexture1, vTexCoord);
    vec4  color2    = texture2D (sTexture2, vTexCoord);

    vec3  col1_hsl1 = RGBtoHSL(color1.rgb);
    float col1_intensity = col1_hsl1.z;

    vec3 col_hsl2  = RGBtoHSL(color2.rgb);
    col_hsl2.z    += col1_intensity * sSelectedIntensity1;
    vec3 col_rgb2  = HSLtoRGB(col_hsl2.rgb);
    color2         = vec4(col_rgb2.rgb, color2.a);

    gl_FragColor = color2;
}

Another nice effect can be achieved by enlightening the areas where the intensity is above 0.8 and darken the areas where the light is below 0.8:

void main ()
{
    vec2  vTexCoord = vec2(vTexCoordIn.x,vTexCoordIn.y);
    vec4  color1    = texture2D (sTexture1, vTexCoord);
    vec4  color2    = texture2D (sTexture2, vTexCoord);

    vec3  col1_hsl1 = RGBtoHSL(color1.rgb);
    float col1_intensity = col1_hsl1.z;

    vec3 col_hsl2  = RGBtoHSL(color2.rgb);

    float constVal = 0.8;
    if (col1_intensity > constVal)
        col_hsl2.z += (col1_intensity-constVal)*sSelectedIntensity1/(1.0-constVal);
    else
        col_hsl2.z += (col1_intensity-constVal)*sSelectedIntensity1/constVal;

    vec3 col_rgb2  = HSLtoRGB(col_hsl2.rgb);
    color2         = vec4(col_rgb2.rgb, color2.a);

    gl_FragColor = color2;
}

There are a lot of possibilities, you've to choose the best function for your needs.


If you want to "dim" the image, then you've to manipulate the lightness of each pixel, dependent on an "inverse" factor or the lightness of the other image (* (1.0 - col1_hsl1.z)) if the slider is below 0.5:

void main ()
{
    vec2  vTexCoord = vec2(vTexCoordIn.x,vTexCoordIn.y);
    vec4  color1    = texture2D (sTexture1, vTexCoord);
    vec4  color2    = texture2D (sTexture2, vTexCoord);

    vec3  col1_hsl1 = RGBtoHSL(color1.rgb);
    float col1_intensity = col1_hsl1.z;

    vec3 col_hsl2  = RGBtoHSL(color2.rgb);

    if (sSelectedIntensity1 < 0.5)
        col_hsl2.z *= (1.0 - col1_intensity * (1.0-2.0*sSelectedIntensity1));
    else
        col_hsl2.z += col1_intensity * (2.0*sSelectedIntensity1-1.0);

    vec3 col_rgb2  = HSLtoRGB(col_hsl2.rgb);
    color2         = vec4(col_rgb2.rgb, color2.a);

    gl_FragColor = color2;
}


来源:https://stackoverflow.com/questions/57622908/change-the-intensity-of-an-image-by-comparing-intensity-of-another-image-opent

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!