2010-06-27 9 views
9

Ich habe eine CI-Grafik, die ich in meinem Cocoa/Objective C-Programm von Farbe zu Schwarz und Weiß konvertieren muss. Peter H. hat mich zuvor auf diesen Link http://www.codingadventures.com/2008/06/threshold-filter-in-glsl/ als mögliche Lösung hingewiesen ... aber ich habe Probleme beim Kompilieren der Kernel-Routine (siehe separaten Thread, falls Interesse besteht).CI Filter zum Erstellen eines Schwarzweißbilds?

Ich frage mich also, ob einer der anderen eingebauten CIFilter erreichen wird, was ich versuche zu tun. Ich möchte kein Graustufenbild ... Ich möchte, dass jedes Pixel im Ergebnisbild entweder Schwarz oder Weiß ist - ich muss dem Filter nur sagen können, wie er bestimmt, welche Pixel schwarz und welche weiß werden sollen . Der "Threshold" -Filter in Photoshop macht genau das - ich kann den "Schwellenwert" angeben und anhand dieses Werts entscheiden, welche Pixel weiß und welche schwarz werden. Dies versuche ich über Code in meinem Xcode-Projekt zu "replizieren".

Irgendwelche Ideen, wenn einer der anderen eingebauten Filter dafür verwendet werden kann? Vielen Dank.

+0

Wie über einen Link zum separaten Thread über die Kernel-Routine? – JWWalker

+0

Hier ist ein Link zu dem anderen Thread: http://StackOverflow.com/Questions/2963218/Applying-Transformations-To-nSbitmapImagerep Folgen Sie dem Hyperlink hinter "Schwellenwertfilter" – Adam

+0

Quartz Composer ist ein großartiger Ort, um mit Core Image zu experimentieren Filter. Ich habe es benutzt, um den durch die Verbindung gegebenen Schwellenwertfilter zu testen. Es gab einen Kompilierungsfehler, verursacht durch etwas, das wie ein Minuszeichen aussah, aber tatsächlich ein Bindestrich war. Sobald ich das behoben hatte, funktionierte es. – JWWalker

Antwort

10

Sie können die CIColorMap filter verwenden. Geben Sie eine 20 (w) mal 1 (h) jpg, wobei die linke Hälfte weiß und die rechte Hälfte schwarz ist (oder andersherum) und verwenden Sie diese als Farbverlauf. Das scheint die Farben gut zu hämmern. Ich probierte ursprünglich ein 2x1-Bild mit 1 weißen Pixel und einem schwarzen, aber es sah so aus, als ob es ein wenig interpoliert wurde. Ich ging bis 20x1 und es hat gut funktioniert.

Hinweis: Ich habe Core Image Funhouse (nicht Quartz Composer) zum Experimentieren verwendet.

+0

Hmmm. Ich habe mit der Technik gespielt, die Sie vorgeschlagen haben, und es produziert nicht die Ergebnisse, die ich erwarte. Ich habe versucht 1x2 schwarz-weiß & weiß-schwarz (vertauscht die Reihenfolge) --- und 1x20 schwarz-weiß & weiß-schwarz Gibt es eine Online-Dokumentation, die beschreibt, wie die Gradientenkarte funktionieren sollte? Oder Beispiele? – Adam

+0

Veröffentlichen Sie den Code, den Sie verwenden, um all dies einzurichten. Funktioniert gut in Core Image Fun House, das nur ein einfacher GUI - Wrapper ist, um die vorhandenen CI - Filter auszuprobieren –

+0

Nach weiteren Experimenten denke ich, dass das Problem mit meinem Source Image Gradientenfilter und nicht mit meinem Code zu tun hat inklusive Copenhagen.jpg Bild .. Es macht genau das, was ich will. Wenn ich jedoch den gleichen Filter auf mein eigenes Bild anwende (dasjenige, das ich in meinem Programm modifizieren muss) ... verhält es sich nicht auf die gleiche Weise. Die Transformation macht mein Bild entweder komplett weiß oder komplett schwarz (je nachdem, ob die linke Seite meines 1x20 Farbverlaufs weiß oder schwarz ist). weiter ... – Adam

6

Es dauerte einige Zeit, um den Code für CIColorMap herauszufinden, also wollte ich dies posten. Joshua hat die Antwort oben. Dies ist nur ein Beispiel für die Implementierung ...

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); 
5

Viele Lösungen im Internet erstellen Graustufenwerte. Es gibt keine Notwendigkeit für Filter. Wenn Sie eine solche benötigen als die Verwendung Code wie

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

Proper Schwellwertfilter folgt: inputThreshold Float-Wert von 0.0f sein kann 0,5f

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

Detaillierte Rezept kann bei https://developer.apple.com/library/ios/documentation/graphicsimaging/Conceptual/CoreImaging/ci_custom_filters/ci_custom_filters.html#//apple_ref/doc/uid/TP30001185-CH6-CJBEDHHH

finden
#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 

Aktualisiert mit einem visuellen Unterschied zwischen schwarz & wh ite (links) und Graustufen (rechts)

enter image description here

+0

"Es gibt keine Notwendigkeit für Filter." Ihre Lösung * verwendet * Filter. Was vermisse ich? –

+0

Sie haben Recht. Ich habe mich etwas falsch ausgedrückt. Die ersten drei Zeilen mit dem "CGImageCreateCopyWithColorSpace" sollen ein Graustufenbild erzeugen, was viele Lösungen im Internet tun. Der folgende Code ist der CIFilter, um ein korrektes schwarzweißes Bild gemäß den Schwellenwerten zu erstellen. –

Verwandte Themen