试图调整特定频道的色调(或者更具体地说,在这种情况下是红色的特定颜色范围).看着色调过滤器,我想也许我可以通过评论绿色和蓝色修饰符,影响到只有红色通道的变化:
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 GPUImageSkinToneFilter

Nsstring *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-glsl
vec3 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-glsl
vec3 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);
}

// Main
void 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通道添加色调/颜色调整(调整红色以更加粉红色或橙色)的更多相关文章

  1. ios – 如何使用GPUImage实现GPUImageMaskFilter

    我需要使用掩码从完整图像剪切并创建被屏蔽的图像.=我试过以下:但是,我生成的输出图像是:请大家携手共进干杯.另外,谢谢BradLarson.解决方法掩码是第二个目标,如在滤镜着色器代码中可以看到的.然后,您需要在黑色背景上“反转”您的面具:白色心脏,因为过滤器使用RGB像素值的“重量”来设置目标图像上的alpha值.所以你的代码应该是和你的面具像预期结果.

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

    试图调整特定频道的色调.看着色调过滤器,我想也许我可以通过评论绿色和蓝色修饰符,影响到只有红色通道的变化:但是,这张照片就是灰色/蓝色,被冲洗掉或是紫色的绿色.我在正确的轨道上吗?

  3. ios – 使用GPUImage和GPUImageHoughTransformLineDetector检测突出显示的文本边界框

    我正在使用GPUImageHoughTransformlineDetector来尝试检测图像中突出显示的文本:我使用以下代码来尝试检测边界蓝框线:无论edgeThreshold还是1023行,每次运行此命令时,结果输出如下所示:我不清楚为什么改变门槛没有做任何事情,但我确信我误解了一些事情.任何人对如何做到这一点有任何想法?解决方法我刚刚在框架中对Hough变换线检测器进行了一些改进,这将对此有所

  4. ios – 使用OpenGL的神秘app崩溃

    我正在使用GPUIImage库来开发iOS相机应用程序.有时,当应用程序在2-3分钟后暂停时,Xcode会在应用程序上发生崩溃,指向方法中的行:可能是这次崩溃的原因是什么?我有一个非常长的摄像头设置,代码本身在GPUImageContext类中.我在这里做错了什么?

  5. swift – 使用Cocoapods与应用程序扩展

    我试图在Xcode6Beta-6中使用cocoapods库构建照片应用程序扩展。Xcode为照片扩展创建的桥接头无法从Cocopapod查看任何内容。唯一的例外是,对于像SVProgressHUD这样的简单pod,以下丑陋的可怕的黑客工程:#import“../Pods/SVProgressHUD/SVProgressHUD/SVProgressHUD.h”。此外,thisSOquestion中描述的问题可能有关,但我反问这个问题,以防我的问题是特定于应用程式额外资讯。正确的方法是更新您的podfile只

  6. 如何在android中使用没有缩放的GPUImage

    如何在不调整原始图像大小的情况下使用GPUImage库,我需要为整个GPUImageView申请像Pixelate或Blur这样的过滤器.我想用GPUImage,但我不知道怎么做.解决方法您更改GPUImage库GPUImageRendering类下面的代码是

  7. android – RGB值到HSL转换器

    Googlemapsapiv3允许将“样式”应用于地图,包括设置各种功能的颜色.但是,它使用的颜色格式是HSL:>hue>亮度>饱和度我设法在线找到RGB到HSL转换器,但我不确定如何以谷歌地图将接受的方式指定转换后的值.例如,转换器给出的典型HSL值为:209°72%49%HSL值如何映射到我从googlemapsapi指定的参数?我仍然不确定如何进行转换.我需要,给定RGB值,快速将其转换为谷歌地图所期望的颜色将是相同的……

  8. 将地图标记设置为自定义颜色Android

    我正在制作一个应用程序,可以在某些点添加地图.我希望我的针脚的颜色与我们的应用程序的主题颜色相匹配.对不起,我真的是个菜鸟.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.color)));不起作用.它不允许我在这里插入自定义颜色.我怎样才能做到这一点?谢谢:)解决方法defaultMarker()方法允许设置自

  9. 使用GPUImage Android进行视频处理

    我想使用GPUImageAndroid实时处理视频.我看到使用不同的过滤器创建图片的示例,但我没有找到任何使用过滤器录制视频的示例.这是可能的GPUImageAndroid?

  10. Centos7.2安装CDH5.7.2core steps

    软件准备jdk-8u121-linux-x64.rpmcloudera-manager-centos7-cm5.7.2_x86_64.tar.gzCDH-5.7.2-1.cdh5.7.2.p0.18-el7.parcelCDH-5.7.2-1.cdh5.7.2.p0.18-el7.parcel.sha更改为sha后缀manifest.jsonMysqL57-community-release-el

