简体   繁体   English

Android,manpulate相机预览帧

[英]Android, manupulate camera preview frames

I want to make an Android application that uses the camera and applies image processing filters on the preview frames. 我想制作一个使用相机的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);        
    }
}

However, I see no changes in the emulator no matter what I do in the onPreviewFrame method. 但是,无论我在onPreviewFrame方法中做什么,我都看不到模拟器中的任何变化。

Another option is to use the OpenCV framework, which has an Android port: 另一个选择是使用OpenCV框架,它有一个Android端口:

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

It's an NDK port of the open source Open Computer Vision project, and it'll take raw preview frames and allow for processing them with OpenCV before displaying them on a SurfaceView. 它是开源Open Computer Vision项目的NDK端口,它将采用原始预览帧并允许在使用OpenCV处理它们,然后在SurfaceView上显示它们。 Because it manipulates the frames it doesn't run at quite the same framerate as just a directly hooked in hardware optimized preview, but because so much of it is native it does a pretty good job. 因为它操纵帧,它的运行速度与硬件优化预览中直接连接的帧速率完全相同,但由于它本身的大部分是本机的,所以它做得非常好。

There's an OpenCV_Sample app in that version linked above which compiled into a demo app which can do much of what you're looking for. 在上面链接的那个版本中有一个OpenCV_Sample应用程序,它编译成一个演示应用程序,可以完成您正在寻找的大部分内容。 It has menu options to enable inverse, blur the image, or do edge detection on the preview area. 它具有菜单选项,可以在预览区域启用反转,模糊图像或进行边缘检测。 Even if it's not exactly what you want, there are some great samples in the source code to learn from. 即使它不是您想要的,也可以在源代码中学习一些很好的示例。

看到这个链接 ,我认为它与您想要实现的类似。

Well that's because the preview buffers that you are getting in the callback is only a copy of the preview buffers, hence any modifications that you do will not be displayed since the buffer that you get is your copy. 那是因为你在回调中得到的预览缓冲区只是预览缓冲区的副本,因此你所做的任何修改都不会显示,因为你得到的缓冲区是你的副本。 Mentioned in the android sdk here 这里提到android sdk

I am not sure how to do this but I have been giving it some thought on how to go about this and here is what I think should be done - 我不知道该怎么做但我已经考虑过如何解决这个问题,这就是我认为应该做的事情 -

  • Register for the preview buffers 注册预览缓冲区
  • Disable the default preview display 禁用默认预览显示
    • If you don't set the preview display to a surface then you should not get any display (but I am not sure if it will work - had read it in some forum not able to recall the source) 如果你没有将预览显示设置为表面,那么你不应该得到任何显示(但我不确定它是否会起作用 - 在某个论坛中读过它无法回想起来源)
    • If the above doesn't work then we will have to hide the view (I know hardly efficient but I couldn't think of anything else..) 如果以上不起作用,那么我们将不得不隐藏视图(我知道几乎没有效率,但我想不出别的......)
  • Reduce the framerate of the preview, so that we will not be overwhelmed with buffers 降低预览的帧率,这样我们就不会被缓冲区所淹没
  • Now to display our buffers, we can either use the default bitmap draw functionality or use opengl to display buffers. 现在要显示我们的缓冲区,我们可以使用默认的位图绘制功能,也可以使用opengl来显示缓冲区。 But I have so far used neither so don't even know if it is feasible, any thoughts on the same? 但是到目前为止我还没用过,所以甚至不知道它是否可行,对此有什么想法?

UPDATE UPDATE
Revisiting the SDK documentation I found this API - setPreviewTexture this API allows us to - "captures frames from an image stream as an OpenGL ES texture". 重新访问SDK文档我发现了这个API - setPreviewTexture这个API允许我们 - “将图像流中的帧捕获为OpenGL ES纹理”。 Once you have the images with the applied texture you can use OpenGL to display your frames. 使用应用的纹理获得图像后,可以使用OpenGL显示帧。 (Take a look at the answer posted by @Stephan on how to do this.) (看看@Stephan发布的关于如何做到这一点的答案。)

NOTE - setPreviewTexture is available from API level 11 onwards! 注意 - setPreviewTexture可从API级别11开始提供! SDK Link SDK链接

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM