简体   繁体   English

如何在 Android Studio 中将 OpenCV Mat 输入帧转换为 Tensorflow 张量?

[英]How to convert OpenCV Mat input frame to Tensorflow tensor in Android Studio?

I've been trying to run a Tensorflow model on android.我一直在尝试在 android 上运行 Tensorflow model。 The solution to do this was to create a tensorflow model(I used a pretrained Mobilenetv2 model) first.解决方案是首先创建一个 tensorflow 模型(我使用了预训练的 Mobilenetv2 模型)。 After training it on my own dataset, I converted it to a.tflite model which is supported by Android.在我自己的数据集上对其进行训练后,我将其转换为由 Android 支持的 a.tflite model。 Since I want to work with realtime video analysis, I am also using OpenCV library built for Android SDK.由于我想使用实时视频分析,我还使用为 Android SDK 构建的 OpenCV 库。

Now the part where I'm currently stuck is - how to convert the inputframe received by opencv JavaCameraView and feed it to the tflite model for inference?现在我目前陷入困境的部分是 - 如何转换 opencv JavaCameraView 接收的输入帧并将其提供给 tflite model 进行推理? I found few solutions to convert Mat datatype to an Input Tensor but nothing seems clear.我发现很少有将 Mat 数据类型转换为输入张量的解决方案,但似乎没有什么清楚的。 Can someone help me out with this?有人可以帮我解决这个问题吗?

edit: Here's the code(need help with onCameraFrame Method below)编辑:这是代码(需要以下 onCameraFrame 方法的帮助)

public class MainActivity extends AppCompatActivity implements CameraBridgeViewBase.CvCameraViewListener2 {`enter code here`

    CameraBridgeViewBase cameraBridgeViewBase;
    BaseLoaderCallback baseLoaderCallback;
  //  int counter = 0;
    Interpreter it;


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


        cameraBridgeViewBase = (JavaCameraView)findViewById(R.id.CameraView);
        cameraBridgeViewBase.setVisibility(SurfaceView.VISIBLE);
        cameraBridgeViewBase.setCvCameraViewListener(this);
        try{
            it=new Interpreter(loadModelFile(this));
        }
        catch(Exception e){
            Toast.makeText(this,"Tf model didn't load",Toast.LENGTH_LONG).show();
        }

        //System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
        baseLoaderCallback = new BaseLoaderCallback(this) {
            @Override
            public void onManagerConnected(int status) {
                super.onManagerConnected(status);

                switch(status){

                    case BaseLoaderCallback.SUCCESS:
                        cameraBridgeViewBase.enableView();
                        break;
                    default:
                        super.onManagerConnected(status);
                        break;
                }


            }

        };




    }
    private MappedByteBuffer loadModelFile(Activity activity) throws IOException {
        AssetFileDescriptor fileDescriptor = activity.getAssets().openFd("model.tflite");
        FileInputStream inputStream = new FileInputStream(fileDescriptor.getFileDescriptor());
        FileChannel fileChannel = inputStream.getChannel();
        long startOffset = fileDescriptor.getStartOffset();
        long declaredLength = fileDescriptor.getDeclaredLength();
        return fileChannel.map(FileChannel.MapMode.READ_ONLY, startOffset, declaredLength);
    }
    @Override
    public Mat onCameraFrame(CameraBridgeViewBase.CvCameraViewFrame inputFrame) {

       //how to convert inputFrame to Input Tensor???



        
    }


    @Override
    public void onCameraViewStarted(int width, int height) {

    }


    @Override
    public void onCameraViewStopped() {

    }


    @Override
    protected void onResume() {
        super.onResume();

        if (!OpenCVLoader.initDebug()){
            Toast.makeText(getApplicationContext(),"There's a problem, yo!", Toast.LENGTH_SHORT).show();
        }

        else
        {
            baseLoaderCallback.onManagerConnected(baseLoaderCallback.SUCCESS);
        }



    }

    @Override
    protected void onPause() {
        super.onPause();
        if(cameraBridgeViewBase!=null){

            cameraBridgeViewBase.disableView();
        }

    }


    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (cameraBridgeViewBase!=null){
            cameraBridgeViewBase.disableView();
        }
    }
}

I suggest that you convert Mat into FloatBuffer as follows:我建议您将Mat转换为FloatBuffer ,如下所示:

Mat floatMat = new Mat();
mat.convertTo(floatMat, CV_32F);
FloatBuffer floatBuffer = floatMat.createBuffer();

Note that the createBuffer method is found within the Mat class of the import org.bytedeco.opencv.opencv_core.Mat not the import org.opencv.core .请注意,在导入org.bytedeco.opencv.opencv_core.Mat而不是导入org.opencv.coreMat class 中找到createBuffer方法

Then you can create a tensor from the floatBuffer variable:然后你可以从floatBuffer变量创建一个张量:

Tensor.create(new long[]{1, image_height, image_width, 3}, floatBuffer)

This creates a tensor that contains a batch of one image (as indicated by the number 1 on the far left), with an image of dimensions (image_height, image_width, 3) which you should know and replace.这将创建一个张量,其中包含一批图像(如最左侧的数字 1 所示),以及您应该知道并替换的尺寸为(image_height, image_width, 3)的图像。 Most image processing and machine learning libraries use the first dimension for the height of the image or the "rows" and the second for the width or the "columns" and the third for the number of channels (RGB = 3 channels).大多数图像处理和机器学习库使用第一个维度表示图像的高度或“行”,第二个维度表示宽度或“列”,第三个维度表示通道数(RGB = 3 个通道)。 If you have a grayscale image, then replace 3 by 1.如果您有灰度图像,则将 3 替换为 1。

Please check whether you can directly feed this tensor to your model or you have to perform some pre-processing steps first such as normalization.请检查您是否可以直接将此张量输入 model 或者您必须先执行一些预处理步骤,例如标准化。

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

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