2014年9月4日木曜日

Android アプリ にっかぼうず

Android アプリ

にっかぼうず

 GooglePlayに新しいアプリを登録しました。



GooglePlay ⇒ にっかぼうず
毎日続けようとしても三日坊主に・・・
そんなときに便利なアプリです。
通知時間の設定をすれば毎日その時間に知らせてくれます。
日課を達成できればボタンを押して今日の分は達成!!
良かったらダウンロードしてください。


Androidアプリ発見プラットフォーム「Appliv」      Appliv - にっかぼうず

Android アプリ 貯金箱管理ツール

Android アプリ

貯金箱管理ツール

 GooglePlayに新しいアプリを登録しました。



GooglePlay ⇒ 貯金箱管理ツール
貯金箱の硬貨の枚数を記録できるアプリです。良かったらダウンロードしてください。


Androidアプリ発見プラットフォーム「Appliv」      Appliv - 貯金箱管理ツール

2014年3月17日月曜日

Android ダイアログ

最近カスタムダイアログに凝っているのですが、少し詰まってしまいました。

なぜカスタムダイアログに凝っているかというと
標準のAlertDialogでは素っ気ないと感じていたので
もっとオリジナリティあふれるものにしたいと思っていたからです。

現在GooglePlayに登録しているアプリは、ほぼカスタムダイアログを使用しています。
よかったらみてください。

さて本題に戻すと、ストラックアウトのゲームを作ったとき
スコアの表示をカスタムダイアログを用いて行っていたのですが
どうせなら目立つものがいいと思い
アニメーションを使いボールが常に回転しているようにしました。

しかし、なぜか実機でのテストで動いてくれず解決方法がわからなかったので
そのままの状態で完成させマ―ケットに登録

その後もう一つの端末でプレイしてみると
なぜか普通に動いていました・・・

もしかしたらバージョンの問題なのかな?

Androidアプリ あみだつなぎ

GooglePlayに新しいアプリを登録しました。

ランキングとレビューから探せるAndroidアプリ情報サイト -Appliv

Appliv - あみだつなぎ

https://play.google.com/store/apps/details?id=gtansu.tansug.amidatunagi

あみだくじの絵を揃える新感覚の頭脳ゲームです。
操作は線を引くだけととても簡単なので誰でも楽しめます。

よかったら遊んでみてください。

アンドロイダー公認デベロッパー認証

2014年1月28日火曜日

2014年1月23日木曜日

Android レイアウト

Android レイアウト

画面の描画のボタンなどの見た目を自分でカスタマイズする方法です。

layoutでそのまま貼り付けて使うと標準のままでまったく素っ気ないものになってしまします。今回はボタンの色をグラデーションを使用したものに変えてみます。

button_shape.xml
/*-------------------------------------------------------------------------------

<?xml version="1.0" encoding="utf-8"?>
<shape
            xmlns:android="http://schemas.android.com/apk/res/android"
            android:shape="rectangle">
            <solid
                android:color="#bce2e8" />
            <corners android:radius="5dip" />
            <gradient
            android:startColor="#f08300"  //この色からグラデーションを開始
            android:endColor="#ea5506" //この色まで
            android:angle="270" //
       />
</shape>

---------------------------------------------------------------------------------------*/

まずこのようなxmlファイルをdrawableなどに作ります。
<gradient>で囲んだ範囲がグラデーションの設定
<corners>で囲んだ範囲が角の丸みの設定をしています。

次にボタンを配置するレイアウトの一部

/*-----------------------------------------------------------------------------------

<Button
            android:id="@+id/button2"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="ボタン"
            android:background="@drawable/button_shape"/>


----------------------------------------------------------------------------------*/

backgroundのところを先ほど作成したものを指定します。
これで作成したものが適用されボタンの背景が変わっています。



2014年1月21日火曜日

Android View

Android View

カメラからの画像を表示させその上に描画を行うとき普通に描画を行うとせっかくカメラから取り込んだものが見えなくなってしまいます。

今回は描画を行うとき透明度を設定する方法です。

