我不知道如何使用NSImage
和CIAreaHistogram
过滤器从CIHistogramDisplayFilter
输入中获取实际,有意义的直方图图像。
我在这里阅读了Apple的“核心图像过滤器参考”和相关帖子,但无论我尝试什么,我都没有得到有意义的输出。
到目前为止,这是我的代码:
- (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;
}
我得到的是具有零表示(=不可见)的64x100图像。如果我使用
创建CI上下文CIContext *context = [[CIContext alloc] init];
然后生成的图像是灰色的,但至少它确实有一个表示:
Histogram image: <NSImage 0x6100002612c0 Size={64, 100} Reps=(
"<NSCGImageSnapshotRep:0x6100002620c0 cgImage=<CGImage 0x6100001a1880>>" )>
输入图像是1024x768 JPEG图像。
我对Core Image或Core Graphics几乎没有经验,所以错误可能是转换回NSImage ......有什么想法吗?
编辑 2016-10-26:通过rickster非常全面的答案,我能够取得很大的进步。
确实是inputExtent
参数弄乱了我的结果。提供CIVector
解决了问题。我发现你不能把它留到默认值;我不知道默认值是什么,但它不是输入图像的完整大小。 (我发现通过过滤器运行图像和镜像版本;我得到了不同的直方图。)
修改 2016-10-28:
所以,我现在有一个可用的,可显示的直方图;我的下一步是弄清楚“中间”直方图(来自滤波器的256x1像素图像)如何能够包含实际的直方图信息,即使除了最后一个像素之外的所有直方图总是(0,0,0,0)。
答案 0 :(得分:1)
我认为代码中的[image bitmapImageRepresentation]
是一个大致相当于(NSBitmapImageRep *)image.representations[0]
的本地类别方法?否则,首先要确保您获得了正确的输入。
接下来,看起来您将ciImage.extent
的原始输出传递给过滤器参数 - 假设所述参数需要CIVector
对象而不是CGRect
结构,那么'可能在运行时将输入结果插入过滤器。通过使用基于字典的过滤方法filterWithName:withInputParameters
或imageByApplyingFilter:withInputParameters:
,您可以获得更有用的此类问题诊断 - 如果您尝试将nil
传递给过滤器密钥或通过一些不是正确对象的东西,你会得到一个编译时错误。后者为您提供了一种简单的方法,可以直接从输入图像到输出图像或链式过滤器,而无需创建中间CIFilter
个对象,并且需要在每个对象上设置输入图像。
相关提示:您传递的大多数参数都是这些过滤器的默认值,因此您只能传递所需的值:
CIImage *hist = [inputImage imageByApplyingFilter:@"CIAreaHistogram"
withInputParameters:@{ @"inputCount": @256 }];
CIImage *outputImage = [hist imageByApplyingFilter:@"CIHistogramDisplayFilter"
withInputParameters:nil];
最后,根据您的输入图像的样子,您可能仍会从CIHistogramDisplayFilter
获得几乎 - 全灰色图像,因为所有直方图区间可能都有非常小的条形图。我为Lenna得到以下信息:
增加kCIInputScaleKey
的值可以帮助解决这个问题。
此外,您无需通过CGImage
即可从CIImage
转到NSImage
- 创建NSCIImageRep
而AppKit会自动管理CIContext
当需要为显示/输出渲染图像时,在幕后。
// 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];