Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[JAVA_API][GSOC] Add Java API bindings #709

Merged
merged 20 commits into from
Dec 12, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions modules/java_api/gradle.properties
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
build_benchmark_app=false
build_java_samples=false
build_kotlin_samples=false
build_hello_query_device=false
72 changes: 72 additions & 0 deletions modules/java_api/samples/README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
# Samples

The OpenVINO samples are simple console applications that show how to utilize specific OpenVINO API capabilities within an application. The following samples are available
- [Benchmark Application](#benchmark-application)
- [Face Detection Java samples](#face-detection-java-samples)
- [Face Detection Kotlin sample](./face_detection_kotlin_sample/README.md)
- [Hello Query Device](#hello-query-device-sample)

# Benchmark Application

This guide describes how to run the benchmark applications.
Expand Down Expand Up @@ -153,3 +161,67 @@ The application will show the image with detected objects enclosed in rectangles

### For ```face_detection_sample_async```
The application will show the video with detected objects enclosed in rectangles in new window.


# Hello Query Device Sample

## How It Works

This sample demonstrates how to show OpenVINO Runtime devices and print their metrics and default configuration values using the Query Device API feature.

## Build

Use Gradle to build **openvino-x-x-x.jar** with OpenVINO Java bindings in `java_api/build/libs` and **hello_query_device.jar** in `java_api/samples/hello_query_device/build/libs`:
```bash
cd openvino_contrib/modules/java_api
gradle build -Pbuild_hello_query_device=true
```

## Running

To run the sample use:
```bash
java -cp ".:${OV_JAVA_DIR}/openvino-x-x-x.jar:samples/hello_query_device/build/libs/hello_query_device.jar" Main
```

## Running in Idea IntelliJ
- Import the project in IntelliJ IDEA. See [here](../README.md#import-to-intellij-idea) for instructions.
- In **Run/Debug Configurations** dropdown, click on **Edit Configurations**.
- Click on **Add New Configuration** and select **Gradle** from the dropdown menu.
- Give the configuration an appropriate name: "HelloQueryDeviceSample", and enter the following command in the **Tasks and arguments** input box.
```bash
:samples:hello_query_device:run -Pbuild_hello_query_device=true
```
- Under **Environment Variables**, select **Edit environment variables** and add the following environment variables:

`INTEL_OPENVINO_DIR=<path-to-openvino_install>`
- Click on **OK** to save the configuration.
- Select the saved configuration from the **Run/Debug Configurations**. Click on the **Run** button to run or the **Debug** button to run in debug mode.

## Sample Output

Below is a sample output for CPU device:

```
[INFO] Available devices:
[INFO] CPU:
[INFO] SUPPORTED_PROPERTIES:
[INFO] AVAILABLE_DEVICES:
[INFO] RANGE_FOR_ASYNC_INFER_REQUESTS: 1 1 1
[INFO] RANGE_FOR_STREAMS: 1 20
[INFO] FULL_DEVICE_NAME: 12th Gen Intel(R) Core(TM) i7-12700H
[INFO] OPTIMIZATION_CAPABILITIES: FP32 FP16 INT8 BIN EXPORT_IMPORT
[INFO] CACHING_PROPERTIES: FULL_DEVICE_NAME
[INFO] NUM_STREAMS: 1
[INFO] AFFINITY: HYBRID_AWARE
[INFO] INFERENCE_NUM_THREADS: 0
[INFO] PERF_COUNT: NO
[INFO] INFERENCE_PRECISION_HINT: f32
[INFO] PERFORMANCE_HINT: LATENCY
[INFO] EXECUTION_MODE_HINT: PERFORMANCE
[INFO] PERFORMANCE_HINT_NUM_REQUESTS: 0
[INFO] ENABLE_CPU_PINNING: YES
[INFO] SCHEDULING_CORE_TYPE: ANY_CORE
[INFO] ENABLE_HYPER_THREADING: YES
[INFO] DEVICE_ID:
```
17 changes: 17 additions & 0 deletions modules/java_api/samples/hello_query_device/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
plugins {
id 'java'
id 'application'
}

sourceSets {
main {
java {
srcDirs = ["src/main/java"]
}
}
}
mainClassName = 'Main'

dependencies {
implementation rootProject
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
rootProject.name = 'hello_query_device'
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import org.intel.openvino.Core;

import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.logging.ConsoleHandler;
import java.util.logging.LogRecord;
import java.util.logging.Logger;
import java.util.logging.SimpleFormatter;

/*
This sample queries all available OpenVINO Runtime Devices and prints
their supported metrics and plugin configuration parameters using Query
Device API feature. The application prints all available devices with
their supported metrics and default values for configuration parameters.

The sample takes no command-line parameters.
*/
public class Main {

private static Logger logger;

static {
logger = Logger.getLogger(Main.class.getName());
logger.setUseParentHandlers(false);
ConsoleHandler handler = new ConsoleHandler();
handler.setFormatter(
new SimpleFormatter() {
private static final String format = "[%1$s] %2$s%n";

@Override
public synchronized String format(LogRecord lr) {
return String.format(
format, lr.getLevel().getLocalizedName(), lr.getMessage());
}
});
logger.addHandler(handler);
}

public static void main(String[] args) throws IOException {
List<String> excludedProperties =
Arrays.asList("SUPPORTED_METRICS", "SUPPORTED_CONFIG_KEYS", "SUPPORTED_PROPERTIES");

Core core = new Core();

logger.info("Available devices:");
for (String device : core.get_available_devices()) {
logger.info(String.format("%s:", device));
logger.info("\tSUPPORTED_PROPERTIES:");

for (String propertyKey : core.get_property(device, "SUPPORTED_PROPERTIES").asList()) {
if (!excludedProperties.contains(propertyKey)) {
String propertyVal;
try {
propertyVal = core.get_property(device, propertyKey).asString();
} catch (Exception e) {
propertyVal = "UNSUPPORTED TYPE";
}
logger.info(String.format("\t\t%s: %s", propertyKey, propertyVal));
}
}
}
}
}
3 changes: 3 additions & 0 deletions modules/java_api/settings.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,6 @@ if (build_java_samples.toBoolean()) {
if (build_kotlin_samples.toBoolean()) {
include 'samples:face_detection_kotlin_sample'
}
if (build_hello_query_device.toBoolean()) {
include 'samples:hello_query_device'
}
32 changes: 32 additions & 0 deletions modules/java_api/src/main/cpp/any.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,38 @@ JNIEXPORT jint JNICALL Java_org_intel_openvino_Any_asInt(JNIEnv *env, jobject ob
return 0;
}

JNIEXPORT jobject JNICALL Java_org_intel_openvino_Any_asList(JNIEnv *env, jobject obj, jlong addr) {
JNI_METHOD("asList",
Any *obj = (Any *)addr;

if (obj->is<std::vector<ov::PropertyName>>()) {
jclass arrayClass = env->FindClass("java/util/ArrayList");
jmethodID arrayInit = env->GetMethodID(arrayClass, "<init>", "()V");
jobject arrayObj = env->NewObject(arrayClass, arrayInit);
jmethodID arrayAdd = env->GetMethodID(arrayClass, "add", "(Ljava/lang/Object;)Z");

for (const auto& it : obj->as<std::vector<ov::PropertyName>>()) {
std::string property_name = it;
jstring string = env->NewStringUTF(property_name.c_str());
env->CallObjectMethod(arrayObj, arrayAdd, string);
}

return arrayObj;
}
return vectorToJavaList(env, obj->as<std::vector<std::string>>());
)
return 0;
}

JNIEXPORT jstring JNICALL Java_org_intel_openvino_Any_asString(JNIEnv *env, jobject obj, jlong addr) {
JNI_METHOD("asString",
Any *obj = (Any *)addr;
std::string n_string = obj->as<std::string>();
return env->NewStringUTF(n_string.c_str());
)
return 0;
}

JNIEXPORT void JNICALL Java_org_intel_openvino_Any_delete(JNIEnv *, jobject, jlong addr)
{
Any *obj = (Any *)addr;
Expand Down
54 changes: 54 additions & 0 deletions modules/java_api/src/main/cpp/compiled_model.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,60 @@ JNIEXPORT jlong JNICALL Java_org_intel_openvino_CompiledModel_CreateInferRequest
return 0;
}

JNIEXPORT jobject JNICALL Java_org_intel_openvino_CompiledModel_GetInputs(JNIEnv * env, jobject obj, jlong modelAddr) {
JNI_METHOD("GetInputs",
CompiledModel *compiled_model = (CompiledModel *) modelAddr;
const std::vector<ov::Output<const ov::Node>>& inputs_vec = compiled_model->inputs();

jclass arrayClass = env->FindClass("java/util/ArrayList");
jmethodID arrayInit = env->GetMethodID(arrayClass, "<init>", "()V");
jobject arrayObj = env->NewObject(arrayClass, arrayInit);
jmethodID arrayAdd = env->GetMethodID(arrayClass, "add", "(Ljava/lang/Object;)Z");

jclass outputClass = env->FindClass("org/intel/openvino/Output");
jmethodID outputConstructor = env->GetMethodID(outputClass,"<init>","(J)V");

Output<const Node> *input;
for (const auto &item : inputs_vec) {
input = new Output<const Node>;
*input = item;

jobject inputObj = env->NewObject(outputClass, outputConstructor, (jlong)(input));
env->CallObjectMethod(arrayObj, arrayAdd, inputObj);
}

return arrayObj;
)
return 0;
}

JNIEXPORT jobject JNICALL Java_org_intel_openvino_CompiledModel_GetOutputs(JNIEnv * env, jobject obj, jlong modelAddr) {
JNI_METHOD("GetOutputs",
CompiledModel *compiled_model = (CompiledModel *) modelAddr;
const std::vector<ov::Output<const ov::Node>>& outputs_vec = compiled_model->outputs();

jclass arrayClass = env->FindClass("java/util/ArrayList");
jmethodID arrayInit = env->GetMethodID(arrayClass, "<init>", "()V");
jobject arrayObj = env->NewObject(arrayClass, arrayInit);
jmethodID arrayAdd = env->GetMethodID(arrayClass, "add", "(Ljava/lang/Object;)Z");

jclass outputClass = env->FindClass("org/intel/openvino/Output");
jmethodID outputConstructor = env->GetMethodID(outputClass,"<init>","(J)V");

Output<const Node> *output;
for (const auto &item : outputs_vec) {
output = new Output<const Node>;
*output = item;

jobject outputObj = env->NewObject(outputClass, outputConstructor, (jlong)(output));
env->CallObjectMethod(arrayObj, arrayAdd, outputObj);
}

return arrayObj;
)
return 0;
}

JNIEXPORT void JNICALL Java_org_intel_openvino_CompiledModel_delete(JNIEnv *, jobject, jlong addr)
{
CompiledModel *compiled_model = (CompiledModel *)addr;
Expand Down
88 changes: 88 additions & 0 deletions modules/java_api/src/main/cpp/core.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,74 @@ JNIEXPORT jlong JNICALL Java_org_intel_openvino_Core_CompileModel(JNIEnv *env, j
return 0;
}

JNIEXPORT jlong JNICALL Java_org_intel_openvino_Core_CompileModel1(JNIEnv *env, jobject obj, jlong coreAddr, jstring path)
{
JNI_METHOD("CompileModel1",
std::string n_path = jstringToString(env, path);

Core *core = (Core *)coreAddr;
CompiledModel *compiled_model = new CompiledModel();
*compiled_model = core->compile_model(n_path);

return (jlong)compiled_model;
)
return 0;
}

JNIEXPORT jlong JNICALL Java_org_intel_openvino_Core_CompileModel2(JNIEnv *env, jobject obj, jlong coreAddr, jstring path, jstring device)
{
JNI_METHOD("CompileModel2",
std::string n_device = jstringToString(env, device);
std::string n_path = jstringToString(env, path);

Core *core = (Core *)coreAddr;
CompiledModel *compiled_model = new CompiledModel();
*compiled_model = core->compile_model(n_path, n_device);

return (jlong)compiled_model;
)
return 0;
}

JNIEXPORT jlong JNICALL Java_org_intel_openvino_Core_CompileModel3(JNIEnv *env, jobject obj, jlong coreAddr, jstring path, jstring device, jobject props)
{
JNI_METHOD("CompileModel3",
std::string n_device = jstringToString(env, device);
std::string n_path = jstringToString(env, path);
AnyMap map;
for (const auto& it : javaMapToMap(env, props)) {
map[it.first] = it.second;
}

Core *core = (Core *)coreAddr;
// AnyMap will be copied inside compile_model, so we don't have to track the lifetime of this object
CompiledModel *compiled_model = new CompiledModel();
rajatkrishna marked this conversation as resolved.
Show resolved Hide resolved
*compiled_model = core->compile_model(n_path, n_device, map);

return (jlong)compiled_model;
)
return 0;
}

JNIEXPORT jlong JNICALL Java_org_intel_openvino_Core_CompileModel4(JNIEnv *env, jobject obj, jlong coreAddr, jlong modelAddr, jstring device, jobject props)
{
JNI_METHOD("CompileModel4",
std::string n_device = jstringToString(env, device);
std::shared_ptr<Model> *model = reinterpret_cast<std::shared_ptr<Model> *>(modelAddr);
AnyMap map;
for (const auto& it : javaMapToMap(env, props)) {
map[it.first] = it.second;
}

Core *core = (Core *)coreAddr;
CompiledModel *compiled_model = new CompiledModel();
*compiled_model = core->compile_model(*model, n_device, map);

return (jlong)compiled_model;
)
return 0;
}

JNIEXPORT jlong JNICALL Java_org_intel_openvino_Core_GetProperty(JNIEnv *env, jobject obj, jlong coreAddr, jstring device, jstring name)
{
JNI_METHOD("GetProperty",
Expand Down Expand Up @@ -104,6 +172,26 @@ JNIEXPORT void JNICALL Java_org_intel_openvino_Core_SetProperty(JNIEnv *env, job
)
}

JNIEXPORT jobject JNICALL Java_org_intel_openvino_Core_GetAvailableDevices(JNIEnv *env, jobject obj, jlong coreAddr) {
JNI_METHOD("GetAvailableDevices",
Core *core = (Core *)coreAddr;
const std::vector<std::string>& devices_vec = core->get_available_devices();

jclass arrayClass = env->FindClass("java/util/ArrayList");
jmethodID arrayInit = env->GetMethodID(arrayClass, "<init>", "()V");
jobject arrayObj = env->NewObject(arrayClass, arrayInit);
jmethodID arrayAdd = env->GetMethodID(arrayClass, "add", "(Ljava/lang/Object;)Z");

for (const std::string &item : devices_vec) {
jstring device = env->NewStringUTF(item.c_str());
env->CallObjectMethod(arrayObj, arrayAdd, device);
}

return arrayObj;
)
return 0;
}

JNIEXPORT void JNICALL Java_org_intel_openvino_Core_delete(JNIEnv *, jobject, jlong addr)
{
Core *core = (Core *)addr;
Expand Down
Loading