什么是最好的Core Image滤镜来产生黑白效果?

32

我正在使用Core Image,并希望对所选图像产生黑白效果。

理想情况下,我希望能够使用类似于Photoshop中可用的选项,例如:红色、青色、绿色、蓝色和品红。目标是创建不同类型的黑白效果。

有人知道最好的滤镜是哪个来操纵这些选项吗?如果没有,有人知道使用其他滤镜创建黑白效果的好方法吗?

谢谢

Oliver

8个回答

57
- (UIImage *)imageBlackAndWhite
{
    CIImage *beginImage = [CIImage imageWithCGImage:self.CGImage];

    CIImage *blackAndWhite = [CIFilter filterWithName:@"CIColorControls" keysAndValues:kCIInputImageKey, beginImage, @"inputBrightness", [NSNumber numberWithFloat:0.0], @"inputContrast", [NSNumber numberWithFloat:1.1], @"inputSaturation", [NSNumber numberWithFloat:0.0], nil].outputImage;
    CIImage *output = [CIFilter filterWithName:@"CIExposureAdjust" keysAndValues:kCIInputImageKey, blackAndWhite, @"inputEV", [NSNumber numberWithFloat:0.7], nil].outputImage; 

    CIContext *context = [CIContext contextWithOptions:nil];
    CGImageRef cgiimage = [context createCGImage:output fromRect:output.extent];
    //UIImage *newImage = [UIImage imageWithCGImage:cgiimage];
    UIImage *newImage = [UIImage imageWithCGImage:cgiimage scale:image.scale orientation:image.imageOrientation];
    CGImageRelease(cgiimage);

    return newImage;
}

更新: 对于 iOS6,有一个 CIColorMonochrome 滤镜,但我试用后发现它不如我的效果好。


1
如果有人感兴趣,我在这里使用了它 https://github.com/codler/Battery-Time-Remaining/commit/4d0ce73d7b1e954fefba7cbda339b67d77a405d0 - Codler
2
@Codler 在阅读了您关于它在Yosemite上无法工作的评论后,我有点想到它在iOS 8上也不会工作。然而,我刚刚测试了一下,并发现它仍然可以完美地在iOS 8上工作 - 甚至保留了图层透明度。但是,我更新了这行代码: UIImage *newImage = [UIImage imageWithCGImage:cgiimage]; 在我的代码中改为: UIImage *newImage = [UIImage imageWithCGImage:cgiimage scale:image.scale orientation:image.imageOrientation]; 以便我可以保留比例和方向。 - u2Fan

14

这里有一个使用CIColorMonochrome的例子。

- (UIImage *)imageBlackAndWhite
{
    CIImage *beginImage = [CIImage imageWithCGImage:self.CGImage];

    CIImage *output = [CIFilter filterWithName:@"CIColorMonochrome" keysAndValues:kCIInputImageKey, beginImage, @"inputIntensity", [NSNumber numberWithFloat:1.0], @"inputColor", [[CIColor alloc] initWithColor:[UIColor whiteColor]], nil].outputImage;

    CIContext *context = [CIContext contextWithOptions:nil];
    CGImageRef cgiimage = [context createCGImage:output fromRect:output.extent];
    UIImage *newImage = [UIImage imageWithCGImage:cgiimage scale:self.scale orientation:self.imageOrientation];

    CGImageRelease(cgiimage);

    return newImage;
}

inputIntensity 默认为 1,无需手动设置。 - Rudolf Adamkovič

8

下面是将排名前的解决方案转换成Swift(适用于iOS 7及以上版本):

func blackAndWhiteImage(image: UIImage) -> UIImage {
    let context = CIContext(options: nil)
    let ciImage = CoreImage.CIImage(image: image)!

    // Set image color to b/w
    let bwFilter = CIFilter(name: "CIColorControls")!
    bwFilter.setValuesForKeysWithDictionary([kCIInputImageKey:ciImage, kCIInputBrightnessKey:NSNumber(float: 0.0), kCIInputContrastKey:NSNumber(float: 1.1), kCIInputSaturationKey:NSNumber(float: 0.0)])
    let bwFilterOutput = (bwFilter.outputImage)!

    // Adjust exposure
    let exposureFilter = CIFilter(name: "CIExposureAdjust")!
    exposureFilter.setValuesForKeysWithDictionary([kCIInputImageKey:bwFilterOutput, kCIInputEVKey:NSNumber(float: 0.7)])
    let exposureFilterOutput = (exposureFilter.outputImage)!

    // Create UIImage from context
    let bwCGIImage = context.createCGImage(exposureFilterOutput, fromRect: ciImage.extent)
    let resultImage = UIImage(CGImage: bwCGIImage, scale: 1.0, orientation: image.imageOrientation)

    return resultImage
}

