How to get meaningful CIAreaHistogram output?

瘦欲@ 提交于 2019-12-05 00:28:55

问题


I want to calculate the histogram of a CGImage. I am using the CIAreaHistogram built-in CoreImage filter.

Justin Mrkva has done something along similar lines. He says:

I get the CIImage for the histogram itself, which I then run through a custom kernel (see end of post) to set alpha values to 1 (since otherwise the alpha value from the histogram calculations is premultiplied) and then convert it to an NSBitmapImageRep.

My question is: is it possible to get the histogram data without having to create a custom kernel? If so, how?

The following code simply tries to render the histogram without chaning the alpha values:

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

}   

Giving the output (when run on a color photo):

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

I tried using CIColorMatrix to set the alpha values to 1.0 before rendering:

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

Even though the output format is ARGB, from what I understand from the Core Image Filter Reference, the alpha component is the last value in the vector (thus W:1.0).

But this yielded the following output:

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

All help and advice will be much appreciated!


EDIT: I know this question seems similar. However, the accepted answer stipulates:

The short of it is: you need to read the values as floats, not ints, which means you'll have to hook up a CGBitmapContext to blit to. Or if you keep everything in CI land, you'll need another filter to read the data and print something out with it.

However, looking at Justin Mrkva's question makes me think that getting integer values should be possible... Please let me know if there is an error in my thinking.

Thanks again!


EDIT 2: Fist of all, thank you to both David and jstn for their comments. Sorry it took so long for me to come back to this. I was working around the clock on a project (in fact it was that project that led me to this problem, but I ended up using an altogether different approach that no longer utilizes CIAreaHistogram). Now that I finally have some time on my hands, I wanted to get back to this. Even though I don't need it per se, I still want to understand how this thing really works!

Following David Hayward's suggestions, I made the following modifications.

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

This gives the following output:

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

Playing around with variations of formats and how the information is parsed yields wildly different and absurd outputs.

I'm quite sure the trouble lies in not properly understanding precisely how the bitmap data is represented.

Any further suggestions?


回答1:


I struggled with this for a while myself, although on iOS. I wanted to get the histogram data from live video for my own visualization, but ran into the same problem as Justin Mrkva.

Even with CIHistogramDisplayFilter the output didn't look quite right to me (too flat?), plus CIAreaHistogram was consuming something like 25-30% CPU all on its own. This is before drawing to an EAGLContext, haven't even brought the data back from the GPU yet...

So I scrapped Core Image altogether and turned to vImage, which works perfectly. It's still CPU intensive, but for me surprisingly less so than CIAreaHistogram, and the output matches what I see in Photoshop. It's not ideal if you're trying stay entirely on the GPU, but depending on your application it may be a better choice (it's certainly more precise).

It doesn't exactly answer your question, but here's how to get the histogram for a CGImage using vImage. I'm doing basically the same thing except with CVPixelBuffer and locking the base address. The channel order is different but it shouldn't matter:

#import <Accelerate/Accelerate.h>

CFDataRef imageData = CGDataProviderCopyData(CGImageGetDataProvider(image));

vImage_Buffer vImageBuffer;
vImageBuffer.data = (UInt8 *)CFDataGetBytePtr(imageData);
vImageBuffer.width = CGImageGetWidth(image);
vImageBuffer.height = CGImageGetHeight(image);
vImageBuffer.rowBytes = CGImageGetBytesPerRow(image);

vImagePixelCount red[256];
vImagePixelCount green[256];
vImagePixelCount blue[256];
vImagePixelCount alpha[256];
vImagePixelCount *histogram[4] = { red, green, blue, alpha };

vImage_Error error = vImageHistogramCalculation_ARGB8888(&vImageBuffer, histogram, 0);

if (error != kvImageNoError)
    NSLog(@"vImage error: %ld", error);

CFRelease(imageData);

// histogram now contains unsigned long counts for each channel

I would still like to know how to make proper use of CIAreaHistogram on iOS!




回答2:


