Android(Java)を始める – カメラから画像を取得&グレースケール化

Filed under Android, Java

Androidの勉強中です。

カメラから画像を取得して、グレスケ化して表示。

Androidでは、カメラから取得出来るデータはRGBではありません。

YUV420形式のbyte型の配列が帰ってきます。

なので、自分でRGBに変換してやらなければいけません。

ただし、グレースケールの場合は処理が簡単。

取得した配列の先頭から、画像の縦×横分のデータをそのまま取ってきて画像とすればOK。

多分だけど。

正直このあたりまだ曖昧。

カメラを利用したリアルタイム処理については、以下の山添さんの資料がとても参考になりました。

ワーキンググループ/金沢支部/第四回勉強会 – 日本Androidの会(日本アンドロイドの会)

以下、今回のソースです。

Main.javaのソース。

package jp.sakef;

import android.app.Activity;
import android.content.pm.ActivityInfo;
import android.os.Bundle;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;

public class Main extends Activity
{
	public void onCreate(Bundle savedInstanceState)
	{
		super.onCreate(savedInstanceState);

		// 画面の向きを横で固定
		setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); 

		// 全画面表示
		getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN); 

		// スリープ無効
		getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); 

		// タイトルの非表示
		requestWindowFeature(Window.FEATURE_NO_TITLE); 

		// レイアウト用
		ViewGroup.LayoutParams layoutParams = new ViewGroup.LayoutParams(
				ViewGroup.LayoutParams.FILL_PARENT,
				ViewGroup.LayoutParams.FILL_PARENT);

		// viewの初期化と追加
		DrawView dView = new DrawView(this);
		CameraView camView = new CameraView(this, dView);
		setContentView(dView, layoutParams);
		addContentView(camView, layoutParams);
	}
}

CameraView.javaのソース。

package jp.sakef;

import java.io.IOException;
import android.content.Context;
import android.hardware.Camera;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

public class CameraView extends SurfaceView implements Camera.PreviewCallback, SurfaceHolder.Callback
{
	private Camera camera;
	private DrawView view;
	private int w=240, h=160;
	private float scaleX, scaleY;
	private int[] grayScales;
	private int[] grayScaleTable;

	// コンストラクタ
	public CameraView(Context context, DrawView view)
	{
		super(context);
		this.view = view;

		// holderの設定
		SurfaceHolder holder = getHolder();
		holder.addCallback(this);
		holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);

		// viewのフォーカス設定
		this.setFocusable(true);
		this.requestFocus();
	}

	// viewに変化があった場合に実行
	public void surfaceChanged(SurfaceHolder holder, int format, int width,	int height)
	{
		scaleX = width / w;
		scaleY = height / h;
		grayScales = new int[w*h];
		grayScaleTable = new int[256];
		for(int i=0 ; i<256 ; i++) grayScaleTable[i] = 0xff000000 + (i<<16) + (i<<8) + i;

		try
		{
			// カメラの設定
			Camera.Parameters parameters = camera.getParameters();
			parameters.setPreviewSize(240 , 160);
			camera.setParameters(parameters);
			camera.setPreviewDisplay(holder);
			camera.setPreviewCallback(this);
			camera.startPreview();
		}
		catch (IOException e) {}
	}

	// viewが作成されたら実効
	public void surfaceCreated(SurfaceHolder holder)
	{
		camera = Camera.open();
	}

	// viewが破棄されたら実効
	public void surfaceDestroyed(SurfaceHolder holder)
	{
		camera.setPreviewCallback(null);
		camera.stopPreview();
		camera.release();
		camera = null;
	}

	//プレビュー画像の取得
	public void onPreviewFrame(byte[] data, Camera camera)
	{
		camera.setPreviewCallback(null);

		int size = w*h;
		int pos = 0;
		for(int i=0 ; i<size ; i+=8)
		{
			int y = data[pos]&0xff;
			grayScales[pos++] = grayScaleTable[y];
			y = data[pos]&0xff;
			grayScales[pos++] = grayScaleTable[y];
			y = data[pos]&0xff;
			grayScales[pos++] = grayScaleTable[y];
			y = data[pos]&0xff;
			grayScales[pos++] = grayScaleTable[y];
			y = data[pos]&0xff;
			grayScales[pos++] = grayScaleTable[y];
			y = data[pos]&0xff;
			grayScales[pos++] = grayScaleTable[y];
			y = data[pos]&0xff;
			grayScales[pos++] = grayScaleTable[y];
			y = data[pos]&0xff;
			grayScales[pos++] = grayScaleTable[y];
		}

		view.drawBitmap(grayScales, scaleX, scaleY, w, h);
		camera.setPreviewCallback(this);
		invalidate();
	}
}

DrawView.javaのソース。

package jp.sakef;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

public class DrawView extends SurfaceView implements SurfaceHolder.Callback
{
	private SurfaceHolder holder;
	private Paint paint;

	public DrawView(Context context)
	{
		super(context);
		holder = getHolder();
		holder.addCallback(this);
		paint = new Paint();
	}

	public void surfaceDestroyed(SurfaceHolder holder)
	{
		holder.removeCallback(this);
		holder=null;
    }

	public void drawBitmap(int[] img, float scaleX, float scaleY, int w, int h)
	{
		Canvas canvas = holder.lockCanvas();
		canvas.scale(scaleX, scaleY);
		canvas.drawBitmap(img, 0, w, 0, 0, w, h,false, paint);
		holder.unlockCanvasAndPost(canvas);
	}

	public void surfaceChanged(SurfaceHolder holder, int format, int width,	int height) {}
	public void surfaceCreated(SurfaceHolder holder) {}
}

Post a Comment

Your email is never published nor shared.