2015-05-21 16 views
23

Sto cercando di aggiungere una correzione del colore alle immagini nella mia app Mac utilizzando i filtri di immagine di base. Innanzitutto, sto cercando di consentire un bilanciamento del bianco personalizzato, per rimuovere un cast da un'immagine. Sembrava che lo CIWhitePointAdjust fosse esattamente quello che stavo cercando, ma dopo averlo provato, non sono sicuro se lo sto usando male, o se non fa quello che pensavo.Come si bilancia il colore in modo efficace un'immagine utilizzando i filtri Core Image?

Partendo da questa immagine, ingiallita dal tempo, e con una sottile striscia di bianco al suo bordo destro:

Original image

ho applicare il filtro, in questo modo:

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

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

e indietro questa immagine:

Image after applying CIFilter

Nota che sembra più scuro e più giallo dell'originale (l'opposto del mio effetto desiderato). Mi aspettavo un effetto più come fare un Auto Colour in Photoshop, in questo modo:

Photoshopped color balance

sto utilizzando CIWhitePointAdjust in modo non corretto, o è lo strumento sbagliato per questo lavoro? Se un altro filtro o una combinazione di filtri funzionasse meglio, mi piacerebbe saperlo.

Poiché sto manipolando le immagini che sono già negli oggetti CALayer, i filtri di Core Image sembrano sicuramente la scelta giusta, ma se questo può essere fatto solo in altro modo, sono aperto a questo.

Aggiornamento

A helpful answer sul sito Signal Processing darmi il nome di quello che sto cercando di attuare. In termini generali, si chiama Histogram Equalization. Sto cercando di capire se c'è un modo per eseguire quel processo usando i filtri Core Image e fino ad ora, non sembra troppo promettente (senza che io scriva il mio).

+0

Questo potrebbe essere utile: http://stackoverflow.com/a/15972314/341994 – matt

+0

@matt, grazie, ma ci ho già provato e sembrava troppo laborioso. La regolazione della temperatura del colore non sembra fare nulla senza anche regolare la tonalità, anche con la tinta non riesco a far sembrare l'immagine giusta, e non voglio dover dare all'utente un cursore Tint. È orientato verso la regolazione della temperatura del colore per le foto, il che non è il mio obiettivo. – Dov

+0

Hai provato a desaturare l'immagine un po 'usando CIColorControls? – joelg

risposta

-1

Prova a ottenere un elenco dei possibili filtri con autoAdjustmentFilters or autoAdjustmentFiltersWithOptions ... probabilmente quest'ultimo in modo che tu possa escludere i filtri che richiedono il rilevamento dei volti, se prevedi di autoadjust le scansioni dei cartoni animati.

+0

Questa è una grande idea (e speravo davvero che funzionasse), ma l'ho provata sull'immagine di prova che sto usando, e sembra che regoli i livelli generali, ma non restituisce alcun filtro per cambiare il colore equilibrio. In particolare, restituisce questi filtri: 'CIVibrance',' CIToneCurve' e 'CIHighlightShadowAdjust'). Questo è deludente :-( – Dov

2

OK, quindi penso di averlo inchiodato! Ecco quello che ho colpita insieme da https://stackoverflow.com/a/30447041/734860 e un paio di bit di colla:

@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; 
} 

Il merito della soluzione va tutto a https://stackoverflow.com/users/4735340/james-bush, ma ho guardato così a lungo senza successo per una soluzione di image-oriented (come contrario all'elaborazione video discussa in questa domanda), ritengo che una risposta pronta come questa sia pertinente. Cercare 'AutoLevels' su OS X o iOS non mi ha portato da nessuna parte, spero che questo possa essere utile a qualcun altro.

+0

per favore condividere la versione rapida – ChanWarde

Problemi correlati