2015-05-21 1 views
23

Ich versuche, Bilder in meiner Mac-App mithilfe von Core Image-Filtern farblich zu korrigieren. Zuerst suche ich nach einem benutzerdefinierten Weißabgleich, um einen Cast von einem Bild zu entfernen. Es sah so aus, als ob die CIWhitePointAdjust genau das ist, wonach ich suche, aber nachdem ich es ausprobiert habe, bin ich mir nicht sicher, ob ich es falsch benutze oder ob es nicht tut, was ich dachte.Wie können Sie ein Bild mithilfe von Core Image-Filtern farblich ausbalancieren?

Beginnend mit diesem Bild, vergilbt mit dem Alter und mit einem dünnen Streifen aus weißem an ihrem rechten Rand:

Original image

I anwenden den Filter, etwa so:

NSColor *whiteSample = // Chosen from the speech bubble's background 
CIColor *whiteInputColor = [[CIColor alloc] initWithColor:whiteSample]; 

layer.filters = @[ 
    [CIFilter filterWithName:@"CIWhitePointAdjust" 
     withInputParameters:@{kCIInputColorKey: whiteInputColor}] 
]; 

und erhalten Sie dieses Bild zurück:

Image after applying CIFilter

Beachten Sie, dass es dunkler und gelber als das Original aussieht (das Gegenteil von meinem gewünschten Effekt). Ich hatte einen Effekt eher wie tut ein Auto Color in Photoshop erwartet, etwa so:

Photoshopped color balance

ich CIWhitePointAdjust falsch verwenden, oder ist es das falsche Werkzeug für diesen Job? Wenn ein anderer Filter oder eine Kombination von Filtern besser funktionieren würde, würde ich es gerne wissen.

Da ich Bilder manipuliere, die bereits in CALayer Objekte sind, scheinen Core Image Filter definitiv die richtige Wahl zu sein, aber wenn dies nur durch ein anderes Mittel möglich ist, bin ich offen dafür.

aktualisieren

A helpful answer auf der Website Signalverarbeitung geben Sie mir den Namen, was zu implementieren Ich versuche. Im Allgemeinen heißt es Histogramm-Entzerrung. Ich versuche herauszufinden, ob es einen Weg gibt, diesen Prozess mit Core Image Filtern durchzuführen und bis jetzt sieht es nicht allzu hoffnungsvoll aus (ohne dass ich selbst schreibe).

+0

Dies könnte nützlich sein: http://StackOverflow.com/a/15972314/341994 – matt

+0

@matt danke, aber ich habe das schon versucht und es schien zu fummelig. Die Farbtemperatureinstellung scheint nichts zu tun, ohne auch den Farbton anzupassen, selbst mit dem Farbton konnte ich das Bild nicht richtig aussehen lassen, und ich möchte dem Benutzer keinen Farbtonregler geben müssen. Es ist darauf ausgerichtet, Farbtemperaturanpassungen für Fotos vorzunehmen, was nicht mein Ziel ist. – Dov

+0

Haben Sie versucht, das Bild mit CIColorControls ein wenig zu desaturieren? – joelg

Antwort

-1

Versuchen Sie, eine Liste der möglichen Filter mit autoAdjustmentFilters or autoAdjustmentFiltersWithOptions ... wahrscheinlich der letzteren zu erhalten, so dass Sie die Filter, die Gesichtserkennung erfordern, ausschließen können, wenn Sie planen, Cartoon-Scans automatisch anzupassen.

+0

