请注意:这适用于在Mac OSX上运行的Cocoa命令行应用,不是iOS应用
我在尝试理解Apple为 CISpotColor 过滤器提供的Limited Documentation时遇到了一些麻烦(使用 CIFilter )。
1)是否有更多关于CIFilter遗漏的文档,特别是CISpotColor?
2)鉴于我想要实现的目标(如下图所示,但简要说明:更换所有不会"看起来红色"白色,并强制每一件事情看起来都是红色的(ish) )"要么是纯红色,要么只是黑色,是CISpotColor我应该使用的正确过滤器吗?
3)如果没有,你建议使用哪种过滤器(或者我应该尝试编写自定义过滤器?)
4)如果CISSpotColor是正确的过滤器,我应该使用哪些参数来实现我想要实现的目标。如果我需要使用CISpotColor CIFilter的几个通道,那很好,我不希望你为我编码,只是指出我正确的方向。
link above给出了参数列表,一些默认值以及图片之前和之后的示例,但没有示例代码在图像之后生成样本,并且没有解释参数实际意味着什么,或者什么他们的有效范围是。
老实说,我不完全确定CISpotColor是否是我所追求的过滤器,除了它的名称,以及句子" 用专色替换一个或多个颜色范围",没有解释它是如何做的。
因为它似乎描述了我所追求的过滤器,所以我选择它作为起点,以这种方式使用过滤器。
输入图片(视频中的一帧)
所需的输出(选项1 - 纯红色 - 使用GIMP创建)
所需的输出(选项2 - 纯黑色 - 也使用GIMP创建)
我的代码获得了什么(请参阅下面的列表)
这接近我所需要的,但它似乎没有考虑到灰色或白色区域的事实。在原始图像中将具有相似数量的红色,绿色和蓝色,而不是主要是红色,这将使其看起来红色"。我可以使用它,如果它过滤掉你在右下角看到的区域,这显然只是被包括在内,因为那里有一些红色像素(以及一些绿色和蓝色,使其在原始中通常为灰色)
这是完整的" main.m"用于cocoa命令行应用程序(Mac OSX)
#import <Foundation/Foundation.h>
#import <CoreGraphics/CoreGraphics.h>
#import <AppKit/AppKit.h>
#import <QuartzCore/QuartzCore.h>
@interface NSImage(saveAsJpegWithName)
- (void) saveAsPNGWithName:(NSString*) fileName;
- (NSImage*) filterEverythingButRed ;
@end
@implementation NSImage(saveAsJpegWithName)
- (void) saveAsPNGWithName:(NSString*) fileName
{
NSData *imageData = [self TIFFRepresentation];
NSBitmapImageRep *imageRep = [NSBitmapImageRep imageRepWithData:imageData];
NSDictionary *imageProps = nil;
imageData = [imageRep representationUsingType:NSPNGFileType properties:imageProps];
[imageData writeToFile:fileName atomically:NO];
}
-(NSImage*) filterEverythingButRed {
CIImage *inputImage = [[CIImage alloc] initWithData:[self TIFFRepresentation]];
CIFilter *hf = [CIFilter filterWithName:@"CISpotColor"];
[hf setDefaults];
[hf setValue:inputImage forKey:@"inputImage"];
[hf setValue:[CIColor colorWithRed:1.0 green:0.0 blue:0.0] forKey: @"inputCenterColor1"];
[hf setValue:[CIColor colorWithRed:1.0 green:0.0 blue:0.0] forKey: @"inputReplacementColor1"];
[hf setValue:[NSNumber numberWithFloat:0.1] forKey: @"inputCloseness1"];
[hf setValue:[NSNumber numberWithFloat:1.0] forKey: @"inputContrast1"];
CIImage *outputImage = [hf valueForKey: @"outputImage"];
NSImage *resultImage = [[NSImage alloc] initWithSize:[outputImage extent].size];
NSCIImageRep *rep = [NSCIImageRep imageRepWithCIImage:outputImage];
[resultImage addRepresentation:rep];
return resultImage;
}
@end
int main(int argc, const char * argv[]) {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
if (argc == 1) {
NSString * appname = [NSString stringWithFormat: @"%s", argv[0]];
NSLog(@"Usage: %@ filename", appname);
} else {
NSString * filename = [NSString stringWithFormat: @"%s", argv[1]];
NSFileManager *fm = [NSFileManager defaultManager];
if ([fm fileExistsAtPath:filename]) {
NSLog(@"opening file:%@", filename);
NSImage *img = [[NSImage alloc] initWithContentsOfFile:filename];
[[img filterEverythingButRed]
saveAsPNGWithName:[[filename stringByDeletingPathExtension] stringByAppendingString:@"-red.png"]];
} else {
NSLog(@"file not found:%@", filename);
}
}
[pool release];
return 0;
}
答案 0 :(得分:1)
CISpotColor
基本上可以进行四种颜色操作:
inputCenterColor1
附近的所有颜色替换为inputReplacementColor1
。inputCenterColor2
附近的所有颜色替换为inputReplacementColor2
。inputCenterColor3
附近的所有颜色替换为inputReplacementColor3
。默认情况下,输入颜色设置为各种偏红/粉红色调。您可以通过在构建代码后检查代码中的这些过滤器值并调用setDefaults
来找到这些值 - 但为了便于说明,这里是Core Image Fun House示例中屏幕截图中的所有默认值代码应用程序:
使用默认选项应用过滤器可以获得:
请注意,红色环(您尝试成为图像中唯一剩余元素的部分)看起来像默认inputReplacementColor3
,右下方的亮起区域看起来像默认inputReplacementColor2
......就像在your output image中一样。这是因为您只配置了第一对中心/替换颜色,并且您将其他两个颜色保留为红色/粉红色默认值。
如果要禁用第二和第三种颜色替换,请将 Closeness 参数降低到0.0和/或将 Contrast 参数调高至1.0。为安全起见,您还可以将中心颜色设置为不会出现在图像中的内容。在您的测试图片中,我发现只需关闭 Closeness 即可:
这会得到以下输出:
顺便说一句,像这样的专色替换是一种简单形式的Color LookUp Table(CLUT)操作,由CIColorCube
过滤器实现。如果您希望能够在CISpotColor
提供的范围之外微调颜色替换,那么颜色立方体选项可能是一个不错的选择。有关于将其用于绿屏效果的教程in Apple's programming guide。
为所有过滤器参数设置适当的值,而不仅仅是前几个,或者其他默认值可能会做您不期望的事情。将inputCloseness2
和inputCloseness3
设置为零并将其他所有内容设置为默认值(但对于您已设置的input...1
参数)似乎适用于您的测试图像。
为过滤器提供实时测试环境确实可以帮助您微调参数(并确保默认值符合您的预期)。 Core Image Fun House非常适合。
答案 1 :(得分:-1)
你是对的,仍然没有文件。例如,使用“核心图像娱乐屋”作为您的信息来源不会给您一个指示,您输入点1中的颜色,以及输入点2中的哪种颜色非常重要...切换它们会给你一个结果差异很大,我在这个特殊的过滤器中发现了更多的问题。就像某些参数的“最大”值一样,代码更像是你所谓的“指南”而非实际规则。 :)使用“有趣的房子”作为一个来源,会让你失去一个有大约10个出口的兔子洞,没有迹象告诉你这些出口在哪里。
这里有一些注意事项,我通过在这个过滤器中投入疯狂的数字,看到什么“卡在墙上”。 (如果有人选择,则需要更多)
//------------------------- picked up a red ski helmet in full sun, included all shadows on helmet, and some yellow from sun.. near perfect mask, but also picked up most skin tones.
//-------------------------- used a color from the helmet color: 0.662745 0.188235 0.223529 1.0 then stretched values to normalize to have one color 1.0 --------------
CIFilter *clampFilter1 = [CIFilter filterWithName:@"CISpotColor"];
[clampFilter1 setValue:[CIColor colorWithRed:1.0 green:0.09 blue:0.33] forKey: @"inputCenterColor1"];
[clampFilter1 setValue:[CIColor colorWithRed:1.0 green:0.0 blue:0.0 alpha:1.0] forKey: @"inputReplacementColor1"];
[clampFilter1 setValue:@(0.86) forKey: @"inputCloseness1"];
[clampFilter1 setValue:@(1.00) forKey: @"inputContrast1"];
[clampFilter1 setValue:@(0.00) forKey: @"inputCloseness2"];
[clampFilter1 setValue:@(1.00) forKey: @"inputContrast2"];
[clampFilter1 setValue:[CIColor colorWithRed:0.00 green:1.0 blue:0.56] forKey: @"inputCenterColor3"];
[clampFilter1 setValue:[CIColor colorWithRed:1.0 green:1.0 blue:1.0 alpha:1.0] forKey: @"inputReplacementColor3"];
[clampFilter1 setValue:@(1.00) forKey: @"inputCloseness3"];
[clampFilter1 setValue:@(1.00) forKey: @"inputContrast3"];
//---------------------------- picked up a blue jacket total, including all the shadows, a near perfect mask of a fairly blue jacket all ranges ---------------------------
[clampFilter1 setValue:[CIColor colorWithRed:0.01 green:0.165 blue:1.0] forKey: @"inputCenterColor1"];
[clampFilter1 setValue:[CIColor colorWithRed:0.0 green:0.0 blue:1.0 alpha:1.0] forKey: @"inputReplacementColor1"];
[clampFilter1 setValue:@(0.86) forKey: @"inputCloseness1"];
[clampFilter1 setValue:@(1.0) forKey: @"inputContrast1"];
//---------------------------- did not need this input but experimenting and left it in to add other changes, same with below experiments ---------------------------
[clampFilter1 setValue:[CIColor colorWithRed:0.01 green:0.165 blue:1.0] forKey: @"inputCenterColor2"];
[clampFilter1 setValue:[CIColor colorWithRed:0.0 green:0.0 blue:1.0 alpha:1.0] forKey: @"inputReplacementColor2"];
[clampFilter1 setValue:@(0.86) forKey: @"inputCloseness2"];
[clampFilter1 setValue:@(1.0) forKey: @"inputContrast2"];
[clampFilter1 setValue:[CIColor colorWithRed:1.0 green:0.5 blue:0.5] forKey: @"inputCenterColor3"];
[clampFilter1 setValue:[CIColor colorWithRed:1.0 green:1.0 blue:1.0 alpha:1.0] forKey: @"inputReplacementColor3"];
[clampFilter1 setValue:@(0.99) forKey: @"inputCloseness3"];
[clampFilter1 setValue:@(0.99) forKey: @"inputContrast3"];
//---------------------------- picked up all reds, total, including some purples, also picked up all skin tones -----------------------------------------------------------
[clampFilter1 setValue:[CIColor colorWithRed:1.0 green:0.0 blue:0.0] forKey: @"inputCenterColor1"];
[clampFilter1 setValue:[CIColor colorWithRed:1.0 green:0.0 blue:0.0 alpha:1.0] forKey: @"inputReplacementColor1"];
[clampFilter1 setValue:@(0.90) forKey: @"inputCloseness1"];
[clampFilter1 setValue:@(1.00) forKey: @"inputContrast1"];
[clampFilter1 setValue:[CIColor colorWithRed:1.0 green:0.0 blue:0.0] forKey: @"inputCenterColor2"];
[clampFilter1 setValue:[CIColor colorWithRed:1.0 green:0.0 blue:0.0 alpha:1.0] forKey: @"inputReplacementColor2"];
[clampFilter1 setValue:@(0.90) forKey: @"inputCloseness2"];
[clampFilter1 setValue:@(1.00) forKey: @"inputContrast2"];
[clampFilter1 setValue:[CIColor colorWithRed:1.0 green:0.0 blue:0.0] forKey: @"inputCenterColor3"];
[clampFilter1 setValue:[CIColor colorWithRed:1.0 green:0.0 blue:0.0 alpha:1.0] forKey: @"inputReplacementColor3"];
[clampFilter1 setValue:@(0.90) forKey: @"inputCloseness3"];
[clampFilter1 setValue:@(1.00) forKey: @"inputContrast3"];
//---------------------------- removed all reds, total, turned all blues all ranges.. to green -----------------------------------------------------------
[clampFilter1 setValue:[CIColor colorWithRed:0.0 green:1.0 blue:0.0] forKey: @"inputCenterColor1"];
[clampFilter1 setValue:[CIColor colorWithRed:0.0 green:1.0 blue:0.0 alpha:1.0] forKey: @"inputReplacementColor1"];
[clampFilter1 setValue:@(0.90) forKey: @"inputCloseness1"];
[clampFilter1 setValue:@(1.00) forKey: @"inputContrast1"];
[clampFilter1 setValue:[CIColor colorWithRed:0.0 green:1.0 blue:0.0] forKey: @"inputCenterColor2"];
[clampFilter1 setValue:[CIColor colorWithRed:0.0 green:1.0 blue:0.0 alpha:1.0] forKey: @"inputReplacementColor2"];
[clampFilter1 setValue:@(0.90) forKey: @"inputCloseness2"];
[clampFilter1 setValue:@(1.00) forKey: @"inputContrast2"];
[clampFilter1 setValue:[CIColor colorWithRed:0.0 green:1.0 blue:0.0] forKey: @"inputCenterColor3"];
[clampFilter1 setValue:[CIColor colorWithRed:0.0 green:1.0 blue:0.0 alpha:1.0] forKey: @"inputReplacementColor3"];
[clampFilter1 setValue:@(0.90) forKey: @"inputCloseness3"];
[clampFilter1 setValue:@(1.00) forKey: @"inputContrast3"];
//---------------------------- removed most reds, but skin still some tint, turned all blues all ranges to green -----------------------------------------------------------
[clampFilter1 setValue:[CIColor colorWithRed:0.0 green:1.0 blue:0.0] forKey: @"inputCenterColor1"];
[clampFilter1 setValue:[CIColor colorWithRed:0.0 green:1.0 blue:0.0 alpha:1.0] forKey: @"inputReplacementColor1"];
[clampFilter1 setValue:@(0.90) forKey: @"inputCloseness1"];
[clampFilter1 setValue:@(1.00) forKey: @"inputContrast1"];
[clampFilter1 setValue:[CIColor colorWithRed:0.0 green:1.0 blue:0.0] forKey: @"inputCenterColor2"];
[clampFilter1 setValue:[CIColor colorWithRed:0.0 green:1.0 blue:0.0 alpha:1.0] forKey: @"inputReplacementColor2"];
[clampFilter1 setValue:@(0.90) forKey: @"inputCloseness2"];
[clampFilter1 setValue:@(0.80) forKey: @"inputContrast2"];
[clampFilter1 setValue:[CIColor colorWithRed:0.0 green:1.0 blue:0.0] forKey: @"inputCenterColor3"];
[clampFilter1 setValue:[CIColor colorWithRed:0.0 green:1.0 blue:0.0 alpha:1.0] forKey: @"inputReplacementColor3"];
[clampFilter1 setValue:@(0.90) forKey: @"inputCloseness3"];
[clampFilter1 setValue:@(0.99) forKey: @"inputContrast3"];
//---------------------------- picked up shadow blue/purple replaced with green -----------------------------------------------------------
[clampFilter1 setValue:[CIColor colorWithRed:0.0 green:1.0 blue:0.0] forKey: @"inputCenterColor1"];
[clampFilter1 setValue:[CIColor colorWithRed:0.0 green:1.0 blue:0.0 alpha:1.0] forKey: @"inputReplacementColor1"];
[clampFilter1 setValue:@(0.90) forKey: @"inputCloseness1"];
[clampFilter1 setValue:@(1.00) forKey: @"inputContrast1"];
[clampFilter1 setValue:[CIColor colorWithRed:0.0 green:1.0 blue:0.0] forKey: @"inputCenterColor2"];
[clampFilter1 setValue:[CIColor colorWithRed:0.0 green:1.0 blue:0.0 alpha:1.0] forKey: @"inputReplacementColor2"];
[clampFilter1 setValue:@(0.90) forKey: @"inputCloseness2"];
[clampFilter1 setValue:@(0.80) forKey: @"inputContrast2"];
[clampFilter1 setValue:[CIColor colorWithRed:1.0 green:0.0 blue:0.0] forKey: @"inputCenterColor3"];
[clampFilter1 setValue:[CIColor colorWithRed:1.0 green:0.0 blue:0.0 alpha:1.0] forKey: @"inputReplacementColor3"];
[clampFilter1 setValue:@(0.90) forKey: @"inputCloseness3"];
[clampFilter1 setValue:@(0.99) forKey: @"inputContrast3"];