it-swarm.com.de

Überlagern Sie Bilder auf der Kamera-Vorschau von SurfaceView

Ich habe eine SurfaceView, die zum Zeichnen von Bildern verwendet wird, und ich möchte sie von der Kamera des Telefons einem Live-Feed überlagern.

Derzeit hat SurfaceView, das die Bilder enthält, einen weißen Hintergrund. Wenn ich sie jedoch in den Kamera-Feed des Telefons einblenden würde, müssten sie transparent sein. Die Kamera- und Animationszeichnung kann nicht auf demselben SurfaceView erstellt werden.

Was ist der beste Weg, um mehrere Ansichten zu verwenden, bei denen die Kamera verwaltet und Bilder gezeichnet werden? Ist es möglich, SurfaceView transparent zu machen? 

32
GobiasKoffi

Nun, ich habe es so gemacht ... Ich hoffe, jemand findet es nützlich, obwohl das Qualcomm AR-Zeug nicht verfügbar ist Als zusätzliche Funktionalität wurden die Touch-Ereignisse eingeführt, obwohl die Rotationsvektoren um ein Vielfaches abweichen - nur zu Demonstrationszwecken und natürlich die über der Kameravorschau überlagerten Würfel, die auf einem Bildschirm verschoben werden können. 


     public class TakeRecieptPicture extends Activity implements Callback {
    private Camera camera;
    private SurfaceView mSurfaceView;
    SurfaceHolder mSurfaceHolder;

    private TouchSurfaceView mGLSurfaceView;

    ShutterCallback shutter = new ShutterCallback(){

        @Override
        public void onShutter() {
            // TODO Auto-generated method stub
            // No action to be perfomed on the Shutter callback.

        }

       };
    PictureCallback raw = new PictureCallback(){
        @Override
        public void onPictureTaken(byte[] data, Camera camera) {
            // TODO Auto-generated method stub
            // No action taken on the raw data. Only action taken on jpeg data.
      }

       };

    PictureCallback jpeg = new PictureCallback(){

        @Override
        public void onPictureTaken(byte[] data, Camera camera) {
            // TODO Auto-generated method stub

            FileOutputStream outStream = null;
            try{
                outStream = new FileOutputStream("/sdcard/test.jpg");
                outStream.write(data);
                outStream.close();
            }catch(FileNotFoundException e){
                Log.d("Camera", e.getMessage());
            } catch (IOException e) {
                // TODO Auto-generated catch block
                Log.d("Camera", e.getMessage());
            }

        }

       };

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        this.requestWindowFeature(Window.FEATURE_NO_TITLE);
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
    WindowManager.LayoutParams.FLAG_FULLSCREEN);


         mGLSurfaceView = new TouchSurfaceView(this); 
     addContentView(mGLSurfaceView, new LayoutParams(LayoutParams.FILL_PARENT,LayoutParams.FILL_PARENT));

        mSurfaceView = new SurfaceView(this);
         addContentView(mSurfaceView, new LayoutParams(LayoutParams.FILL_PARENT,LayoutParams.FILL_PARENT));
       mSurfaceHolder = mSurfaceView.getHolder();
       mSurfaceHolder.addCallback(this);
       mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_Push_BUFFERS);
       mSurfaceHolder.setFormat(PixelFormat.TRANSLUCENT|LayoutParams.FLAG_BLUR_BEHIND); 
       }

    private void takePicture() {
        // TODO Auto-generated method stub
        camera.takePicture(shutter, raw, jpeg);
    }

    @Override
    public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) {
        // TODO Auto-generated method stub
        Camera.Parameters p = camera.getParameters();
        p.setPreviewSize(arg2, arg3);
        try {
        camera.setPreviewDisplay(arg0);
        } catch (IOException e) {
        e.printStackTrace();
        }
        camera.startPreview();
    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        // TODO Auto-generated method stub
    camera = Camera.open();
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        // TODO Auto-generated method stub
        camera.stopPreview();
        camera.release();
    }
    }
   

