2012-03-02 18 views
1

Androidでのロボットのラインフォロワを作成しています(Java/Androidプログラミングを学ぶため)、現在私は画像処理の問題に直面しています。カメラプレビューはYUVという画像フォーマットを返しますラインがどこにあるのかを知るために閾値に変換したいのですが、どのようにすればいいでしょうか?Androidでのカメラプレビュー処理

は、今のところ私は、私は間違いなくカメラのプレビューからデータを読み取ることができ、光強度が上の特定の領域でオーバーまたは一定値以下であれば、いくつかの奇跡でさえ知っている、何かを得て成功してきました画面。私の目標は、カメラのプレビュー上のオーバーレイにロボットのパスを描くことです。それはある程度は機能しますが、問題はYUVの管理です。あなたは暗い領域が横向きに描かれているだけでなく見ることができますが、それはまた、それ自体を4回繰り返し、プレビュー画像が引き伸ばされたよう

Galaxy Nexus Screenshot

、私はこれらの問題を解決する方法を見つけ出すことはできません。

は、ここでは、コードの関連部分です:私の問題の少なくともですrelease後に呼び出されているいくつかの方法、のためにアプリケーションを終了するとき

public void surfaceCreated(SurfaceHolder arg0) { 
    // TODO Auto-generated method stub 

    // camera setup 
    mCamera = Camera.open(); 

    Camera.Parameters parameters = mCamera.getParameters(); 
    List<Camera.Size> sizes = parameters.getSupportedPreviewSizes(); 
    for(int i=0; i<sizes.size(); i++) 
    { 
     Log.i("CS", i+" - width: "+sizes.get(i).width+" height: "+sizes.get(i).height+" size: "+(sizes.get(i).width*sizes.get(i).height)); 
    } 

    // change preview size 
    final Camera.Size cs = sizes.get(8); 
    parameters.setPreviewSize(cs.width, cs.height); 

    // initialize image data array 
    imgData = new int[cs.width*cs.height]; 

    // make picture gray scale 
    parameters.setColorEffect(Camera.Parameters.EFFECT_MONO); 
    parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO); 
    mCamera.setParameters(parameters); 

    // change display size 
    LayoutParams params = (LayoutParams) mSurfaceView.getLayoutParams(); 
    params.height = (int) (mSurfaceView.getWidth()*cs.height/cs.width); 
    mSurfaceView.setLayoutParams(params); 

    LayoutParams overlayParams = (LayoutParams) swOverlay.getLayoutParams(); 
    overlayParams.width = mSurfaceView.getWidth(); 
    overlayParams.height = mSurfaceView.getHeight(); 
    swOverlay.setLayoutParams(overlayParams); 

    try 
    { 
     mCamera.setPreviewDisplay(mSurfaceHolder); 
     mCamera.setDisplayOrientation(90); 
     mCamera.startPreview(); 
    } 
    catch (IOException e) 
    { 
     e.printStackTrace(); 
     mCamera.stopPreview(); 
     mCamera.release(); 
    } 

    // callback every time a new frame is available 
    mCamera.setPreviewCallback(new PreviewCallback() { 
     public void onPreviewFrame(byte[] data, Camera camera) 
     { 
      // create bitmap from camera preview 
      int pixel, pixVal, frameSize = cs.width*cs.height; 
      for(int i=0; i<frameSize; i++) 
      { 
       pixel = (0xff & ((int) data[i])) - 16; 
       if(pixel < threshold) 
       { 
        pixVal = 0; 
       } 
       else 
       { 
        pixVal = 1; 
       } 
       imgData[i] = pixVal; 
      } 

      int cp = imgData[(int) (cs.width*(0.5+(cs.height/2)))]; 

      //Log.i("CAMERA", "Center pixel RGB: "+cp); 
      debug.setText("Center pixel: "+cp); 

      // process preview image data 
      Paint paint = new Paint(); 
      paint.setColor(Color.YELLOW); 


      int start, finish, last; 
      start = finish = last = -1; 
      float x_ratio = mSurfaceView.getWidth()/cs.width; 
      float y_ratio = mSurfaceView.getHeight()/cs.height; 

      // display calculated path on overlay using canvas 
      Canvas overlayCanvas = overlayHolder.lockCanvas(); 
      overlayCanvas.drawColor(0, Mode.CLEAR); 

      // start by finding the tape from bottom of the screen  
      for(int y=cs.height; y>0; y--) 
      { 
       for(int x=0; x<cs.width; x++) 
       { 
        pixel = imgData[y*cs.height+x]; 

        if(pixel == 1 && last == 0 && start == -1) 
        { 
         start = x; 
        } 
        else if(pixel == 0 && last == 1 && finish == -1) 
        { 
         finish = x; 
         break; 
        } 
        last = pixel; 
       } 
       //overlayCanvas.drawLine(start*x_ratio, y*y_ratio, finish*x_ratio, y*y_ratio, paint); 
       //start = finish = last = -1; 
      } 
      overlayHolder.unlockCanvasAndPost(overlayCanvas); 
     } 
    }); 
} 

このコードは、時々エラーが発生します。


UPDATE:

今の向きの問題が修正されていること(CCDセンサの向き)私はまだ繰り返し問題に直面しています、これはおそらく私のYUVデータ管理に関連している...

enter image description here

答えて

2

あなたの表面およびカメラ管理が正しいように見えますが、私はいくつかのカメラの実装が拒否(つまりカメラ、実際に受け入れられたプレビューサイズの設定をdoublecheckう

あなたがポートレートモードで作業しているとき、カメラは、指向性についての怒りを与えません - その座標原点はCCDチップによって決定され、常に右隅にあり、スキャン方向は上から下、右から左へ - オーバーレイキャンバスとはまったく異なります。 (しかし、あなたがランドスケープモードであれば、すべて正しい);) - これは奇妙な描画結果の正真正銘のソースです

あなたのスレッショルドは現実には少しナイーブであまり役に立たないです - 私は適応型スレッシュロックを提案します。

(パッチは歓迎)

http://sourceforge.net/projects/javaocr/

パフォーマンスの二値化は、単一の画像列上で動作するように改善することができます。私たちのjavaocrプロジェクト(純粋なJava、またAndroidのデモを持っている)で、我々は、効率的なsauvolaの二値化を実装(デモを参照してください)画像のUV部分と

問題は簡単です - デフォルト・フォアマンはNV21で、輝度が最初 を来て、これは単なるバイトストリームで、あなたはすべての画像のUV部分は必要ありません(上記のデモに見える)

+0

をいただき、ありがとうございますCCDチップ、それは実際には問題でしたが、今度はどのように繰り返し、これは間違いなくYUVの管理に関係しています。私はそれを動作させると、私はそれを動的なしきい値で最適化します。 – Solenoid

+0

... liminanceの問題について歓迎 –