【问题标题】:Can I use TextureView to show the camera preview and detected line at the same time?我可以使用 TextureView 同时显示相机预览和检测到的线吗?
【发布时间】:2018-03-02 08:18:27
【问题描述】:

我想显示我实时检测到的相机和线条(使用 i.MX6 和 Android 4.4)。我使用 Android 相机 .addCallbackBuffer 获取帧并使用 TextureView 显示相机预览。

JNI (C++) : get frame buffer->convert byte[] to Mat->然后用OpenCV做图像处理

JNI 可以返回 Mat(use .getNativeObjAddr()) 已经在其上绘制线或返回两个坐标,即线的起点和终点

这段代码在 JNI 中新建 Mat 并希望只返回两个坐标。如果此方法不起作用,我将在 JAVA 中新建 Mat 并将 .getNativeObjAddr() 发送到 JNI,然后返回 Mat。在 TextureView 中显示 Mat?

问题: 如何使用 TextureView 同时显示相机预览和检测到的线?

在 MainActivity.java 中

public class MainActivity extends Activity implements TextureView.SurfaceTextureListener, PreviewCallback {
protected Camera mCamera;
private TextureView mTextureView;
public byte[][] cameraBuffer;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    this.requestWindowFeature(Window.FEATURE_NO_TITLE);
    setContentView(R.layout.activity_main);

    mTextureView = new TextureView(this);
    mTextureView.setSurfaceTextureListener(this);
    setContentView(mTextureView);
}
....
@Override
public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
    mCamera = Camera.open(0);
    int bufferSize = mCamera.getParameters().getPictureSize().width * mCamera.getParameters().getPictureSize().height
            * ImageFormat.getBitsPerPixel(mCamera.getParameters().getPreviewFormat()) / 8;
    cameraBuffer = new byte[3][bufferSize];

    thread = new getFrameThread( this, kCameraWidth, kCameraHeight);
    for (int i = 0; i < 3; ++i)
        mCamera.addCallbackBuffer(cameraBuffer[i]);

    mCamera.setPreviewCallbackWithBuffer(this);             
    thread.start();

    if (mCamera == null) {
        throw new RuntimeException("Default camera not available");
    }
    try {
        mCamera.setPreviewTexture(surface);
        mCamera.startPreview();
    } catch (IOException ioe) {
        // Something bad happened
    }
}

@Override
public void onPreviewFrame(byte[] data, Camera camera) {
    // TODO Auto-generated method stub
    camera.addCallbackBuffer(data);//callback data to cameraBuffer
    thread.refresh(data, countFrame);//send new frame data to JNI
}
....
static {
    System.loadLibrary("opencv_java"); //load opencv_java lib
    System.loadLibrary("testLib");
}
public native void getRawFrame(byte[] data,int width, int height, int count);

}

在getFrameThread(运行JNI函数'getRawFrame'的线程)

public class getFrameThread extends Thread{
  public byte[] data;
  {
  .....
  mainActivity.getRawFrame(data, 480, 720);
  .....
  }

  public void refresh(byte[] data, int countFrame){
      this.data = data;
  }
}

在 JNI 中

#include <jni.h>
#include <stdio.h>
#include <stdlib.h>

#include <opencv2/opencv.hpp>
using namespace cv;

extern"C"
{
.....
JNIEXPORT void JNICALL Java_com_example_adas_MainActivity_getRawFrame( JNIEnv* env, jobject thisobject,
    jbyteArray data, jint width, jint height){

  int length = env->GetArrayLength(data);
  unsigned char *bufferIn = (unsigned char*) env->GetPrimitiveArrayCritical(data, NULL);

  yuvMat = Mat(height  * 3/2, width, CV_8UC1, bufferIn);
  cvtColor(yuvMat, grayMat, cv::COLOR_YUV2GRAY_I420);


  //Do lines detected
  .....
  env->ReleasePrimitiveArrayCritical(data, bufferIn, JNI_ABORT);
}

【问题讨论】:

    标签: java android opencv camera textureview


    【解决方案1】:

    您可以使用图像视图覆盖相机实时 TextureView,让该图像部分透明是可以的。但这不是增强现实的好解决方案。原因是 OpenCV 生成的内容有延迟。这种延迟可能不是很明显,但对用户来说可能很烦人。

    如果隐藏实时摄像头流并显示由 OpenCV 处理更改的图像(来自onPreviewFrame()),结果会好得多。屏幕上显示的 AR 会延迟几毫秒(与相机实时取景相比),但场景会与检测到的线条一致。我在blog post 中找到了一个很好的示例(以及详细的编程说明)。

    您仍然需要 TextureView,因为 Android 相机 API 规定您有实时预览以接收 onPreviewFrame() 回调。为了隐藏它,你可以用一些其他的视图覆盖它,或者在 OpenGL 的级别上操作纹理。

    您也可以使用 OpenGL 来显示 OpenCV 的结果:这种工作流程的性能通常比使用其他方式显示图像要好得多。

    您也可以使用 OpenGL 绘制线条 - OpenCV 处理的结果 - 而不是 位图 的形式,并使用相机预览作为单独的纹理。

    【讨论】:

    • 谢谢,我会试试 'OpenGL to display the result of OpenCV' 这个方法。
    • 你能给我一个提示或函数使用OpenGL来显示OpenCV的结果吗?谢谢。
    • 我可以推荐graphika作为一个很好的起点来学习OpenGL与Android相机的关系。您可能还会发现这个article 很有用。它说明了我的主要观点:红点固定在屏幕上的正确像素上,即使整个流程有点延迟。
    • 再次感谢。文章解释得很详细。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-06-05
    • 1970-01-01
    • 2014-10-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多