10

ユーザーが特定の一連の写真フィルターを適用できる iOS アプリケーションに取り組んでいます。各フィルターは基本的に、特定のパラメーターを持つ Photoshop アクションのセットです。このアクションは次のとおりです。

  • レベル調整
  • 輝度コントラスト
  • 色相・彩度
  • 単一および複数のオーバーレイ

画像内のすべてのピクセルをループする算術式を使用して、コードでこのすべてのアクションを繰り返しました。しかし、iPhone 4 でアプリを実行すると、各フィルターの適用に約 3 ~ 4 秒かかり、ユーザーが待機するのにかなりの時間がかかります。画像サイズは 640 x 640 px で、Retina ディスプレイに表示されるため、私のビュー サイズの 2 倍です。私の主な問題は、ガンマを調整する必要があるたびに pow() C 関数を呼び出すレベルの変更であることがわかりました。もちろん、ARMv6 と ARMv7 は double では遅いため、double ではなく float を使用しています。Thumb を有効または無効にしようとしましたが、同じ結果が得られました。

私のアプリで最も単純なフィルターの例ですが、かなり高速に実行されます (2 秒)。他のフィルターにはより多くの式と pow() 呼び出しが含まれているため、処理が遅くなります。

https://gist.github.com/1156760

高速な画像変更のために Accelerate Framework vDSP マトリックス変換を使用しているソリューションをいくつか見てきました。OpenGL ES ソリューションも見てきました。それらが私のニーズに対応できるかどうかはわかりません。しかし、おそらく、一連の変更を適切な畳み込み行列に変換するだけの問題でしょうか?

どんなアドバイスも役に立ちます。

ありがとう、
アンドレイ。

4

6 に答える 6

13

サンプルコードのフィルターでは、ルックアップテーブルを使用してフィルターを大幅に高速化できます。入力画像は1色あたり8ビットであり、この関数に渡す前にフロートに変換していると仮定します。各色について、これは256の可能な値のみを提供し、したがって256の可能な出力値のみを提供します。これらを事前に計算して、配列に格納することができます。これpow()により、事前計算にそれらを考慮に入れることができるため、計算と境界チェックを回避できます。

次のようになります。

unsigned char table[256];
for(int i=0; i<256; i++) {
    float tmp = pow((float)i/255.0f, 1.3f) * 255.0; 
    table[i] = tmp > 255 ? 255 : (unsigned char)tmp;
}

for(int i=0; i<length; ++i)
    m_OriginalPixelBuf[i] = table[m_OriginalPixelBuf[i]];

この場合、実行する必要がpow()あるのは3 * 640*640回ではなく256回だけです。また、コストがかかる可能性のあるメイン画像ループの境界チェックによって引き起こされる分岐を回避できます。フロートに変換する必要もありません。

さらに高速な方法は、プログラムの外部でテーブルを事前に計算し、256個の係数をコードに入れることです。

そこにリストした操作はどれも、畳み込みや行列の乗算さえも必要としません。これらはすべてピクセル単位の操作です。つまり、各出力ピクセルは、対応する単一の入力ピクセルにのみ依存します。複数の入力ピクセルが単一の出力ピクセルに影響を与えるブラーやシャープニングなどの操作では、畳み込みを考慮する必要があります。

于 2011-08-19T14:20:20.207 に答える
10

これを行うための絶対的な最速の方法を探している場合は、GPU を使用して処理を処理することをお勧めします。単一ピクセルの色調整など、大規模な並列操作を実行するように構築されています。

他の回答で述べたように、CPU の代わりに OpenGL ES を使用して画像処理操作を実行すると、14 倍から 28 倍のパフォーマンスの向上が測定されました。Accelerate フレームワークを使用して、より高速なオン CPU 画像操作を行うことができます (Apple は、ここで約 4 ~ 5 倍のブーストが可能であると主張していると思います) が、OpenGL ES ほど高速ではありません。ただし、実装が簡単になる可能性があるため、OpenGL ES で Accelerate を使用することがあります。

iOS 5.0 はまた、デスクトップから Core Image をもたらします。これにより、この種のオン GPU 画像調整の優れたラッパーが提供されます。ただし、iOS Core Image の実​​装には、OpenGL ES 2.0 シェーダーを直接操作する場合にはないいくつかの制限があります。