Three suggestions:

  • use inputScale to gain the histogram counts up. If inputScale is 1, then a resulting histogram bin value will be 1.0 (255 if rendered to ARGB8) if the entire area has that bin value)
  • pass CI's working colorspace to render:toBitmap:. On Mavericks the working space is kCGColorSpaceGenericRGBLinear. On Yosemite it is linear sRGB.
  • on OS X you can use kCIFormatRGBAf to get float data
  • on iOS you can use kCIFormatRGBAh to get half-float data



回答3:


Here's how to do what you wanted to do originally; as it turns out, changing the format in the context is what gives you all the different results you were getting.

This sample code, by the way, uses an EAGLContext, which is supposedly faster, although, in my experience so far, it is not. Nevertheless, here it is:

    CIFilter* histogram = [CIFilter filterWithName:@"CIAreaHistogram"];
[histogram setValue:inputImage forKey:@"inputImage"];
[histogram setValue:[CIVector vectorWithX:0.0 Y:0.0 Z:self.inputImage.extent.size.width W:self.inputImage.extent.size.height] forKey:@"inputExtent"];
[histogram setValue:@256 forKey:@"inputCount"];
[histogram setValue:@1.0 forKey:@"inputScale"];
/*id histogramData = [histogram valueForKey:@"outputData"];
if (histogramData)
    NSLog(@"outputData: %@", histogramData);*/

@autoreleasepool {
    CIImage* histogramImage = [histogram valueForKey:@"outputImage"];
    int rowBytes = 256 * 4; // ARGB has 4 components
    uint8_t byteBuffer[rowBytes]; // Buffer to render into

    EAGLContext *myEAGLContext = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];
    NSDictionary *options = @{ kCIContextWorkingColorSpace : [NSNull null] };
    CIContext *ctx = [CIContext contextWithEAGLContext:myEAGLContext options:options];
    //CIContext* ctx = [[CIContext alloc] init];
    [ctx render:histogramImage toBitmap:byteBuffer
       rowBytes:rowBytes
         bounds:[histogramImage extent]
         format:kCIFormatRGBAf
     colorSpace:nil];

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



回答4:


By the way, here's working (and accurate) code for getting values from the CIAreaAverage Core Image filter:

- (CIImage *)outputImage
    CGRect inputExtent = [self.inputImage extent];
    CIVector *extent = [CIVector vectorWithX:inputExtent.origin.x
                                           Y:inputExtent.origin.y
                                           Z:inputExtent.size.width
                                           W:inputExtent.size.height];
    CIImage* inputAverage = [CIFilter filterWithName:@"CIAreaAverage" keysAndValues:@"inputImage", self.inputImage, @"inputExtent", extent, nil].outputImage;

    //CIImage* inputAverage = [self.inputImage imageByApplyingFilter:@"CIAreaMinimum" withInputParameters:@{@"inputImage" : inputImage, @"inputExtent" : extent}];
    EAGLContext *myEAGLContext = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];
    NSDictionary *options = @{ kCIContextWorkingColorSpace : [NSNull null] };
    CIContext *myContext = [CIContext contextWithEAGLContext:myEAGLContext options:options];

    size_t rowBytes = 32 ; // ARGB has 4 components
    uint8_t byteBuffer[rowBytes]; // Buffer to render into

    [myContext render:inputAverage toBitmap:byteBuffer rowBytes:rowBytes bounds:[inputAverage extent] format:kCIFormatRGBA8 colorSpace:nil];

    const uint8_t* pixel = &byteBuffer[0];
    float red   = pixel[0] / 255.0;
    float green = pixel[1] / 255.0;
    float blue  = pixel[2] / 255.0;
    NSLog(@"%f, %f, %f\n", red, green, blue);


    return outputImage;

Sample output:

