Как получить значимый вывод CIAreaHistogram?

Я хочу рассчитать гистограммуCGImage, Я используюCIAreaHistogram встроенныйCoreImage фильтр.

Джастин Мрква сделалчто-то похожее, Он говорит:

Я получаю CIImage для самой гистограммы, которую затем запускаю через собственное ядро ​​(см. Конец поста), чтобы установить альфа-значения равными 1 (поскольку в противном случае альфа-значение из вычислений гистограммы предварительно умножается), а затем преобразую его в NSBitmapImageRep.

Мой вопрос:Можно ли получить данные гистограммы без необходимости создания собственного ядра? Если так, то как?

Следующий код просто пытается отобразить гистограмму без изменения значений альфа:

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

}   

Предоставление вывода (при запуске на цветной фотографии):

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

Я пытался с помощьюCIColorMatrix установить значения альфа на 1.0 перед рендерингом:

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

Несмотря на то, что выходной формат - ARGB, из того, что я понял из справочника по фильтру базовых изображений, альфа-компонент является последним значением в векторе (таким образом,W:1.0).

Но это дало следующий вывод:

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

Вся помощь и советы будут высоко оценены!

РЕДАКТИРОВАТЬ: я знаюэтот вопрос кажется похожим. Однако принятый ответ предусматривает:

Суть в том, что вы должны читать значения как числа с плавающей запятой, а не как целые числа, что означает, что вам нужно подключить CGBitmapContext, чтобы переместиться к нему. Или, если вы храните все на земле CI, вам понадобится другой фильтр, чтобы читать данные и распечатывать их вместе с ними.

Тем не менее, глядя наВопрос Джастина Мрквы заставляет меня думать, что получение целочисленных значений должно быть возможным ... Пожалуйста, дайте мне знать, если в моем мышлении есть ошибка.

Еще раз спасибо!

РЕДАКТИРОВАТЬ 2: Во-первых, спасибо и Дэвид и JSTN за их комментарии. Извините, что я так долго возвращался к этому. Я круглосуточно работал над проектом (на самом деле, именно этот проект привел меня к этой проблеме, но в итоге я использовал совершенно другой подход, который больше не использует CIAreaHistogram). Теперь, когда у меня наконец-то появилось время, я хотел вернуться к этому. Хотя я ненеобходимость само по себе, я все еще хочу понять, как эта штука действительно работает!

Следуя предложениям Дэвида Хейворда, я внес следующие изменения.

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

Это дает следующий вывод:

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

Игра с вариациями форматов и анализом информации дает совершенно разные и абсурдные результаты.

Я совершенно уверен, что проблема заключается в неправильном понимании того, как точечные данные представлены.

Есть еще предложения?

Ответы на вопрос(6)

Ваш ответ на вопрос