Wie erhalte ich eine aussagekräftige CIAreaHistogram-Ausgabe?

Ich möchte das Histogramm eines @ berechnCGImage. Ich benutze dasCIAreaHistogram Built-inCoreImage filter.

Justin Mrkva hat @ getetwas in ähnlicher Richtung. Er sagt

Ich erhalte das CIImage für das Histogramm selbst, das ich dann durch einen benutzerdefinierten Kernel (siehe Ende des Beitrags) laufe, um die Alpha-Werte auf 1 zu setzen (da sonst der Alpha-Wert aus den Histogramm-Berechnungen vormultipliziert wird) und konvertiere es dann in ein NSBitmapImageRep .

Meine Frage ist: Ist es möglich, die Histogrammdaten abzurufen, ohne einen benutzerdefinierten Kernel erstellen zu müssen? Wenn das so ist, wie

Der folgende Code versucht einfach, das Histogramm zu rendern, ohne die Alpha-Werte zu ändern:

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

}   

Geben der Ausgabe (bei Ausführung auf einem Farbfoto):

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

Ich habe versucht mitCIColorMatrix, um die Alpha-Werte vor dem Rendern auf 1.0 zu setzen:

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

Auch wenn das Ausgabeformat ARGB ist, ist die Alpha-Komponente nach dem, was ich aus der Core Image Filter Reference verstehe, der letzte Wert im Vektor (alsoW:1.0).

Aber dies ergab die folgende Ausgabe:

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

Alle Hilfe und Ratschläge werden sehr geschätzt!

EDIT: Ich weißdiese Frag scheint ähnlich. Die akzeptierte Antwort lautet jedoch:

Das kurze daran ist: Sie müssen die Werte als Float und nicht als Ints lesen, was bedeutet, dass Sie einen CGBitmapContext anschließen müssen, mit dem Sie blitten möchten. Oder wenn Sie alles im CI-Land behalten, benötigen Sie einen weiteren Filter, um die Daten zu lesen und etwas damit auszudrucken.

Jedoch auf der Suche nach Justin Mrkva die Frage lässt mich denken, dass es möglich sein sollte, ganzzahlige Werte zu erhalten ... Bitte lassen Sie mich wissen, wenn ein Fehler in meinem Denken vorliegt.

Danke noch einmal

EDIT 2: Zunächst einmal vielen Dank an David und jstn für ihre Kommentare. Es tut mir leid, dass ich so lange gebraucht habe, um darauf zurückzukommen. Ich habe rund um die Uhr an einem Projekt gearbeitet (tatsächlich hat mich dieses Projekt zu diesem Problem geführt, aber ich habe einen völlig anderen Ansatz gewählt, bei dem CIAreaHistogram nicht mehr verwendet wird). Jetzt, da ich endlich Zeit habe, wollte ich darauf zurückkommen. Auch wenn ich nichtbrauche it per se, ich möchte immer noch verstehen, wie das Ding wirklich funktioniert!

Folgend den Vorschlägen von David Hayward habe ich die folgenden Änderungen vorgenommen.

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

Dies ergibt die folgende Ausgabe:

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

Das Spielen mit verschiedenen Formaten und das Analysieren von Informationen führt zu völlig unterschiedlichen und absurden Ergebnissen.

Ich bin mir ziemlich sicher, dass das Problem darin liegt, nicht genau zu verstehen, wie die Bitmap-Daten dargestellt werden.

Irgendwelche weiteren Vorschläge?

Antworten auf die Frage(12)

Ihre Antwort auf die Frage