/*-------------------------------------------------------------------------

Canvas canvas;
Paint paint = new Paint();

paint.setStyle(Paint.Style.FILL);
paint.setColor(Color.parseColor("#7fff00"));//色の設定
paint.setAlpha(40);//透明度の設定

canvas.drawRect( 0, 0, width, height,paint);

----------------------------------------------------------------------------*/

paint.setAlpha( * );で*の値を決めることで透明度を設定できます。

値は0~255の間で0に近づくほど薄くなり255に近づくほど濃くなります。

これで半透明の描画ができます。これでメーターみたいなものを描画し、カメラビューと組み合わせるとスカウターみたいな画面にすることもできます。

2014年1月20日月曜日

Android OpenCV 応用

Android OpenCV 応用

OpenCVを用いて輪郭の取得を行いましたが今回はその応用です。

輪郭の取得を行いその中で最も大きい輪郭だけを表示する方法

輪郭の取得はImgproc.findContoursを用いますがその前に入力画像をシングルチャンネルに変換します。今回は肌色の部分だけが残るように抽出します。

/*------------------------------------------------------------------------------------------------

@Override
 public Mat onCameraFrame(Mat inputFrame) {
       Mat image = new Mat();
       image = inputFrame;

     Imgproc.cvtColor(image  , image , Imgproc.COLOR_RGB2HSV);//色空間をRGB→HSVに変換
     Core.inRange(image , new Scalar(0, 60, 80), new Scalar(25, 255, 255), image );//肌色抽出

       List<MatOfPoint> contours =  new ArrayList<MatOfPoint>();
       Mat hierarchy = Mat.zeros(new Size(5,5), CvType.CV_8UC1);

      Imgproc.findContours( image,  contours, hierarchy,
Imgproc.RETR_EXTERNAL, Imgproc.CHAIN_APPROX_TC89_L1);

//途中
}

--------------------------------------------------------------------------------------------------*/

ここまでで肌色の部分の輪郭を取得することができます。

次にもっとも大きい輪郭=面積が一番大きいものなのでImgproc.contourAreaを用いて各輪郭の面積を比較します。


/*----------------------------------------------------------------------------------------------------

int i=0;
double maxarea = 0;
if(contours.size()>0){//サイズが0の場合エラーになるので
          while(contours.size() != 1){//contoursが1つなるまで繰り返す
              if(maxarea < Imgproc.contourArea(contours.get(i))){//maxareaより大きいか
                   maxarea = Imgproc.contourArea(contours.get(i));
                   contours.remove(0);
                   i=1;
              }else{
                 contours.remove(i);
              }
             }
}

----------------------------------------------------------------------------------------------*/

まず輪郭の数が0の場合は無視するために
if(contours.size()>0){}
で0の場合は処理しないようにします。

次に輪郭の数が1つだけならばその輪郭が1番大きいので
while(contours.size() != 1){}
で輪郭が1つの場合ループを抜けるようにします。

ループの中は
contours.get(i)でi番目の輪郭の情報が取れるので
Imgproc.contourArea(contours.get(i))で輪郭の面積を出します。

※maxareaより大きい場合はその輪郭の面積をmaxareaに代入し、1番初めにある輪郭を消去します。
それ以外の場合はその輪郭を消去します。

※を輪郭が1つになるまで処理を繰り返すと残った輪郭が1番大きい輪郭となります。そして輪郭が1つだけなのでループを抜けすべての処理が終わります。





2014年1月19日日曜日

Android OpenCV 円検出

Android OpenCV 円検出

前回の記事 直線検出では直線の検出をしましたが今回は円の検出をしたいと思います。

円の検出には以下の関数を用いることでできます。(OpenCV リファレンス参照)


