CIAreaHistogram gives me all 0 except the last element?
Asked Answered
P

3

4

I want to calculate histogram of an NSImage, so I turned to CIFilter naturally. There's a filter named CIAreaHistogram does what I want. Here's my code:

NSBitmapImageRep *rep = [image bitmapImageRepresentation];
CIImage* hImage = nil;
@autoreleasepool {
    CIImage *input = [[CIImage alloc] initWithBitmapImageRep:rep];
    CIFilter *histogramFilter = [CIFilter filterWithName:@"CIAreaHistogram"];
    [histogramFilter setDefaults];
    [histogramFilter setValue:input forKey:kCIInputImageKey];
    [histogramFilter setValue:[CIVector vectorWithCGRect:[input extent]] forKeyPath:@"inputExtent"];
    [histogramFilter setValue:[NSNumber numberWithInt:256] forKeyPath:@"inputCount"];
    [histogramFilter setValue:[NSNumber numberWithFloat:1.0] forKey:@"inputScale"];

    hImage = [histogramFilter valueForKey:kCIOutputImageKey];
    input = nil;

    NSImage *result = nil;
    @autoreleasepool
    {
        NSCIImageRep *rep = [NSCIImageRep imageRepWithCIImage:hImage];
        result = [[NSImage alloc] initWithSize:rep.size];
        [result addRepresentation:rep];
    }

    NSBitmapImageRep *imgRep = [result bitmapImageRepresentation];
    for (int y = 0; y < imgRep.size.height; y ++) {
        for (int x = 0; x < imgRep.size.width; x ++) {
            NSUInteger pixel[4];
            [imgRep getPixel:pixel atX:x y:y];
            NSLog(@"(%d, %d): %lu - %lu - %lu - %lu", x, y, pixel[0], pixel[1], pixel[2], pixel[3]);
        }
    }
}

The bitmapImageRepresentation is just a help method that converts NSImage to NSBitmapImageRep. I've tested and used a lot with it, seems it's cool.

And the output is listed below:

