2016-10-24 1 views
0

Irgendwie kann ich nicht herausfinden, ein tatsächliches, aussagekräftiges Histogramm Bild von einem NSImage Eingang mit den CIAreaHistogram und CIHistogramDisplayFilter Filter zu bekommen.Working CIAreaHistogram/CIHistogramDisplayFilter Beispiel für NSImage

Ich lese Apples "Core Image Filter Reference" und die relevanten Beiträge hier auf SO, aber was auch immer ich versuche, ich bekomme keine sinnvolle Ausgabe.

Hier ist mein Code so weit:

- (void) testHist3:(NSImage *)image { 

    CIContext* context = [[NSGraphicsContext currentContext] CIContext]; 

    NSBitmapImageRep *rep = [image bitmapImageRepresentation]; 
    CIImage *ciImage = [[CIImage alloc] initWithBitmapImageRep:rep]; 


    ciImage = [CIFilter filterWithName:@"CIAreaHistogram" keysAndValues:kCIInputImageKey, ciImage, @"inputExtent", ciImage.extent, @"inputScale", [NSNumber numberWithFloat:1.0], @"inputCount", [NSNumber numberWithFloat:256.0], nil].outputImage; 
    ciImage = [CIFilter filterWithName:@"CIHistogramDisplayFilter" keysAndValues:kCIInputImageKey, ciImage, @"inputHeight", [NSNumber numberWithFloat:100.0], @"inputHighLimit", [NSNumber numberWithFloat:1.0], @"inputLowLimit", [NSNumber numberWithFloat:0.0], nil].outputImage; 


    CGImageRef cgImage2 = [context createCGImage:ciImage fromRect:ciImage.extent]; 
    NSImage *img2 = [[NSImage alloc] initWithCGImage:cgImage2 size:ciImage.extent.size]; 

    NSLog(@"Histogram image: %@", img2); 
    self.histImage = img2; 


} 

Was ich erhalte, ist ein 64x100 Bild mit Null Darstellungen (= unsichtbar). Wenn ich den CI Zusammenhang mit

CIContext *context = [[CIContext alloc] init]; 

dann dem resultierenden Bild zu erstellen ist grau, aber zumindest hat es eine Darstellung hat:

Histogram image: <NSImage 0x6100002612c0 Size={64, 100} Reps=(
    "<NSCGImageSnapshotRep:0x6100002620c0 cgImage=<CGImage 0x6100001a1880>>")> 

Das Eingangsbild ist ein 1024x768 JPEG-Bild.

Ich habe wenig Erfahrung mit Core Image oder Core Graphics, also könnte der Fehler mit der Konvertierung zurück zu NSImage sein ... irgendwelche Ideen?


bearbeiten 2016.10.26: Mit sehr umfassenden Antwort des rickster konnte ich viele Fortschritte machen.

In der Tat war es der inputExtent Parameter, der mein Ergebnis durcheinander brachte. Die Lieferung eines CIVector dort löste das Problem. Ich habe festgestellt, dass Sie das auch nicht auf den Standard setzen können; Ich weiß nicht, wie der Standardwert ist, aber es ist nicht die volle Größe des Eingabebildes. (Ich fand heraus, indem sie ein Bild und eine gespiegelte Version davon durch den Filter läuft, ich verschiedene Histogramme bekam.)

bearbeiten 2016.10.28:

So habe ich eine Arbeits bekam , anzeigbares Histogramm jetzt; Mein nächster Schritt wird sein, herauszufinden, wie das "intermediäre" Histogramm (das 256x1 Pixel Bild, das aus dem Filter kommt) die tatsächliche Histogramminformation enthalten kann, obwohl alle außer dem letzten Pixel immer (0, 0, 0, 0) sind.

Antwort

1

Ich nehme an, die [image bitmapImageRepresentation] in Ihrem Code ist eine lokale Kategorie-Methode, die in etwa entspricht (NSBitmapImageRep *)image.representations[0]? Stellen Sie andernfalls sicher, dass Sie die richtige Eingabe erhalten.

Als nächstes sieht es aus wie Sie die Rohausgangssignal von ciImage.extent in Ihre Filterparameter vorbei sind - gegeben, dass der Parameter erwartet ein CIVector Objekt und keine CGRect Struktur, sind Sie wahrscheinlich den Eingang zu Ihrem Filter zur Laufzeit Borking . Mit den wörterbuchbasierten Filtermethoden filterWithName:withInputParameters oder imageByApplyingFilter:withInputParameters: können Sie ein wenig mehr nützliche Diagnosen für solche Probleme bekommen - wenn Sie also versuchen, nil für einen Filterschlüssel zu übergeben oder etwas zu übergeben, das kein richtiges Objekt ist, werden Sie Erhalte einen Fehler bei der Kompilierung. Letzteres bietet Ihnen eine einfache Möglichkeit, direkt vom Eingabebild zum Ausgabebild oder Kettenfilter zu gelangen, ohne dazwischenliegende CIFilter Objekte zu erstellen und das Eingabebild auf jedes zu setzen.

Ein verwandtes Tipp: die meisten Parameter sind Sie vorbei die Standardwerte für die Filter, so dass Sie nur die Werte passieren können benötigen Sie:

CIImage *hist = [inputImage imageByApplyingFilter:@"CIAreaHistogram" 
           withInputParameters:@{ @"inputCount": @256 }]; 
CIImage *outputImage = [hist imageByApplyingFilter:@"CIHistogramDisplayFilter" 
           withInputParameters:nil]; 

Schließlich könnte man noch eine bekommen fast -all-graues Bild aus CIHistogramDisplayFilter, abhängig davon, wie das Eingabebild aussieht, da alle Histogramm-Bins sehr kleine Balken haben können. Ich werde nach dem für Lenna:

small bars histogram

den Wert für kCIInputScaleKey Erhöhung kann dabei helfen.


Auch Sie müssen nicht durch CGImage gehen CIImage-NSImage zu bekommen - erstellen Sie ein NSCIImageRep statt und AppKit wird automatisch ein CIContext hinter den Kulissen verwalten, wenn es Zeit für die Anzeige um das Bild aufzubereiten/Ausgabe.

// input from NSImage 
NSBitmapImageRep *inRep = [nsImage bitmapImageRepresentation]; 
CIImage *inputImage = [[CIImage alloc] initWithBitmapImageRep:inRep]; 

CIImage *outputImage = // filter, rinse, repeat 

// output to NSImage 
NSCIImageRep *outRep = [NSCIImageRep imageRepWithCIImage: outputImage]; 
NSImage *outNSImage = [[NSImage alloc] init]; 
[outNSImage addRepresentation: outRep];