2012-01-17 2 views
5

私のアプリでカスタムフィルターを使いたいです。今私はコアイメージフレームワークを使用する必要があることを知っているが、私は正しい方法であることを確認していない。 コアイメージフレームワークがMac OSiOS 5.0に使用されています。カスタムCIFilterエフェクトに使用できるかどうかはわかりません。 この問題を手伝ってもらえますか? ありがとうございます!Core Image Frameworkを使用してiOS向けの簡単なカスタムフィルタを作成するにはどうすればよいですか?

答えて

5

まだ独自のカスタムカーネル/フィルタをiOSで作成することはできません。具体的には、http://developer.apple.com/library/mac/#documentation/graphicsimaging/Conceptual/CoreImaging/ci_intro/ci_intro.htmlを参照してください:

この文書は、参照ライブラリに含まれていますが、それは、iOS 5.0で詳細に更新されていない ました。今後のリビジョンでは、iOS上のCore Imageの相違点について詳細にご説明します。 特に、キー の違いは、iOSのコアイメージに カスタム画像フィルタを作成する機能が含まれていないことです。アダム状態として

(太字鉱山)

+0

注あなたはできますが、その独自のカーネルを作成するのではなく、既存のCIFilterを組み合わせて、効果を得ることができます。あなたはどんな効果を生み出していますか? – user1118321

+0

確かに。データに直接操作して、独自の画像フィルタ関数を完全に記述することもできます。 Accelerateフレームワークを賢明に使用すると、ハードウェアのサポートも大幅に向上します。 –

+2

iOS 8にはカスタムCoreImageフィルタ(カスタム 'CIKernel')が追加されています。 –

20

、古いマックの実装がないように、現在のiOS上のコアイメージは、カスタムカーネルをサポートしていません。これは、フレームワークでできることを、既存のフィルタを何らかの組み合わせにすることに制限します。

(更新:2012年2月13日)。このため

は、私はあなたがカスタムフィルタは、OpenGL ESを使用して画像や動画に適用されるように作成することができますGPUImageと呼ばれるiOSのためのオープンソースのフレームワークを、作成しました2.0フラグメントシェーダ。このフレームワークがどのように動作するかについては、my post on the topicで詳しく説明します。基本的には、独自のカスタムOpenGLシェーディング言語(GLSL)フラグメントシェーダを用意してカスタムフィルタを作成し、静的イメージまたはライブビデオに対してそのフィルタを実行することができます。このフレームワークは、OpenGL ES 2.0をサポートするすべてのiOSデバイスと互換性があり、iOS 4.0を対象とするアプリケーションを作成できます。

は、たとえば、次のようなコードを使用してライブビデオのフィルタリングを設定することができますフィルタを定義するカスタムフラグメントシェーダプログラムの一例として、

GPUImageVideoCamera *videoCamera = [[GPUImageVideoCamera alloc] initWithSessionPreset:AVCaptureSessionPreset640x480 cameraPosition:AVCaptureDevicePositionBack]; 
GPUImageFilter *customFilter = [[GPUImageFilter alloc] initWithFragmentShaderFromFile:@"CustomShader"]; 
GPUImageView *filteredVideoView = [[GPUImageView alloc] initWithFrame:CGRectMake(0.0, 0.0, viewWidth, viewHeight)]; 

// Add the view somewhere so it's visible 

[videoCamera addTarget:thresholdFilter]; 
[customFilter addTarget:filteredVideoView]; 

[videoCamera startCameraCapture]; 

、次のようにセピア調の効果を適用します。

varying highp vec2 textureCoordinate; 

uniform sampler2D inputImageTexture; 

void main() 
{ 
    lowp vec4 textureColor = texture2D(inputImageTexture, textureCoordinate); 
    lowp vec4 outputColor; 
    outputColor.r = (textureColor.r * 0.393) + (textureColor.g * 0.769) + (textureColor.b * 0.189); 
    outputColor.g = (textureColor.r * 0.349) + (textureColor.g * 0.686) + (textureColor.b * 0.168);  
    outputColor.b = (textureColor.r * 0.272) + (textureColor.g * 0.534) + (textureColor.b * 0.131); 

    gl_FragColor = outputColor; 
} 

Mac上でカスタムCore Imageカーネルを書き込むために使用される言語は、GLSLと非常に似ています。実際、Core Imageのカーネル言語にはGLSLが持つもの(分岐など)がないため、デスクトップのCore Imageではできないことがいくつかあります。

+0