Das ist eine großartige Idee (und ich hoffte wirklich, dass es funktionieren würde), aber ich habe es auf dem Testbild ausprobiert, und es sieht so aus, als ob es die Gesamtebenen anpasst, aber keine Filter zurückgibt, um die Farbe zu ändern Balance. Insbesondere gibt es diese Filter zurück: 'CIVibrance',' CIToneCurve' und 'CIHighlightShadowAdjust'). Das ist enttäuschend :-( – Dov

2

OK, also ich denke, ich habe es genagelt! Hier ist, was ich verprügelt haben zusammen aus https://stackoverflow.com/a/30447041/734860 und ein paar Kleber Bits:

@import Accelerator; 

// I haven't yet found a way to do it within Core Image 

// use this when you need to CIImage* -> CGImageRef 
CIImage *ciImage = [CIImage imageWithCGImage:cgImage]; 

... 

// use this when you need to CGImageRef -> CIImage* 
CIContext* context = [[CIContext alloc] init]; 
CGImageRef cgImage = [context createCGImage:ciImage fromRect:ciImage.extent]; 

... 

// the algorithm itself, which uses vImage and has to convert to/from it via CGImage 
CGImageRef CreateEqualisedCGImageFromCGImage(CGImageRef original) 
{ 
    vImage_Error err; 
    vImage_Buffer _img; 
    vImage_CGImageFormat format = { 
     .bitsPerComponent = 8, 
     .bitsPerPixel = 32, 
     .colorSpace = NULL, 
     .bitmapInfo = (CGBitmapInfo)kCGImageAlphaFirst, 
     .version = 0, 
     .decode = NULL, 
     .renderingIntent = kCGRenderingIntentDefault, 
    }; 

    CGFloat width = CGImageGetWidth(original); 
    CGFloat height = CGImageGetHeight(original); 

    vImage_Buffer _dstA, _dstR, _dstG, _dstB; 

    err = vImageBuffer_InitWithCGImage(&_img, &format, NULL, original, kvImageNoFlags); 
    if (err != kvImageNoError) 
     NSLog(@"vImageBuffer_InitWithCGImage error: %ld", err); 

    err = vImageBuffer_Init(&_dstA, height, width, 8 * sizeof(uint8_t), kvImageNoFlags); 
    if (err != kvImageNoError) 
     NSLog(@"vImageBuffer_Init (alpha) error: %ld", err); 

    err = vImageBuffer_Init(&_dstR, height, width, 8 * sizeof(uint8_t), kvImageNoFlags); 
    if (err != kvImageNoError) 
     NSLog(@"vImageBuffer_Init (red) error: %ld", err); 

    err = vImageBuffer_Init(&_dstG, height, width, 8 * sizeof(uint8_t), kvImageNoFlags); 
    if (err != kvImageNoError) 
     NSLog(@"vImageBuffer_Init (green) error: %ld", err); 

    err = vImageBuffer_Init(&_dstB, height, width, 8 * sizeof(uint8_t), kvImageNoFlags); 
    if (err != kvImageNoError) 
     NSLog(@"vImageBuffer_Init (blue) error: %ld", err); 

    err = vImageConvert_ARGB8888toPlanar8(&_img, &_dstA, &_dstR, &_dstG, &_dstB, kvImageNoFlags); 
    if (err != kvImageNoError) 
     NSLog(@"vImageConvert_ARGB8888toPlanar8 error: %ld", err); 

    err = vImageEqualization_Planar8(&_dstR, &_dstR, kvImageNoFlags); 
    if (err != kvImageNoError) 
     NSLog(@"vImageEqualization_Planar8 (red) error: %ld", err); 

    err = vImageEqualization_Planar8(&_dstG, &_dstG, kvImageNoFlags); 
    if (err != kvImageNoError) 
     NSLog(@"vImageEqualization_Planar8 (green) error: %ld", err); 

    err = vImageEqualization_Planar8(&_dstB, &_dstB, kvImageNoFlags); 
    if (err != kvImageNoError) 
     NSLog(@"vImageEqualization_Planar8 (blue) error: %ld", err); 

    err = vImageConvert_Planar8toARGB8888(&_dstA, &_dstR, &_dstG, &_dstB, &_img, kvImageNoFlags); 
    if (err != kvImageNoError) 
     NSLog(@"vImageConvert_Planar8toARGB8888 error: %ld", err); 

    err = vImageContrastStretch_ARGB8888(&_img, &_img, kvImageNoError); 
    if (err != kvImageNoError) 
     NSLog(@"vImageContrastStretch_ARGB8888 error: %ld", err); 

    free(_dstA.data); 
    free(_dstR.data); 
    free(_dstG.data); 
    free(_dstB.data); 

    CGImageRef result = vImageCreateCGImageFromBuffer(&_img, &format, NULL, NULL, kvImageNoFlags, &err); 
    if (err != kvImageNoError) 
     NSLog(@"vImageCreateCGImageFromBuffer error: %ld", err); 

    free(_img.data); 

    return result; 
} 

Das Verdienst der Lösung geht alles zu https://stackoverflow.com/users/4735340/james-bush, aber ich habe so lange gesucht, ohne Erfolg für eine bildorientierte Lösung (wie im Gegensatz zu der Video-Verarbeitung in dieser Frage diskutiert), dass ich denke, eine fertige Antwort wie diese ist relevant. Nach 'AutoLevels' auf OS X oder iOS zu suchen hat mich nirgendwohin gebracht, ich hoffe, dass dies für jemand anderen nützlich sein kann.

+0

Bitte teilen Sie die schnelle Version – ChanWarde

Verwandte Themen