8
为了创建纯单色效果,我使用了CIColorMatrix,其中R、G和B向量参数都设置为(0.2125, 0.7154, 0.0721, 0),而alpha和bias向量则保留其默认值。
这些值是我在互联网上查找的RGB到灰度转换系数。通过更改这些系数,您可以更改输入通道的贡献。通过缩放每个向量的副本,并可选地设置偏置向量,您可以着色输出。

任何人都可以查看此帖子以了解如何使用 CIColorMatrix:https://dev59.com/e2DVa4cB1Zd3GeqPh-6Z - guozqzzu

4

3

以下是@Shmidt的UIImage扩展,使用Swift编写并进行了性能更新,这是最受欢迎的答案:

import CoreImage

extension UIImage
{
    func imageBlackAndWhite() -> UIImage?
    {
        if let beginImage = CoreImage.CIImage(image: self)
        {
            let paramsColor: [String : AnyObject] = [kCIInputBrightnessKey: NSNumber(double: 0.0),
                                                     kCIInputContrastKey:   NSNumber(double: 1.1),
                                                     kCIInputSaturationKey: NSNumber(double: 0.0)]
            let blackAndWhite = beginImage.imageByApplyingFilter("CIColorControls", withInputParameters: paramsColor)

            let paramsExposure: [String : AnyObject] = [kCIInputEVKey: NSNumber(double: 0.7)]
            let output = blackAndWhite.imageByApplyingFilter("CIExposureAdjust", withInputParameters: paramsExposure)

            let processedCGImage = CIContext().createCGImage(output, fromRect: output.extent)
            return UIImage(CGImage: processedCGImage, scale: self.scale, orientation: self.imageOrientation)
        }
        return nil
    }
}

3

这是@FBente将@Shmidt的答案转换成Swift 3版本的macOS(NSImage):

extension NSImage
{
    func imageBlackAndWhite() -> NSImage?
    {
        if let cgImage = self.cgImage(forProposedRect: nil, context: nil, hints: nil)
        {
            let beginImage = CIImage.init(cgImage: cgImage)
            let paramsColor: [String : AnyObject] = [kCIInputBrightnessKey: NSNumber(value: 0.0),
                                                     kCIInputContrastKey:   NSNumber(value: 1.1),
                                                     kCIInputSaturationKey: NSNumber(value: 0.0)]
            let blackAndWhite = beginImage.applyingFilter("CIColorControls", withInputParameters: paramsColor)

            let paramsExposure: [String : AnyObject] = [kCIInputEVKey: NSNumber(value: 0.7)]
            let output = blackAndWhite.applyingFilter("CIExposureAdjust", withInputParameters: paramsExposure)

            if let processedCGImage = CIContext().createCGImage(output, from: output.extent) {
                return NSImage(cgImage: processedCGImage, size: self.size)
            }
        }
        return nil
    }
}

-1

我尝试了Shmidt的解决方案,但在iPad Pro上对我来说似乎过度曝光。我只使用他解决方案的第一部分,没有曝光滤镜:

- (UIImage *)imageBlackAndWhite
{
    CIImage *beginImage = [CIImage imageWithCGImage:self.CGImage];

    CIImage *blackAndWhite = [CIFilter filterWithName:@"CIColorControls" keysAndValues:kCIInputImageKey, beginImage, @"inputBrightness", [NSNumber numberWithFloat:0.0], @"inputContrast", [NSNumber numberWithFloat:1.1], @"inputSaturation", [NSNumber numberWithFloat:0.0], nil].outputImage;
    CIImage *output = [blackAndWhite valueForKey:@"outputImate"]; 

    CIContext *context = [CIContext contextWithOptions:nil];
    CGImageRef cgiimage = [context createCGImage:output fromRect:output.extent];
    //UIImage *newImage = [UIImage imageWithCGImage:cgiimage];
    UIImage *newImage = [UIImage imageWithCGImage:cgiimage scale:image.scale orientation:image.imageOrientation];
    CGImageRelease(cgiimage);

    return newImage;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接