Androidアプリ開発 画像処理 ColorMatrixで画像に色々なフィルターをかける

2017年10月06日(編集2017年10月06日)
このエントリーをはてなブックマークに追加

Androidアプリを作成するとき、ColorMatrixで画像にフィルター処理を施すことができます。
この記事は、AndroidアプリでColorMatrixを使って、画像に様々なフィルター処理をする方法を記載した記事です。

環境はAndroid 8.0 (API level 26) です。

環境

  • macOS Sierra
  • android sdk 26
  • Android Studio 2.3.3
  • kotlin 1.1.2

難易度

中級者向け(行列や画像処理の基本的な知識を含む)

サンプルコード

Android-Image-Demo

ColorMatrix

ColorMatrix(カラーマトリクス)は、RGB空間の座標を定義する行列です。
ColorMatrixの仕様や計算方法はこの記事に記載しています。
今回の記事では、実際のアプリで利用可能なフィルター処理を実装します。色々なColorMatrixを用意したので、アプリ開発に役立ててください。

グレースケール

グレースケールは、画像をモノクロ写真のように変換するフィルターです。

{project_folder}/app/src/main/java/colormatrix/ColorMatrixActivity
    internal fun grayScale() {
        val colorMatrix = ColorMatrix()
        colorMatrix.setSaturation(0.0f)
        val matrix = colorMatrix.array
        img.colorFilter = ColorMatrixColorFilter(colorMatrix)
    }
          

■ 実装の解説

1. Saturationの設定

ColorMatrixでSaturationを設定します。

colorMatrix.setSaturation(0.0f)
        

setSaturationで生成されるcolorMatrix行列は、以下のような行列になります。

fig1. グレースケール colorMatrix

AndroidのcolorMatrix行列は、setSaturation(0.0f)を設定することで、映像システム係数のグレースケールを利用します。

では、上記のコードを実行して、画像を確認します。

fig2. グレースケール Lena画像

綺麗なグレースケールフィルタが掛かった画像が表示されました。

セピア

セピア(sepia)は、イカ墨のことです。
多くのアプリで利用されているフィルターです。

以下のようにコードを実装します。

{project_folder}/app/src/main/java/colormatrix/ColorMatrixActivity
    internal fun sepia() {
        val colorMatrix = ColorMatrix()
        colorMatrix.set(floatArrayOf(
                0.393f, 0.769f, 0.189f, 0.0f, 0.0f,
                0.349f, 0.686f, 0.168f, 0.0f, 0.0f,
                0.272f, 0.534f, 0.131f, 0.0f, 0.0f,
                0.0f, 0.0f, 0.0f, 1.0f, 0.0f))

        img.colorFilter = ColorMatrixColorFilter(colorMatrix)
    }
          

セピアのcolorMatrix行列は、以下のような行列になります。

fig3. セピア colorMatrix

では、上記のコードを実行して、画像を確認します。

fig4. セピア Lena画像

Brownie

Brownieは、レンズフィルターです。

{project_folder}/app/src/main/java/colormatrix/ColorMatrixActivity
    internal fun brownie() {
        val colorMatrix = ColorMatrix()
        colorMatrix.set(floatArrayOf(
                0.5997023498159715f, 0.34553243048391263f, -0.2708298674538042f, 0.0f, 47.43192855600873f,
                -0.037703249837783157f, 0.8609577587992641f, 0.15059552388459913f, 0.0f, -36.96841498319127f,
                0.24113635128153335f, -0.07441037908422492f, 0.44972182064877153f, 0.0f, -7.562075277591283f,
                0.0f, 0.0f, 0.0f, 1.0f, 0.0f))
        img.colorFilter = ColorMatrixColorFilter(colorMatrix)
    }
          

BrownieのcolorMatrix行列は、以下のような行列になります。

fig5. Brownie colorMatrix

では、上記のコードを実行して、画像を確認します。

fig6. Brownie Lena画像

赤色が強く出ています。(1, 5)の47.43192855600873fの足し算が効いているのがわかります。

vintagePinhole

vintagePinholeも、レンズフィルターです。

{project_folder}/app/src/main/java/colormatrix/ColorMatrixActivity
    internal fun vintagePinhole() {
        val colorMatrix = ColorMatrix()
        colorMatrix.set(floatArrayOf(
                0.6279345635605994f, 0.3202183420819367f, -0.03965408211312453f, 0.0f, 9.651285835294123f,
                0.02578397704808868f, 0.6441188644374771f, 0.03259127616149294f, 0.0f, 7.462829176470591f,
                0.0466055556782719f, -0.0851232987247891f, 0.5241648018700465f, 0.0f, 5.159190588235296f,
                0.0f, 0.0f, 0.0f, 1.0f, 0.0f))
        img.colorFilter = ColorMatrixColorFilter(colorMatrix)
    }
          

vintagePinholeのcolorMatrix行列は、以下のような行列になります。