Die TouchSurfaceView ist unten definiert: 


   class TouchSurfaceView extends GLSurfaceView {  

    public TouchSurfaceView(Context context) {       
        super(context); 
        cr  = new CubeRenderer(true);
        this.setEGLConfigChooser(8, 8, 8, 8, 16, 0);
        this.setRenderer(cr);
        this.setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);  
        this.getHolder().setFormat(PixelFormat.TRANSPARENT);

        }  

    public boolean onTrackballEvent(MotionEvent e) {     
        cr.mAngleX += e.getX() * TRACKBALL_SCALE_FACTOR;      
        cr.mAngleY += e.getY() * TRACKBALL_SCALE_FACTOR;    
        requestRender();   
        return true;    }   

    @Override
    public boolean onTouchEvent(MotionEvent e) {      
        float x = e.getX();       
        float y = e.getY();     
        switch (e.getAction()) {    
        case MotionEvent.ACTION_MOVE:     
            float dx = x - mPreviousX;         
            float dy = y - mPreviousY;           
            cr.mAngleX += dx * TOUCH_SCALE_FACTOR;   
            cr.mAngleY += dy * TOUCH_SCALE_FACTOR;       
            requestRender();      
            }     
        mPreviousX = x;  
        mPreviousY = y;     
        return true;  

    }
    private final float TOUCH_SCALE_FACTOR = 180.0f / 320;  
    private final float TRACKBALL_SCALE_FACTOR = 36.0f;   
    public  CubeRenderer cr ;
    private float mPreviousX;   
    private float mPreviousY;


}

Und der CubeRenderer ist gegeben durch: 


    class CubeRenderer implements GLSurfaceView.Renderer {  
    public CubeRenderer(boolean useTranslucentBackground) { 
        mTranslucentBackground = useTranslucentBackground;   
        mCube = new Cube();  
       }  


    public void onDrawFrame(GL10 gl) {  
        gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);  
        gl.glMatrixMode(GL10.GL_MODELVIEW);     
        gl.glLoadIdentity();    
        gl.glTranslatef(0, 0, -5.0f);  
        gl.glRotatef(mAngle,        0, 1, 0);  
        gl.glRotatef(mAngle*0.25f,  1, 0, 0);     
        gl.glEnableClientState(GL10.GL_VERTEX_ARRAY); 
        gl.glEnableClientState(GL10.GL_COLOR_ARRAY);    
        mCube.draw(gl);      
        gl.glRotatef(mAngle*2.0f, 0, 1, 1);    
        gl.glTranslatef(0.5f, 0.5f, 0.5f);     
        mCube.draw(gl);     
        mAngle += 1.2f;  
        }  
    public void onSurfaceChanged(GL10 gl, int width, int height) {     
        gl.glViewport(0, 0, width, height);    
        float ratio = (float) width / height;     
        gl.glMatrixMode(GL10.GL_PROJECTION);       
        gl.glLoadIdentity();     
        gl.glFrustumf(-ratio, ratio, -1, 1, 1, 10);
        } 

    public void onSurfaceCreated(GL10 gl, EGLConfig config) {      

        gl.glDisable(GL10.GL_DITHER);     
        gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_FASTEST);   
        if (mTranslucentBackground) {          
            gl.glClearColor(0,0,0,0);      
            } else {        
                gl.glClearColor(1,1,1,1);     
                }       
        gl.glEnable(GL10.GL_CULL_FACE);     
        gl.glShadeModel(GL10.GL_SMOOTH);     
        gl.glEnable(GL10.GL_DEPTH_TEST);   
        }  

    public void setAngle(float _angle){

    }
    private boolean mTranslucentBackground;  
    private Cube mCube;  
    private float mAngle;
      public  float mAngleX;  
       public float mAngleY;

}
   

Und schließlich ist der Würfel selbst gegeben durch:


    class Cube{   
    public Cube()  
    {        int one = 0x10000;    
    int vertices[] = {  
            -one, -one, -one,   
            one, -one, -one,     
            one,  one, -one,      
            -one,  one, -one,           
            -one, -one,  one,         
            one, -one,  one,           
            one,  one,  one,          
            -one,  one,  one,        };  

    float[] colors = {      
            0f,    0f,    0f,  0.5f, 
            1f ,  0f,  0f, 0.1f,    
            1f,1f,0f,0.5f,   
            0f,  1f,    0f,  0.1f,      
            0f,    0f,  1f,  0.1f,       
            1f,    0f,  1f,  0.2f,      
            1f,  1f,  1f,  0.1f,        
            0f,  1f,  1f,  0.1f,        };    

    byte indices[] = {          
            0, 4, 5,    0, 5, 1,    
            1, 5, 6,    1, 6, 2,     
            2, 6, 7,    2, 7, 3,      
            3, 7, 4,    3, 4, 0,      
            4, 7, 6,    4, 6, 5,       
            3, 0, 1,    3, 1, 2        };   


    ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length*4);   
    vbb.order(ByteOrder.nativeOrder());     
    mVertexBuffer = vbb.asIntBuffer();    
    mVertexBuffer.put(vertices);      
    mVertexBuffer.position(0);      
    ByteBuffer cbb = ByteBuffer.allocateDirect(colors.length*4);   
    cbb.order(ByteOrder.nativeOrder());     
    mColorBuffer = cbb.asFloatBuffer();      
    mColorBuffer.put(colors);     
    mColorBuffer.position(0);      
    mIndexBuffer = ByteBuffer.allocateDirect(indices.length);     
    mIndexBuffer.put(indices);     
    mIndexBuffer.position(0);    } 
    public void draw(GL10 gl)    {    
        gl.glFrontFace(gl.GL_CW);     
        gl.glVertexPointer(3, gl.GL_FIXED, 0, mVertexBuffer);  
        gl.glColorPointer(4, gl.GL_FIXED, 0, mColorBuffer);     
        gl.glDrawElements(gl.GL_TRIANGLES, 36, gl.GL_UNSIGNED_BYTE, mIndexBuffer);    } 

    private IntBuffer   mVertexBuffer;  
    private FloatBuffer   mColorBuffer;   
    private ByteBuffer  mIndexBuffer;

    }
   

