2011-06-23 15 views
6

カメラを使用するAndroidアプリケーションを作成し、プレビューフレームに画像処理フィルタを適用したいと考えています。Android、カメラプレビューフレームを操作する

package alex.filter; 

import java.io.IOException; 

import android.content.Context; 
import android.graphics.Canvas; 
import android.hardware.Camera; 
import android.hardware.Camera.PreviewCallback; 
import android.view.SurfaceHolder; 
import android.view.SurfaceView; 

class Preview extends SurfaceView implements SurfaceHolder.Callback { 

    SurfaceHolder mHolder; 
    public Camera camera; 

    Preview(Context context) { 
     super(context); 
     mHolder = getHolder(); 
     mHolder.addCallback(this); 
     mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); 
    } 

    public void surfaceCreated(SurfaceHolder holder) {   
     camera = Camera.open();   

     try { 
      camera.setPreviewDisplay(holder); 

      camera.setPreviewCallback(new PreviewCallback() { 
       public void onPreviewFrame(byte[] data, Camera arg1) {      
        for(int i = 0 ; i < data.length ; i ++){ 
         data[ i] = 0; // or some sirius filter 
        }                
        Preview.this.invalidate(); 
       } 
      }); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
     } 

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

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

    @Override 
    public void draw(Canvas canvas) { 
     super.draw(canvas);   
    } 
} 

はしかし、私は関係なく、私がonPreviewFrame方法で何をすべきかエミュレータには変化は見られません。

+1

+1また、プレビューフレームを直接操作することが可能かどうかも疑問です。 –

答えて

1

これは、コールバックで取得しているプレビューバッファがプレビューバッファのコピーにすぎないため、取得したバッファがコピーであるため表示されません。私はこれを行う方法がわからないですが、私はそれをこのについて移動する方法についていくつかの考えを与え、ここで私は行われるべきだと思うものですされているAndroidのSDK here

に言及 -

  • 登録は、のためにあなたは、あなたが任意の表示を得るべきではない表面にプレビュー表示を設定していない場合、プレビューバッファ
  • は、デフォルトのプレビュー表示
    • を無効にしてください(私はそれが動作するかどうかわからない - いくつかでそれを読んでいましたフォーラムはソースを思い出すことができません)
    • 我々はそのよう
    • 以上が動作しない場合、我々はビューを非表示にする必要がありますが(私はほとんど効率的に知っているが、私は何かを考えることができませんでした。)
  • は、プレビューのフレームレートを削減しますバッファーで圧倒されることはありません
  • バッファーを表示するには、デフォルトのビットマップ描画機能を使用するか、またはバッファーを表示するためにopenglを使用します。しかし、私はこれまで使用していないので、それが可能かどうか、同じ考えを知っていない?私は、このAPIを発見したSDKのドキュメント再訪

UPDATE
- "OpenGL ESのテクスチャとして画像ストリームからフレームをキャプチャする" - このAPI setPreviewTextureはに私たちをことができます。テクスチャが適用されたイメージを取得したら、OpenGLを使用してフレームを表示できます。 (@Stephanが投稿した回答をご覧ください。)

注 - setPreviewTextureはAPIレベル11以降で利用可能です! SDK Link

+0

あなたはどこに行くのか分かります。 'SurfaceView'を使わずに' SurfaceHolder'を使う方法はありますか?もしそれを使ってプレビューデータを取得し、処理されたフレームを描画するための最適化された 'GLSurfaceView'を使用すれば、妥当なフレームレートを得ることができました。 –

+2

私はこれを分解したかもしれないと思います - カメラのドキュメンテーションをもう一度見て、この 'setPreviewTexture'を見つけました。これは"イメージストリームからフレームをOpenGL ESテクスチャとしてキャプチャ "できます。私はこのOpenGL ESテクスチャは方法だと思います行く。ここでも、OpenGLを使ってフレームを表示することができます。 [SurfaceTexture](http://developer.android.com/reference/android/graphics/Sur​​faceTexture.html) – bluefalcon

+0

ニース! APIレベル11のものなので、ドキュメントには載っていませんでした。私はAPIレベル8で動作するものを探していますが、それでもあなたの答えに含めてください。なぜなら、代替案がない場合には賞金を授与するからです。 –

2

this linkを参照してください。これは達成したいと似ていると思います。

+0

私はOpenGLを使用してバッファを表示することについて私の質問に答えていると思います。ありがとう! +1 – bluefalcon

+0

最初に動作しない場合は、このコード行に注意してください: 'this.setEGLConfigChooser(8,8,8,8,16,0); ' – Stephan

4

別のオプションは、Androidのポートを持っているOpenCVのフレームワークを使用することです:

http://opencv.willowgarage.com/wiki/Android2.3.0

それがオープンソースオープンコンピュータビジョンプロジェクトのNDKポートだし、それは生のプレビュー枠を取るだろうとそれらをOpenCVで処理してからSurfaceViewに表示することができます。フレームを操作するので、ハードウェアに最適化されたプレビューに直接フックされたものと全く同じフレームレートでは動作しませんが、その多くがネイティブであるため、かなり良い仕事をします。

あなたが探しているものの多くを行うことができるデモアプリケーションにコンパイルされた上記のバージョンのOpenCV_Sampleアプリケーションがあります。これには、反転を有効にする、画像をぼかす、またはプレビュー領域でエッジ検出を行うためのメニューオプションがあります。たとえそれがあなたの望むものではないとしても、ソースコードにはいくつかの素晴らしいサンプルがあります。

+0

リンクが壊れています! – acrespo

関連する問題