bytedeco / javacpp

The missing bridge between Java and native C++
Other
4.48k stars 581 forks source link

Protobuf Parsing Error with ONNX Runtime in Linux, Works in Windows #762

Closed alawasoft closed 3 months ago

alawasoft commented 3 months ago

I am encountering a Protobuf parsing error when attempting to load an ONNX model using javacpp on Linux. The same model loads successfully on Windows. Despite trying several solutions, the issue persists.

Environment Operating System: Linux (Ubuntu 20.04) Java Version: OpenJDK 17 ONNX Runtime Version: 1.16.3 Local Protobuf Version: 3.21.12 JavaCV Version: 1.5.10

Model exists: true Loading onnx model from model/onnx/yolov10s.onnx Canonical Path: /app/model/onnx/yolov10s.onnx File Permissions: true, true, true Model Path Pointer: /app/model/onnx/yolov10s.onnx java.lang.RuntimeException: Load model from / failed:Protobuf parsing failed. Error loading model: Load model from / failed:Protobuf parsing failed. at org.bytedeco.onnxruntime.Session.allocate(Native Method) | => rat org.bytedeco.onnxruntime.Session.(Session.java:28)

  lazy val session: Session = {
    println(s"Model exists: ${weightPath.exists()}")
    println(s"Loading onnx model from ${weightPath.getPath}")
    println(s"Canonical Path: ${weightPath.getCanonicalPath}")
    println(s"File Permissions: ${weightPath.canRead}, ${weightPath.canWrite}, ${weightPath.canExecute}")

    try {
      val modelPath = new CharPointer(weightPath.getCanonicalPath)
      println(s"Model Path Pointer: ${modelPath.getString}")
      new Session(env, modelPath, sessionOptions)
    }
    catch {
      case e: Exception =>
        println(s"Error loading model: ${e.getMessage}")
        e.printStackTrace()
        throw e
    }
  }

this exact code works in windows-x86-64, but not the linux-amd64 version.

the onnx model file is exactly the same as the one ran on windows.

saudet commented 3 months ago

Please try without CharPointer

alawasoft commented 3 months ago

Thank you for your response.

The Session class implementation in the javacpp onnxruntime bindings indeed requires a Pointer for the model path. Here is the relevant portion of the Session class:

package org.bytedeco.onnxruntime;

import org.bytedeco.javacpp.*;
import org.bytedeco.javacpp.annotation.*;

@Namespace("Ort") @Properties(inherit = org.bytedeco.onnxruntime.presets.onnxruntime.class)
public class Session extends SessionImpl {
    static { Loader.load(); }
    public Session(Pointer p) { super(p); }

    public Session(@Const @ByRef Env env, @Cast("const ORTCHAR_T*") Pointer model_path, @Const @ByRef SessionOptions options) {
        super((Pointer)null);
        allocate(env, model_path, options);
    }

    private native void allocate(@Const @ByRef Env env, @Cast("const ORTCHAR_T*") Pointer model_path, @Const @ByRef SessionOptions options);
}

As you can see, the constructor for Session expects a Pointer for the model path. Therefore, using CharPointer to convert the string path to a Pointer seems necessary.

saudet commented 3 months ago

Does this sample code work: https://github.com/bytedeco/javacpp-presets/blob/master/onnxruntime/samples/CXXApiSample.java#L41

alawasoft commented 3 months ago

I've overlooked this example. thank you for pointing out, BytePointer indeed works well ! thank you !

saudet commented 3 months ago

From what I understand about ONNX Runtime's API, yes