ios – GPUImage为每个RGB通道添加色调颜色调整(调整红色以更加粉红色或橙色)

ios – GPUImage为每个RGB通道添加色调颜色调整(调整红色以更加粉红色或橙色),第1张

概述试图调整特定频道的色调(或者更具体地说,在这种情况下是红色的特定颜色范围).看着色调过滤器,我想也许我可以通过评论绿色和蓝色修饰符,影响到只有红色通道的变化: precision highp float; varying highp vec2 textureCoordinate; uniform sampler2D inputImageTexture; uniform mediump fl 试图调整特定频道的色调(或者更具体地说,在这种情况下是红色的特定颜色范围).看着色调过滤器,我想也许我可以通过评论绿色和蓝色修饰符,影响到只有红色通道的变化:
precision highp float; varying highp vec2 textureCoordinate; uniform sampler2D inputimageTexture; uniform mediump float hueAdjust; const highp  vec4  kRGBToYPrime = vec4 (0.299,0.587,0.114,0.0); const highp  vec4  kRGBToI     = vec4 (0.595716,-0.274453,-0.321263,0.0); const highp  vec4  kRGBToQ     = vec4 (0.211456,-0.522591,0.31135,0.0); const highp  vec4  kYIQToR   = vec4 (1.0,0.9563,0.6210,0.0); const highp  vec4  kYIQToG   = vec4 (1.0,-0.2721,-0.6474,0.0); const highp  vec4  kYIQToB   = vec4 (1.0,-1.1070,1.7046,0.0); voID main () {     // Sample the input pixel     highp vec4 color   = texture2D(inputimageTexture,textureCoordinate);     // Convert to YIQ     highp float   YPrime  = dot (color,kRGBToYPrime);     highp float   I      = dot (color,kRGBToI);     highp float   Q      = dot (color,kRGBToQ);     // Calculate the hue and chroma     highp float   hue     = atan (Q,I);     highp float   chroma  = sqrt (I * I + Q * Q);     // Make the user's adjustments     hue += (-hueAdjust); //why negative rotation?     // Convert back to YIQ     Q = chroma * sin (hue);     I = chroma * cos (hue);     // Convert back to RGB     highp vec4    yIQ   = vec4 (YPrime,I,Q,0.0);     color.r = dot (yIQ,kYIQToR);//  -->    color.g = dot (yIQ,kYIQToG); //  -->   color.b = dot (yIQ,kYIQToB);     // Save the result     gl_Fragcolor = color; });

但是,这张照片就是灰色/蓝色,被冲洗掉或是紫色的绿色.我在正确的轨道上吗?如果没有,如何修改此过滤器以影响个别渠道,同时保留其他渠道?

一些例子:

原来,我试图实现的效果:

(第二个图像几乎没有什么不同,然而红色通道的色调已经变得更加粉红色了,我需要能够在粉红色的橙色之间进行调整).

但是,这里是我得到的B和G评论:

(左侧:<0º,右侧:>0º) 它看起来像我不喜欢以红色的方式影响红色的色调;可能我正在接近这个错误,或者如果我在正确的轨道上,这段代码没有正确调整红色通道色调? (我也尝试使用GPUImagecolorMatrixFilter来实现这个效果,但是我并没有得到很多). 编辑:这是我现在使用@ VB_overflow的代码GPUImage包装器着色器的迭代,其功能上影响输入图像的方式类似于我的目标:

#import "GPUImageSkinToneFilter.h"@implementation GPUImageSkinToneFilterNsstring *const kGPUImageSkinToneFragmentShaderString = SHADER_STRING( varying highp vec2 textureCoordinate; uniform sampler2D inputimageTexture; // [-1;1] <=> [pink;orange] uniform highp float skinToneAdjust; // will make reds more pink // Other parameters uniform mediump float skinHue; uniform mediump float skinHueThreshold; uniform mediump float maxHueShift; uniform mediump float maxSaturationShift; // RGB <-> HSV conversion,thanks to http://lolengine.net/blog/2013/07/27/rgb-to-hsv-in-glsl highp vec3 rgb2hsv(highp vec3 c){    highp vec4 K = vec4(0.0,-1.0 / 3.0,2.0 / 3.0,-1.0);    highp vec4 p = mix(vec4(c.bg,K.wz),vec4(c.gb,K.xy),step(c.b,c.g));    highp vec4 q = mix(vec4(p.xyw,c.r),vec4(c.r,p.yzx),step(p.x,c.r));    highp float d = q.x - min(q.w,q.y);    highp float e = 1.0e-10;    return vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)),d / (q.x + e),q.x);} // HSV <-> RGB conversion,thanks to http://lolengine.net/blog/2013/07/27/rgb-to-hsv-in-glsl highp vec3 hsv2rgb(highp vec3 c){    highp vec4 K = vec4(1.0,1.0 / 3.0,3.0);    highp vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);    return c.z * mix(K.xxx,clamp(p - K.xxx,0.0,1.0),c.y);} // Main voID main (){    // Sample the input pixel    highp vec4 colorRGB = texture2D(inputimageTexture,textureCoordinate);    // Convert color to HSV,extract hue    highp vec3 colorHSV = rgb2hsv(colorRGB.rgb);    highp float hue = colorHSV.x;    // check how far from skin hue    highp float dist = hue - skinHue;    if (dist > 0.5)        dist -= 1.0;    if (dist < -0.5)        dist += 1.0;    dist = abs(dist)/0.5; // normalized to [0,1]    // Apply Gaussian like filter    highp float weight = exp(-dist*dist*skinHueThreshold);    weight = clamp(weight,1.0);    // We want more orange,so increase saturation    if (skinToneAdjust > 0.0)        colorHSV.y += skinToneAdjust * weight * maxSaturationShift;    // we want more pinks,so decrease hue    else        colorHSV.x += skinToneAdjust * weight * maxHueShift;    // final color    highp vec3 finalcolorRGB = hsv2rgb(colorHSV.rgb);    // display    gl_Fragcolor = vec4(finalcolorRGB,1.0);});#pragma mark -#pragma mark Initialization and teardown@synthesize skinToneAdjust;@synthesize skinHue;@synthesize skinHueThreshold;@synthesize maxHueShift;@synthesize maxSaturationShift;- (ID)init{    if(! (self = [super initWithFragmentShaderFromString:kGPUImageSkinToneFragmentShaderString]) )    {        return nil;    }    skinToneAdjustUniform = [filterProgram uniformIndex:@"skinToneAdjust"];    skinHueUniform = [filterProgram uniformIndex:@"skinHue"];    skinHueThresholdUniform = [filterProgram uniformIndex:@"skinHueThreshold"];    maxHueShiftUniform = [filterProgram uniformIndex:@"maxHueShift"];    maxSaturationShiftUniform = [filterProgram uniformIndex:@"maxSaturationShift"];    self.skinHue = 0.05;    self.skinHueThreshold = 50.0;    self.maxHueShift = 0.14;    self.maxSaturationShift = 0.25;    return self;}#pragma mark -#pragma mark Accessors- (voID)setSkinToneAdjust:(CGfloat)newValue{    skinToneAdjust = newValue;    [self setfloat:newValue forUniform:skinToneAdjustUniform program:filterProgram];}- (voID)setSkinHue:(CGfloat)newValue{    skinHue = newValue;    [self setfloat:newValue forUniform:skinHueUniform program:filterProgram];}- (voID)setSkinHueThreshold:(CGfloat)newValue{    skinHueThreshold = newValue;    [self setfloat:newValue forUniform:skinHueThresholdUniform program:filterProgram];}- (voID)setMaxHueShift:(CGfloat)newValue{    maxHueShift = newValue;    [self setfloat:newValue forUniform:maxHueShiftUniform program:filterProgram];}- (voID)setMaxSaturationShift:(CGfloat)newValue{    maxSaturationShift = newValue;    [self setfloat:newValue forUniform:maxSaturationShiftUniform program:filterProgram];}@end
解决方法 我在 ShaderToy上做了一个例子.使用最新的Chrome来查看它,就我而言,它在firefox或IE上不起作用,因为它使用视频作为输入.

经过一些实验,在我看来,红色的色调要更加“粉红色”,你需要减少色调,但要获得更多的“橙色”,你需要增加饱和度.

在代码中,我转换为HSV而不是YIQ,因为它更快,使调整饱和成为可能,仍然允许调整色调. HSV组件也在[0-1]间隔,所以不需要处理弧度.

所以这里是这样做的:

>您选择参考色调或颜色(在您的情况下为红色色调)
着色器计算从当前像素色调到参考色调的“距离”
>根据这个距离,如果你想粉红色,减少色调,如果你想要橙色增加饱和度
>重要的是要注意,色调的表现与饱和度和值的不同:它应该被视为一个角度(更多信息here).

参考色调应该被硬编码,由用户(通过颜色选择图像)选择,或者通过分析图像内容来找到.

在计算距离方面有许多不同的可能方法,在这个例子中,我选择使用色相之间的角距离.

您也需要在计算距离之后应用某种过滤,以“选择”最近的颜色,如gaussian like function.

这里是代码,没有ShaderToy的东西:

precision highp float;// [-1;1] <=> [pink;orange]const float EFFECT_AMOUNT = -0.25; // will make reds more pink// Other parameters const float SKIN_HUE = 0.05;const float SKIN_HUE_TolERANCE = 50.0;    const float MAX_HUE_SHIFT = 0.04;const float MAX_SATURATION_SHIFT = 0.25;// RGB <-> HSV conversion,thanks to http://lolengine.net/blog/2013/07/27/rgb-to-hsv-in-glslvec3 rgb2hsv(vec3 c){    vec4 K = vec4(0.0,-1.0);    vec4 p = mix(vec4(c.bg,c.g));    vec4 q = mix(vec4(p.xyw,c.r));    float d = q.x - min(q.w,q.y);    float e = 1.0e-10;    return vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)),q.x);}// HSV <-> RGB conversion,thanks to http://lolengine.net/blog/2013/07/27/rgb-to-hsv-in-glslvec3 hsv2rgb(vec3 c){    vec4 K = vec4(1.0,3.0);    vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);    return c.z * mix(K.xxx,c.y);}// MainvoID main (){       // Sample the input pixel    vec4 colorRGB = texture2D(inputimageTexture,textureCoordinate);    // get effect amount to apply    float skin_tone_shift = EFFECT_AMOUNT;    // Convert color to HSV,extract hue    vec3 colorHSV = rgb2hsv(colorRGB.rgb);      float hue = colorHSV.x;    // check how far from skin hue    float dist = hue - SKIN_HUE;            if (dist > 0.5)        dist -= 1.0;    if (dist < -0.5)        dist += 1.0;    dist = abs(dist)/0.5; // normalized to [0,1]    // Apply Gaussian like filter    float weight = exp(-dist*dist*SKIN_HUE_TolERANCE);      weight = clamp(weight,so increase saturation    if (skin_tone_shift > 0.0)        colorHSV.y += skin_tone_shift * weight * MAX_SATURATION_SHIFT;    // we want more pinks,so decrease hue    else        colorHSV.x += skin_tone_shift * weight * MAX_HUE_SHIFT;    // final color    vec3 finalcolorRGB = hsv2rgb(colorHSV.rgb);         // display     gl_Fragcolor = vec4(finalcolorRGB,1.0);}

更多橙色:

更多粉色:

– 编辑 –

在我看来,您没有在ObjectiveC代码中设置统一值.如果你忘记了这个着色器,所有这些都将为零.

代码应如下所示:

- (ID)init{    if(! (self = [super initWithFragmentShaderFromString:kGPUImageSkinToneFragmentShaderString]) )    {        return nil;    }    skinToneAdjustUniform = [filterProgram uniformIndex:@"skinToneAdjust"];    [self setfloat:0.5 forUniform:skinToneAdjustUniform program:filterProgram]; // here 0.5 so should increase saturation    skinHueUniform = [filterProgram uniformIndex:@"skinHue"];    self.skinHue = 0.05;    [self setfloat:self.skinHue forUniform:skinHueUniform program:filterProgram];    skinHuetoleranceUniform = [filterProgram uniformIndex:@"skinHuetolerance"];    self.skinHuetolerance = 50.0;    [self setfloat:self.skinHuetolerance forUniform:skinHuetoleranceUniform program:filterProgram];    maxHueShiftUniform = [filterProgram uniformIndex:@"maxHueShift"];    self.maxHueShift = 0.04;    [self setfloat:self.maxHueShift forUniform:maxHueShiftUniform program:filterProgram];    maxSaturationShiftUniform = [filterProgram uniformIndex:@"maxSaturationShift"];        self.maxSaturationShift = 0.25;            [self setfloat:self.maxSaturationShift forUniform:maxSaturationShiftUniform program:filterProgram];    return self;}@end
总结

以上是内存溢出为你收集整理的ios – GPUImage为每个RGB通道添加色调/颜色调整(调整红色以更加粉红色或橙色)全部内容,希望文章能够帮你解决ios – GPUImage为每个RGB通道添加色调/颜色调整(调整红色以更加粉红色或橙色)所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/1095807.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-28
下一篇 2022-05-28

发表评论

登录后才能评论

评论列表(0条)

保存