cocoa - ¿Cómo se equilibra efectivamente una imagen con los filtros Core Image?
core-image (2)
Estoy tratando de agregar alguna corrección de color a las imágenes en la aplicación de mi Mac usando los filtros Core Image. En primer lugar, estoy considerando permitir un balance de blancos personalizado para eliminar un lanzamiento de una imagen. Parecía que el CIWhitePointAdjust
era exactamente lo que estaba buscando, pero después de probarlo, no estoy seguro de si lo estoy usando mal o si no hace lo que pensé.
Comenzando con esta imagen, amarilleando con la edad y con una delgada franja de blanco en el borde derecho:
Aplico el filtro, así:
NSColor *whiteSample = // Chosen from the speech bubble''s background
CIColor *whiteInputColor = [[CIColor alloc] initWithColor:whiteSample];
layer.filters = @[
[CIFilter filterWithName:@"CIWhitePointAdjust"
withInputParameters:@{kCIInputColorKey: whiteInputColor}]
];
y recupera esta imagen:
Tenga en cuenta que se ve más oscuro y más amarillo que el original (lo contrario de mi efecto deseado). Había estado esperando un efecto más parecido a hacer un Auto Color en Photoshop, así:
¿Estoy usando CIWhitePointAdjust
incorrectamente o es la herramienta incorrecta para este trabajo? Si otro filtro o combinación de filtros funcionara mejor, me encantaría saberlo.
Ya que estoy manipulando imágenes que ya están en los objetos CALayer
, los filtros Core Image definitivamente parecen ser la opción correcta, pero si esto solo se puede hacer de otra manera, estoy abierto a eso.
Actualizar
Una respuesta útil en el sitio de procesamiento de señales me da el nombre de lo que estoy tratando de implementar. En términos generales, se llama ecualización de histogramas. Estoy tratando de averiguar si hay una manera de realizar ese proceso utilizando filtros de Core Image y hasta ahora, no parece demasiado esperanzador (sin que yo escriba el mío).
Intente obtener una lista de posibles filtros con autoAdjustmentFilters o autoAdjustmentFiltersWithOptions ... probablemente este último para que pueda excluir los filtros que requieren detección de rostros, si planea ajustar automáticamente los escaneos de dibujos animados.
OK, entonces creo que lo he clavado! Esto es lo que he juntado de https://.com/a/30447041/734860 y un par de bits de pegamento:
@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;
}
El mérito de la solución se debe a https://.com/users/4735340/james-bush , pero he buscado durante mucho tiempo sin éxito una solución orientada a la imagen (a diferencia del procesamiento de video discutido en esa pregunta). ) que creo que una respuesta preparada como esta es relevante. Buscando ''AutoLevels'' en OS X o iOS no me llevó a ninguna parte, espero que esto pueda ser útil para otra persona.