我一直在尝试在android上运行Tensorflow模型。这样做的解决方案是首先创建一个tensorflow模型(我使用了一个预训练的Mobilenev2模型(。在我自己的数据集上训练后,我将其转换为Android支持的.tflite模型。由于我想进行实时视频分析,我也在使用为Android SDK构建的OpenCV库。
现在,我目前陷入困境的部分是——如何转换opencv JavaCameraView接收到的输入帧,并将其提供给tflite模型进行推理?我发现了一些将Mat数据类型转换为输入张量的解决方案,但似乎没有什么明确的。有人能帮我吗?
编辑:这是代码(需要以下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();
}
}
}
我建议您将Mat
转换为FloatBuffer
,如下所示:
Mat floatMat = new Mat();
mat.convertTo(floatMat, CV_32F);
FloatBuffer floatBuffer = floatMat.createBuffer();
请注意,createBuffer
方法位于导入org.bytedeco.opencv.opencv_core.Mat
的Mat
类中,而不是导入org.opencv.core
中。
然后您可以从floatBuffer
变量创建一个张量:
Tensor.create(new long[]{1, image_height, image_width, 3}, floatBuffer)
这将创建一个张量,其中包含一批图像(如最左边的数字1所示(,以及一个尺寸为(image_height, image_width, 3)
的图像,您应该知道并替换该图像。大多数图像处理和机器学习库使用第一维度作为图像的高度;行";第二个代表宽度或";列";第三个用于通道的数量(RGB=3个通道(。如果有灰度图像,请将3替换为1。
请检查您是否可以直接将此张量提供给您的模型,或者您必须首先执行一些预处理步骤,例如归一化。