¿Cómo obtener resultados significativos de CIAreaHistogram?

Quiero calcular el histograma de unCGImage. Estoy usando elCIAreaHistogram incorporadoCoreImage filtrar.

Justin Mrkva ha hechoalgo a lo largo de líneas similares. Él dice:

Obtengo el CIImage para el histograma en sí, que luego ejecuto a través de un núcleo personalizado (vea el final de la publicación) para establecer los valores alfa a 1 (ya que de lo contrario el valor alfa de los cálculos del histograma se premultiplica) y luego lo convierto en un NSBitmapImageRep.

Mi pregunta es:¿Es posible obtener los datos del histograma sin tener que crear un núcleo personalizado? ¿Si es así, cómo?

El siguiente código simplemente intenta representar el histograma sin cambiar los valores alfa:

- (void)printHistogram:(CGImageRef)img {

    NSNumber* buckets = @10;

    CIImage* img_ = [CIImage imageWithCGImage:img];

    CIFilter* histF = [CIFilter filterWithName:@"CIAreaHistogram"];
    [histF setValue:img_ forKey:@"inputImage"];
    [histF setValue:[CIVector vectorWithX:0.0
                                        Y:0.0
                                        Z:CGImageGetWidth(img)
                                        W:CGImageGetHeight(img)]
             forKey:@"inputExtent"];
    [histF setValue:buckets forKey:@"inputCount"];
    [histF setValue:@1.0 forKey:@"inputScale"];

    CIImage* histImg = [histF valueForKey:@"outputImage"];

    int rowBytes = [buckets intValue] * 4; // ARGB has 4 components
    uint8_t byteBuffer[rowBytes]; // Buffer to render into
    CGColorSpaceRef cspace = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB);

    CIContext* ctx = [[CIContext alloc] init];
    [ctx render:histImg
       toBitmap:byteBuffer
       rowBytes:rowBytes
         bounds:[histImg extent]
         format:kCIFormatARGB8
     colorSpace:cspace];

    CGColorSpaceRelease(cspace);

    for (int i=0; i<[buckets intValue]; i++) {
        const uint8_t* pixel = &byteBuffer[i*4];
        printf("%d:%u-%u-%u-%u\n",i,pixel[0],pixel[1],pixel[2],pixel[3]);
    }

}   

Dando la salida (cuando se ejecuta en una foto en color):

0:0-0-0-0
1:0-0-0-0
2:0-0-0-0
3:0-0-0-0
4:0-0-0-0
5:0-0-0-0
6:0-0-0-0
7:0-0-0-0
8:0-0-0-0
9:255-33-6-7

Traté de usarCIColorMatrix para establecer los valores alfa a 1.0 antes de renderizar:

CIFilter* biasF = [CIFilter filterWithName:@"CIColorMatrix"];
[biasF setDefaults];
[biasF setValue:histImg forKey:@"inputImage"];
[biasF setValue:[CIVector vectorWithX:0.0 Y:0.0 Z:0.0 W:1.0] forKey:@"inputBiasVector"];

Aunque el formato de salida es ARGB, por lo que entiendo de la Referencia del filtro de imagen central, el componente alfa es el último valor en el vector (por lo tantoW:1.0)

Pero esto produjo el siguiente resultado:

0:255-255-255-255
1:255-255-255-255
2:255-255-255-255
3:255-255-255-255
4:255-255-255-255
5:255-255-255-255
6:255-255-255-255
7:255-255-255-255
8:255-255-0-255
9:255-66-11-15

¡Toda ayuda y consejo serán muy apreciados!

EDITAR: lo séesta pregunta Parece similar Sin embargo, la respuesta aceptada estipula:

En resumen, debe leer los valores como flotantes, no como ints, lo que significa que tendrá que conectar un CGBitmapContext para hacerlo. O si mantiene todo en tierra de CI, necesitará otro filtro para leer los datos e imprimir algo con ellos.

Sin embargo, mirandoLa pregunta de Justin Mrkva me hace pensar que debería ser posible obtener valores enteros ... Avíseme si hay un error en mi pensamiento.

¡Gracias de nuevo!

EDIT 2: Puño de todos, gracias a David y jstn por sus comentarios. Lo siento, me tomó tanto tiempo volver a esto. Estaba trabajando las 24 horas en un proyecto (de hecho, fue ese proyecto el que me llevó a este problema, pero terminé usando un enfoque completamente diferente que ya no utiliza el CIAreaHistogram). Ahora que finalmente tengo algo de tiempo en mis manos, quería volver a esto. Aunque yo nonecesitar ¡per se, todavía quiero entender cómo funciona esto realmente!

Siguiendo las sugerencias de David Hayward, hice las siguientes modificaciones.

- (void)printHistogram:(CGImageRef)img {

    NSNumber* buckets = @10;

    CIImage* img_ = [CIImage imageWithCGImage:img];

    CIFilter* histF = [CIFilter filterWithName:@"CIAreaHistogram"];
    [histF setValue:img_ forKey:@"inputImage"];
    [histF setValue:[CIVector vectorWithX:0.0
                                        Y:0.0
                                        Z:CGImageGetWidth(img)
                                        W:CGImageGetHeight(img)]
             forKey:@"inputExtent"];
    [histF setValue:buckets forKey:@"inputCount"];
    [histF setValue:@1.0 forKey:@"inputScale"];

    CIImage* histImg = [histF valueForKey:@"outputImage"];

    NSUInteger arraySize = [buckets intValue] * 4; // ARGB has 4 components

    // CHANGE 1: Since I will be rendering in float values, I set up the
    //           buffer using CGFloat
    CGFloat byteBuffer[arraySize]; // Buffer to render into

    // CHANGE 2: I wasn't supposed to call [[CIContext alloc] init]
    //           this is a more proper way of getting the context
    CIContext* ctx = [[NSGraphicsContext currentContext] CIContext];

    // CHANGE 3: I use colorSpace:NULL to use the output cspace of the ctx
    // CHANGE 4: Format is now kCIFormatRGBAf
    [ctx render:histImg
       toBitmap:byteBuffer
       rowBytes:arraySize
         bounds:[histImg extent]
         format:kCIFormatRGBAf
     colorSpace:NULL]; // uses the output cspace of the contetxt

    // CHANGE 5: I print the float values
    for (int i=0; i<[buckets intValue]; i++) {
        const CGFloat* pixel = &byteBuffer[i*4];
        printf("%d: %0.2f , %0.2f , %0.2f , %0.2f\n", i,pixel[0],pixel[1],pixel[2],pixel[3]);
    }
}   

Esto da el siguiente resultado:

0: 0.00 , 0.00 , 0.00 , 0.00
1: 0.00 , 0.00 , 0.00 , 0.00
2: 0.00 , 0.00 , 0.00 , 0.00
3: 0.00 , 0.00 , 0.00 , 0.00
4: 0.00 , 0.00 , 0.00 , 0.00
5: 0.00 , 0.00 , 0.00 , 0.00
6: 0.00 , 0.00 , 1.00 , 0.00
7: 0.00 , 0.00 , 0.00 , 0.00
8: 0.00 , 0.00 , 0.00 , 0.00
9: 3.00 , 0.00 , 0.00 , 0.00

Jugar con variaciones de formatos y cómo se analiza la información produce resultados muy diferentes y absurdos.

Estoy bastante seguro de que el problema radica en no comprender correctamente exactamente cómo se representan los datos de mapa de bits.

¿Alguna sugerencia adicional?

Respuestas a la pregunta(6)

Su respuesta a la pregunta