fig7. vintagePinhole colorMatrix

では、上記のコードを実行して、画像を確認します。

fig8. vintagePinhole Lena画像

polaroid

ポラロイドカメラのような雰囲気を表現するフィルターです。

{project_folder}/app/src/main/java/colormatrix/ColorMatrixActivity
    internal fun polaroid() {
        val colorMatrix = ColorMatrix()
        colorMatrix.set(floatArrayOf(
                1.438f, -0.062f, -0.062f, 0.0f, 0.0f,
                -0.122f, 1.378f, -0.122f, 0.0f, 0.0f,
                -0.016f, -0.016f, 1.483f, 0.0f, 0.0f,
                0.0f, 0.0f, 0.0f, 1.0f, 0.0f))
        colorFilter(colorMatrix)
    }
          

polaroidのcolorMatrix行列は、以下のような行列になります。

fig9. polaroid colorMatrix

では、上記のコードを実行して、画像を確認します。

fig10. polaroid Lena

brightness

brightnessは、画像の明るさを調整します。インスタグラム等の画像アプリでは必須の人気フィルターです。別名、光とばし。

{project_folder}/app/src/main/java/colormatrix/ColorMatrixActivity
    internal fun brightness(brightness: Float) {
        val b = brightness + 1
        val colorMatrix = ColorMatrix()
        colorMatrix.set(floatArrayOf(
                b, 0.0f, 0.0f, 0.0f, 0.0f,
                0.0f, b, 0.0f, 0.0f, 0.0f,
                0.0f, 0.0f, b, 0.0f, 0.0f,
                0.0f, 0.0f, 0.0f, 1.0f, 0.0f))
        img.colorFilter = ColorMatrixColorFilter(colorMatrix)
    }
          

RGBの要素をスケールするだけの変換行列です。

引数に0.7を渡して、RGBの値を1.7倍にスケールして実行します。

fig11. brightness Lena

LSD

薬物的な印象のフィルター

{project_folder}/app/src/main/java/colormatrix/ColorMatrixActivity
    internal fun lsd() {
        val colorMatrix = ColorMatrix()
        colorMatrix.set(floatArrayOf(
                2.0f, -0.4f, 0.5f, 0.0f, 0.0f,
                -0.5f, 2.0f, -0.4f, 0.0f, 0.0f,
                -0.4f, -0.5f, 3.0f, 0.0f, 0.0f,
                0.0f, 0.0f, 0.0f, 1.0f, 0.0f))
        img.colorFilter = ColorMatrixColorFilter(colorMatrix)
    }
          

では、上記のコードを実行して、画像を確認します。

fig12. LSD Lena画像

不気味ですね。

Contrast

Contrastは画像の表示における明暗の差です。
brightnessとの違いは、加算用の成分も使って、色の明暗を変更しています。

{project_folder}/app/src/main/java/colormatrix/ColorMatrixActivity
    internal fun contrast(amount: Float = 0.0f) {
        val v = Math.max(amount, 0f) + 1f
        val o = -128 * (v - 1);
        val colorMatrix = ColorMatrix()
        colorMatrix.set(floatArrayOf(
                v, 0.0f, 0.0f, 0.0f, o,
                0.0f, v, 0.0f, 0.0f, o,
                0.0f, 0.0f, v, 0.0f, o,
                0.0f, 0.0f, 0.0f, 1.0f, 0.0f))
        img.colorFilter = ColorMatrixColorFilter(colorMatrix)
    }

          

val oを加算成分として利用しています。

上記のコードを実行して、画像を確認します。

fig13. Contrast Lena画像

色が濃くなりました。

Bitray

Bitrayは二値化です。画像を白黒に変換します。
グレースケールと閾値のマトリクスを掛け合わせます。

{project_folder}/app/src/main/java/colormatrix/ColorMatrixActivity
    internal fun binary() {
        val colorMatrix = ColorMatrix()
        colorMatrix.setSaturation(0.0f)
        val m = 255f;
        val t = -255f*128f;
        val threshold = ColorMatrix()
        threshold.set(floatArrayOf(
                m, 0.0f, 0.0f, 1.0f, t,
                0.0f, m, 0.0f, 1.0f, t,
                0.0f, 0.0f, m, 1.0f, t,
                0.0f, 0.0f, 0.0f, 1.0f, 0.0f))
        colorMatrix.postConcat(threshold)
        img.colorFilter = ColorMatrixColorFilter(colorMatrix)
    }
          

計算されたcolorMatrix行列は、以下のような行列となります。

fig14. Bitray colorMatrix

上記のコードを実行して、画像を確認します。

fig15. Bitray Lena

二値化した画像が出力されました。

結論

ColorMatrixだけでも色々なフィルターが利用可能です。画像加工をするときは利用してみてください。

関連記事

タグ検索で調べてみよう

画像処理 Android8.0 kotlin1.1.1