あなたの答えをありがとう!はい、OpenGLを使用している場合は、これは私にとって最良の結果です。しかし、今私はopenGLでこの機能について少し知っている –

+1

ブラッド、あなたは素晴らしいです! – openfrog

8

元の回答は償却されます。 iOS 8からフィルタ用のカスタムカーネルを作成できます。あなたは画像ユニットプラグインのよりも簡単iOS用のカスタムフィルタを作成することができます

+0

更新いただきありがとうございます。これは古い質問です。iOS 8 SDKを使用している場合、新しい回答が他の人々にいくつかの新しい詳細を見つけるのに役立つと思います。 –

0

:あなたはこの詳細な情報を見つけることができますMacOS X、Image UnitプラグインがiOSでサポートされていたとしても、それらが好まれるほどです。問題は実際にはそれらを「パッケージ化」することができないか、Image Unitプラグインのようなリソースとしてバンドルすることができないことです。ソースコードを使用する開発者にソースコードを公開する必要があります。さらに、それらは開発者にとって有用です。サードパーティのCore ImageフィルタをインポートするMacOS Xグラフィックスアプリケーションと同じように、iOSグラフィックスアプリケーションのエンドユーザにそれらを配布することはできません。そのためには、それらをPhoto Editing Extensionに埋め込む必要があります。

iOS用のカスタムCore Imageフィルタを使用して画像を処理することは、Image Unitプラグインを使用する場合よりも簡単です。インポートはありません。その後、.plistとdescriptionファイルを設定するという混乱する作業と無関係な作業があります。

iOS向けカスタムCore Imageフィルタは、CIFilterのサブクラスであるCocoa Touchクラスです。入力パラメータ(常に少なくとも画像)、カスタム属性の設定とそのデフォルト値、および組み込みまたはカスタムのCore Imageフィルタの任意の組み合わせを指定します。画像処理パイプラインにOpenGLカーネルを追加する場合は、CIKernelメソッドを追加するだけで、別のファイルに書き込む.cikernelをロードします。

iOS用のカスタムコア・イメージフィルタを開発するためのこの特定の方法の美しさは、カスタムフィルタがインスタンス化されることで、組み込みフィルタと同じように呼ばれる:

CIFilter* PrewittKernel = [CIFilter filterWithName:@"PrewittKernel"]; 

CIImage *result = [CIFilter filterWithName:@"PrewittKernel" keysAndValues:kCIInputImageKey, self.inputImage, nil].outputImage; 

ここでOpenGLを使用して簡単な例ですPrewitt Operatorを画像に適用する。まず、ココアタッチクラス(CIFilterをサブクラス化する)、次いで、(のOpenGL ES 3.0コードを含む)CIKernelファイル:

ヘッダファイル:

// 
// PrewittKernel.h 
// Photo Filter 
// 
// Created by James Alan Bush on 5/23/15. 
// 
// 

#import <CoreImage/CoreImage.h> 

@interface PrewittKernel : CIFilter 
{ 
    CIImage *inputImage; 
} 

@property (retain, nonatomic) CIImage *inputImage; 

@end 

実装ファイル:

// 
// PrewittKernel.m 
// Photo Filter 
// 
// Created by James Alan Bush on 5/23/15. 
// 
// 

#import <CoreImage/CoreImage.h> 

@interface PrewittKernel : CIFilter 
{ 
    CIImage *inputImage; 
} 

@property (retain, nonatomic) CIImage *inputImage; 

@end 


@implementation PrewittKernel 

@synthesize inputImage; 

- (CIKernel *)prewittKernel 
{ 
    static CIKernel *kernelPrewitt = nil; 

    NSBundle *bundle = [NSBundle bundleForClass:NSClassFromString(@"PrewittKernel")]; 
    NSStringEncoding encoding = NSUTF8StringEncoding; 
    NSError  *error = nil; 
    NSString *code = [NSString stringWithContentsOfFile:[bundle pathForResource:@"PrewittKernel" ofType:@"cikernel"] encoding:encoding error:&error]; 

    static dispatch_once_t onceToken; 
    dispatch_once(&onceToken, ^{ 
     kernelPrewitt = [CIKernel kernelWithString:code]; 
    }); 

    return kernelPrewitt; 
} 

- (CIImage *)outputImage 
{ 
    CIImage *result = self.inputImage; 
    return [[self prewittKernel] applyWithExtent:result.extent roiCallback:^CGRect(int index, CGRect rect) { 
     return CGRectMake(0, 0, CGRectGetWidth(result.extent), CGRectGetHeight(result.extent)); 
    } arguments:@[result]]; 
} 