ここの記事で、OpenGL ES 2.0 シェーダー イメージ フィルターの例を紹介します。この種の処理を行う上で最も難しいのは、OpenGL ES の足場をセットアップすることです。 そこにある私のサンプル アプリケーションを使用すると、そのセットアップ コードを抽出し、それを使用して独自のフィルターを適用できるはずです。これを簡単にするために、OpenGL ES のすべてのやり取りを処理するGPUImageというオープン ソース フレームワークを作成しました。上記のほとんどすべてのフィルターがあり、ほとんどが iPhone 4 の 640x480 フレームのビデオで 2.5 ミリ秒未満で実行されるため、CPU で処理されるどのフィルターよりもはるかに高速です。

于 2011-08-19T18:11:51.983 に答える
3

コメントで述べたように、この質問は公式の Apple Developer Forums にも投稿する必要があります。

それはさておき、1 つの本当に簡単なチェック: 電話ですかpow( )、それともpowf( )? データがfloatであっても、 を呼び出すpow( )と倍精度の数学ライブラリ関数が得られますが、これは単精度のバリアントよりも大幅に遅くなりpowf( )ます (また、 と の間の追加の変換も支払う必要がありますfloat) double

2 つ目のチェック: Instruments でフィルターのプロファイルを作成しましたか? 実行時間が費やされている場所を実際に知っていますか、それとも推測していますか?

于 2011-08-19T16:49:41.660 に答える
3

私は実際にこれらすべてを自分でやりたかったのですが、Silverberg のImage Filtersを見つけました。画像にさまざまな instagram タイプの画像フィルターを適用できます。これは、GLImageProcessing や Cimg などの他の画像フィルターよりもはるかに優れています。

iPhone の Instagram 画像フィルターも確認してください。

お役に立てれば...

于 2011-08-19T16:57:00.827 に答える
2

iOS 5 以降では、Core Image フィルタを使用して、適切な範囲の画像パラメータを調整できます。

たとえば、コントラストを調整するには、次のコードが魅力的です。

    - (void)setImageContrast:(float)contrast forImageView:(UIImageView *)imageView {

    if (contrast > MIN_CONTRAST && contrast < MAX_CONTRAST) {
        CIImage *inputImage = [[CIImage alloc] initWithImage:imageView.image];
        CIFilter *exposureAdjustmentFilter = [CIFilter filterWithName:@"CIColorControls"];
        [exposureAdjustmentFilter setDefaults];
        [exposureAdjustmentFilter setValue:inputImage forKey:@"inputImage"];
        [exposureAdjustmentFilter setValue:[NSNumber numberWithFloat:contrast] forKey:@"inputContrast"]; //default = 1.00
//        [exposureAdjustmentFilter setValue:[NSNumber numberWithFloat:1.0f] forKey:@"inputSaturation"]; //default = 1.00
//        [exposureAdjustmentFilter setValue:[NSNumber numberWithFloat:0.0f] forKey:@"inputBrightness"];
        CIImage *outputImage = [exposureAdjustmentFilter valueForKey:@"outputImage"];
        CIContext *context = [CIContext contextWithOptions:nil];
        imageView.image = [UIImage imageWithCGImage:[context createCGImage:outputImage fromRect:outputImage.extent]];
    }

}

注意: コントラストのデフォルト値は 1.0 です (推奨される最大値は 4.0 です)。
また、ここで imageView の画像に対してコントラストが計算されるため、このメソッドを繰り返し呼び出すと、コントラストが累積されます。つまり、最初にコントラスト値 2.0 を指定してこのメ​​ソッドを呼び出し、次にコントラスト値 3.0 を指定して呼び出すと、コントラスト値が 5.0 ではなく 6.0 (2.0 * 3.0) 増加した元の画像が得られます。

その他のフィルターとパラメーターについては、 Apple のドキュメントを確認してください。

コードで使用可能なすべてのフィルターとパラメーターを一覧表示するには、次のループを実行します。

NSArray* filters = [CIFilter filterNamesInCategories:nil];
for (NSString* filterName in filters)
{
    NSLog(@"Filter: %@", filterName);
    NSLog(@"Parameters: %@", [[CIFilter filterWithName:filterName] attributes]);
}
于 2013-07-17T05:05:53.740 に答える
0

これは古いスレッドですが、SO の別のリンクからたどり着いたので、人々はまだそれを読んでいます。

iOS 5 では、Apple は Core Image のサポートと、かなりの数の Core イメージ フィルタを追加しました。OPが言及したものはすべて利用可能であると確信しています

Core Image は内部で OpenGL シェーダーを使用しているため、非常に高速です。ただし、OpenGL よりもはるかに使いやすいです。まだ OpenGL で作業しておらず、単に CGImage または UIIMage オブジェクトにフィルターを適用したい場合は、Core Image フィルターが適しています。

于 2012-05-27T23:40:54.677 に答える