次のような画像処理をandroidでやってみましょう。
- 画像を読み込む
- 平均値フィルタをかけて、画像をぼかす
- 処理をした画像を表示する
今回はこの画像をぼかして(平滑化して)みようと思います。
ソース
package com.android.avg_filter;
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.os.Bundle;
import android.widget.ImageView;
public class main extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// 1. 画像を読み込む
Bitmap src = BitmapFactory.decodeResource(getResources(), R.drawable.lenna);
// 2. 平均値フィルタをかけて、画像をぼかす
Bitmap dst;
dst = avgFilter(src);
// 3. 処理をした画像を表示する
ImageView iv = (ImageView)findViewById(R.id.ImageView01);
iv.setImageBitmap(dst);
}
// 画像をぼかす(平滑化する)メソッド
private Bitmap avgFilter(Bitmap src) {
Bitmap dst = Bitmap.createBitmap(src.getWidth(), src.getHeight(),Bitmap.Config.ARGB_8888);
int width = src.getWidth();
int height = src.getHeight();
// 出力画像の初期化処理
int initpixels[] = new int[width * height];
dst.setPixels(initpixels, 0, width, 0, 0, width, height);
// カーネルの宣言
double[][] kernel = {
{1.0/9.0, 1.0/9.0, 1.0/9.0},
{1.0/9.0, 1.0/9.0, 1.0/9.0},
{1.0/9.0, 1.0/9.0, 1.0/9.0}};
// 処理を行う
int dstpixels[] = new int[width * height];
for(int i = 1; i < width - 1; i++){
for(int j = 1; j < height - 1; j++){
double red = 0.0;
double green = 0.0;
double blue = 0.0;
// 畳込み演算
for(int inR = -1; inR <=1; inR++){
for(int inC = -1; inC <=1; inC++){
red += kernel[inR+1][inC+1]*Color.red(src.getPixel(i+inR, j+inC));
green += kernel[inR+1][inC+1]*Color.green(src.getPixel(i+inR, j+inC));
blue += kernel[inR+1][inC+1]*Color.blue(src.getPixel(i+inR, j+inC));
}
}
dstpixels[i + j * width] = Color.rgb((int)red, (int)green, (int)blue);
}
}
// 画素値をセットする
dst.setPixels(dstpixels, 0, width, 0, 0, width, height);
return dst;
}
}
結果はこちら
それではポイントを見ていきましょう。
// 1. 画像を読み込む
Bitmap src = BitmapFactory.decodeResource(getResources(), R.drawable.lenna);
では res/drawable に入っている lenna.jpg からBitmapインスタンスを生成しています。
// dstの初期化処理
int initpixels[] = new int[width * height];
dst.setPixels(initpixels, 0, width, 0, 0, width, height);
では出力画像の初期化を行っています。
initpixelsの型はint[]で、その大きさは総画素数(width * height)に等しいです。
ちなみにandroidではひとつの画素値はintで与えられており、
24bit~17bitまでが赤、16bit~9bitまでが緑、8bit~1bitが青となっています。
従ってある画素値をvalueとしたとき、RGB成分はそれぞれ
// RGBの取得
int R = (value & 0x00FF0000) >> 16;
int G = (value & 0x0000FF00) >> 8;
int B = (value & 0x000000FF);
とすることで取得できますね。
最後に計算結果をBimapインスタンスにセットします。
// ピクセル値をセットする
dst.setPixels(dstpixels, 0, width, 0, 0, width, height);
これには
Bitmap.setPixelsを利用します。
setPixelsは7個の引数があります。
Referenceをみると次のようになっています。
public void setPixels (int[] pixels, int offset, int stride, int x, int y, int width, int height)
多くの場合、計算した結果の画素数とそれをセットしたいBitmapのインスタンスの画素数は同じであると思うので,
offset = 0,
Stride = 画像の横方向の画素数,
width = Strideと一緒,
height = 画像の縦方向の画素数
でいいかと思います。
以上簡単な画像処理に関する解説でした。
伊原 頌二 藤枝 崇史 柴田 文彦
インプレスジャパン
売り上げランキング: 20532
おすすめ度の平均:
わかりやすいが間違いが多い
索引が充実していれば…
「GLSerfaceView」クラスを使ったサンプル有り