随机推荐

  1. iOS实现拖拽View跟随手指浮动效果

    这篇文章主要为大家详细介绍了iOS实现拖拽View跟随手指浮动,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  2. iOS – genstrings:无法连接到输出目录en.lproj

    使用我桌面上的项目文件夹,我启动终端输入:cd然后将我的项目文件夹拖到终端,它给了我路径.然后我将这行代码粘贴到终端中找.-name*.m|xargsgenstrings-oen.lproj我在终端中收到此错误消息:genstrings:无法连接到输出目录en.lproj它多次打印这行,然后说我的项目是一个目录的路径?没有.strings文件.对我做错了什么的想法?

  3. iOS 7 UIButtonBarItem图像没有色调

    如何确保按钮图标采用全局色调?解决方法只是想将其转换为根注释,以便为“回答”复选标记提供更好的上下文,并提供更好的格式.我能想出这个!

  4. ios – 在自定义相机层的AVFoundation中自动对焦和自动曝光

    为AVFoundation定制图层相机创建精确的自动对焦和曝光的最佳方法是什么?

  5. ios – Xcode找不到Alamofire,错误:没有这样的模块’Alamofire’

    我正在尝试按照github(https://github.com/Alamofire/Alamofire#cocoapods)指令将Alamofire包含在我的Swift项目中.我创建了一个新项目,导航到项目目录并运行此命令sudogeminstallcocoapods.然后我面临以下错误:搜索后我设法通过运行此命令安装cocoapodssudogeminstall-n/usr/local/bin

  6. ios – 在没有iPhone6s或更新的情况下测试ARKit

    我在决定下载Xcode9之前.我想玩新的框架–ARKit.我知道要用ARKit运行app我需要一个带有A9芯片或更新版本的设备.不幸的是我有一个较旧的.我的问题是已经下载了新Xcode的人.在我的情况下有可能运行ARKit应用程序吗?那个或其他任何模拟器?任何想法或我将不得不购买新设备?解决方法任何iOS11设备都可以使用ARKit,但是具有高质量AR体验的全球跟踪功能需要使用A9或更高版本处理器的设备.使用iOS11测试版更新您的设备是必要的.

  7. 将iOS应用移植到Android

    我们制作了一个具有2000个目标c类的退出大型iOS应用程序.我想知道有一个最佳实践指南将其移植到Android?此外,由于我们的应用程序大量使用UINavigation和UIView控制器,我想知道在Android上有类似的模型和实现.谢谢到目前为止,guenter解决方法老实说,我认为你正在计划的只是制作难以维护的糟糕代码.我意识到这听起来像很多工作,但从长远来看它会更容易,我只是将应用程序的概念“移植”到android并从头开始编写.

  8. ios – 在Swift中覆盖Objective C类方法

    我是Swift的初学者,我正在尝试在Swift项目中使用JSONModel.我想从JSONModel覆盖方法keyMapper,但我没有找到如何覆盖模型类中的Objective-C类方法.该方法的签名是:我怎样才能做到这一点?解决方法您可以像覆盖实例方法一样执行此操作,但使用class关键字除外:

  9. ios – 在WKWebView中获取链接URL

    我想在WKWebView中获取tapped链接的url.链接采用自定义格式,可触发应用中的某些操作.例如HTTP://我的网站/帮助#深层链接对讲.我这样使用KVO:这在第一次点击链接时效果很好.但是,如果我连续两次点击相同的链接,它将不报告链接点击.是否有解决方法来解决这个问题,以便我可以检测每个点击并获取链接?任何关于这个的指针都会很棒!解决方法像这样更改addobserver在observeValue函数中,您可以获得两个值

  10. ios – 在Swift的UIView中找到UILabel

    我正在尝试在我的UIViewControllers的超级视图中找到我的UILabels.这是我的代码:这是在Objective-C中推荐的方式,但是在Swift中我只得到UIViews和CALayer.我肯定在提供给这个方法的视图中有UILabel.我错过了什么?我的UIViewController中的调用:解决方法使用函数式编程概念可以更轻松地实现这一目标.

返回
顶部