@end 

CIKernel(のOpenGL ES 3.0):

/* PrewittKernel.cikernel */ 

kernel vec4 prewittKernel(sampler image) 
{ 
    vec2 xy = destCoord(); 
    vec4 bottomLeftIntensity = sample(image, samplerTransform(image, xy + vec2(-1, -1))); 
    vec4 topRightIntensity = sample(image, samplerTransform(image, xy + vec2(+1, +1))); 
    vec4 topLeftIntensity = sample(image, samplerTransform(image, xy + vec2(+1, -1))); 
    vec4 bottomRightIntensity = sample(image, samplerTransform(image, xy + vec2(-1, +1))); 
    vec4 leftIntensity = sample(image, samplerTransform(image, xy + vec2(-1, 0))); 
    vec4 rightIntensity = sample(image, samplerTransform(image, xy + vec2(+1, 0))); 
    vec4 bottomIntensity = sample(image, samplerTransform(image, xy + vec2(0, -1))); 
    vec4 topIntensity = sample(image, samplerTransform(image, xy + vec2(0, +1))); 
    vec4 h = vec4(-topLeftIntensity - topIntensity - topRightIntensity + bottomLeftIntensity + bottomIntensity + bottomRightIntensity); 
    vec4 v = vec4(-bottomLeftIntensity - leftIntensity - topLeftIntensity + bottomRightIntensity + rightIntensity + topRightIntensity); 
    float h_max = max(h.r, max(h.g, h.b)); 
    float v_max = max(v.r, max(v.g, v.b)); 
    float mag = length(vec2(h_max, v_max)) * 1.0; 

    return vec4(vec3(mag), 1.0); 
} 

ここunshを生成する別のフィルタです内蔵のCore Imageフィルタを使用してガウスのぼやけた画像を元の画像から減算(または、むしろ差異化)することにより、arpマスクを生成します。Core Imageカーネルコード(OpenGL)はありません。それは、つまり、ガウスぼかしの半径をカスタム属性を指定して使用する方法を示しています。

ヘッダファイル:

// 
// GaussianKernel.h 
// Chroma 
// 
// Created by James Alan Bush on 7/12/15. 
// Copyright © 2015 James Alan Bush. All rights reserved. 
// 

#import <CoreImage/CoreImage.h> 

@interface GaussianKernel : CIFilter 
{ 
    CIImage *inputImage; 
    NSNumber *inputRadius; 
} 

@property (retain, nonatomic) CIImage *inputImage; 
@property (retain, nonatomic) NSNumber *inputRadius; 

@end 

実装ファイル:

// 
// GaussianKernel.m 
// Chroma 
// 
// Created by James Alan Bush on 7/12/15. 
// Copyright © 2015 James Alan Bush. All rights reserved. 
// 

#import "GaussianKernel.h" 

@implementation GaussianKernel 

@synthesize inputImage; 
@synthesize inputRadius; 

+ (NSDictionary *)customAttributes 
{ 
    return @{ 
      @"inputRadius" : 
       @{ 
        kCIAttributeMin  : @3.0, 
        kCIAttributeMax  : @15.0, 
        kCIAttributeDefault : @7.5, 
        kCIAttributeType  : kCIAttributeTypeScalar 
        } 
      }; 
} 

- (void)setDefaults 
{ 
    self.inputRadius = @7.5; 
} 

    - (CIImage *)outputImage 
    { 
     CIImage *result = self.inputImage; 

     CGRect rect = [[GlobalCIImage sharedSingleton].ciImage extent]; 
     rect.origin = CGPointZero; 
     CGRect cropRectLeft = CGRectMake(0, 0, rect.size.width, rect.size.height); 
     CIVector *cropRect = [CIVector vectorWithX:rect.origin.x Y:rect.origin.y Z:rect.size.width W:rect.size.height]; 

    result = [[CIFilter filterWithName:@"CIGaussianBlur" keysAndValues:kCIInputImageKey, result, @"inputRadius", [NSNumber numberWithFloat:inputRadius.floatValue], nil].outputImage imageByCroppingToRect:cropRectLeft]; 

    result = [CIFilter filterWithName:@"CICrop" keysAndValues:@"inputImage", result, @"inputRectangle", cropRect, nil].outputImage; 

    result = [CIFilter filterWithName:@"CIDifferenceBlendMode" keysAndValues:kCIInputImageKey, result, kCIInputBackgroundImageKey, result, nil].outputImage; 

     return result; 
    } 

    @end 
関連する問題