2014/01/27

[iOS]カメラ勉強備忘録 - その1



iOSのプログラミングについて備忘録的に書いていこうと思います。

最終的には、AVFoundation を使用してリアルタイム顔認識したいです。

まずは、CoreImageを使ってフィルターの勉強をするために
以下のサイトを参考にさせていただきました。

・iPhoneカメラアプリ開発入門(第一回)

実装方法の詳細は上記サイトの通りなので、
CIFilterを作成する際にちょっと一工夫。

/** 画像に指定されたフィルタを適用する */
+ (UIImage *)adhibitionFilter:(UIImage *)image withFilter:(TImageFilters)type
{
    if (type == TImageFilterNone) {
        return image;
    }
    
    // CoreImageFilterを作成する
    CIFilter *filter = [[self class] createFilterWithType:type intensity:1.0f targetImage:image];
    
    // coreimageコンテクストを作成
    CIContext *ciContext = [CIContext contextWithOptions:nil];
    
    // フィルタを適用
    CGImageRef cgImage = [ciContext createCGImage:filter.outputImage fromRect:[filter.outputImage extent]];
    
    // UIImageに変換
    UIImage *retImage = [UIImage imageWithCGImage:cgImage scale:image.scale orientation:UIImageOrientationUp];
    
    CGImageRelease(cgImage);
    
    return retImage;
    
}

/** フィルターを生成する */
+ (CIFilter *)createFilterWithType:(TImageFilters)type
                         intensity:(CGFloat)intensity
                       targetImage:(UIImage *)image
{
    CIImage *ciImage = [[CIImage alloc] initWithImage:image];

    // CoreImageFilterを作成する
    CIFilter *filter = [CIFilter filterWithName:[[self class] createFilterNameWithType:type]];
    
    [filter setValue:ciImage forKey:kCIInputImageKey];

    /** ### */
    /** パラメータを動的に生成して、どんなフィルタ名にも対応できるようにしています */
    /** ### */
    NSDictionary *params = [[self class] createFilterParametarWithType:type];
    NSArray *keys = [params allKeys];
    for (NSString *key in keys) {
        /** フィルタに存在しないパラメータの場合は設定しない */
        if ([filter respondsToSelector:NSSelectorFromString(key)] == NO) {
            continue;
        }
        
        [filter setValue:[params objectForKey:key] forKey:key];
    }
    
    return filter;
}

/** フィルタータイプにあったフィルタ名を生成する */
+ (NSString *)createFilterNameWithType:(TImageFilters)type
{
    
    NSString *name = nil;
    
    switch (type) {
        case TImageFilterMonochrome:
        case TImageFilterMonoSepia:
            name = kFilterNameMonochrome;
            break;
            
        case TImageFilterSepiaTone:
            name = kFilterNameSepiaTone;
            break;
            
        case TImageFilterNone:
        default:
            name = nil;
            break;
    }
    
    return name;
}

/** フィルタータイプにあったパラメータを生成する */
+ (NSDictionary *)createFilterParametarWithType:(TImageFilters)type
{
    
    NSMutableDictionary *params = [[NSMutableDictionary alloc] init];
    
    // CIFilterに指定するパラメータ名
    NSString * const keyInputColor     = @"inputColor";
    NSString * const keyInputIntensity = @"inputIntensity";
    
    switch (type) {
        case TImageFilterMonochrome:
        case TImageFilterMonoSepia:
            
            // パラメータ:入力色(RGBのフィルタ係数)
            [params setObject:[[self class] createCIColorWithType:type] forKey:keyInputColor];
            // パラメータ:適用度 (0.5で半分になる)
            [params setObject:[NSNumber numberWithFloat:1.0f] forKey:keyInputIntensity];
            
            break;
            
        case TImageFilterSepiaTone:
            // パラメータ:適用度 (0.5で半分になる)
            [params setObject:[NSNumber numberWithFloat:1.0f] forKey:keyInputIntensity];
            break;
            
        case TImageFilterNone:
        default:

            break;
    }
    
    return params;
}

実行結果は以下のとおりです。
UIPickerView を使ってフィルターを動的に選択できるようにしています。

 ・フィルター無し

 ・モノクロ

 ・セピア(CIColorMonochromeフィルタ)

・セピア(CISepiaToneフィルタ)

次回は、AVFoundation についての勉強か iOS Dev Program に登録します。