Android 相机像素操作

标签 android image-processing camera surfaceview

我正在尝试构建一个相机应用程序,它接受相机预览、处理像素,然后显示新图像。我需要实时进行操作。

根据我在网上阅读的内容和此处的问题,您需要制作自定义表面 View 并通过 onPreviewFrame 方法操作像素数组。我已经构建了一个自定义表面 View 并运行了这个方法。我已将 YUV 转换为 RGB

现在,我的问题是,如何在屏幕上实时显示这个新的像素阵列?我是否以某种方式在 onPreviewFrame 方法中返回它?我必须更改 byte[] 数组吗?我是否使用我的新像素阵列并使用位图显示它?有没有办法在不显示预览的情况下从相机预览中获取 byte[] 数组?

如果有人能回答这些问题,并提供代码示例,那就太好了!我是 Android 的新手,所以我需要对答案的解释足以让我理解。这是我运行相机预览的部分代码:

public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
        // If your preview can change or rotate, take care of those events here.
        // Make sure to stop the preview before resizing or reformatting it.

        if (mHolder.getSurface() == null){
          // preview surface does not exist
          return;
        }

        // stop preview before making changes
        try {
            mCamera.stopPreview();
        } catch (Exception e){
          // ignore: tried to stop a non-existent preview
        }

        // start preview with new settings
        try {
            //parameters.setPreviewSize(w, h);
            mCamera.setParameters(parameters);
            mCamera.setPreviewDisplay(mHolder);
            mCamera.setPreviewCallback(new PreviewCallback() {
                public void onPreviewFrame(byte[] data, Camera camera)
                {
                    System.out.println("onPreviewFrame");
                    //transforms NV21 pixel data into RGB pixels  
                    decodeYUV420SP(pixels, data, previewSize.width,  previewSize.height);  

//Outuput the value of the top left pixel in the preview to LogCat  
                    Log.i("Pixels", "The top right pixel has the following RGB (hexadecimal) values:"  
                           +Integer.toHexString(pixels[0]));  


                }
            });
            mCamera.startPreview();

        } catch (Exception e){
            Log.d(null, "Error starting camera preview: " + e.getMessage());
        }
    }

这给了我想要显示而不是预览的 rgb 像素阵列。我该怎么做?

最佳答案

您无法操纵连接到相机预览的表面。您在 onPreviewFrame() 中收到的字节数组只是框架在屏幕上显示的内容的副本。此外,您会发现这两个流是异步的:您可以减慢回调速度(例如,通过将一些 sleep() 添加到您的回调中),但预览表面仍然会更新。

您可以通过在其上放置其他 View 来隐藏预览 SurfaceView,或者您可以使用 setPreviewTexture() 而不是 完全摆脱此 View >setPreviewDisplay()(注意:在 API 级别 11 中添加)。隐藏表面并不像看起来那么容易:框架可能会将其弹出到顶部,这需要仔细同步相机启动或重新启动布局。

无论如何,隐藏表面后,您可以使用 onPreviewFrame() 中接收的字节数组生成图像并显示它。您可以根据自己的喜好自由操作像素。我认为最佳技术是将像素数据发送到 OpenGL:您可以使用着色器将 YCrCb (NV21) 到 RGB 的转换卸载到 GPU。

关于Android 相机像素操作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13548045/

相关文章:

android - 理论上在游戏中使用 fontawesome(图标)

java - android.view.InflateException 由 : java. lang.OutOfMemoryError 引起

android - 当 fragment 包含相机预览时 ViewPager 滑动滞后

opengl - 你如何使用glm quat防止万向节锁定

Android以编程方式将linearLayout添加到tableRow

java - AndroidJUnitRunner 不运行包中的测试

image-processing - 将 2 张图像合并为 1 个 Google map 标记图标

algorithm - k表示使用现有信息进行分割

iphone - iOS图像比较

java - 自定义相机 android 中的闪光灯