iOS
CoreImage
Swift

プログラミング教室で Core Image を使った画像処理について説明しました

More than 1 year has passed since last update.

前回


概要

  • 今回は趣向を変えて iOS アプリというより画像処理に焦点を当てます
  • Core Image を使用して Swift が画像処理を行います
  • CIDetector を使って顔検出を行います
  • ちなみに俺はそんなに画像処理について詳しくない

画像処理

画像処理(がぞうしょり、Image processing)とは、電子工学的(主に情報工学的)に画像を処理して、別の画像に変形したり、画像から何らかの情報を取り出すために行われる処理全般を指す

https://ja.wikipedia.org/wiki/画像処理

画像の色を変えたり、変形・回転させる他にもエッジ検出をしたりすることも画像処理です。

伝統的には画像を RGB に分解して3次元の配列として色々計算したりしてました。

for (int b = 0; b < size; b++) {
    for (int g = 0; g < size; r++) {
        for (int r = 0; r < size; r ++) {
            cubeData[b][g][r] = <# output R value #>;
            cubeData[b][g][r] = <# output G value #>;
            cubeData[b][g][r] = <# output B value #>;
            cubeData[b][g][r] = <# output A value #>;
        }
    }
}

これをやるのは非常に大変なので予め用意されたライブラリを使ってお手軽に画像処理を行います。

Core Image ?

Core Image は Apple が提供している画像処理の Framework です。

フィルタというものを使って画像や動画に色々な視覚効果(ぼかしとか)を適用することができます。

フィルタは最初から170個以上入っています。 独自のカスタムフィルタを作ることも可能です。

フィルタのドキュメント(サンプル画像もあるのでどのような効果なのか確認できます)

いろいろな例

やること

Xcode の Playground を使って swift で画像処理のコードを書いていきます。

自分の好きな画像を用意します(カラーでそんなにサイズが大きくないものが良いです)。

用意した画像は playground の左のツリーの Resources フォルダにドラッグしておきます。

画像処理の流れ

画像処理は元画像にフィルタを通して加工済み画像を作ります。 カッコ内は使用するクラス名です。 CI は Core Image の略です。

元画像(CIImage) -> フィルタ(CIFilter) -> 加工済み画像(CIImage)

フィルタにはパラメータがある場合があります。 パラメータによって例えば画像のぼかし具合を変えたりすることができます。

白黒画像にしてみる

CIPhotoEffectMono というフィルタを使います。

画像のファイル名("Lenna.jpg")は自分の画像のファイル名に合わせてください。

import UIKit

let image = UIImage(named: "Lenna.jpg")!
let ciImage = CIImage(image: image)

let filter = CIFilter(name: "CIPhotoEffectMono")!

filter.setDefaults()
filter.setValue(ciImage, forKey: kCIInputImageKey)

let output = filter.outputImage

プレビューを出すには画像の変数の行の右側の + ボタンを押します。

image

このフィルタにはパラメータはありません。

ぼかし

CIBoxBlur というフィルタを使います。

さっきのコードの

let filter = CIFilter(name: "CIPhotoEffectMono")!

の部分を

let filter = CIFilter(name: "CIBoxBlur")! 

にしてみます。

image

このフィルタにはパラメータがあります。

  • kCIInputRadiusKey(inputRadius): ぼかしの表示半径の数値. デフォルトは 10.

パラメータは outputImage の前に filter.setValue(50, forKey: kCIInputRadiusKey) と書いて設定します。

以下は kCIInputRadiusKey を 50 にした例(output1)です。

image

他にも以下のように沢山のフィルタがあるので色々試してみよう。

CIBoxBlur
CIDiscBlur
CIGaussianBlur
CIMaskedVariableBlur
CIMedianFilter
CIMotionBlur
CINoiseReduction
CIZoomBlur

エッジ検出

色々あるけど CIEdges を使ってみる。

image

歪ませる

image

回転

CIStraightenFilter を使う。

kCIInputAngleKey で角度(ラジアン)を指定する。

image

拡大縮小

CILanczosScaleTransform を使う。

kCIInputScaleKey で倍率を指定する。

image

遷移アニメーション

1枚目の画像から2枚目の画像に遷移する画像を生成できる。 アニメーションするためには自分で制御する必要がある。

CIModTransition を使う。

kCIInputTimeKey をいじるとだんだん遷移するエフェクトが確認できる。

image

顔検出

CIDetector を使用して顔検出を行う。

import UIKit

let image = UIImage(named: "Lenna.jpg")!
let ciImage = CIImage(image: image)


let detector = CIDetector(ofType: CIDetectorTypeFace, context: nil, options: nil)
let features = detector.featuresInImage(ciImage!)

let imageView = UIImageView(image: image)

if let first = features.first {

    let bounds = CGRect(x: first.bounds.origin.x,
                        // 原点[0, 0] が左下にあるので反転させる(UI は原点が左上).
                        y: image.size.height - (first.bounds.height + first.bounds.origin.y),
                        width: first.bounds.width,
                        height: first.bounds.height)

    let faceRectView = UIView(frame: bounds)
    faceRectView.layer.borderWidth = 1.0
    faceRectView.layer.borderColor = UIColor.redColor().CGColor
    imageView.addSubview(faceRectView)

}

image

まとめ

  • Core Image を使って画像処理について学びました
  • ボカシ処理などの簡単な加工ができるようなりました
  • 画像の顔検出もできるようになりました
  • Playground のプレビュー機能を使って動作を確認しながらプログラミングを行う方法を学びました

開催場所: TENTO さいたま