CI过滤器创建Black&白色图像?

时间:2010-06-27 03:52:44

标签: objective-c cocoa

我有一个CIImage我需要在我的Cocoa / Objective C程序中从颜色转换为Black和White。 Peter H.之前向我指出了这个链接http://www.codingadventures.com/2008/06/threshold-filter-in-glsl/作为一种潜在的解决方案......但是我在那里编译内核例程时遇到了麻烦(如果感兴趣,请参见单独的线程)。

所以我想知道其他一个内置的CIFilter是否会完成我想要做的事情。我不想要灰度图像...我希望结果图像中的每个像素都是黑色或白色 - 我只需要能够告诉过滤器如何确定哪些像素应该变成黑色哪个像素应该变成白色。 Photoshop中的“阈值”滤镜就是这样 - 它让我指定“阈值”然后它使用此值来决定哪些像素变为白色而哪些像素变为黑色。这就是我试图通过我的Xcode项目中的代码“复制”。

任何想法,如果其中一个内置的过滤器可用于此?感谢。

3 个答案:

答案 0 :(得分:10)

您可以使用CIColorMap filter。 给它一个20(w)乘1(h)的jpg,其中左半部分是白色,右半部分是黑色(或者相反),并将其用作颜色图渐变。这似乎很好地打破了颜色。我最初尝试使用1个白色像素和一个黑色的2x1图像,但看起来它有点内插。我上升到20x1并且工作正常。

提示:我使用Core Image Funhouse(不是Quartz Composer)进行实验。

答案 1 :(得分:6)

花了一些时间来弄清楚CIColorMap的代码所以我想发布这个。约书亚有上面的答案。这只是实施的一个例子......

CIImage *beginImage = [CIImage imageWithContentsOfURL:[NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"wedding" ofType:@"jpg"]]];
CIImage *inputGradientImage = [CIImage imageWithContentsOfURL:[NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"grad" ofType:@"png"]]];
CIContext *context = [CIContext contextWithOptions:nil];
CIFilter *filter = [CIFilter filterWithName:@"CIColorMap" keysAndValues:kCIInputImageKey, beginImage, @"inputGradientImage",inputGradientImage, nil];
CIImage *outputImage = [filter outputImage];
CGImageRef cgimg = [context createCGImage:outputImage fromRect:[outputImage extent]];
UIImage *newImage = [UIImage imageWithCGImage:cgimg];
self.imageView.image = newImage;
CGImageRelease(cgimg);

答案 2 :(得分:5)

互联网上的许多解决方案都会创建灰度值。不需要过滤器。如果你需要使用代码,比如

CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceGray();
CGImageRef greyImage = CGImageCreateCopyWithColorSpace(backingImage, colorSpace);
CGColorSpaceRelease(colorSpace);

正确的阈值过滤器如下: inputThreshold可以是0.0f到0.5f的浮点值

https://gist.github.com/xhruso00/a3f8a9c8ae7e33b8b23d

详细食谱可在https://developer.apple.com/library/ios/documentation/graphicsimaging/Conceptual/CoreImaging/ci_custom_filters/ci_custom_filters.html#//apple_ref/doc/uid/TP30001185-CH6-CJBEDHHH

找到
#import "BlackAndWhiteThresholdFilter.h"



@interface  BlackAndWhiteThresholdFilter()
{
    CIKernel *_kernel;
}

@end

@implementation BlackAndWhiteThresholdFilter {
  NSNumber *inputThreshold;
  CIImage *inputImage;
}


//more https://developer.apple.com/library/ios/documentation/graphicsimaging/Conceptual/CoreImaging/ci_image_units/ci_image_units.html#//apple_ref/doc/uid/TP30001185-CH7-SW8
+ (void)registerFilter
{
  NSDictionary *attributes = @{
                               kCIAttributeFilterCategories: @[
                                   kCICategoryVideo,
                                   kCICategoryStillImage,
                                   kCICategoryCompositeOperation,
                                   kCICategoryInterlaced,
                                   kCICategoryNonSquarePixels
                                   ],
                               kCIAttributeFilterDisplayName: @"Black & White Threshold",

                               };

  [CIFilter registerFilterName:@"BlackAndWhiteThreshold"
                   constructor:(id <CIFilterConstructor>)self
               classAttributes:attributes];
}


+ (CIFilter *)filterWithName:(NSString *)aName
{
  CIFilter  *filter;
  filter = [[self alloc] init];

  return filter;
}

- (instancetype)init {
  self = [super init];
    if (self) {
    NSString *kernelText = @"kernel vec4 thresholdKernel(sampler image, float inputThreshold)\n"
    "{\n"
    "  float pass = 1.0;\n"
    "  float fail = 0.0;\n"
    "  const vec4   vec_Y = vec4( 0.299, 0.587, 0.114, 0.0 );\n"
    "  vec4     src = unpremultiply( sample(image, samplerCoord(image)) );\n"
    "  float        Y = dot( src, vec_Y );\n"
    "  src.rgb = vec3( compare( Y - inputThreshold, fail, pass));\n"
    "  return premultiply(src);\n"
    "}";

        _kernel = [[CIKernel kernelsWithString:kernelText] objectAtIndex:0];
    }

    return self;
}

- (NSArray *)inputKeys {
  return @[@"inputImage",@"inputThreshold"];
}

- (NSArray *)outputKeys {
    return @[@"outputImage"];
}


- (NSDictionary *)customAttributes
{
  NSDictionary *thresholDictionary = @{
                                       kCIAttributeType: kCIAttributeTypeScalar,
                                       kCIAttributeMin: @0.0f,
                                       kCIAttributeMax: @1.0f,
                                       kCIAttributeIdentity : @0.00,
                                       kCIAttributeDefault: @0.5f,
                                       };

  return @{
           @"inputThreshold": thresholDictionary,
           // This is needed because the filter is registered under a different name than the class.
           kCIAttributeFilterName : @"BlackAndWhiteThreshold"
           };
}

- (CIImage *)outputImage {
  if (inputImage == nil) {
    return nil;
  }

  CISampler *sampler;

  sampler = [CISampler samplerWithImage:inputImage];

    NSArray * outputExtent = [NSArray arrayWithObjects:
                            [NSNumber numberWithInt:[inputImage extent].origin.x],
                            [NSNumber numberWithInt:[inputImage extent].origin.y],
                            [NSNumber numberWithFloat:[inputImage extent].size.width],
                            [NSNumber numberWithFloat:[inputImage extent].size.height],nil];


  CIImage *outputImage =  [self apply: _kernel,
          sampler,
          inputThreshold,
          kCIApplyOptionExtent, outputExtent,
          kCIApplyOptionDefinition, [sampler definition],
          nil];


    return outputImage;
}

@end

更新了黑白(左)和灰度(右)

之间的视觉差异

enter image description here