diff --git a/README.md b/README.md index bee3ea6..f6909a1 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,13 @@ # sishu-yolo-sdk +javac -h cpp/include src/main/java/com/bonus/sdk/YoloSdk.java src/main/java/com/bonus/sdk/Detection.java + +windows cmake -S cpp -B build/windows -G "Visual Studio 17 2022" -A x64 -DCMAKE_TOOLCHAIN_FILE=%VCPKG_ROOT%\scripts\buildsystems\vcpkg.cmake + cmake --build build/windows --config Release + +linux +JAVA_HOME=/usr/lib/jvm/java-11-openjdk-amd64 cmake -S cpp -B build/linux + +cmake --build build/linux diff --git a/cpp/CMakeLists.txt b/cpp/CMakeLists.txt index edc1bac..0b8a9e0 100644 --- a/cpp/CMakeLists.txt +++ b/cpp/CMakeLists.txt @@ -2,11 +2,9 @@ cmake_minimum_required(VERSION 3.18) project(MyYoloSdk CXX) set(CMAKE_CXX_STANDARD 17) -# --- 1. -find_package(JNI REQUIRED) -# --- 2. if(WIN32) + find_package(JNI COMPONENTS JNI REQUIRED) message(STATUS "Configuring for Windows (using vcpkg OpenCV + manual ONNX)") # @@ -16,6 +14,11 @@ if(WIN32) set(ORT_MANUAL_PATH ${CMAKE_SOURCE_DIR}/../prebuilt_libs/onnxruntime-win-x64-1.23.2) elseif(UNIX) + set(JNI_INCLUDE_DIRS + "/usr/lib/jvm/java-11-openjdk-amd64/include" + "/usr/lib/jvm/java-11-openjdk-amd64/include/linux" + ) + set(JNI_LIBRARIES "/usr/lib/jvm/java-11-openjdk-amd64/lib/server/libjvm.so") message(STATUS "Configuring for Linux (using apt OpenCV + manual ONNX)") # diff --git a/cpp/src/YoloCore.cpp b/cpp/src/YoloCore.cpp index 94937e6..af5c1c8 100644 --- a/cpp/src/YoloCore.cpp +++ b/cpp/src/YoloCore.cpp @@ -96,12 +96,8 @@ YoloDetector::YoloDetector(const ORTCHAR_T* model_path, int in_width, int in_hei Ort::SessionOptions session_options; - - OrtCUDAProviderOptions cuda_options; - session_options.AppendExecutionProvider_CUDA(cuda_options); + // session_options.AppendExecutionProvider_CPU(0); - - session = std::make_unique(env, model_path, session_options); diff --git a/cpp/src/YoloSdk_JNI.cpp b/cpp/src/YoloSdk_JNI.cpp index f6c1a25..e88219a 100644 --- a/cpp/src/YoloSdk_JNI.cpp +++ b/cpp/src/YoloSdk_JNI.cpp @@ -119,7 +119,7 @@ JNIEXPORT jobjectArray JNICALL Java_com_bonus_sdk_YoloSdk_nativePredict jclass detClass = env->FindClass("com/bonus/sdk/Detection"); if (!detClass) return nullptr; - jmethodID detConstructor = env->GetMethodID(detClass, "", "(IFFIIII)V"); + jmethodID detConstructor = env->GetMethodID(detClass, "", "(IFIIII)V"); if (!detConstructor) return nullptr; jobjectArray resultArray = env->NewObjectArray(results_cpp.size(), detClass, nullptr); diff --git a/pom.xml b/pom.xml index 50b1690..822b084 100644 --- a/pom.xml +++ b/pom.xml @@ -14,7 +14,20 @@ UTF-8 - + + + org.junit.jupiter + junit-jupiter-api + 5.10.0 + test + + + org.junit.jupiter + junit-jupiter-engine + 5.10.0 + test + + src/main/java @@ -25,7 +38,9 @@ libmy_yolo_sdk.so libonnxruntime.so* - libopencv_world.so* + libopencv_dnn.so* + libopencv_imgproc.so* + libopencv_core.so* lib/linux-x86_64 @@ -36,7 +51,9 @@ my_yolo_sdk.dll onnxruntime.dll - opencv_world*.dll + opencv_core4.dll + opencv_dnn4.dll + opencv_imgproc4.dll lib/win-x64 @@ -52,6 +69,12 @@ 11 + + + org.apache.maven.plugins + maven-surefire-plugin + 3.2.5 + \ No newline at end of file diff --git a/prebuilt_libs/linux-x86_64/libmy_yolo_sdk.so b/prebuilt_libs/linux-x86_64/libmy_yolo_sdk.so index 8b04d42..c88c667 100755 Binary files a/prebuilt_libs/linux-x86_64/libmy_yolo_sdk.so and b/prebuilt_libs/linux-x86_64/libmy_yolo_sdk.so differ diff --git a/prebuilt_libs/linux-x86_64/libonnxruntime.so b/prebuilt_libs/linux-x86_64/libonnxruntime.so new file mode 100755 index 0000000..64ef20a Binary files /dev/null and b/prebuilt_libs/linux-x86_64/libonnxruntime.so differ diff --git a/prebuilt_libs/linux-x86_64/libonnxruntime.so.1 b/prebuilt_libs/linux-x86_64/libonnxruntime.so.1 new file mode 100755 index 0000000..64ef20a Binary files /dev/null and b/prebuilt_libs/linux-x86_64/libonnxruntime.so.1 differ diff --git a/prebuilt_libs/linux-x86_64/libonnxruntime_providers_shared.so b/prebuilt_libs/linux-x86_64/libonnxruntime_providers_shared.so new file mode 100755 index 0000000..14283b1 Binary files /dev/null and b/prebuilt_libs/linux-x86_64/libonnxruntime_providers_shared.so differ diff --git a/src/main/java/com/bonus/sdk/YoloSdk.java b/src/main/java/com/bonus/sdk/YoloSdk.java index 9d74a7f..b97bef4 100644 --- a/src/main/java/com/bonus/sdk/YoloSdk.java +++ b/src/main/java/com/bonus/sdk/YoloSdk.java @@ -1,4 +1,4 @@ -package com.bonus.sdk; // +package com.bonus.sdk; import java.awt.image.BufferedImage; import java.awt.image.DataBufferByte; @@ -10,9 +10,11 @@ import java.util.Set; public class YoloSdk implements AutoCloseable { - private long nativeHandle; + private long nativeHandle; // private static final Set loadedLibraries = new HashSet<>(); + /** + * */ static { try { loadSdkLibrary(); @@ -29,7 +31,7 @@ public class YoloSdk implements AutoCloseable { String[] dependencyLibs = {}; if (osName.contains("win") && osArch.contains("64")) { - + libPathInJar = "/lib/win-x64/"; dependencyLibs = new String[]{ @@ -40,20 +42,18 @@ public class YoloSdk implements AutoCloseable { "opencv_core4.dll", "opencv_imgproc4.dll", "opencv_dnn4.dll" - }; sdkLibName = "my_yolo_sdk.dll"; } else if ((osName.contains("nix") || osName.contains("nux")) && osArch.contains("64")) { - libPathInJar = "/lib/linux-x86_64/"; - + dependencyLibs = new String[]{ - "libonnxruntime.so.1.23.2", - "libopencv_core.so.4.6.0", - "libopencv_imgproc.so.4.6.0", - "libopencv_dnn.so.4.6.0" + "libonnxruntime.so.1.23.2", + "libopencv_core.so.4.6.0", + "libopencv_imgproc.so.4.6.0", + "libopencv_dnn.so.4.6.0" }; sdkLibName = "libmy_yolo_sdk.so"; @@ -62,18 +62,20 @@ public class YoloSdk implements AutoCloseable { throw new UnsupportedOperationException("Unsupported OS/Arch: " + osName + "/" + osArch); } + // 1. for (String lib : dependencyLibs) { loadLibraryFromJar(libPathInJar + lib); } - + // 2. loadLibraryFromJar(libPathInJar + sdkLibName); } - + /** + * */ private static void loadLibraryFromJar(String path) throws IOException { String libName = new File(path).getName(); if (loadedLibraries.contains(libName)) { - return; + return; // } try (InputStream in = YoloSdk.class.getResourceAsStream(path)) { @@ -90,6 +92,7 @@ public class YoloSdk implements AutoCloseable { } } + // --- private native long nativeInit(String modelPath, int inputWidth, int inputHeight); private native void nativeRelease(long handle); private native Detection[] nativePredict( @@ -124,6 +127,8 @@ public class YoloSdk implements AutoCloseable { } } + /** + * */ private byte[] getBgrBytes(BufferedImage image) { if (image.getType() == BufferedImage.TYPE_3BYTE_BGR) { return ((DataBufferByte) image.getRaster().getDataBuffer()).getData(); diff --git a/src/test/java/com/bonus/sdk/YoloSdkTest.java b/src/test/java/com/bonus/sdk/YoloSdkTest.java new file mode 100644 index 0000000..3ae7bf1 --- /dev/null +++ b/src/test/java/com/bonus/sdk/YoloSdkTest.java @@ -0,0 +1,102 @@ +package com.bonus.sdk; + + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Assumptions; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; + + +import javax.imageio.ImageIO; +import java.awt.image.BufferedImage; +import java.io.File; +import java.io.IOException; + +/** + * */ +public class YoloSdkTest { + + + + private static final String modelPath = "test_data/model.onnx"; + private static final String imagePath = "test_data/test_image.jpg"; + + private static File modelFile; + private static File imageFile; + + /** + * */ + @BeforeAll + public static void setupTestFiles() { + System.out.println("--- [YoloSdkTest] Setting up test files..."); + + modelFile = new File(modelPath); + imageFile = new File(imagePath); + + + + boolean modelExists = modelFile.exists(); + boolean imageExists = imageFile.exists(); + + System.out.println("Checking model: " + modelFile.getAbsolutePath() + " (Exists: " + modelExists + ")"); + System.out.println("Checking image: " + imageFile.getAbsolutePath() + " (Exists: " + imageExists + ")"); + + + + Assumptions.assumeTrue(modelExists, "SKIPPING TEST: Model file not found at " + modelPath); + Assumptions.assumeTrue(imageExists, "SKIPPING TEST: Test image not found at " + imagePath); + } + + /** + * */ + @Test + public void testSdkInitializationAndPrediction() { + System.out.println("--- [YoloSdkTest] Running testSdkInitializationAndPrediction..."); + + try { + System.out.println("Loading image from: " + imageFile.getAbsolutePath()); + BufferedImage image = ImageIO.read(imageFile); + Assertions.assertNotNull(image, "Failed to read image. ImageIO.read() returned null."); + + + System.out.println("Initializing YoloSdk with model: " + modelFile.getAbsolutePath()); + + + try (YoloSdk sdk = new YoloSdk(modelFile.getAbsolutePath(), 640, 640)) { + + System.out.println("Native SDK initialized successfully."); + + System.out.println("Running prediction..."); + + Detection[] results = sdk.predict(image, 0.45f, 0.5f); + System.out.println("Prediction complete."); + + Assertions.assertNotNull(results, "Prediction results array should not be null."); + + System.out.println("--- [YoloSdkTest] PREDICTION RESULTS ---"); + System.out.println("--- [YoloSdkTest] Found " + results.length + " objects ---"); + if (results.length == 0) { + System.out.println("No objects detected."); + } else { + System.out.println("Detected " + results.length + " objects:"); + for (Detection d : results) { + System.out.println(" - " + d.toString()); + } + } + System.out.println("--- [YoloSdkTest] END OF RESULTS ---"); + + + } + System.out.println("SDK closed successfully."); + + } catch (IOException e) { + Assertions.fail("Failed to read image file", e); + } catch (Exception e) { + + e.printStackTrace(); + Assertions.fail("SDK test failed with a runtime exception: " + e.getMessage()); + } + + System.out.println("--- [YoloSdkTest] Test finished successfully. ---"); + } +} \ No newline at end of file diff --git a/test_data/model.onnx b/test_data/model.onnx new file mode 100644 index 0000000..66aacff Binary files /dev/null and b/test_data/model.onnx differ diff --git a/test_data/test_image.jpg b/test_data/test_image.jpg new file mode 100644 index 0000000..96d4039 Binary files /dev/null and b/test_data/test_image.jpg differ