2015-05-23 15:58:10.854 CIFunHouse[2400:489896] BSXPCMessage received error for message: Connection interrupted
2015-05-23 15:58:15.470 CIFunHouse[2400:489913] 0.000000, 0.000000, 0.305882
2015-05-23 15:58:15.582 CIFunHouse[2400:489913] 0.501961, 0.380392, 0.898039
2015-05-23 15:58:15.622 CIFunHouse[2400:489913] 0.564706, 0.917647, 0.831373
2015-05-23 15:58:15.665 CIFunHouse[2400:489913] 0.501961, 0.380392, 0.898039
2015-05-23 15:58:15.706 CIFunHouse[2400:489913] 0.501961, 0.380392, 0.898039
2015-05-23 15:58:15.748 CIFunHouse[2400:489913] 0.564706, 0.917647, 0.831373
2015-05-23 15:58:15.792 CIFunHouse[2400:489913] 0.564706, 0.917647, 0.831373
2015-05-23 15:58:15.834 CIFunHouse[2400:489913] 0.752941, 0.858824, 0.890196
2015-05-23 15:58:15.874 CIFunHouse[2400:489913] 0.690196, 0.309804, 0.819608
2015-05-23 15:58:15.915 CIFunHouse[2400:489913] 0.752941, 0.858824, 0.890196
2015-05-23 15:58:15.956 CIFunHouse[2400:489913] 0.752941, 0.858824, 0.890196
2015-05-23 15:58:15.998 CIFunHouse[2400:489913] 0.752941, 0.858824, 0.890196
2015-05-23 15:58:16.040 CIFunHouse[2400:489913] 0.690196, 0.309804, 0.819608
2015-05-23 15:58:16.079 CIFunHouse[2400:489913] 0.501961, 0.380392, 0.898039
2015-05-23 15:58:16.121 CIFunHouse[2400:489913] 0.501961, 0.380392, 0.898039
2015-05-23 15:58:16.163 CIFunHouse[2400:489913] 0.501961, 0.380392, 0.898039
2015-05-23 15:58:16.205 CIFunHouse[2400:489913] 0.501961, 0.380392, 0.898039
2015-05-23 15:58:16.247 CIFunHouse[2400:489913] 0.690196, 0.309804, 0.819608
2015-05-23 15:58:16.288 CIFunHouse[2400:489913] 0.501961, 0.380392, 0.898039
2015-05-23 15:58:16.330 CIFunHouse[2400:489913] 0.501961, 0.380392, 0.898039
2015-05-23 15:58:16.372 CIFunHouse[2400:489913] 0.501961, 0.380392, 0.898039
2015-05-23 15:58:16.413 CIFunHouse[2400:489895] 0.690196, 0.309804, 0.819608
2015-05-23 15:58:16.455 CIFunHouse[2400:489895] 0.501961, 0.380392, 0.898039
2015-05-23 15:58:16.496 CIFunHouse[2400:489913] 0.690196, 0.309804, 0.819608
2015-05-23 15:58:16.543 CIFunHouse[2400:489913] 0.501961, 0.380392, 0.898039
2015-05-23 15:58:16.579 CIFunHouse[2400:489913] 0.752941, 0.858824, 0.890196
2015-05-23 15:58:16.623 CIFunHouse[2400:489913] 0.564706, 0.917647, 0.831373
2015-05-23 15:58:16.667 CIFunHouse[2400:489913] 0.752941, 0.858824, 0.890196
2015-05-23 15:58:16.705 CIFunHouse[2400:489913] 0.564706, 0.917647, 0.831373
2015-05-23 15:58:16.746 CIFunHouse[2400:489913] 0.564706, 0.917647, 0.831373
2015-05-23 15:58:16.788 CIFunHouse[2400:489913] 0.752941, 0.858824, 0.890196
2015-05-23 15:58:16.829 CIFunHouse[2400:489913] 0.690196, 0.309804, 0.819608
2015-05-23 15:58:16.873 CIFunHouse[2400:489913] 0.690196, 0.309804, 0.819608
2015-05-23 15:58:16.912 CIFunHouse[2400:489970] 0.752941, 0.858824, 0.890196
2015-05-23 15:58:16.955 CIFunHouse[2400:489913] 0.690196, 0.309804, 0.819608
2015-05-23 15:58:16.996 CIFunHouse[2400:489913] 0.752941, 0.858824, 0.890196
2015-05-23 15:58:17.038 CIFunHouse[2400:489913] 0.752941, 0.858824, 0.890196
2015-05-23 15:58:17.080 CIFunHouse[2400:489913] 0.752941, 0.858824, 0.890196
2015-05-23 15:58:17.122 CIFunHouse[2400:489913] 0.752941, 0.858824, 0.890196
2015-05-23 15:58:17.163 CIFunHouse[2400:489913] 0.690196, 0.309804, 0.819608
2015-05-23 15:58:17.205 CIFunHouse[2400:489913] 0.690196, 0.309804, 0.819608
2015-05-23 15:58:17.246 CIFunHouse[2400:489913] 0.690196, 0.309804, 0.819608
2015-05-23 15:58:17.288 CIFunHouse[2400:489970] 0.690196, 0.309804, 0.819608
2015-05-23 15:58:17.330 CIFunHouse[2400:489913] 0.752941, 0.858824, 0.890196
2015-05-23 15:58:17.371 CIFunHouse[2400:489913] 0.752941, 0.858824, 0.890196
2015-05-23 15:58:17.415 CIFunHouse[2400:489913] 0.690196, 0.309804, 0.819608
2015-05-23 15:58:17.456 CIFunHouse[2400:489913] 0.752941, 0.858824, 0.890196
2015-05-23 15:58:17.496 CIFunHouse[2400:489913] 0.690196, 0.309804, 0.819608
2015-05-23 15:58:17.539 CIFunHouse[2400:489913] 0.690196, 0.309804, 0.819608
2015-05-23 15:58:17.580 CIFunHouse[2400:489895] 0.501961, 0.380392, 0.898039
2015-05-23 15:58:17.622 CIFunHouse[2400:489895] 0.690196, 0.309804, 0.819608
2015-05-23 15:58:17.664 CIFunHouse[2400:489895] 0.690196, 0.309804, 0.819608
2015-05-23 15:58:17.705 CIFunHouse[2400:489895] 0.690196, 0.309804, 0.819608
2015-05-23 15:58:17.746 CIFunHouse[2400:489895] 0.752941, 0.858824, 0.890196
2015-05-23 15:58:17.788 CIFunHouse[2400:489895] 0.752941, 0.858824, 0.890196
2015-05-23 15:58:17.830 CIFunHouse[2400:489895] 0.752941, 0.858824, 0.890196
2015-05-23 15:58:17.873 CIFunHouse[2400:489895] 0.690196, 0.309804, 0.819608
2015-05-23 15:58:17.914 CIFunHouse[2400:489895] 0.752941, 0.858824, 0.890196
2015-05-23 15:58:17.956 CIFunHouse[2400:489895] 0.690196, 0.309804, 0.819608
2015-05-23 15:58:17.997 CIFunHouse[2400:489913] 0.501961, 0.941176, 0.831373
2015-05-23 15:58:18.038 CIFunHouse[2400:489913] 0.752941, 0.858824, 0.890196
2015-05-23 15:58:18.080 CIFunHouse[2400:489913] 0.752941, 0.858824, 0.890196
2015-05-23 15:58:18.122 CIFunHouse[2400:489913] 0.752941, 0.858824, 0.890196
2015-05-23 15:58:18.163 CIFunHouse[2400:489913] 0.690196, 0.309804, 0.819608
2015-05-23 15:58:18.206 CIFunHouse[2400:489913] 0.690196, 0.309804, 0.819608
2015-05-23 15:58:18.248 CIFunHouse[2400:489913] 0.752941, 0.858824, 0.890196
2015-05-23 15:58:18.289 CIFunHouse[2400:489913] 0.752941, 0.858824, 0.890196
2015-05-23 15:58:18.330 CIFunHouse[2400:489895] 0.690196, 0.309804, 0.819608
2015-05-23 15:58:18.372 CIFunHouse[2400:489895] 0.752941, 0.858824, 0.890196
2015-05-23 15:58:18.413 CIFunHouse[2400:489895] 0.690196, 0.309804, 0.819608
2015-05-23 15:58:18.459 CIFunHouse[2400:489895] 0.752941, 0.858824, 0.890196
2015-05-23 15:58:18.497 CIFunHouse[2400:489895] 0.752941, 0.858824, 0.890196
2015-05-23 15:58:18.538 CIFunHouse[2400:489895] 0.690196, 0.309804, 0.819608
2015-05-23 15:58:18.580 CIFunHouse[2400:489895] 0.690196, 0.309804, 0.819608
2015-05-23 15:58:18.622 CIFunHouse[2400:489895] 0.752941, 0.858824, 0.890196
2015-05-23 15:58:18.663 CIFunHouse[2400:489913] 0.690196, 0.309804, 0.819608
2015-05-23 15:58:18.706 CIFunHouse[2400:489913] 0.690196, 0.309804, 0.819608
2015-05-23 15:58:18.747 CIFunHouse[2400:489895] 0.690196, 0.309804, 0.819608
2015-05-23 15:58:18.789 CIFunHouse[2400:489895] 0.752941, 0.858824, 0.890196
2015-05-23 15:58:18.830 CIFunHouse[2400:489913] 0.690196, 0.309804, 0.819608
2015-05-23 15:58:18.868 CIFunHouse[2400:489913] 0.690196, 0.309804, 0.819608
2015-05-23 15:58:18.907 CIFunHouse[2400:489913] 0.752941, 0.858824, 0.890196
2015-05-23 15:58:18.949 CIFunHouse[2400:489913] 0.752941, 0.858824, 0.890196
2015-05-23 15:58:18.990 CIFunHouse[2400:489913] 0.690196, 0.309804, 0.819608
2015-05-23 15:58:19.044 CIFunHouse[2400:489913] 0.690196, 0.309804, 0.819608
2015-05-23 15:58:19.091 CIFunHouse[2400:489913] 0.690196, 0.309804, 0.819608
2015-05-23 15:58:19.134 CIFunHouse[2400:489913] 0.690196, 0.309804, 0.819608
2015-05-23 15:58:19.173 CIFunHouse[2400:489913] 0.752941, 0.858824, 0.890196
2015-05-23 15:58:19.213 CIFunHouse[2400:489913] 0.690196, 0.309804, 0.819608
2015-05-23 15:58:19.254 CIFunHouse[2400:489913] 0.752941, 0.858824, 0.890196
2015-05-23 15:58:19.298 CIFunHouse[2400:489913] 0.564706, 0.917647, 0.831373
2015-05-23 15:58:19.337 CIFunHouse[2400:489913] 0.752941, 0.858824, 0.890196
2015-05-23 15:58:19.377 CIFunHouse[2400:489913] 0.752941, 0.858824, 0.890196
2015-05-23 15:58:19.415 CIFunHouse[2400:489913] 0.564706, 0.917647, 0.831373
2015-05-23 15:58:19.455 CIFunHouse[2400:489913] 0.564706, 0.917647, 0.831373
2015-05-23 15:58:19.498 CIFunHouse[2400:489913] 0.752941, 0.858824, 0.890196
2015-05-23 15:58:19.540 CIFunHouse[2400:489913] 0.564706, 0.917647, 0.831373
2015-05-23 15:58:19.588 CIFunHouse[2400:489913] 0.501961, 0.380392, 0.898039
2015-05-23 15:58:19.630 CIFunHouse[2400:489913] 0.690196, 0.309804, 0.819608
2015-05-23 15:58:19.674 CIFunHouse[2400:489913] 0.501961, 0.380392, 0.898039
2015-05-23 15:58:19.719 CIFunHouse[2400:489913] 0.690196, 0.309804, 0.819608
2015-05-23 15:58:19.763 CIFunHouse[2400:489913] 0.690196, 0.309804, 0.819608
2015-05-23 15:58:19.806 CIFunHouse[2400:489913] 0.690196, 0.309804, 0.819608
2015-05-23 15:58:19.851 CIFunHouse[2400:489913] 0.752941, 0.858824, 0.890196
2015-05-23 15:58:19.902 CIFunHouse[2400:489913] 0.690196, 0.309804, 0.819608
2015-05-23 15:58:19.960 CIFunHouse[2400:489913] 0.690196, 0.309804, 0.819608
2015-05-23 15:58:20.016 CIFunHouse[2400:489913] 0.690196, 0.309804, 0.819608
2015-05-23 15:58:20.073 CIFunHouse[2400:489913] 0.690196, 0.309804, 0.819608
2015-05-23 15:58:20.139 CIFunHouse[2400:489913] 0.000000, 0.882353, 0.898039
2015-05-23 15:58:20.198 CIFunHouse[2400:489913] 0.000000, 0.882353, 0.898039
2015-05-23 15:58:20.253 CIFunHouse[2400:489913] 0.000000, 0.882353, 0.898039
2015-05-23 15:58:20.316 CIFunHouse[2400:489913] 0.313726, 0.894118, 0.831373
2015-05-23 15:58:20.389 CIFunHouse[2400:489913] 0.313726, 0.894118, 0.831373
2015-05-23 15:58:20.472 CIFunHouse[2400:489913] 0.313726, 0.894118, 0.831373
2015-05-23 15:58:20.554 CIFunHouse[2400:489913] 0.313726, 0.894118, 0.831373
2015-05-23 15:58:20.631 CIFunHouse[2400:489913] 0.690196, 0.309804, 0.819608
2015-05-23 15:58:20.714 CIFunHouse[2400:489913] 0.752941, 0.858824, 0.890196
2015-05-23 15:58:20.784 CIFunHouse[2400:489913] 0.752941, 0.858824, 0.890196
2015-05-23 15:58:20.839 CIFunHouse[2400:489913] 0.690196, 0.309804, 0.819608
2015-05-23 15:58:20.887 CIFunHouse[2400:489913] 0.690196, 0.309804, 0.819608
2015-05-23 15:58:20.935 CIFunHouse[2400:489913] 0.752941, 0.858824, 0.890196
2015-05-23 15:58:20.981 CIFunHouse[2400:489913] 0.752941, 0.858824, 0.890196