Imgproc.HoughCircles(Mat image, Mat circles, int method, double dp, double minDist, double param1, double param2, int minRadius, int maxRadius)

  • image – 8ビット,シングルチャンネル,グレースケールの入力画像.
  • circles – 検出された円を出力するベクトル.各ベクトルは,3要素の浮動小数点型ベクトル (x, y, radius) としてエンコードされます.
  • method – 現在のところ, CV_HOUGH_GRADIENT メソッドのみが実装されています.基本的には 2段階ハフ変換 で,これについては Yuen90 で述べられています.
  • dp – 画像分解能に対する投票分解能の比率の逆数.例えば, dp=1 の場合は,投票空間は入力画像と同じ分解能をもちます.また dp=2 の場合は,投票空間の幅と高さは半分になります.
  • minDist – 検出される円の中心同士の最小距離.このパラメータが小さすぎると,正しい円の周辺に別の円が複数誤って検出されることになります.逆に大きすぎると,検出できない円がでてくる可能性があります.
  • param1 – 手法依存の 1 番目のパラメータ. CV_HOUGH_GRADIENT の場合は, Canny() エッジ検出器に渡される2つの閾値の内,大きい方の閾値を表します(小さい閾値は,この値の半分になります).
  • param2 – 手法依存の 2 番目のパラメータ. CV_HOUGH_GRADIENT の場合は,円の中心を検出する際の投票数の閾値を表します.これが小さくなるほど,より多くの誤検出が起こる可能性があります.より多くの投票を獲得した円が,最初に出力されます.
  • minRadius – 円の半径の最小値.
  • maxRadius – 円の半径の最大値.


直線の時は輪郭(エッジ)の画像に変換してから直線を取得しましたが円検出の場合はぼかし(平滑化)を行ってから検出するほうが誤検出起こりにくいみたいです。ですが、実際にやってみた結果あまり変化がないというよりは平滑化するとほぼ円を認識しなくなり確かに誤検出は減りますが円を認識してもらわないと困るので誤検出が多い場合のみ使用したほうがよさそうです。

/*-----------------------------------------------------------------------

Mat src;
Mat dst;
Imgproc.cvtColor(src, dst, Imgproc.COLOR_RGB2GRAY);

GaussianBlur( dst, dst, Size(9, 9), 2, 2 );//←別になくてもよい

Mat image = dst;
Mat lines;
Imgproc.HoughLinesP(image, lines, Imgproc.CV_HOUGH_GRADIENT, 2, 10, 160, 50, 50, 120);

--------------------------------------------------------------------------------------------------*/

 

Android OpenCV 直線検出

Android OpenCV 直線検出

輪郭の抽出などをやってきましたが今回は直線についてやりたいと思います。

直線検出には

Imgproc.HoughLines(Mat image, Mat lines, double rho, double theta, int threshold, double srn, double stn)
  • image – 8ビット,シングルチャンネルの2値入力画像.この画像は関数により書き換えられる可能性があります.
  • lines – 検出された直線が出力されるベクトル.各直線は,2要素のベクトル (\rho, \theta) で表現されます. \rho は原点(画像の左上コーナー)からの距離, \theta はラジアン単位で表される直線の回転角度(0 \sim 垂直線, \pi/2 \sim 水平線)です.
  • rho – ピクセル単位で表される投票空間の距離分解能.
  • theta – ラジアン単位で表される投票空間の角度分解能.
  • threshold – 投票の閾値パラメータ.十分な票( >\texttt{threshold} )を得た直線のみが出力されます.
  • srn – マルチスケールハフ変換において,距離分解能 rho の除数となる値.投票空間の粗い距離分解能は rho となり,細かい分解能は rho/srn となります.もし srn=0 かつ stn=0 の場合は,古典的ハフ変換が利用されます.そうでない場合は,両方のパラメータが正値である必要があります.
  • stn – マルチスケールハフ変換において,角度分解能 theta の除数となる値.


Imgproc.HoughLinesP(Mat image, Mat lines, double rho, double theta, int threshold, double minLineLength, double maxLineGap)
  • image – 8ビット,シングルチャンネルの2値入力画像.この画像は関数により書き換えられる可能性があります.
  • lines – 検出された線分が出力されるベクトル.各線分は,4要素のベクトル (x_1, y_1, x_2, y_2) で表現されます.ここで (x_1,y_1) および (x_2, y_2) は,検出された各線分の端点です.
  • rho – ピクセル単位で表される投票空間の距離分解能.
  • theta – ラジアン単位で表される投票空間の角度分解能.
  • threshold – 投票の閾値パラメータ.十分な票( >\texttt{threshold} )を得た直線のみが出力されます.
  • minLineLength – 最小の線分長.これより短い線分は棄却されます.
  • maxLineGap – 2点が同一線分上にあると見なす場合に許容される最大距離.
