Como obter uma saída CIAreaHistogram significativa?

Eu quero calcular o histograma de umCGImage. Estou usando oCIAreaHistogram construídas emCoreImage filtro.

Justin Mrkva fezalgo semelhante. Ele diz:

Eu recebo o CIImage para o próprio histograma, que, em seguida, corro através de um kernel personalizado (consulte o final da postagem) para definir valores alfa como 1 (caso contrário, o valor alfa dos cálculos do histograma é pré-multiplicado) e depois o converto em um NSBitmapImageRep.

Minha pergunta é:é possível obter os dados do histograma sem ter que criar um kernel personalizado? Se sim, como?

O código a seguir simplesmente tenta renderizar o histograma sem procurar os 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]);
    }

}   

Fornecendo a saída (quando executada em uma foto colorida):

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

Eu tentei usarCIColorMatrix para definir os valores alfa como 1.0 antes da renderização:

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"];

Mesmo que o formato de saída seja ARGB, pelo que entendi na Referência do filtro de imagem principal, o componente alfa é o último valor do vetor (assimW:1.0)

Mas isso produziu a seguinte saída:

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 a ajuda e conselhos serão muito apreciados!

EDIT: eu seiessa questão parece semelhante. No entanto, a resposta aceita estipula:

O resumo é: você precisa ler os valores como flutuadores, não como ints, o que significa que você precisará conectar um CGBitmapContext ao qual desejar. Ou, se você mantiver tudo na área de IC, precisará de outro filtro para ler os dados e imprimir algo com eles.

No entanto, olhando paraPergunta de Justin Mrkva me faz pensar que a obtenção de valores inteiros deve ser possível ... Entre em contato se houver algum erro no meu pensamento.

Obrigado novamente!

EDIT 2: Primeiro de tudo, obrigado a David e jstn por seus comentários. Desculpe, demorou tanto tempo para eu voltar a isso. Eu estava trabalhando dia e noite em um projeto (na verdade, foi o projeto que me levou a esse problema, mas acabei usando uma abordagem totalmente diferente que não utiliza mais o CIAreaHistogram). Agora que finalmente tenho algum tempo em minhas mãos, queria voltar a isso. Mesmo que eu nãonecessidade por si só, ainda quero entender como isso realmente funciona!

Seguindo as sugestões de David Hayward, fiz as seguintes modificações.

- (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]);
    }
}   

Isso fornece a seguinte saída:

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

Brincar com variações de formatos e como a informação é analisada produz resultados totalmente diferentes e absurdos.

Tenho certeza de que o problema está em não entender corretamente exatamente como os dados de bitmap são representados.

Mais alguma sugestão?

questionAnswers(6)

yourAnswerToTheQuestion