Ich hoffe, jemand findet das nützlich ... 

20
bala singareddy

Ich mache auch eine erweiterte Anwendung und habe das gleiche Problem, das Sie getroffen haben. Es gibt sehr wenige Informationen, wie das Problem richtig gelöst werden kann. Ich habe jedoch ein Framework namens mixare gefunden - damit können Sie eine AR-App für Android erstellen. Du solltest es definitiv anschauen source - es sieht ziemlich vielversprechend aus. Hoffe, das wird dir helfen.

6
matekm

Ich habe mit dem folgenden Ansatz Erfolg gehabt.

Erstellen Sie zunächst eine Layout-XML-Datei, die ungefähr so ​​aussieht (beachten Sie die Reihenfolge der beiden Ansichten):

<FrameLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
    Android:layout_width="fill_parent" Android:layout_height="fill_parent"
    Android:orientation="vertical">

    <com.yourcustom.OverlayView
        Android:id="@+id/overlay" Android:layout_width="fill_parent"
        Android:layout_height="fill_parent">
    </com.yourcustom.OverlayView>

    <SurfaceView Android:id="@+id/surface"
        Android:layout_width="fill_parent" Android:layout_height="fill_parent">
    </SurfaceView>

</FrameLayout>

OverlayView ist eine Unterklasse von SurfaceView mit den Zeichnungs- und Animations-Thread-Implementierungen. Die andere SurfaceView ist die Oberfläche, die die Kameravorschau behandelt. Innerhalb von onCreate sollten Sie Ihre Ansichten folgendermaßen einrichten:

    mView = (OverlayView)this.findViewById(R.id.overlay);
    mView.getHolder().setFormat(PixelFormat.TRANSLUCENT); 

    mSurfaceView = (SurfaceView)this.findViewById(R.id.surface);
    mSurfaceHolder = mSurfaceView.getHolder();
    mSurfaceHolder.addCallback(this);
    mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_Push_BUFFERS);

Sie sollten eine SurfaceHolder.Callback-Implementierung zur SurfaceHolder von mView hinzufügen, die den Animationsthread behandelt. Ein Beispiel für die Implementierung in der Unterklasse und die Verwendung von Animations-/Zeichnungs-Threads finden Sie im alten LunarLander-Beispiel hier: http://developer.Android.com/resources/samples/LunarLander/src/com/example /Android/lunarlander/LunarView.html

Außerdem richten Sie die Kamera SurfaceView auf dieselbe Weise wie in diesem Beispiel ein: http://developer.Android.com/resources/samples/ApiDemos/src/com/example/Android/apis/graphics/CameraPreview. html

5
Frank

Might dieser Code Hilfe? `

1
Pontus Gagge

Ich habe gerade einen etwas seltsamen Nachbeben gefunden, als ich mein Handy auf 4.0.4 aufgerüstet habe. Ich habe eine durchsichtige gl-Vollbild-Überlagerung für eine Ganzbildkamera-Vorschau, die bei einem früheren ics-Build recht gut funktioniert hat (ich glaube, es war 4.0.3, aber nicht sicher). Nach dem Upgrade auf 4.0.4 wurde die Vorschau etwas durcheinander gebracht, wobei das Kamerabild psychedelische primäre Farbbereiche in einem der helleren Bereiche des Kamerabildes zeigte (dunklere Teile sahen in Ordnung aus). Schließlich stellte sich heraus, dass sich die Glanzfarbe auf 0,0,0,0 von 0,5, 0,5, 0,5 ändert. 0 hat es aussortiert.

Es scheint, dass, obwohl das Alpha auf den ungenutzten Teilen der gl-Überlagerung null war, die Mischfunktion immer noch den grauen gl-Hintergrund berücksichtigte.

0
pootle