(0, 0): 0 - 0 - 0 - 0
(1, 0): 0 - 0 - 0 - 0
(2, 0): 0 - 0 - 0 - 0
(3, 0): 0 - 0 - 0 - 0
(4, 0): 0 - 0 - 0 - 0
(5, 0): 0 - 0 - 0 - 0
(6, 0): 0 - 0 - 0 - 0
(7, 0): 0 - 0 - 0 - 0
(8, 0): 0 - 0 - 0 - 0
(9, 0): 0 - 0 - 0 - 0
(10, 0): 0 - 0 - 0 - 0
(11, 0): 0 - 0 - 0 - 0
(12, 0): 0 - 0 - 0 - 0
(13, 0): 0 - 0 - 0 - 0
(14, 0): 0 - 0 - 0 - 0
(15, 0): 0 - 0 - 0 - 0
(16, 0): 0 - 0 - 0 - 0
(17, 0): 0 - 0 - 0 - 0
(18, 0): 0 - 0 - 0 - 0
(19, 0): 0 - 0 - 0 - 0
(20, 0): 0 - 0 - 0 - 0
(21, 0): 0 - 0 - 0 - 0
(22, 0): 0 - 0 - 0 - 0
(23, 0): 0 - 0 - 0 - 0
(24, 0): 0 - 0 - 0 - 0
(25, 0): 0 - 0 - 0 - 0
(26, 0): 0 - 0 - 0 - 0
(27, 0): 0 - 0 - 0 - 0
(28, 0): 0 - 0 - 0 - 0
(29, 0): 0 - 0 - 0 - 0
(30, 0): 0 - 0 - 0 - 0
(31, 0): 0 - 0 - 0 - 0
(32, 0): 0 - 0 - 0 - 0
(33, 0): 0 - 0 - 0 - 0
(34, 0): 0 - 0 - 0 - 0
(35, 0): 0 - 0 - 0 - 0
(36, 0): 0 - 0 - 0 - 0
(37, 0): 0 - 0 - 0 - 0
(38, 0): 0 - 0 - 0 - 0
(39, 0): 0 - 0 - 0 - 0
(40, 0): 0 - 0 - 0 - 0
(41, 0): 0 - 0 - 0 - 0
(42, 0): 0 - 0 - 0 - 0
(43, 0): 0 - 0 - 0 - 0
(44, 0): 0 - 0 - 0 - 0
(45, 0): 0 - 0 - 0 - 0
(46, 0): 0 - 0 - 0 - 0
(47, 0): 0 - 0 - 0 - 0
(48, 0): 0 - 0 - 0 - 0
(49, 0): 0 - 0 - 0 - 0
(50, 0): 0 - 0 - 0 - 0
(51, 0): 0 - 0 - 0 - 0
(52, 0): 0 - 0 - 0 - 0
(53, 0): 0 - 0 - 0 - 0
(54, 0): 0 - 0 - 0 - 0
(55, 0): 0 - 0 - 0 - 0
(56, 0): 0 - 0 - 0 - 0
(57, 0): 0 - 0 - 0 - 0
(58, 0): 0 - 0 - 0 - 0
(59, 0): 0 - 0 - 0 - 0
(60, 0): 0 - 0 - 0 - 0
(61, 0): 0 - 0 - 0 - 0
(62, 0): 0 - 0 - 0 - 0
(63, 0): 0 - 0 - 0 - 0
(64, 0): 0 - 0 - 0 - 0
(65, 0): 0 - 0 - 0 - 0
(66, 0): 0 - 0 - 0 - 0
(67, 0): 0 - 0 - 0 - 0
(68, 0): 0 - 0 - 0 - 0
(69, 0): 0 - 0 - 0 - 0
(70, 0): 0 - 0 - 0 - 0
(71, 0): 0 - 0 - 0 - 0
(72, 0): 0 - 0 - 0 - 0
(73, 0): 0 - 0 - 0 - 0
(74, 0): 0 - 0 - 0 - 0
(75, 0): 0 - 0 - 0 - 0
(76, 0): 0 - 0 - 0 - 0
(77, 0): 0 - 0 - 0 - 0
(78, 0): 0 - 0 - 0 - 0
(79, 0): 0 - 0 - 0 - 0
(80, 0): 0 - 0 - 0 - 0
(81, 0): 0 - 0 - 0 - 0
(82, 0): 0 - 0 - 0 - 0
(83, 0): 0 - 0 - 0 - 0
(84, 0): 0 - 0 - 0 - 0
(85, 0): 0 - 0 - 0 - 0
(86, 0): 0 - 0 - 0 - 0
(87, 0): 0 - 0 - 0 - 0
(88, 0): 0 - 0 - 0 - 0
(89, 0): 0 - 0 - 0 - 0
(90, 0): 0 - 0 - 0 - 0
(91, 0): 0 - 0 - 0 - 0
(92, 0): 0 - 0 - 0 - 0
(93, 0): 0 - 0 - 0 - 0
(94, 0): 0 - 0 - 0 - 0
(95, 0): 0 - 0 - 0 - 0
(96, 0): 0 - 0 - 0 - 0
(97, 0): 0 - 0 - 0 - 0
(98, 0): 0 - 0 - 0 - 0
(99, 0): 0 - 0 - 0 - 0
(100, 0): 0 - 0 - 0 - 0
(101, 0): 0 - 0 - 0 - 0
(102, 0): 0 - 0 - 0 - 0
(103, 0): 0 - 0 - 0 - 0
(104, 0): 0 - 0 - 0 - 0
(105, 0): 0 - 0 - 0 - 0
(106, 0): 0 - 0 - 0 - 0
(107, 0): 0 - 0 - 0 - 0
(108, 0): 0 - 0 - 0 - 0
(109, 0): 0 - 0 - 0 - 0
(110, 0): 0 - 0 - 0 - 0
(111, 0): 0 - 0 - 0 - 0
(112, 0): 0 - 0 - 0 - 0
(113, 0): 0 - 0 - 0 - 0
(114, 0): 0 - 0 - 0 - 0
(115, 0): 0 - 0 - 0 - 0
(116, 0): 0 - 0 - 0 - 0
(117, 0): 0 - 0 - 0 - 0
(118, 0): 0 - 0 - 0 - 0
(119, 0): 0 - 0 - 0 - 0
(120, 0): 0 - 0 - 0 - 0
(121, 0): 0 - 0 - 0 - 0
(122, 0): 0 - 0 - 0 - 0
(123, 0): 0 - 0 - 0 - 0
(124, 0): 0 - 0 - 0 - 0
(125, 0): 0 - 0 - 0 - 0
(126, 0): 0 - 0 - 0 - 0
(127, 0): 0 - 0 - 0 - 0
(128, 0): 0 - 0 - 0 - 0
(129, 0): 0 - 0 - 0 - 0
(130, 0): 0 - 0 - 0 - 0
(131, 0): 0 - 0 - 0 - 0
(132, 0): 0 - 0 - 0 - 0
(133, 0): 0 - 0 - 0 - 0
(134, 0): 0 - 0 - 0 - 0
(135, 0): 0 - 0 - 0 - 0
(136, 0): 0 - 0 - 0 - 0
(137, 0): 0 - 0 - 0 - 0
(138, 0): 0 - 0 - 0 - 0
(139, 0): 0 - 0 - 0 - 0
(140, 0): 0 - 0 - 0 - 0
(141, 0): 0 - 0 - 0 - 0
(142, 0): 0 - 0 - 0 - 0
(143, 0): 0 - 0 - 0 - 0
(144, 0): 0 - 0 - 0 - 0
(145, 0): 0 - 0 - 0 - 0
(146, 0): 0 - 0 - 0 - 0
(147, 0): 0 - 0 - 0 - 0
(148, 0): 0 - 0 - 0 - 0
(149, 0): 0 - 0 - 0 - 0
(150, 0): 0 - 0 - 0 - 0
(151, 0): 0 - 0 - 0 - 0
(152, 0): 0 - 0 - 0 - 0
(153, 0): 0 - 0 - 0 - 0
(154, 0): 0 - 0 - 0 - 0
(155, 0): 0 - 0 - 0 - 0
(156, 0): 0 - 0 - 0 - 0
(157, 0): 0 - 0 - 0 - 0
(158, 0): 0 - 0 - 0 - 0
(159, 0): 0 - 0 - 0 - 0
(160, 0): 0 - 0 - 0 - 0
(161, 0): 0 - 0 - 0 - 0
(162, 0): 0 - 0 - 0 - 0
(163, 0): 0 - 0 - 0 - 0
(164, 0): 0 - 0 - 0 - 0
(165, 0): 0 - 0 - 0 - 0
(166, 0): 0 - 0 - 0 - 0
(167, 0): 0 - 0 - 0 - 0
(168, 0): 0 - 0 - 0 - 0
(169, 0): 0 - 0 - 0 - 0
(170, 0): 0 - 0 - 0 - 0
(171, 0): 0 - 0 - 0 - 0
(172, 0): 0 - 0 - 0 - 0
(173, 0): 0 - 0 - 0 - 0
(174, 0): 0 - 0 - 0 - 0
(175, 0): 0 - 0 - 0 - 0
(176, 0): 0 - 0 - 0 - 0
(177, 0): 0 - 0 - 0 - 0
(178, 0): 0 - 0 - 0 - 0
(179, 0): 0 - 0 - 0 - 0
(180, 0): 0 - 0 - 0 - 0
(181, 0): 0 - 0 - 0 - 0
(182, 0): 0 - 0 - 0 - 0
(183, 0): 0 - 0 - 0 - 0
(184, 0): 0 - 0 - 0 - 0
(185, 0): 0 - 0 - 0 - 0
(186, 0): 0 - 0 - 0 - 0
(187, 0): 0 - 0 - 0 - 0
(188, 0): 0 - 0 - 0 - 0
(189, 0): 0 - 0 - 0 - 0
(190, 0): 0 - 0 - 0 - 0
(191, 0): 0 - 0 - 0 - 0
(192, 0): 0 - 0 - 0 - 0
(193, 0): 0 - 0 - 0 - 0
(194, 0): 0 - 0 - 0 - 0
(195, 0): 0 - 0 - 0 - 0
(196, 0): 0 - 0 - 0 - 0
(197, 0): 0 - 0 - 0 - 0
(198, 0): 0 - 0 - 0 - 0
(199, 0): 0 - 0 - 0 - 0
(200, 0): 0 - 0 - 0 - 0
(201, 0): 0 - 0 - 0 - 0
(202, 0): 0 - 0 - 0 - 0
(203, 0): 0 - 0 - 0 - 0
(204, 0): 0 - 0 - 0 - 0
(205, 0): 0 - 0 - 0 - 0
(206, 0): 0 - 0 - 0 - 0
(207, 0): 0 - 0 - 0 - 0
(208, 0): 0 - 0 - 0 - 0
(209, 0): 0 - 0 - 0 - 0
(210, 0): 0 - 0 - 0 - 0
(211, 0): 0 - 0 - 0 - 0
(212, 0): 0 - 0 - 0 - 0
(213, 0): 0 - 0 - 0 - 0
(214, 0): 0 - 0 - 0 - 0
(215, 0): 0 - 0 - 0 - 0
(216, 0): 0 - 0 - 0 - 0
(217, 0): 0 - 0 - 0 - 0
(218, 0): 0 - 0 - 0 - 0
(219, 0): 0 - 0 - 0 - 0
(220, 0): 0 - 0 - 0 - 0
(221, 0): 0 - 0 - 0 - 0
(222, 0): 0 - 0 - 0 - 0
(223, 0): 0 - 0 - 0 - 0
(224, 0): 0 - 0 - 0 - 0
(225, 0): 0 - 0 - 0 - 0
(226, 0): 0 - 0 - 0 - 0
(227, 0): 0 - 0 - 0 - 0
(228, 0): 0 - 0 - 0 - 0
(229, 0): 0 - 0 - 0 - 0
(230, 0): 0 - 0 - 0 - 0
(231, 0): 0 - 0 - 0 - 0
(232, 0): 0 - 0 - 0 - 0
(233, 0): 0 - 0 - 0 - 0
(234, 0): 0 - 0 - 0 - 0
(235, 0): 0 - 0 - 0 - 0
(236, 0): 0 - 0 - 0 - 0
(237, 0): 0 - 0 - 0 - 0
(238, 0): 0 - 0 - 0 - 0
(239, 0): 0 - 0 - 0 - 0
(240, 0): 0 - 0 - 0 - 0
(241, 0): 0 - 0 - 0 - 0
(242, 0): 0 - 0 - 0 - 0
(243, 0): 0 - 0 - 0 - 0
(244, 0): 0 - 0 - 0 - 0
(245, 0): 0 - 0 - 0 - 0
(246, 0): 0 - 0 - 0 - 0
(247, 0): 0 - 0 - 0 - 0
(248, 0): 0 - 0 - 0 - 0
(249, 0): 0 - 0 - 0 - 0
(250, 0): 0 - 0 - 0 - 0
(251, 0): 0 - 0 - 0 - 0
(252, 0): 0 - 0 - 0 - 0
(253, 0): 0 - 0 - 0 - 0
(254, 0): 0 - 0 - 0 - 0
(255, 0): 0 - 0 - 0 - 255

All of the buckets are 0 except the last alpha value. And I wonder if anyone has ever used this filter, and is kind enough to explain to me... Big thanks!

Prakrit answered 7/7, 2014 at 15:11 Comment(0)
K
1

I've written a post on how to do this here: http://shapeof.com/archives/2011/08/drawing_a_histogram_with_core_image.html

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.

Kurdistan answered 26/10, 2014 at 16:26 Comment(0)
F
1

When using Core Image (which you should do in your case), the format argument of a context determines what gobbledegook is returned by code that enables pixel-by-pixel processing.

Having chosen the right format, here's the code I used to access output from the CIAreaHistogram:

    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]);
    }
}
Fiat answered 29/4, 2015 at 1:58 Comment(0)
S
0

You need to pass the pixel as a reference.

[imgRep getPixel:&pixel atX:x y:y];
Sofko answered 22/10, 2014 at 13:2 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.