を用いることでできます。(OpenCV リファレンス参照)

直線を取得する前に輪郭(エッジ)の画像に変換してから直線を取得します。

/*-----------------------------------------------------------------------

Mat src;
Mat dst;
Imgproc.cvtColor(src, dst, Imgproc.COLOR_RGB2GRAY);

Mat image = dst;
Mat edges;
Imgproc.Canny( image, edges, 80, 100);

Mat image2 = edges;
Mat lines;
Imgproc.HoughLinesP(image, lines, 1, Math.PI / 180 , 50, 100 ,10);

--------------------------------------------------------------------------------------------------*/
 

Android OpenCV ぼかし

Android OpenCV ぼかし

Android-OpenCV 輪郭抽出(2) のおまけ
OpenCVで輪郭を抽出するときノイズなどが入ってしまい期待しているような輪郭が得られない場合があります。

画像をぼかすことでノイズの影響を減らすことができます。

画像をぼかす(平滑化)には以下の関数(OpenCVリファレンスを参考)

Imgproc.GaussianBlur(Mat src, Mat dst, Size ksize, double sigmaX, double sigmaY)
  • src – 入力画像.
  • dstsrc と同じサイズ,同じ型の出力画像.
  • ksize – ガウシアンカーネルサイズ. ksize.widthksize.height は別の値を取ることができますが,両方とも正の奇数でなければいけません.または 0 をとることも可能で,その場合のサイズは sigma* から算出されます.
  • sigmaY (sigmaX,) – ガウシアンカーネルの,XとY方向の標準偏差. sigmaY が 0 ならば, sigmaX と等しくなるようにセットされます.両方の値が 0 の場合は,それぞれ ksize.widthksize.height から求められます. getGaussianKernel() を参照してください.将来これらの引数の意味が変更されたとしても,それに関係なく結果を完全に制御するために, ksize , sigmaX および sigmaY のすべての値を指定することが推奨されます.
  • borderType – ピクセル外挿手法. borderInterpolate() を参照してください.

  • .Imgproc.medianBlur(Mat src, Mat dst, int ksize)
  • src – 1-, 3- あるいは 4-チャンネルの入力画像. ksize が 3 または 5 ならば,この画像のビット深度は CV_8U , CV_16U または CV_32F となります.それ以上のアパーチャサイズの場合は CV_8U だけが可能です.
  • dstsrc と同じサイズ,同じ型の出力画像.
  • ksize – アパーチャサイズ.1より大きな奇数,例えば 3, 5, 7 ... でなければいけません.

  • Imgproc.boxFilter(Mat src, Mat dst, int ddepth, Size ksize, Point anchor, boolean normalize, int borderType)
    • src – 入力画像.
    • dstsrc と同じサイズ,同じ型の出力画像.
    • ksize – 平滑化カーネルのサイズ.
    • anchor – アンカー点.デフォルト値の Point(-1,-1) は,アンカーがカーネル中心にあることを意味します.
    • normalize – カーネルが面積で正規化されているか否かを指定します.
    • borderType – 画像外のピクセルを外挿するために利用される境界モード.


    のいずれかを使うことでできます。


    /*------------------------------------------------------------------------------------

    Mat src;
    Mat dst;

    Imgproc.GaussianBlur( src,  dst, new Size(5,3), 6, 4);

    Mat image = dst;
    List<MatOfPoint> contours;
    Mat hierarchy;

    Imgproc.findContours( image,  contours,  hierarchy, Imgproc.RETR_EXTERNAL, Imgproc.CHAIN_APPROX_TC89_L1);

    --------------------------------------------------------------------------------------------------*/

    これでノイズを軽減した画像から輪郭の抽出ができます。精度が上がりますが処理が多くなるので場合によって使い分けるほうがいいのかもしれません。

    Android SurfaceView 背景透過描画

    Android SurfaceView 背景透過描画

    Androidで画面の描画を行うときViewを用いて図形や画像などの描画ができます。タッチをした時だけだったり一定時間毎に画面の更新がない場合はViewで大丈夫ですが、ゲームなどで一定時間ごとに画面の更新がある場合はSurfaceViewを用います。

    そこで一番困ったことがSurfaceViewを用いて描画を行うとその描画が残ってしまいます。
    ゲームなどの描画ではループの始まりに背景を書き直すことで対処できますが、カメラからのビューを背景に用いて描画を重ねて表示する場合リセットするために全体を白色などで塗りつぶしてしまっては意味がありません。

    そこで透過をしながら画面をリセットするためには

    Canvas.drawColor(int color, Mode mode)を使います。

    引数にcolor Color.TRANSPARENT,mode PorterDuff.Mode.CLEAR指定することによって透過をしながら画面をリセットできます。


    /*----------------------------------------------------------------------------
    @Override
     public void run() {

      while(true){
       try {
        Canvas canvas = surfaceholder.lockCanvas();

        canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);

        /*
            描画処理・・・
        */
      
        surfaceholder.unlockCanvasAndPost(canvas);
      
        Thread.sleep(50);
       } catch (InterruptedException e) {
        e.printStackTrace();
       }
      }
     }

    ---------------------------------------------------------------------------------*/

    2014年1月18日土曜日

    Android-OpenCV 輪郭抽出(2)

    Android-OpenCV 輪郭抽出(2)

    前回の記事 Android-OpenCV 輪郭抽出でCannyを使用した輪郭抽出を行いましたが今回はさらに抽出した輪郭の情報も取得したいと思います。

    輪郭の情報を取得するには

    Imgproc.findContours(Mat image, List<MatOfPoint> contours, Mat hierarchy, int mode, int method)
    • image – 入力画像,8ビット,シングルチャンネル.0以外のピクセルは 1として,0のピクセルは0のまま扱われます.つまり,入力画像は 2値画像 として扱われます.グレースケールやカラー画像から2値画像を得るには, compare() , inRange() , threshold() , adaptiveThreshold() , Canny() などの関数を利用します.また,この関数は,輪郭抽出処理中に入力画像 image の中身を書き換えます.
    • contours – 検出された輪郭.各輪郭は,点のベクトルとして格納されます.
    • hiararchy – オプション.画像のトポロジーに関する情報を含む出力ベクトル.これは,輪郭数と同じ数の要素を持ちます.各輪郭 contours[i] に対して,要素 hierarchy[i][0] , hiearchy[i][1] , hiearchy[i][2] , hiearchy[i][3] にはそれぞれ,同じ階層レベルに存在する前後の輪郭,最初の子輪郭,および親輪郭の contours インデックス(0 基準)がセットされます.また,輪郭 i において,前後,親,子の輪郭が存在しない場合,それに対応する hierarchy[i] の要素は,負の値になります.
    • mode – 輪郭抽出モード
      • CV_RETR_EXTERNAL 最も外側の輪郭のみを抽出します.すべての輪郭に対して hierarchy[i][2]=hierarchy[i][3]=-1 がセットされます.
      • CV_RETR_LIST すべての輪郭を抽出しますが,一切の階層構造を保持しません.
      • CV_RETR_CCOMP すべての輪郭を抽出し,それらを2階層構造として保存します:上のレベルには,連結成分の外側の境界線が,下のレベルには,連結成分の内側に存在する穴の境界線が属します.ある連結成分の穴の内側に別の輪郭が存在する場合,その穴は上のレベルに属します.
      • CV_RETR_TREE すべての輪郭を抽出し,入れ子構造になった輪郭を完全に表現する階層構造を構成します.この完全な階層構造は,OpenCVの contours.c デモで見ることができます.
    • method – 輪郭の近似手法:
      • CV_CHAIN_APPROX_NONE すべての輪郭点を完全に格納します.つまり,この手法により格納された任意の隣り合う2点は,互いに8近傍に存在します.
      • CV_CHAIN_APPROX_SIMPLE 水平・垂直・斜めの線分を圧縮し,それらの端点のみを残します.例えば,まっすぐな矩形の輪郭線は,4つの点にエンコードされます.
      • CV_CHAIN_APPROX_TC89_L1,CV_CHAIN_APPROX_TC89_KCOS Teh-Chinチェーン近似アルゴリズムの1つを適用します. TehChin89 を参照してください.
    • offset – オプションのオフセット.各輪郭点はこの値の分だけシフトします.これは,ROIの中で抽出された輪郭を,画像全体に対して位置づけて解析する場合に役立ちます.

    を用います。(OpenCV リファレンス参照)

    今回は
    mode Imgproc.RETR_EXTERNAL(最も外側の輪郭のみを抽出),
    method Imgproc.CHAIN_APPROX_TC89_L1(Teh-Chinチェーン近似アルゴリズムの1つを適用します)
    を指定します。

    /*------------------------------------------------------------------------------------------------

    Mat image;
    List<MatOfPoint> contours;
    Mat hierarchy;

    Imgproc.findContours( image,  contours,  hierarchy, Imgproc.RETR_EXTERNAL, Imgproc.CHAIN_APPROX_TC89_L1);

    --------------------------------------------------------------------------------------------------*/

    これで入力画像から抽出した輪郭の情報が取得できます。

    取得した輪郭の情報はcontoursに入っています。

    Android-OpenCV 輪郭抽出

    Android OpenCV 輪郭抽出


    今回は取り込んだ画像の輪郭を検出する方法です。

    輪郭(エッジ)の表示は

    Imgproc.Canny(Mat image, Mat edges, double threshold1, double threshold2)

    • image – 8ビット,シングルチャンネルの入力画像.
    • edges – 出力されるエッジのマップ. image と同じサイズ,同じ型です.
    • threshold1 – ヒステリシスが存在する処理の,1番目の閾値.
    • threshold2 – ヒステリシスが存在する処理の,2番目の閾値.
    • apertureSizeSobel() オペレータのアパーチャサイズ.
    • L2gradient – 画像勾配の強度を求めるために,より精度の高い L_2 ノルム =\sqrt{(dI/dx)^2 + (dI/dy)^2} を利用するか, L_1 ノルム =|dI/dx|+|dI/dy| で十分( L2gradient=false )かを指定します.

    を用いることでできます。(OpenCV リファレンス参照)

    srcにはシングルチャンネルである必要があるので

    上の関数に入れる前に入力画像を

    Imgproc.cvtColor(Mat src, Mat dst, int code)

    codeにImgproc.COLOR_RGB2GRAYを指定することによってRGBからグレースケールのシングルチャンネルの画像に変換されます。

    /*-----------------------------------------------------------------------

    Mat src;
    Mat dst;
    Imgproc.cvtColor(src, dst, Imgproc.COLOR_RGB2GRAY);

    Mat image = dst;
    Mat edges;
    Imgproc.Canny( image, edges, 80, 100);

    -----------------------------------------------------------------------*/

    これで輪郭が抽出された画像が出力されます。

    2014年1月17日金曜日

    Android-OpenCV 肌色抽出(2)

    Android-OpenCV 肌色抽出(2)

    前回の記事 Android-OpenCV 肌色抽出で肌色の部分だけが白色の画像が出力されましたがこれだけではおもしろくないので今回は肌色の部分だけが色が残っている画像を出力します。


    /*--------------------------------------------------------------------

    Mat src;//入力画像
    Mat dst;//出力画像
    Imgproc.cvtColor(src, dst, Imgproc.COLOR_RGB2HSV);

    Mat src2 = dst;//入力画像
    Mat dst2;//出力画像
    Scalar lowerb = new Scalar( 0,60,80);//下限値
    Scalar lowerb = new Scalar(30,255,255);//上限値
    Core.inRange( src2,  lowerb,  upperb, dst2);

    ---------------------------------------------------------------------*/

    ここまでで肌色の部分だけ値を持った画像になります。

    次に色のついている入力画像と肌色の抽出した画像とを比べて値があるところだけ色を残したいと思います。

    Core.bitwise_and(Mat src1, Mat src2, Mat dst)

    src1-入力画像1
    src2-入力画像2
    dst-出力画像

    今回はsrc1に元の画像、src2に肌色を抽出した画像をいれます。

    出力画像は肌色の部分だけ色が残りそれ以外はなにも値がない画像になります。


    /*--------------------------------------------------------------------

    Mat src;//入力画像
    Mat dst;//出力画像
    Imgproc.cvtColor(src, dst, Imgproc.COLOR_RGB2HSV);

    Mat src2 = dst;//入力画像
    Mat dst2;//出力画像
    Scalar lowerb = new Scalar( 0,60,80);//下限値
    Scalar lowerb = new Scalar(30,255,255);//上限値
    Core.inRange( src2,  lowerb,  upperb, dst2);

    Mat src3 = dst2;
    Mat dst3;
    Core.bitwise_and( src, src3,  dst3);

    ---------------------------------------------------------------------*/

    Android OpenCV カメラビュー

    Android アプリ開発 OpenCV カメラビュー

    OpenCV を用いたカメラビューのサンプルコード

    Android for OpenCVを使ってカメラビューおよびビューをMatで取り込む方法
    取り込んだ画像からいろいろな変換などができます。

    /*-------------------------------------------------------------------------------------------------------------------

    public class MainActivity extends Activity implements CvCameraViewListener{
        private CameraBridgeViewBase mCameraView;
        private Mat mOutputFrame;
     
        private BaseLoaderCallback mLoaderCallback = new BaseLoaderCallback(this) {
            @Override
            public void onManagerConnected(int status) {
                switch (status) {
                case LoaderCallbackInterface.SUCCESS:
                    mCameraView.enableView();
                    break;
                default:
                    super.onManagerConnected(status);
                    break;
                }
            }
        };
       
     @Override
     protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
       getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
          requestWindowFeature(Window.FEATURE_NO_TITLE);
          setContentView(R.layout.activity_main);
          mCameraView = (CameraBridgeViewBase)findViewById(R.id.camera_view);
          mCameraView.setCvCameraViewListener(this);
     }

        @Override
        public void onResume() {
            super.onResume();
            OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_2_4_6, this, mLoaderCallback);
        }
     
        @Override
        public void onPause() {
            super.onPause();
            if (mCameraView != null) {
                mCameraView.disableView();
            }
        }
       
        @Override
        public void onDestroy() {
            super.onDestroy();
            if (mCameraView != null) {
                mCameraView.disableView();
            }
        }
       
        @Override
        public void onCameraViewStarted(int width, int height) {
            mOutputFrame = new Mat(height, width, CvType.CV_8UC1);
          }
       
        @Override
        public void onCameraViewStopped() {
         if(mOutputFrame != null)mOutputFrame.release();
         mOutputFrame = null;
       }
     @Override
     public Mat onCameraFrame(Mat inputFrame) {
         //ここでビューから取り込んだ画像を取得できる
            return inputFrame;
     }
    }

    --------------------------------------------------------------------------------------*/

    activity_main.xml

    /*-----------------------------------------------------------------------------------

    <RelativeLayout xmlns:android=http://schemas.android.com/apk/res/android
        xmlns:tools=http://schemas.android.com/tools
        xmlns:opencv=http://schemas.android.com/apk/res-auto
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:keepScreenOn="true"
        tools:context=".MainActivity" >
       
      <org.opencv.android.JavaCameraView
        android:id="@+id/camera_view"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:visibility="visible"
        opencv:camera_id="any"
        opencv:show_fps="true" />

    </RelativeLayout>

    ------------------------------------------------------------------------------------------*/

    Android-OpenCV 肌色抽出

    Android for OpenCV


    Androidで取り込んだ画像から肌色を抽出する方法

    肌色を抽出するとき色空間がRGBの画像から肌色の範囲を選択してもできますが明るさによって値が大きく変わるのであまり適していません。そこで明るさなどの影響を減らすために色空間をRGBからHSVに変換します。

    Imgproc.cvtColor(Mat src, Mat dst, int code)//色空間の変換
    src-入力画像、dst-出力画像(入力画像と同じサイズ)、code-変換コード

    変換コードのところをRGBからHSVに変換するコードを指定します。

    Imgproc.COLOR_RGB2HSV(RGB→HSV)

    /*--------------------------------------------------------------------

    Mat src;//入力画像
    Mat dst;//出力画像
    Imgproc.cvtColor(src, dst, Imgproc.COLOR_RGB2HSV);

    ---------------------------------------------------------------------*/

    これで画像の色空間がHSVに変わりました。

    次に肌色の範囲を指定します。

    H-色相、S-彩度、V-明度

    だいたいHが0~30、Sが60~255、Vが80~255の間の値で肌色になります。
    この値を変えることによって肌色を抽出する精度が上がりますが今回はこの値にします。

    Core.inRange(Mat src, Scalar lowerb, Scalar upperb, Mat dst)
    src-入力画像、lowerb-範囲の下限値、upperb-範囲の上限値、dst-出力画像

    今回の場合ScalarはScalar(H、S、V);の順番で指定します。

    /*--------------------------------------------------------------------

    Mat src;//入力画像
    Mat dst;//出力画像
    Scalar lowerb = new Scalar( 0,60,80);//下限値
    Scalar lowerb = new Scalar(30,255,255);//上限値
    Core.inRange( src,  lowerb,  upperb, dst);

    ---------------------------------------------------------------------*/

    これで肌色の部分だけが抽出された画像が出力されます。

    2014年1月13日月曜日

    Android Viewを重ねて表示

    Android Viewを重ねて表示


    AndroidでViewなどを重ねて表示する方法
    AvtivityのCreateでaddContentView(view,params)を使うことによって重ねて表示できます。
    カメラから取り込んだものの上に表示させることもできます。

    /*------------------------------------------

    @Override
    protected void onCreate(Bundle bundle) {
    super.onCreate(bundle);
    MyView myView = new MyView(this);//独自のViewクラス

    //ここをカメラビューにすることで背面がカメラから取り込んだものになる
    setContentView(R.layout.activity_main);

    //ここに重ねて表示したいものを指定する
    addContentView(myView, new LayoutParams(
    LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT) );
    }
    ---------------------------------------------*/

    これでactivityのレイアウトとViewを重ねて表示することができます。

    レイアウトをカメラビューなどに変えて表示させるの一番有効的な使い方ですが、ボタンなどの配置をレイアウトに入れてView上にそのレイアウトを表示させる方法もあります。

    Android カメラビュー

    Android カメラビュー


    Androidカメラビューのサンプルコード

    カメラからの取り込んだものを画面に表示させます。画面をタッチして写真が撮れるようにするとカメラアプリが作れます。
    本体のカメラを使うには権限が必要なのでアプリのマニュフェストにカメラを使えるようにしておきます。

    /*------------------------------------------------------------------------------
    import android.app.Activity;
    import android.content.Context;
    import android.hardware.Camera;
    import android.os.Bundle;
    import android.view.Menu;
    import android.view.SurfaceHolder;
    import android.view.SurfaceView;
    public class MainActivity extends Activity {

     @Override
     protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(new MyCameraView(this));
     }

     public class MyCameraView extends SurfaceView implements SurfaceHolder.Callback{
       private Camera camera;

       public MyCameraView(Context context){
        super(context);
        getHolder().addCallback(this);
        getHolder().setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
       }

       public void surfaceCreated(SurfaceHolder holder){
        camera = Camera.open();
       try {
        camera.setPreviewDisplay(holder);
       } catch (Exception e) {
        e.printStackTrace();
       }
       }

       public void surfaceChanged(SurfaceHolder holder, int format, int width, int height){
        Camera.Parameters parameters = camera.getParameters();
        parameters.setPreviewSize(width, height);
        camera.setParameters(parameters);
        camera.startPreview();
       }

       public void surfaceDestroyed(SurfaceHolder holder){
        camera.release();
        camera = null;
       }

      }

    }

    -------------------------------------------------------------------------------------------------*/

    カメラの利用には以下の文をマニュフェストに追加します。
    <uses-permission android:name="android.permission.CAMERA" />