回答5:


I worked on this for some time, but never got kCIFormatARGB8 to work. Another poster said that kCIFormatARGBf doesn't work on iOS, so I tried kCIFormatRGBAh, instead.

kCIFormatRGBAh is strange: it's RGBA data packed as 16-bit floats ("half-floats"). C does not have a native half-float type, and you must rely on compiler-specific data-types. Fortunately, both gcc and clang seem to support the type as __fp16.

// img is input
histogramFilter = [CIFilter filterWithName:@"CIAreaHistogram" keysAndValues:@"inputScale", @1, @"inputCount", @256, nil];
CIVector *extent = [[CIVector alloc] initWithCGRect:img.extent];
[histogramFilter setValue:extent forKey:@"inputExtent"];
[histogramFilter setValue:img forKey:kCIInputImageKey];
CIImage *histImg = histogramFilter.outputImage;

int rowBytes = 256 * 4; // ARGB has 4 components.
__fp16 byteBuffer[rowBytes]; // Buffer to render into
rowBytes *= 2; //__fp16 is 2 bytes

EAGLContext *myEAGLContext = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];
NSDictionary *options = @{ kCIContextWorkingColorSpace : [NSNull null] };
CIContext *ctx = [CIContext contextWithEAGLContext:myEAGLContext options:options];
[ctx render:histImg toBitmap:byteBuffer
   rowBytes:rowBytes
     bounds:[histImg extent]
     format:kCIFormatRGBAh
 colorSpace:nil];

for (int i = 0; i < 256; i++)
{
    const __fp16* pixel = &byteBuffer[i*4];

    NSLog(@"%d: %f, %f, %f, %f\n", i, (float)pixel[0], (float)pixel[1], (float)pixel[2], (float)pixel[3]);
}

I don't think this will work on the simulator, because the simulator doesn't support kCIFormatRGBAh.




回答6:


There is an undocumented method on CIAreaHistogram call outputData that may be useful.



来源:https://stackoverflow.com/questions/27237297/how-to-get-meaningful-ciareahistogram-output

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!