diff --git a/MODULE.bazel b/MODULE.bazel
index 8ff586ac..84cc8fd4 100644
--- a/MODULE.bazel
+++ b/MODULE.bazel
@@ -8,10 +8,10 @@ module(
)
# Import external dependencies
-bazel_dep(name = "rules_cc", version = "0.1.0")
+bazel_dep(name = "rules_cc", version = "0.1.1")
bazel_dep(name = "rules_foreign_cc", version = "0.11.1")
bazel_dep(name = "rules_python", version = "0.40.0")
-bazel_dep(name = "platforms", version = "0.0.10")
+bazel_dep(name = "platforms", version = "0.0.11")
bazel_dep(name = "googletest", version = "1.15.2")
bazel_dep(name = "apple_support", version = "1.17.1", repo_name = "build_bazel_apple_support")
bazel_dep(name = "curl", version = "8.8.0")
@@ -19,6 +19,7 @@ bazel_dep(name = "nlohmann_json", version = "3.11.3")
bazel_dep(name = "hedron_compile_commands", dev_dependency = True)
bazel_dep(name = "flatbuffers", version = "24.3.25")
bazel_dep(name = "opentelemetry-cpp", version = "1.19.0")
+bazel_dep(name = "opencv", version = "4.11.0.bcr.2")
# Hedron's Compile Commands Extractor for Bazel
git_override(
diff --git a/MODULE.bazel.lock b/MODULE.bazel.lock
index fe44bb0a..34ecf36d 100644
--- a/MODULE.bazel.lock
+++ b/MODULE.bazel.lock
@@ -69,6 +69,8 @@
"https://bcr.bazel.build/modules/curl/8.7.1/MODULE.bazel": "088221c35a2939c555e6e47cb31a81c15f8b59f4daa8009b1e9271a502d33485",
"https://bcr.bazel.build/modules/curl/8.8.0/MODULE.bazel": "7da3b3e79b0b4ee8f8c95d640bc6ad7b430ce66ef6e9c9d2bc29b3b5ef85f6fe",
"https://bcr.bazel.build/modules/curl/8.8.0/source.json": "d7d138b6878cf38891692fee0649ace35357fd549b425614d571786f054374d4",
+ "https://bcr.bazel.build/modules/eigen/4.0.0-20241125.bcr.2/MODULE.bazel": "c91e304c16bf95884333152b383a32aacdcfbde3b06f9f4908d31e6f60e44404",
+ "https://bcr.bazel.build/modules/eigen/4.0.0-20241125.bcr.2/source.json": "fbc35faefa352e7ab59a0175d809f05f2205712a34f06f3f52c807c8fe00267b",
"https://bcr.bazel.build/modules/flatbuffers/24.3.25/MODULE.bazel": "2794b084ee385ecd08a22fd90614b93851508ceb7a97e63da399886dedbc696c",
"https://bcr.bazel.build/modules/flatbuffers/24.3.25/source.json": "0cea4d62612a34154ffe0208a85f9f197edbb1f8f37a8855ec4aa722fea69276",
"https://bcr.bazel.build/modules/gazelle/0.26.0/MODULE.bazel": "6bf5f61b15648e7e35db25fb23cef6b4164fc71c3064ac42ecacafcb6d02abe6",
@@ -103,13 +105,19 @@
"https://bcr.bazel.build/modules/grpc/1.66.0.bcr.2/source.json": "d2b273a925507d47b5e2d6852f194e70d2991627d71b13793cc2498400d4f99e",
"https://bcr.bazel.build/modules/jsoncpp/1.9.5/MODULE.bazel": "31271aedc59e815656f5736f282bb7509a97c7ecb43e927ac1a37966e0578075",
"https://bcr.bazel.build/modules/jsoncpp/1.9.5/source.json": "4108ee5085dd2885a341c7fab149429db457b3169b86eb081fa245eadf69169d",
+ "https://bcr.bazel.build/modules/libjpeg_turbo/2.1.91/MODULE.bazel": "bcc23b7c4866af2d7777ee49db435603ca1e35b90ea0689f8051900fa8c73c6b",
+ "https://bcr.bazel.build/modules/libjpeg_turbo/2.1.91/source.json": "42ea85708058e2408f229075e1cbeaad13fa2719918ff9c505be5e22b57ef17b",
"https://bcr.bazel.build/modules/libpfm/4.11.0/MODULE.bazel": "45061ff025b301940f1e30d2c16bea596c25b176c8b6b3087e92615adbd52902",
"https://bcr.bazel.build/modules/libpfm/4.11.0/source.json": "caaffb3ac2b59b8aac456917a4ecf3167d40478ee79f15ab7a877ec9273937c9",
+ "https://bcr.bazel.build/modules/libpng/1.6.47/MODULE.bazel": "66470450c2040f07d3fc3ee4b72ed25f50ec6b41388a9cf80160b39a1dc75ed1",
+ "https://bcr.bazel.build/modules/libpng/1.6.47/source.json": "80f668824b3605b52c99e705062019f2c6f9066ec024b70ea5ee88db1e89b6b6",
"https://bcr.bazel.build/modules/mbedtls/3.6.0/MODULE.bazel": "8e380e4698107c5f8766264d4df92e36766248447858db28187151d884995a09",
"https://bcr.bazel.build/modules/mbedtls/3.6.0/source.json": "1dbe7eb5258050afcc3806b9d43050f71c6f539ce0175535c670df606790b30c",
"https://bcr.bazel.build/modules/nlohmann_json/3.11.3/MODULE.bazel": "87023db2f55fc3a9949c7b08dc711fae4d4be339a80a99d04453c4bb3998eefc",
"https://bcr.bazel.build/modules/nlohmann_json/3.11.3/source.json": "296c63a90c6813e53b3812d24245711981fc7e563d98fe15625f55181494488a",
"https://bcr.bazel.build/modules/nlohmann_json/3.6.1/MODULE.bazel": "6f7b417dcc794d9add9e556673ad25cb3ba835224290f4f848f8e2db1e1fca74",
+ "https://bcr.bazel.build/modules/opencv/4.11.0.bcr.2/MODULE.bazel": "8eeccd6402fd5cee483501c11409df6b80e94a8d5d53b71c5e9293aaa51be3d6",
+ "https://bcr.bazel.build/modules/opencv/4.11.0.bcr.2/source.json": "2776c8954ea4e18fad23ca7be60d235493a8decafac3c943bab5134da5ea633c",
"https://bcr.bazel.build/modules/opentelemetry-cpp/1.14.2/MODULE.bazel": "089a5613c2a159c7dfde098dabfc61e966889c7d6a81a98422a84c51535ed17d",
"https://bcr.bazel.build/modules/opentelemetry-cpp/1.19.0/MODULE.bazel": "3455326c08b28415648a3d60d8e3c811847ebdbe64474f75b25878f25585aea1",
"https://bcr.bazel.build/modules/opentelemetry-cpp/1.19.0/source.json": "4e48137e4c3ecb99401ff99876df8fa330598d7da051869bec643446e8a8ff95",
@@ -119,7 +127,8 @@
"https://bcr.bazel.build/modules/opentracing-cpp/1.6.0/MODULE.bazel": "b3925269f63561b8b880ae7cf62ccf81f6ece55b62cd791eda9925147ae116ec",
"https://bcr.bazel.build/modules/opentracing-cpp/1.6.0/source.json": "da1cb1add160f5e5074b7272e9db6fd8f1b3336c15032cd0a653af9d2f484aed",
"https://bcr.bazel.build/modules/platforms/0.0.10/MODULE.bazel": "8cb8efaf200bdeb2150d93e162c40f388529a25852b332cec879373771e48ed5",
- "https://bcr.bazel.build/modules/platforms/0.0.10/source.json": "f22828ff4cf021a6b577f1bf6341cb9dcd7965092a439f64fc1bb3b7a5ae4bd5",
+ "https://bcr.bazel.build/modules/platforms/0.0.11/MODULE.bazel": "0daefc49732e227caa8bfa834d65dc52e8cc18a2faf80df25e8caea151a9413f",
+ "https://bcr.bazel.build/modules/platforms/0.0.11/source.json": "f7e188b79ebedebfe75e9e1d098b8845226c7992b307e28e1496f23112e8fc29",
"https://bcr.bazel.build/modules/platforms/0.0.4/MODULE.bazel": "9b328e31ee156f53f3c416a64f8491f7eb731742655a47c9eec4703a71644aee",
"https://bcr.bazel.build/modules/platforms/0.0.5/MODULE.bazel": "5733b54ea419d5eaf7997054bb55f6a1d0b5ff8aedf0176fef9eea44f3acda37",
"https://bcr.bazel.build/modules/platforms/0.0.6/MODULE.bazel": "ad6eeef431dc52aefd2d77ed20a4b353f8ebf0f4ecdd26a807d2da5aa8cd0615",
@@ -159,13 +168,14 @@
"https://bcr.bazel.build/modules/rules_cc/0.0.14/MODULE.bazel": "5e343a3aac88b8d7af3b1b6d2093b55c347b8eefc2e7d1442f7a02dc8fea48ac",
"https://bcr.bazel.build/modules/rules_cc/0.0.15/MODULE.bazel": "6704c35f7b4a72502ee81f61bf88706b54f06b3cbe5558ac17e2e14666cd5dcc",
"https://bcr.bazel.build/modules/rules_cc/0.0.16/MODULE.bazel": "7661303b8fc1b4d7f532e54e9d6565771fea666fbdf839e0a86affcd02defe87",
+ "https://bcr.bazel.build/modules/rules_cc/0.0.17/MODULE.bazel": "2ae1d8f4238ec67d7185d8861cb0a2cdf4bc608697c331b95bf990e69b62e64a",
"https://bcr.bazel.build/modules/rules_cc/0.0.2/MODULE.bazel": "6915987c90970493ab97393024c156ea8fb9f3bea953b2f3ec05c34f19b5695c",
"https://bcr.bazel.build/modules/rules_cc/0.0.5/MODULE.bazel": "be41f87587998fe8890cd82ea4e848ed8eb799e053c224f78f3ff7fe1a1d9b74",
"https://bcr.bazel.build/modules/rules_cc/0.0.6/MODULE.bazel": "abf360251023dfe3efcef65ab9d56beefa8394d4176dd29529750e1c57eaa33f",
"https://bcr.bazel.build/modules/rules_cc/0.0.8/MODULE.bazel": "964c85c82cfeb6f3855e6a07054fdb159aced38e99a5eecf7bce9d53990afa3e",
"https://bcr.bazel.build/modules/rules_cc/0.0.9/MODULE.bazel": "836e76439f354b89afe6a911a7adf59a6b2518fafb174483ad78a2a2fde7b1c5",
- "https://bcr.bazel.build/modules/rules_cc/0.1.0/MODULE.bazel": "2fef03775b9ba995ec543868840041cc69e8bc705eb0cb6604a36eee18c87d8b",
- "https://bcr.bazel.build/modules/rules_cc/0.1.0/source.json": "8a4e832d75e073ab56c74dd77008cf7a81e107dec4544019eb1eefc1320d55be",
+ "https://bcr.bazel.build/modules/rules_cc/0.1.1/MODULE.bazel": "2f0222a6f229f0bf44cd711dc13c858dad98c62d52bd51d8fc3a764a83125513",
+ "https://bcr.bazel.build/modules/rules_cc/0.1.1/source.json": "d61627377bd7dd1da4652063e368d9366fc9a73920bfa396798ad92172cf645c",
"https://bcr.bazel.build/modules/rules_fuzzing/0.5.2/MODULE.bazel": "40c97d1144356f52905566c55811f13b299453a14ac7769dfba2ac38192337a8",
"https://bcr.bazel.build/modules/rules_fuzzing/0.5.2/source.json": "c8b1e2c717646f1702290959a3302a178fb639d987ab61d548105019f11e527e",
"https://bcr.bazel.build/modules/rules_go/0.33.0/MODULE.bazel": "a2b11b64cd24bf94f57454f53288a5dacfe6cb86453eee7761b7637728c1910c",
@@ -254,7 +264,8 @@
"https://bcr.bazel.build/modules/zlib/1.2.13/MODULE.bazel": "aa6deb1b83c18ffecd940c4119aff9567cd0a671d7bba756741cb2ef043a29d5",
"https://bcr.bazel.build/modules/zlib/1.3.1.bcr.1/MODULE.bazel": "6a9fe6e3fc865715a7be9823ce694ceb01e364c35f7a846bf0d2b34762bc066b",
"https://bcr.bazel.build/modules/zlib/1.3.1.bcr.3/MODULE.bazel": "af322bc08976524477c79d1e45e241b6efbeb918c497e8840b8ab116802dda79",
- "https://bcr.bazel.build/modules/zlib/1.3.1.bcr.3/source.json": "2be409ac3c7601245958cd4fcdff4288be79ed23bd690b4b951f500d54ee6e7d",
+ "https://bcr.bazel.build/modules/zlib/1.3.1.bcr.5/MODULE.bazel": "eec517b5bbe5492629466e11dae908d043364302283de25581e3eb944326c4ca",
+ "https://bcr.bazel.build/modules/zlib/1.3.1.bcr.5/source.json": "22bc55c47af97246cfc093d0acf683a7869377de362b5d1c552c2c2e16b7a806",
"https://bcr.bazel.build/modules/zlib/1.3.1/MODULE.bazel": "751c9940dcfe869f5f7274e1295422a34623555916eb98c174c1e945594bf198",
"https://bcr.bazel.build/modules/zlib/1.3/MODULE.bazel": "6a9c02f19a24dcedb05572b2381446e27c272cd383aed11d41d99da9e3167a72"
},
@@ -11772,23 +11783,6 @@
]
}
},
- "@@platforms//host:extension.bzl%host_platform": {
- "general": {
- "bzlTransitiveDigest": "xelQcPZH8+tmuOHVjL9vDxMnnQNMlwj0SlvgoqBkm4U=",
- "usagesDigest": "hgylFkgWSg0ulUwWZzEM1aIftlUnbmw2ynWLdEfHnZc=",
- "recordedFileInputs": {},
- "recordedDirentsInputs": {},
- "envVariables": {},
- "generatedRepoSpecs": {
- "host_platform": {
- "bzlFile": "@@platforms//host:extension.bzl",
- "ruleClassName": "host_platform_repo",
- "attributes": {}
- }
- },
- "recordedRepoMappingEntries": []
- }
- },
"@@pybind11_bazel~//:internal_configure.bzl%internal_configure_extension": {
"general": {
"bzlTransitiveDigest": "CyAKLVVonohnkTSqg9II/HA7M49sOlnMkgMHL3CmDuc=",
diff --git a/docs/Doxyfile b/docs/Doxyfile
index 57013e7e..620cd0ac 100644
--- a/docs/Doxyfile
+++ b/docs/Doxyfile
@@ -1810,7 +1810,7 @@ FULL_SIDEBAR = NO
# Minimum value: 0, maximum value: 20, default value: 4.
# This tag requires that the tag GENERATE_HTML is set to YES.
-ENUM_VALUES_PER_LINE = 4
+ENUM_VALUES_PER_LINE = 1
# When the SHOW_ENUM_VALUES tag is set doxygen will show the specified
# enumeration values besides the enumeration mnemonics.
@@ -2813,7 +2813,7 @@ DIR_GRAPH_MAX_DEPTH = 1
# The default value is: png.
# This tag requires that the tag HAVE_DOT is set to YES.
-DOT_IMAGE_FORMAT = png
+DOT_IMAGE_FORMAT = svg
# If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to
# enable generation of interactive SVG images that allow zooming and panning.
diff --git a/framework/include/vx_internal.h b/framework/include/vx_internal.h
index c9a0835a..941f305b 100644
--- a/framework/include/vx_internal.h
+++ b/framework/include/vx_internal.h
@@ -155,7 +155,7 @@
/*! \brief Maximum number of parameters to a kernel.
* \ingroup group_int_defines
*/
-#define VX_INT_MAX_PARAMS (15)
+#define VX_INT_MAX_PARAMS (22)
/*! \brief Maximum number of loadable modules.
* \ingroup group_int_defines
diff --git a/framework/src/vx_kernel.cpp b/framework/src/vx_kernel.cpp
index 5a35cd49..a274943a 100644
--- a/framework/src/vx_kernel.cpp
+++ b/framework/src/vx_kernel.cpp
@@ -341,7 +341,8 @@ VX_API_ENTRY vx_status VX_API_CALL vxLoadKernels(vx_context context, const vx_ch
status = publish((vx_context)context);
if (status != VX_SUCCESS)
{
- VX_PRINT(VX_ZONE_ERROR, "Failed to publish kernels in module\n");
+ VX_PRINT(VX_ZONE_ERROR,
+ "Failed to publish kernels in module with status %d\n", status);
Osal::unloadModule(context->modules[m].handle);
context->modules[m].handle = nullptr;
}
@@ -875,6 +876,8 @@ VX_API_ENTRY vx_status VX_API_CALL vxAddParameterToKernel(vx_kernel kernel,
(Parameter::isValidDirection(dir) == vx_false_e) ||
(Parameter::isValidState(state) == vx_false_e))
{
+ VX_PRINT(VX_ZONE_ERROR,
+ "Invalid data type, param direction, or param state!\n");
status = VX_ERROR_INVALID_PARAMETERS;
}
else
@@ -893,6 +896,8 @@ VX_API_ENTRY vx_status VX_API_CALL vxAddParameterToKernel(vx_kernel kernel,
(Parameter::isValidState(state) == vx_false_e)) ||
(data_type == VX_TYPE_DELAY && dir != VX_INPUT))
{
+ VX_PRINT(VX_ZONE_ERROR,
+ "Invalid data type, param direction, or param state!\n");
status = VX_ERROR_INVALID_PARAMETERS;
}
else
@@ -906,6 +911,7 @@ VX_API_ENTRY vx_status VX_API_CALL vxAddParameterToKernel(vx_kernel kernel,
}
else
{
+ VX_PRINT(VX_ZONE_ERROR, "Invalid number of parameters associated!\n");
status = VX_ERROR_INVALID_PARAMETERS;
}
}
diff --git a/framework/src/vx_parameter.cpp b/framework/src/vx_parameter.cpp
index 5437770e..85d0913d 100644
--- a/framework/src/vx_parameter.cpp
+++ b/framework/src/vx_parameter.cpp
@@ -34,7 +34,7 @@ Parameter::~Parameter()
vx_bool Parameter::isValidDirection(vx_enum dir)
{
- if ((dir == VX_INPUT) || (dir == VX_OUTPUT)) /* Bidirectional is not valid for user kernels */
+ if ((dir == VX_INPUT) || (dir == VX_OUTPUT) || (dir == VX_BIDIRECTIONAL))
{
return vx_true_e;
}
diff --git a/include/VX/vx_corevx_ext.h b/include/VX/vx_corevx_ext.h
index 57de24de..6967b51b 100644
--- a/include/VX/vx_corevx_ext.h
+++ b/include/VX/vx_corevx_ext.h
@@ -171,8 +171,8 @@
*/
/*!
- * \brief The OpenVX CoreVX Vendor Extension.
- * \defgroup group_corevx_ext Extension: CoreVX
+ * \brief The OpenVX EdgeAI Vendor Extension.
+ * \defgroup group_corevx_ext Extension: AI/ML
* \ingroup group_extensions
*
* \defgroup group_ort_function_cpu_inference Kernel: ORT Inference
diff --git a/samples/README.md b/samples/README.md
new file mode 100644
index 00000000..43dc1966
--- /dev/null
+++ b/samples/README.md
@@ -0,0 +1,38 @@
+[](https://opensource.org/licenses/MIT)
+
+

+
+# Sample Applications
+
+Khronos OpenVX™ is an open, royalty-free standard for cross-platform acceleration of computer vision applications. OpenVX enables performance and power-optimized computer vision processing, especially important in embedded and real-time use cases such as face, body, and gesture tracking, smart video surveillance, advanced driver assistance systems (ADAS), object and scene reconstruction, augmented reality, visual inspection, robotics and more.
+
+In this project, we provide samples that use our optimized libraries to build applications that showcase potential usage or may used as reference to develop your own products.
+
+## Bubble Pop
+
+In this sample we will create an OpenVX graph to run Bubble Pop on a live camera. This sample application uses OpenCV to decode input image, draw bubbles/donuts and display the output.
+
+ 
+
+## Canny Edge Detector
+
+In this sample we will create an OpenVX graph to run canny edge detection on an image or a live camera. This sample application uses OpenCV to decode input image and display the output.
+
+ 
+
+## Optical Flow
+
+This sample [application](./optical_flow/README.md#openvx-samples) we will create an OpenVX graph to run Optical Flow on a video/live. This sample application uses OpenCV to decode input video and display the output.
+
+
+
+## Skin Tone Detector
+
+In this sample we will create an OpenVX graph to run skintone detection on an image or a live camera. This sample application uses OpenCV to decode input image and display the output.
+
+ 
+
+## ORB (Oriented FAST and Rotated BRIEF)
+In this sample we will create an OpenVX graph to run ORB (Oriented FAST and Rotated BRIEF) on a live camera. This sample application uses OpenCV to detect and display keypoints.
+
+ 
\ No newline at end of file
diff --git a/samples/bubble-pop/BUILD b/samples/bubble-pop/BUILD
new file mode 100644
index 00000000..6e504ebd
--- /dev/null
+++ b/samples/bubble-pop/BUILD
@@ -0,0 +1,57 @@
+
+
+cc_import(
+ name = "import_vx_pop",
+ shared_library = ":vx_pop",
+)
+
+cc_shared_library(
+ name = "vx_pop",
+ deps = [":vx_pop_a"]
+)
+
+cc_library(
+ name = "vx_pop_a",
+ srcs = [
+ "source/AMD_VX_Pop_Bubble.cpp",
+ "source/AMD_VX_Pop_Donut.cpp",
+ "source/internal_dataTranslator.cpp",
+ "source/internal_publishKernels.cpp",
+ "source/internal_vxNodes.cpp"
+ ],
+ deps = [
+ "//:corevx",
+ "@opencv",
+ "//targets/ai_server:imported_openvx_ai_server",
+ "//targets/c_model:imported_openvx_c_model",
+ "//targets/debug:imported_openvx_debug",
+ "//targets/extras:imported_openvx_extras",
+ "//targets/liteRT:imported_openvx_liteRT",
+ "//targets/opencl:imported_openvx_opencl",
+ "//targets/onnxRT:imported_openvx_onnxRT",
+ "//targets/executorch:imported_openvx_torch",
+ "//third_party:opencv-prebuilt",
+ ],
+ hdrs = glob([
+ "include/*.h"
+ ]),
+ includes = ["include"],
+)
+
+cc_binary(
+ name = "bubble-pop",
+ srcs = [
+ "source/AMD_app.cpp",
+ "include/vx_ext_pop.h",
+ "include/vx_pop.h",
+ ],
+ includes = ["include"],
+ data = [
+ "image/bubble.png",
+ ],
+ deps = [
+ ":vx_pop_a",
+ ":import_vx_pop"
+ ],
+ visibility = ["//visibility:public"],
+)
\ No newline at end of file
diff --git a/samples/bubble-pop/README.md b/samples/bubble-pop/README.md
new file mode 100644
index 00000000..9a1dd6d1
--- /dev/null
+++ b/samples/bubble-pop/README.md
@@ -0,0 +1,65 @@
+## Bubble Pop Sample
+In this sample we will create an OpenVX graph to run Bubble Pop on a live camera. This sample application uses OpenCV to decode input image, draw bubbles/donuts and display the output.
+
+ 
+
+### Prerequisites
+
+* [Conformant OpenVX Implementation](https://github.com/KhronosGroup/Khronosdotorg/blob/master/api/openvx/resources.md)
+
+* [OpenCV](https://github.com/opencv/opencv/releases/tag/3.4.0)
+
+* Camera
+
+### Steps to run the Bubble Pop sample
+
+* **Step - 1:** Build and install [Conformant OpenVX Implementation](https://github.com/KhronosGroup/OpenVX-sample-impl). In this example we will use the OpenVX Sample Implementation available on [GitHub](https://github.com/KhronosGroup/OpenVX-sample-impl)
+
+```
+Build OpenVX on Linux
+
+* Git Clone project with a recursive flag to get submodules
+
+ git clone --recursive https://github.com/KhronosGroup/OpenVX-sample-impl.git
+
+* Use Build.py script
+
+ cd OpenVX-sample-impl/
+ python Build.py --os=Linux --arch=64 --conf=Debug --conf_vision --enh_vision --conf_nn
+```
+
+* **Step - 2:** Export OpenVX Directory Path
+
+```
+export OPENVX_DIR=$(pwd)/install/Linux/x64/Debug
+```
+
+* **Step - 3:** Clone the OpenVX Samples project and build the bubble pop application
+
+```
+cd ~/ && mkdir OpenVXSample-pop
+cd OpenVXSample-pop/
+git clone https://github.com/kiritigowda/openvx-samples.git
+```
+
+* **Step - 4:** CMake and Build the pop application
+
+```
+mkdir pop-build && cd pop-build
+cmake -DOPENVX_INCLUDES=$OPENVX_DIR/include -DOPENVX_LIBRARIES=$OPENVX_DIR/bin/libopenvx.so ../openvx-samples/bubble-pop/
+make
+```
+
+* **Step - 5:** Run VX Pop application
+
+ * **Bubbles**
+
+ ```
+ ./vxPop --bubble
+ ```
+
+ * **Donuts**
+
+ ````
+ ./vxPop --donut
+ ````
diff --git a/samples/bubble-pop/image/bubble.png b/samples/bubble-pop/image/bubble.png
new file mode 100644
index 00000000..09fe7731
Binary files /dev/null and b/samples/bubble-pop/image/bubble.png differ
diff --git a/samples/bubble-pop/include/internal_opencvTunnel.h b/samples/bubble-pop/include/internal_opencvTunnel.h
new file mode 100644
index 00000000..a546fbfe
--- /dev/null
+++ b/samples/bubble-pop/include/internal_opencvTunnel.h
@@ -0,0 +1,107 @@
+/*
+Copyright (c) 2020 Advanced Micro Devices, Inc. All rights reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+#ifndef CV_TUNNEL
+#define CV_TUNNEL
+
+#if _WIN32
+#include
+#endif
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "vx_pop.h"
+
+using namespace cv;
+using namespace std;
+
+#define STATUS_ERROR_CHECK(call){vx_status status = call; if(status!= VX_SUCCESS) return status;}
+#define PARAM_ERROR_CHECK(call){vx_status status = call; if(status!= VX_SUCCESS) goto exit;}
+
+int VX_to_CV_Image(Mat**, vx_image);
+int VX_to_CV_MATRIX(Mat**, vx_matrix);
+
+int CV_to_VX_Pyramid(vx_pyramid, vector);
+int CV_to_VX_Image(vx_image, Mat*);
+
+int CV_to_VX_keypoints(vector, vx_array);
+int CVPoints2f_to_VX_keypoints(vector, vx_array);
+int CV_DESP_to_VX_DESP(Mat, vx_array, int);
+
+int match_vx_image_parameters(vx_image, vx_image);
+void overlay_bubble(const Mat &, const Mat &, Mat &, Point2i);
+
+class Kernellist
+{
+public:
+ struct node{ public: std::function func; node* next; };
+ int count;
+ Kernellist(int max){ top = nullptr; maxnum = max; count = 0;}
+
+ vx_status ADD(std::function element)
+ {
+ vx_status status = VX_SUCCESS;
+ if (count == maxnum) return VX_ERROR_NO_RESOURCES;
+ else
+ {
+ node *newTop = new node;
+ if (top == nullptr){ newTop->func = element; newTop->next = nullptr; top = newTop; count++; }
+ else{ newTop->func = element; newTop->next = top; top = newTop; count++; }
+ }
+ return status;
+ }
+
+ vx_status REMOVE()
+ {
+ vx_status status = VX_SUCCESS;
+ if (top == nullptr) return VX_ERROR_NO_RESOURCES;
+ else{ node * old = top; top = top->next; count--; delete(old); }
+ return status;
+ }
+
+ vx_status PUBLISH(vx_context context)
+ {
+ vx_status status = VX_SUCCESS;
+
+ if (top == nullptr) { vxAddLogEntry((vx_reference)context, VX_ERROR_NO_RESOURCES, "PUBLISH Fail, Kernel list is empty"); return VX_ERROR_NO_RESOURCES; }
+
+ else
+ {
+ node * Kernel = top;
+ for (int i = 0; i < count; i++){ STATUS_ERROR_CHECK(Kernel->func(context)); Kernel = Kernel->next;}
+ }
+ return status;
+ }
+
+private:
+ node *top; int maxnum;
+};
+
+static Kernellist *Kernel_List;
+
+#endif /* CV_TUNNEL */
diff --git a/samples/bubble-pop/include/internal_publishKernels.h b/samples/bubble-pop/include/internal_publishKernels.h
new file mode 100644
index 00000000..59784d77
--- /dev/null
+++ b/samples/bubble-pop/include/internal_publishKernels.h
@@ -0,0 +1,46 @@
+/*
+Copyright (c) 2015 Advanced Micro Devices, Inc. All rights reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+#ifndef PUBLISH_KERNELS_H
+#define PUBLISH_KERNELS_H
+
+#include "internal_opencvTunnel.h"
+
+#if _WIN32
+#define SHARED_PUBLIC __declspec(dllexport)
+#else
+#define SHARED_PUBLIC __attribute__ ((visibility ("default")))
+#endif
+
+#define MAX_KERNELS 10
+
+extern "C" SHARED_PUBLIC vx_status VX_API_CALL vxPublishKernels(vx_context context);
+
+vx_status ADD_KERENEL(std::function);
+vx_status get_kernels_to_publish();
+
+vx_status VX_bubbles_pop_Register(vx_context);
+vx_status VX_donut_pop_Register(vx_context);
+
+#define VX_KERNEL_EXT_POP_BUBBLE_POP_NAME "org.pop.bubble_pop"
+#define VX_KERNEL_EXT_POP_DONUT_POP_NAME "org.pop.donut_pop"
+
+#endif /* PUBLISH_KERNELS_H */
diff --git a/samples/bubble-pop/include/vx_ext_pop.h b/samples/bubble-pop/include/vx_ext_pop.h
new file mode 100644
index 00000000..2d8aed6a
--- /dev/null
+++ b/samples/bubble-pop/include/vx_ext_pop.h
@@ -0,0 +1,68 @@
+/*
+Copyright (c) 2020 Advanced Micro Devices, Inc. All rights reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+#include "VX/vx.h"
+#include
+#include
+#include
+#include
+
+#if _WIN32
+#define SHARED_PUBLIC __declspec(dllexport)
+#else
+#define SHARED_PUBLIC __attribute__ ((visibility ("default")))
+#endif
+
+#ifndef dimof
+#define dimof(x) (sizeof(x)/sizeof(x[0]))
+#endif
+
+vx_node vxCreateNodeByStructure(vx_graph graph, vx_enum kernelenum, vx_reference params[], vx_uint32 num);
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+ /*!***********************************************************************************************************
+ VX POP - Bubble Pop VX_API_ENTRY C Function NODE
+ *************************************************************************************************************/
+ /*! \brief [Graph] Creates a OpenCV blur function node.
+ * \param [in] graph The reference to the graph.
+ * \param [in] input The input image in \ref VX_DF_IMAGE_U8 format.
+ * \param [out] output The output image is as same size and type of input.
+ * \return \ref vx_node.
+ * \retval vx_node A node reference. Any possible errors preventing a successful creation should be checked using \ref vxGetStatus*/
+ extern "C" SHARED_PUBLIC vx_node VX_API_CALL vxExtPopNode_bubblePop(vx_graph graph, vx_image input, vx_image output);
+
+ /*!***********************************************************************************************************
+ VX POP - Donut Pop VX_API_ENTRY C Function NODE
+ *************************************************************************************************************/
+ /*! \brief [Graph] Creates a OpenCV blur function node.
+ * \param [in] graph The reference to the graph.
+ * \param [in] input The input image in \ref VX_DF_IMAGE_U8 format.
+ * \param [out] output The output image is as same size and type of input.
+ * \return \ref vx_node.
+ * \retval vx_node A node reference. Any possible errors preventing a successful creation should be checked using \ref vxGetStatus*/
+ extern "C" SHARED_PUBLIC vx_node VX_API_CALL vxExtPopNode_donutPop(vx_graph graph, vx_image input, vx_image output);
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/samples/bubble-pop/include/vx_pop.h b/samples/bubble-pop/include/vx_pop.h
new file mode 100644
index 00000000..edd7a7d1
--- /dev/null
+++ b/samples/bubble-pop/include/vx_pop.h
@@ -0,0 +1,54 @@
+/*
+Copyright (c) 2020 Advanced Micro Devices, Inc. All rights reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+
+#ifndef _VX_EXT_AMD_POP_H_
+#define _VX_EXT_AMD_POP_H_
+
+#include"vx_ext_pop.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*! \brief The AMD extension library for Pop */
+#define VX_LIBRARY_EXT_POP 3
+
+ /*!
+ * \brief The list of available vision kernels in the Pop extension library.
+ */
+ enum vx_kernel_ext_amd_pop_e
+ {
+ /*!
+ * \brief The Bubble Pop kernel. Kernel name is "org.pop.bubble_pop".
+ */
+ VX_KERNEL_EXT_POP_BUBBLE_POP = VX_KERNEL_BASE(VX_ID_AMD, VX_LIBRARY_EXT_POP) + 0x001,
+ /*!
+ * \brief The Donut Pop kernel. Kernel name is "org.pop.donut_pop".
+ */
+ VX_KERNEL_EXT_POP_DONUT_POP = VX_KERNEL_BASE(VX_ID_AMD, VX_LIBRARY_EXT_POP) + 0x002,
+ };
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/samples/bubble-pop/source/AMD_VX_Pop_Bubble.cpp b/samples/bubble-pop/source/AMD_VX_Pop_Bubble.cpp
new file mode 100644
index 00000000..46d25742
--- /dev/null
+++ b/samples/bubble-pop/source/AMD_VX_Pop_Bubble.cpp
@@ -0,0 +1,415 @@
+/*
+Copyright (c) 2020 Advanced Micro Devices, Inc. All rights reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+#include
+
+#include "internal_publishKernels.h"
+
+int poppedBubbles = 0;
+int globalBubblesflag = 0;
+Mat globalBubblesRefImage;
+int globalBubblesChange = 0;
+Mat bubble_PNG;
+
+/************************************************************************************************************
+Overlay Image Function
+*************************************************************************************************************/
+void overlayImage(const Mat &background, const Mat &foreground,Mat &output, Point2i location)
+{
+ background.copyTo(output);
+
+ for (int y = std::max(location.y, 0); y < background.rows; ++y)
+ {
+ int fY = y - location.y;
+ if (fY >= foreground.rows)
+ break;
+
+ for (int x = std::max(location.x, 0); x < background.cols; ++x)
+ {
+ int fX = x - location.x;
+
+
+ if (fX >= foreground.cols)
+ break;
+
+ double opacity =
+ ((double)foreground.data[fY * foreground.step + fX * foreground.channels() + 3])
+
+ / 255.;
+
+ for (int c = 0; opacity > 0 && c < output.channels(); ++c)
+ {
+ unsigned char foregroundPx =
+ foreground.data[fY * foreground.step + fX * foreground.channels() + c];
+ unsigned char backgroundPx =
+ background.data[y * background.step + x * background.channels() + c];
+ output.data[y*output.step + output.channels()*x + c] =
+ backgroundPx * (1. - opacity) + foregroundPx * opacity;
+ }
+ }
+ }
+}
+
+/************************************************************************************************************
+Bubbles
+*************************************************************************************************************/
+class AMD_bubble_pop
+{
+private:
+ int bubbleX, bubbleY, bubbleWidth, bubbleHeight;
+
+public:
+ AMD_bubble_pop(int bX, int bY, int bW, int bH)
+ {
+ bubbleX = bX; bubbleY = bY; bubbleWidth = bW; bubbleHeight = bH;
+ bubble_PNG = imread("./samples/bubble-pop/image/bubble.png", -1);
+ }
+
+ ~AMD_bubble_pop()
+ {
+ bubbleX = 0; bubbleY = 0; bubbleWidth = 0; bubbleHeight = 0;
+ }
+
+ int update(int width, int height, Mat *Image)
+ {
+ (void)width;
+ int movementAmount = 0;
+ if (globalBubblesflag > 10)
+ {
+ Mat diff_image;
+ absdiff(*Image, globalBubblesRefImage, diff_image);
+ blur(diff_image, diff_image, Size(3, 3));
+
+ cv::erode(diff_image, diff_image, getStructuringElement(MORPH_ELLIPSE, Size(3, 3)));
+ cv::erode(diff_image, diff_image, getStructuringElement(MORPH_ELLIPSE, Size(3, 3)));
+ cv::dilate(diff_image, diff_image, getStructuringElement(MORPH_ELLIPSE, Size(3, 3)));
+ cv::dilate(diff_image, diff_image, getStructuringElement(MORPH_ELLIPSE, Size(3, 3)));
+
+ cv::threshold(diff_image, diff_image, 160, 255, 0);
+
+ unsigned char *input = (unsigned char*)(diff_image.data);
+ int b;
+
+ for (int x = bubbleX; x <= (bubbleX + (bubbleWidth - 1)); x++)
+ for (int y = bubbleY; y <= (bubbleY + (bubbleWidth - 1)); y++)
+ {
+ if ((x < diff_image.cols && x > 0) && (y < diff_image.rows && y > 0))
+ {
+ b = input[diff_image.cols * y + x];
+ if (b == 255)
+ movementAmount++;
+ }
+ }
+ }
+
+ if (movementAmount > 100)
+ {
+ poppedBubbles++;
+ return 1;
+ }
+ else
+ {
+ bubbleY += 5;
+
+ if (bubbleY > height)
+ return 1;
+
+ Mat test_image;
+ test_image = *Image;
+
+ // draw bubbles
+ if(bubble_PNG.empty()){ printf("--image/bubble.png-- Image not found\n"); return -1;};
+ overlayImage(test_image, bubble_PNG, *Image, cv::Point(bubbleX, bubbleY));
+
+ return 0;
+ }
+ }
+};
+
+struct Linked_list_pop{
+ AMD_bubble_pop bubble;
+ int data;
+ struct Linked_list_pop* next;
+};
+typedef struct Linked_list_pop BubbleNode;
+
+//Function Prototyping
+BubbleNode* insert_pop(BubbleNode* head, BubbleNode* x);
+BubbleNode* pop_position_delete(BubbleNode* head, int p);
+BubbleNode* pop_clean_node(BubbleNode* head);
+void draw_pop_bubbles(int, int, Mat*);
+BubbleNode *POPbubble = NULL;
+
+/************************************************************************************************************
+Draw Bubbles
+*************************************************************************************************************/
+void draw_pop_bubbles(int width, int height, Mat *Image)
+{
+ static int count = 0;
+
+ int randx = rand() % (width + 1);
+ AMD_bubble_pop new_element = AMD_bubble_pop(randx, 0, 20, 20);
+
+ BubbleNode * temp = (BubbleNode*)malloc(sizeof(BubbleNode));
+ temp->bubble = new_element;
+ temp->next = NULL;
+ POPbubble = insert_pop(POPbubble, temp);
+ count++;
+
+ BubbleNode *_bubbles;
+ _bubbles = POPbubble;
+ int K = 0;
+ int flag = 0;
+
+ while (_bubbles != NULL)
+ {
+ K++;
+ flag = 0;
+
+ if (_bubbles->bubble.update(width, height, Image) == 1)
+ {
+ _bubbles = _bubbles->next;
+ POPbubble = pop_position_delete(POPbubble, K);
+ count--;
+ K--;
+ flag = 1;
+ }
+
+ if (flag == 0)
+ _bubbles = _bubbles->next;
+ }
+
+ (void)count;
+ return;
+
+}
+
+/************************************************************************************************************
+input parameter validator.
+param [in] node The handle to the node.
+param [in] index The index of the parameter to validate.
+*************************************************************************************************************/
+static vx_status VX_CALLBACK VX_bubbles_InputValidator(vx_node node, vx_uint32 index)
+{
+ vx_status status = VX_SUCCESS;
+ vx_parameter param = vxGetParameterByIndex(node, index);
+
+ if (index == 0)
+ {
+ vx_image image;
+ vx_df_image df_image = VX_DF_IMAGE_VIRT;
+ STATUS_ERROR_CHECK(vxQueryParameter(param, VX_PARAMETER_ATTRIBUTE_REF, &image, sizeof(vx_image)));
+ STATUS_ERROR_CHECK(vxQueryImage(image, VX_IMAGE_ATTRIBUTE_FORMAT, &df_image, sizeof(df_image)));
+ if (df_image != VX_DF_IMAGE_U8)
+ status = VX_ERROR_INVALID_VALUE;
+ vxReleaseImage(&image);
+ }
+
+ else if (index == 1)
+ {
+ vx_image image;
+ vx_df_image df_image = VX_DF_IMAGE_VIRT;
+ STATUS_ERROR_CHECK(vxQueryParameter(param, VX_PARAMETER_ATTRIBUTE_REF, &image, sizeof(vx_image)));
+ STATUS_ERROR_CHECK(vxQueryImage(image, VX_IMAGE_ATTRIBUTE_FORMAT, &df_image, sizeof(df_image)));
+ if (df_image != VX_DF_IMAGE_U8 && df_image != VX_DF_IMAGE_RGB)
+ status = VX_ERROR_INVALID_VALUE;
+ vxReleaseImage(&image);
+ }
+
+ vxReleaseParameter(¶m);
+ return status;
+}
+
+/************************************************************************************************************
+output parameter validator.
+*************************************************************************************************************/
+static vx_status VX_CALLBACK VX_bubbles_OutputValidator(vx_node node, vx_uint32 index, vx_meta_format meta)
+{
+ vx_status status = VX_SUCCESS;
+ if (index == 1)
+ {
+ vx_parameter output_param = vxGetParameterByIndex(node, 1);
+ vx_image output; vx_uint32 width = 0, height = 0; vx_df_image format = VX_DF_IMAGE_VIRT;
+
+ STATUS_ERROR_CHECK(vxQueryParameter(output_param, VX_PARAMETER_ATTRIBUTE_REF, &output, sizeof(vx_image)));
+ STATUS_ERROR_CHECK(vxQueryImage(output, VX_IMAGE_ATTRIBUTE_FORMAT, &format, sizeof(format)));
+ STATUS_ERROR_CHECK(vxQueryImage(output, VX_IMAGE_ATTRIBUTE_WIDTH, &width, sizeof(width)));
+ STATUS_ERROR_CHECK(vxQueryImage(output, VX_IMAGE_ATTRIBUTE_HEIGHT, &height, sizeof(height)));
+
+ if (format != VX_DF_IMAGE_U8 && format != VX_DF_IMAGE_RGB)
+ status = VX_ERROR_INVALID_VALUE;
+
+ STATUS_ERROR_CHECK(vxSetMetaFormatAttribute(meta, VX_IMAGE_ATTRIBUTE_WIDTH, &width, sizeof(width)));
+ STATUS_ERROR_CHECK(vxSetMetaFormatAttribute(meta, VX_IMAGE_ATTRIBUTE_HEIGHT, &height, sizeof(height)));
+ STATUS_ERROR_CHECK(vxSetMetaFormatAttribute(meta, VX_IMAGE_ATTRIBUTE_FORMAT, &format, sizeof(format)));
+
+ vxReleaseImage(&output);
+ vxReleaseParameter(&output_param);
+ }
+ return status;
+}
+
+/************************************************************************************************************
+Execution Kernel
+*************************************************************************************************************/
+static vx_status VX_CALLBACK VX_bubbles_Kernel(vx_node node, const vx_reference *parameters, vx_uint32 num)
+{
+ (void)node;
+ (void)num;
+ vx_status status = VX_SUCCESS;
+
+ vx_image image_in = (vx_image)parameters[0];
+ vx_image image_out = (vx_image)parameters[1];
+ Mat *mat, bl;
+
+ // wait to restart - press any key
+ if(poppedBubbles >= 1015){ poppedBubbles = 0; waitKey(0);}
+
+ //Converting VX Image to OpenCV Mat
+ STATUS_ERROR_CHECK(VX_to_CV_Image(&mat, image_in));
+ Mat Image = *mat, clean_img;
+ flip(Image, Image, 1);
+
+ if (globalBubblesflag == 0){ globalBubblesRefImage = Image;} else{clean_img = Image;}
+
+ draw_pop_bubbles(Image.cols, Image.rows, &Image);
+
+ std::ostringstream statusStr;
+ if (poppedBubbles >= 1000)
+ {
+ statusStr << "Congratulations! Click any Key to Contiue Popping!";
+ cv::putText(Image, statusStr.str(), cv::Point(5, int(Image.rows/2)), FONT_HERSHEY_COMPLEX_SMALL, 1, cv::Scalar(200, 200, 250), 1, cv::LINE_AA);
+ }
+ else
+ {
+ statusStr << "Bubbles Popped: " << poppedBubbles;
+ cv::putText(Image, statusStr.str(), cv::Point(30, 30), FONT_HERSHEY_COMPLEX_SMALL, 1.2, cv::Scalar(200, 200, 250), 1, cv::LINE_AA);
+ }
+
+ //Converting OpenCV Mat into VX Image
+ STATUS_ERROR_CHECK(CV_to_VX_Image(image_out, &Image));
+
+ if (globalBubblesflag == 0) globalBubblesflag++; else{ globalBubblesRefImage = clean_img; globalBubblesflag++; }
+
+ return status;
+}
+
+/************************************************************************************************************
+Function to Register the Kernel for Publish
+*************************************************************************************************************/
+vx_status VX_bubbles_pop_Register(vx_context context)
+{
+ vx_status status = VX_SUCCESS;
+ vx_kernel kernel = vxAddKernel(context,
+ "org.pop.bubble_pop",
+ VX_KERNEL_EXT_POP_BUBBLE_POP,
+ VX_bubbles_Kernel,
+ 2,
+ VX_bubbles_InputValidator,
+ VX_bubbles_OutputValidator,
+ nullptr,
+ nullptr);
+
+ if (kernel)
+ {
+ PARAM_ERROR_CHECK(vxAddParameterToKernel(kernel, 0, VX_INPUT, VX_TYPE_IMAGE, VX_PARAMETER_STATE_REQUIRED));
+ PARAM_ERROR_CHECK(vxAddParameterToKernel(kernel, 1, VX_OUTPUT, VX_TYPE_IMAGE, VX_PARAMETER_STATE_REQUIRED));
+ PARAM_ERROR_CHECK(vxFinalizeKernel(kernel));
+ }
+
+ if (status != VX_SUCCESS)
+ {
+ exit: vxRemoveKernel(kernel); return VX_FAILURE;
+ }
+
+ return status;
+}
+
+/*
+* linked_list.c
+* Author: Kiriti Nagesh Gowda
+*/
+
+//Insert a variable function
+BubbleNode* insert_pop(BubbleNode* head, BubbleNode* x)
+{
+ BubbleNode* temp;
+ BubbleNode* temp1 = x;
+
+ if (head == NULL)
+ head = temp1;
+
+ else{
+ temp = head;
+ while (temp->next != NULL){
+ temp = temp->next;
+ }
+ temp->next = temp1;
+ }
+ return (head);
+}
+
+//Delete a node from the list
+BubbleNode* pop_position_delete(BubbleNode* head, int p)
+{
+ BubbleNode* temp;
+ BubbleNode* temp1;
+ int count = 2;
+ temp = head;
+
+ if (temp == NULL || p <= 0){
+ printf("The List is empty or the position is invalid\n");
+ return (head);
+ }
+
+ if (p == 1){
+ head = temp->next;
+ free(temp);
+ return (head);
+ }
+ while (temp != NULL){
+ if (count == (p))
+ {
+ temp1 = temp->next;
+ temp->next = temp1->next;
+ free(temp1);
+ return (head);
+ }
+ temp = temp->next;
+
+ if (temp == NULL) break;
+ ++count;
+ }
+ return head;
+}
+
+//clean node
+BubbleNode *pop_clean_node(BubbleNode * head)
+{
+
+ BubbleNode *temp1;
+ while (head != NULL){
+ temp1 = head->next;
+ free(head);
+ head = temp1;
+ }
+ return(head);
+}
diff --git a/samples/bubble-pop/source/AMD_VX_Pop_Donut.cpp b/samples/bubble-pop/source/AMD_VX_Pop_Donut.cpp
new file mode 100644
index 00000000..e4f5108c
--- /dev/null
+++ b/samples/bubble-pop/source/AMD_VX_Pop_Donut.cpp
@@ -0,0 +1,390 @@
+/*
+Copyright (c) 2020 Advanced Micro Devices, Inc. All rights reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+#include
+
+#include "internal_publishKernels.h"
+
+int poppedDonuts = 0;
+int globalDonutFlag = 0;
+Mat globalDonutRefImage;
+int globalDonutChange = 0;
+
+/************************************************************************************************************
+Bubbles
+*************************************************************************************************************/
+class AMD_donut_pop
+{
+private:
+ int donutX, donutY, donutWidth, donutHeight;
+
+public:
+ AMD_donut_pop(int bX, int bY, int bW, int bH)
+ {
+ donutX = bX; donutY = bY; donutWidth = bW; donutHeight = bH;
+ }
+
+ ~AMD_donut_pop()
+ {
+ donutX = 0; donutY = 0; donutWidth = 0; donutHeight = 0;
+ }
+
+ int update(int width, int height, Mat *Image)
+ {
+ (void)width;
+ int movementAmount = 0;
+ if (globalDonutFlag > 10)
+ {
+ Mat diff_image;
+ absdiff(*Image, globalDonutRefImage, diff_image);
+ blur(diff_image, diff_image, Size(3, 3));
+
+ cv::erode(diff_image, diff_image, getStructuringElement(MORPH_ELLIPSE, Size(3, 3)));
+ cv::erode(diff_image, diff_image, getStructuringElement(MORPH_ELLIPSE, Size(3, 3)));
+ cv::dilate(diff_image, diff_image, getStructuringElement(MORPH_ELLIPSE, Size(3, 3)));
+ cv::dilate(diff_image, diff_image, getStructuringElement(MORPH_ELLIPSE, Size(3, 3)));
+
+ cv::threshold(diff_image, diff_image, 160, 255, 0);
+
+ unsigned char *input = (unsigned char*)(diff_image.data);
+ int b;
+
+ for (int x = donutX; x <= (donutX + (donutWidth - 1)); x++)
+ for (int y = donutY; y <= (donutY + (donutWidth - 1)); y++)
+ {
+ if ((x < diff_image.cols && x > 0) && (y < diff_image.rows && y > 0))
+ {
+ b = input[diff_image.cols * y + x];
+ if (b == 255)
+ movementAmount++;
+ }
+ }
+ }
+
+ if (movementAmount > 100)
+ {
+ poppedDonuts++;
+ return 1;
+ }
+ else
+ {
+ donutY += 5;
+
+ if (donutY > height)
+ return 1;
+
+ Mat test_image;
+ test_image = *Image;
+
+ // draw Donuts
+ if (globalDonutChange == 0)
+ {
+ Point2f cen(donutX, donutY);
+ cv::circle(*Image, cen, 8, cv::Scalar(255, 255, 55), 5);
+ }
+ else
+ {
+ Point2f cen(donutX, donutY);
+ cv::circle(*Image, cen, 5, cv::Scalar(255, 255, 55), 5);
+ }
+
+ return 0;
+ }
+ }
+};
+
+struct Linked_list_pop{
+ AMD_donut_pop donut;
+ int data;
+ struct Linked_list_pop* next;
+};
+typedef struct Linked_list_pop donutNode;
+
+//Function Prototyping
+donutNode* donut_insert(donutNode* head, donutNode* x);
+donutNode* donut_position_delete(donutNode* head, int p);
+donutNode* donut_clean_node(donutNode* head);
+int draw_pop_donuts(int, int, Mat*);
+donutNode *PopDonuts = NULL;
+
+/************************************************************************************************************
+Draw Bubbles
+*************************************************************************************************************/
+int draw_pop_donuts(int width, int height, Mat *Image)
+{
+ static int count = 0;
+
+ int randx = rand() % (width + 1);
+ AMD_donut_pop new_element = AMD_donut_pop(randx, 0, 20, 20);
+
+ donutNode * temp = (donutNode*)malloc(sizeof(donutNode));
+ temp->donut = new_element;
+ temp->next = NULL;
+ PopDonuts = donut_insert(PopDonuts, temp);
+ count++;
+
+ donutNode *_donuts;
+ _donuts = PopDonuts;
+ int K = 0;
+ int flag = 0;
+
+ while (_donuts != NULL)
+ {
+ K++;
+ flag = 0;
+
+ if (_donuts->donut.update(width, height, Image) == 1)
+ {
+ _donuts = _donuts->next;
+ PopDonuts = donut_position_delete(PopDonuts, K);
+ count--;
+ K--;
+ flag = 1;
+ }
+
+ if (flag == 0)
+ _donuts = _donuts->next;
+ }
+
+ (void)count;
+ return 0;
+
+}
+
+/************************************************************************************************************
+input parameter validator.
+param [in] node The handle to the node.
+param [in] index The index of the parameter to validate.
+*************************************************************************************************************/
+vx_status VX_CALLBACK VX_bubbles_InputValidator(vx_node node, vx_uint32 index)
+{
+ vx_status status = VX_SUCCESS;
+ vx_parameter param = vxGetParameterByIndex(node, index);
+
+ if (index == 0)
+ {
+ vx_image image;
+ vx_df_image df_image = VX_DF_IMAGE_VIRT;
+ STATUS_ERROR_CHECK(vxQueryParameter(param, VX_PARAMETER_ATTRIBUTE_REF, &image, sizeof(vx_image)));
+ STATUS_ERROR_CHECK(vxQueryImage(image, VX_IMAGE_ATTRIBUTE_FORMAT, &df_image, sizeof(df_image)));
+ if (df_image != VX_DF_IMAGE_U8)
+ status = VX_ERROR_INVALID_VALUE;
+ vxReleaseImage(&image);
+ }
+
+ else if (index == 1)
+ {
+ vx_image image;
+ vx_df_image df_image = VX_DF_IMAGE_VIRT;
+ STATUS_ERROR_CHECK(vxQueryParameter(param, VX_PARAMETER_ATTRIBUTE_REF, &image, sizeof(vx_image)));
+ STATUS_ERROR_CHECK(vxQueryImage(image, VX_IMAGE_ATTRIBUTE_FORMAT, &df_image, sizeof(df_image)));
+ if (df_image != VX_DF_IMAGE_U8 && df_image != VX_DF_IMAGE_RGB)
+ status = VX_ERROR_INVALID_VALUE;
+ vxReleaseImage(&image);
+ }
+
+ vxReleaseParameter(¶m);
+ return status;
+}
+
+/************************************************************************************************************
+output parameter validator.
+*************************************************************************************************************/
+vx_status VX_CALLBACK VX_bubbles_OutputValidator(vx_node node, vx_uint32 index, vx_meta_format meta)
+{
+ vx_status status = VX_SUCCESS;
+ if (index == 1)
+ {
+ vx_parameter output_param = vxGetParameterByIndex(node, 1);
+ vx_image output; vx_uint32 width = 0, height = 0; vx_df_image format = VX_DF_IMAGE_VIRT;
+
+ STATUS_ERROR_CHECK(vxQueryParameter(output_param, VX_PARAMETER_ATTRIBUTE_REF, &output, sizeof(vx_image)));
+ STATUS_ERROR_CHECK(vxQueryImage(output, VX_IMAGE_ATTRIBUTE_FORMAT, &format, sizeof(format)));
+ STATUS_ERROR_CHECK(vxQueryImage(output, VX_IMAGE_ATTRIBUTE_WIDTH, &width, sizeof(width)));
+ STATUS_ERROR_CHECK(vxQueryImage(output, VX_IMAGE_ATTRIBUTE_HEIGHT, &height, sizeof(height)));
+
+ if (format != VX_DF_IMAGE_U8 && format != VX_DF_IMAGE_RGB)
+ status = VX_ERROR_INVALID_VALUE;
+
+ STATUS_ERROR_CHECK(vxSetMetaFormatAttribute(meta, VX_IMAGE_ATTRIBUTE_WIDTH, &width, sizeof(width)));
+ STATUS_ERROR_CHECK(vxSetMetaFormatAttribute(meta, VX_IMAGE_ATTRIBUTE_HEIGHT, &height, sizeof(height)));
+ STATUS_ERROR_CHECK(vxSetMetaFormatAttribute(meta, VX_IMAGE_ATTRIBUTE_FORMAT, &format, sizeof(format)));
+
+ vxReleaseImage(&output);
+ vxReleaseParameter(&output_param);
+ }
+ return status;
+}
+
+/************************************************************************************************************
+Execution Kernel
+*************************************************************************************************************/
+vx_status VX_CALLBACK VX_bubbles_Kernel(vx_node node, const vx_reference *parameters, vx_uint32 num)
+{
+ (void)node;
+ (void)num;
+ vx_status status = VX_SUCCESS;
+
+ vx_image image_in = (vx_image)parameters[0];
+ vx_image image_out = (vx_image)parameters[1];
+ Mat *mat, bl;
+
+ // wait to restart - press any key
+ if(poppedDonuts >= 1015){ poppedDonuts = 0; waitKey(0);}
+
+ //Converting VX Image to OpenCV Mat
+ STATUS_ERROR_CHECK(VX_to_CV_Image(&mat, image_in));
+ Mat Image = *mat, clean_img;
+ flip(Image, Image, 1);
+
+ if (globalDonutFlag == 0){
+ globalDonutRefImage = Image;
+ }
+ else{
+ clean_img = Image;
+ }
+
+ // change donut size - press "d"
+ if(waitKey(2) == 100){if (globalDonutChange == 0) globalDonutChange = 1; else globalDonutChange = 0;}
+ if(draw_pop_donuts(Image.cols, Image.rows, &Image))
+ return VX_FAILURE;
+
+ std::ostringstream statusStr;
+ if (poppedDonuts >= 1000)
+ {
+ statusStr << "Congratulations! Click any Key to Contiue Popping!";
+ cv::putText(Image, statusStr.str(), cv::Point(5, int(Image.rows/2)), FONT_HERSHEY_COMPLEX_SMALL, 1, cv::Scalar(200, 200, 250), 1, cv::LINE_AA);
+ }
+ else
+ {
+ statusStr << "Bubbles Popped: " << poppedDonuts;
+ cv::putText(Image, statusStr.str(), cv::Point(30, 30), FONT_HERSHEY_COMPLEX_SMALL, 1.2, cv::Scalar(200, 200, 250), 1, cv::LINE_AA);
+ }
+
+ //Converting OpenCV Mat into VX Image
+ STATUS_ERROR_CHECK(CV_to_VX_Image(image_out, &Image));
+
+ if (globalDonutFlag == 0) globalDonutFlag++; else{ globalDonutRefImage = clean_img; globalDonutFlag++; }
+
+ return status;
+}
+
+/************************************************************************************************************
+Function to Register the Kernel for Publish
+*************************************************************************************************************/
+vx_status VX_donut_pop_Register(vx_context context)
+{
+ vx_status status = VX_SUCCESS;
+ vx_kernel kernel = vxAddKernel(context,
+ "org.pop.donut_pop",
+ VX_KERNEL_EXT_POP_DONUT_POP,
+ VX_bubbles_Kernel,
+ 2,
+ VX_bubbles_InputValidator,
+ VX_bubbles_OutputValidator,
+ nullptr,
+ nullptr);
+
+ if (kernel)
+ {
+ PARAM_ERROR_CHECK(vxAddParameterToKernel(kernel, 0, VX_INPUT, VX_TYPE_IMAGE, VX_PARAMETER_STATE_REQUIRED));
+ PARAM_ERROR_CHECK(vxAddParameterToKernel(kernel, 1, VX_OUTPUT, VX_TYPE_IMAGE, VX_PARAMETER_STATE_REQUIRED));
+ PARAM_ERROR_CHECK(vxFinalizeKernel(kernel));
+ }
+
+ if (status != VX_SUCCESS)
+ {
+ exit: vxRemoveKernel(kernel); return VX_FAILURE;
+ }
+
+ return status;
+}
+
+/*
+* linked_list.c
+* Author: Kiriti Nagesh Gowda
+*/
+
+//Insert a variable function
+donutNode* donut_insert(donutNode* head, donutNode* x)
+{
+ donutNode* temp;
+ donutNode* temp1 = x;
+
+ if (head == NULL)
+ head = temp1;
+
+ else{
+ temp = head;
+ while (temp->next != NULL){
+ temp = temp->next;
+ }
+ temp->next = temp1;
+ }
+ return (head);
+}
+
+//Delete a node from the list
+donutNode* donut_position_delete(donutNode* head, int p)
+{
+ donutNode* temp;
+ donutNode* temp1;
+ int count = 2;
+ temp = head;
+
+ if (temp == NULL || p <= 0){
+ printf("The List is empty or the position is invalid\n");
+ return (head);
+ }
+
+ if (p == 1){
+ head = temp->next;
+ free(temp);
+ return (head);
+ }
+ while (temp != NULL){
+ if (count == (p))
+ {
+ temp1 = temp->next;
+ temp->next = temp1->next;
+ free(temp1);
+ return (head);
+ }
+ temp = temp->next;
+
+ if (temp == NULL) break;
+ ++count;
+ }
+ return head;
+}
+
+//clean node
+donutNode *donut_clean_node(donutNode * head)
+{
+
+ donutNode *temp1;
+ while (head != NULL){
+ temp1 = head->next;
+ free(head);
+ head = temp1;
+ }
+ return(head);
+}
\ No newline at end of file
diff --git a/samples/bubble-pop/source/AMD_app.cpp b/samples/bubble-pop/source/AMD_app.cpp
new file mode 100644
index 00000000..f6572114
--- /dev/null
+++ b/samples/bubble-pop/source/AMD_app.cpp
@@ -0,0 +1,288 @@
+#include
+
+#include
+#include
+
+#include "vx_ext_pop.h"
+
+using namespace cv;
+using namespace std;
+
+#define ERROR_CHECK_STATUS( status ) { \
+ vx_status status_ = (status); \
+ if(status_ != VX_SUCCESS) { \
+ printf("ERROR: failed with status = (%d) at " __FILE__ "#%d\n", status_, __LINE__); \
+ exit(1); \
+ } \
+}
+
+#define ERROR_CHECK_OBJECT( obj ) { \
+ vx_status status_ = vxGetStatus((vx_reference)(obj)); \
+ if(status_ != VX_SUCCESS) { \
+ printf("ERROR: failed with status = (%d) at " __FILE__ "#%d\n", status_, __LINE__); \
+ exit(1); \
+ } \
+}
+
+static void VX_CALLBACK log_callback(vx_context context, vx_reference ref, vx_status status, const vx_char string[])
+{
+ (void)context;
+ (void)ref;
+ (void)status;
+ size_t len = strlen(string);
+ if (len > 0) {
+ printf("%s", string);
+ if (string[len - 1] != '\n')
+ printf("\n");
+ fflush(stdout);
+ }
+}
+
+int main(int argc, char **argv)
+{
+ if (argc < 2) {
+ printf("Usage:\n"
+ "./vxPop --donut\n"
+ "./vxPop --bubble \n");
+ return 0;
+ }
+
+ int width = 720, height = 480;
+
+ // create OpenVX Context
+ vx_context context = vxCreateContext();
+ ERROR_CHECK_OBJECT(context);
+ vxRegisterLogCallback(context, log_callback, vx_false_e);
+
+ // load vx_pop kernels
+ ERROR_CHECK_STATUS(vxLoadKernels(context, "vx_pop"));
+
+ // create OpenVX Graph
+ vx_graph graph = vxCreateGraph(context);
+ ERROR_CHECK_OBJECT(graph);
+
+ // create OpenVX Images
+ vx_image input_rgb_image = vxCreateImage(context, width, height, VX_DF_IMAGE_RGB);
+ vx_image output_pop_image = vxCreateImage(context, width, height, VX_DF_IMAGE_U8);
+ ERROR_CHECK_OBJECT(input_rgb_image);
+ ERROR_CHECK_OBJECT(output_pop_image);
+
+ // create intermediate images
+ vx_image yuv_image = vxCreateVirtualImage(graph, width, height, VX_DF_IMAGE_IYUV);
+ vx_image luma_image = vxCreateVirtualImage(graph, width, height, VX_DF_IMAGE_U8);
+ vx_image output_canny_image = vxCreateVirtualImage(graph, width, height, VX_DF_IMAGE_U8);
+ vx_image output_skinTone_image = vxCreateVirtualImage(graph, width, height, VX_DF_IMAGE_U8);
+ vx_image output_canny_skinTone_image = vxCreateVirtualImage(graph, width, height, VX_DF_IMAGE_U8);
+ ERROR_CHECK_OBJECT(yuv_image);
+ ERROR_CHECK_OBJECT(luma_image);
+ ERROR_CHECK_OBJECT(output_canny_image);
+ ERROR_CHECK_OBJECT(output_skinTone_image);
+ ERROR_CHECK_OBJECT(output_canny_skinTone_image);
+
+ // create threshold variable
+ vx_threshold hyst = vxCreateThreshold(context, VX_THRESHOLD_TYPE_RANGE, VX_TYPE_UINT8);
+ vx_int32 lower = 80, upper = 100;
+ vxSetThresholdAttribute(hyst, VX_THRESHOLD_ATTRIBUTE_THRESHOLD_LOWER, &lower, sizeof(lower));
+ vxSetThresholdAttribute(hyst, VX_THRESHOLD_ATTRIBUTE_THRESHOLD_UPPER, &upper, sizeof(upper));
+ ERROR_CHECK_OBJECT(hyst);
+ vx_int32 gradient_size = 3;
+
+ // create intermediate images which are not accessed by the user to be mem optimized
+ vx_image R_image = vxCreateVirtualImage(graph, width, height, VX_DF_IMAGE_U8);
+ vx_image G_image = vxCreateVirtualImage(graph, width, height, VX_DF_IMAGE_U8);
+ vx_image B_image = vxCreateVirtualImage(graph, width, height, VX_DF_IMAGE_U8);
+ vx_image RmG_image = vxCreateVirtualImage(graph, width, height, VX_DF_IMAGE_U8);
+ vx_image RmB_image = vxCreateVirtualImage(graph, width, height, VX_DF_IMAGE_U8);
+ vx_image R95_image = vxCreateVirtualImage(graph, width, height, VX_DF_IMAGE_U8);
+ vx_image G40_image = vxCreateVirtualImage(graph, width, height, VX_DF_IMAGE_U8);
+ vx_image B20_image = vxCreateVirtualImage(graph, width, height, VX_DF_IMAGE_U8);
+ vx_image RmG15_image = vxCreateVirtualImage(graph, width, height, VX_DF_IMAGE_U8);
+ vx_image RmB0_image = vxCreateVirtualImage(graph, width, height, VX_DF_IMAGE_U8);
+ vx_image and1_image = vxCreateVirtualImage(graph, width, height, VX_DF_IMAGE_U8);
+ vx_image and2_image = vxCreateVirtualImage(graph, width, height, VX_DF_IMAGE_U8);
+ vx_image and3_image = vxCreateVirtualImage(graph, width, height, VX_DF_IMAGE_U8);
+ ERROR_CHECK_OBJECT(R_image);
+ ERROR_CHECK_OBJECT(G_image);
+ ERROR_CHECK_OBJECT(B_image);
+ ERROR_CHECK_OBJECT(RmG_image);
+ ERROR_CHECK_OBJECT(RmB_image);
+ ERROR_CHECK_OBJECT(R95_image);
+ ERROR_CHECK_OBJECT(G40_image);
+ ERROR_CHECK_OBJECT(B20_image);
+ ERROR_CHECK_OBJECT(RmG15_image);
+ ERROR_CHECK_OBJECT(RmB0_image);
+ ERROR_CHECK_OBJECT(and1_image);
+ ERROR_CHECK_OBJECT(and2_image);
+ ERROR_CHECK_OBJECT(and3_image);
+
+ // create threshold values
+ vx_threshold thresh95 = vxCreateThreshold(context, VX_THRESHOLD_TYPE_BINARY, VX_TYPE_UINT8);
+ vx_int32 thresValue95 = 95;
+ vxSetThresholdAttribute(thresh95, VX_THRESHOLD_THRESHOLD_VALUE, &thresValue95, sizeof(vx_int32));
+ ERROR_CHECK_OBJECT(thresh95);
+ vx_threshold thresh40 = vxCreateThreshold(context, VX_THRESHOLD_TYPE_BINARY, VX_TYPE_UINT8);
+ vx_int32 thresValue40 = 40;
+ vxSetThresholdAttribute(thresh40, VX_THRESHOLD_THRESHOLD_VALUE, &thresValue40, sizeof(vx_int32));
+ ERROR_CHECK_OBJECT(thresh40);
+ vx_threshold thresh20 = vxCreateThreshold(context, VX_THRESHOLD_TYPE_BINARY, VX_TYPE_UINT8);
+ vx_int32 thresValue20 = 20;
+ vxSetThresholdAttribute(thresh20, VX_THRESHOLD_THRESHOLD_VALUE, &thresValue20, sizeof(vx_int32));
+ ERROR_CHECK_OBJECT(thresh20);
+ vx_threshold thresh15 = vxCreateThreshold(context, VX_THRESHOLD_TYPE_BINARY, VX_TYPE_UINT8);
+ vx_int32 thresValue15 = 15;
+ vxSetThresholdAttribute(thresh15, VX_THRESHOLD_THRESHOLD_VALUE, &thresValue15, sizeof(vx_int32));
+ ERROR_CHECK_OBJECT(thresh15);
+ vx_threshold thresh0 = vxCreateThreshold(context, VX_THRESHOLD_TYPE_BINARY, VX_TYPE_UINT8);
+ vx_int32 thresValue0 = 0;
+ vxSetThresholdAttribute(thresh0, VX_THRESHOLD_THRESHOLD_VALUE, &thresValue0, sizeof(vx_int32));
+ ERROR_CHECK_OBJECT(thresh0);
+
+ // add nodes to the graph
+ string option = argv[1];
+ if (option == "--bubble")
+ {
+ vx_node nodes[] =
+ {
+ // extract R,G,B channels and compute R-G and R-B
+ vxChannelExtractNode(graph, input_rgb_image, VX_CHANNEL_R, R_image),
+ vxChannelExtractNode(graph, input_rgb_image, VX_CHANNEL_G, G_image),
+ vxChannelExtractNode(graph, input_rgb_image, VX_CHANNEL_B, B_image),
+ vxSubtractNode(graph, R_image, G_image, VX_CONVERT_POLICY_SATURATE, RmG_image),
+ vxSubtractNode(graph, R_image, B_image, VX_CONVERT_POLICY_SATURATE, RmB_image),
+ // compute threshold
+ vxThresholdNode(graph, R_image, thresh95, R95_image),
+ vxThresholdNode(graph, G_image, thresh40, G40_image),
+ vxThresholdNode(graph, B_image, thresh20, B20_image),
+ vxThresholdNode(graph, RmG_image, thresh15, RmG15_image),
+ vxThresholdNode(graph, RmB_image, thresh0, RmB0_image),
+ // aggregate all thresholded values to produce SKIN pixels
+ vxAndNode(graph, R95_image, G40_image, and1_image),
+ vxAndNode(graph, and1_image, B20_image, and2_image),
+ vxAndNode(graph, RmG15_image, RmB0_image, and3_image),
+ vxAndNode(graph, and2_image, and3_image, output_skinTone_image),
+ // create canny edge
+ vxColorConvertNode(graph, input_rgb_image, yuv_image),
+ vxChannelExtractNode(graph, yuv_image, VX_CHANNEL_Y, luma_image),
+ vxCannyEdgeDetectorNode(graph, luma_image, hyst, gradient_size, VX_NORM_L1, output_canny_image),
+ // or - canny & skintone images
+ vxOrNode(graph, output_canny_image, output_skinTone_image, output_canny_skinTone_image),
+ // vx pop - bubble pop
+ vxExtPopNode_bubblePop(graph, output_canny_skinTone_image, output_pop_image)
+ };
+ for( vx_size i = 0; i < sizeof( nodes ) / sizeof( nodes[0] ); i++ )
+ {
+ ERROR_CHECK_OBJECT( nodes[i] );
+ ERROR_CHECK_STATUS( vxReleaseNode( &nodes[i] ) );
+ }
+ }
+ else
+ {
+ vx_node nodes[] =
+ {
+ // extract R,G,B channels and compute R-G and R-B
+ vxChannelExtractNode(graph, input_rgb_image, VX_CHANNEL_R, R_image),
+ vxChannelExtractNode(graph, input_rgb_image, VX_CHANNEL_G, G_image),
+ vxChannelExtractNode(graph, input_rgb_image, VX_CHANNEL_B, B_image),
+ vxSubtractNode(graph, R_image, G_image, VX_CONVERT_POLICY_SATURATE, RmG_image),
+ vxSubtractNode(graph, R_image, B_image, VX_CONVERT_POLICY_SATURATE, RmB_image),
+ // compute threshold
+ vxThresholdNode(graph, R_image, thresh95, R95_image),
+ vxThresholdNode(graph, G_image, thresh40, G40_image),
+ vxThresholdNode(graph, B_image, thresh20, B20_image),
+ vxThresholdNode(graph, RmG_image, thresh15, RmG15_image),
+ vxThresholdNode(graph, RmB_image, thresh0, RmB0_image),
+ // aggregate all thresholded values to produce SKIN pixels
+ vxAndNode(graph, R95_image, G40_image, and1_image),
+ vxAndNode(graph, and1_image, B20_image, and2_image),
+ vxAndNode(graph, RmG15_image, RmB0_image, and3_image),
+ vxAndNode(graph, and2_image, and3_image, output_skinTone_image),
+ // create canny edge
+ vxColorConvertNode(graph, input_rgb_image, yuv_image),
+ vxChannelExtractNode(graph, yuv_image, VX_CHANNEL_Y, luma_image),
+ vxCannyEdgeDetectorNode(graph, luma_image, hyst, gradient_size, VX_NORM_L1, output_canny_image),
+ // or - canny & skintone images
+ vxOrNode(graph, output_canny_image, output_skinTone_image, output_canny_skinTone_image),
+ // vx pop - donut pop
+ vxExtPopNode_donutPop(graph, output_canny_skinTone_image, output_pop_image)
+ };
+ for( vx_size i = 0; i < sizeof( nodes ) / sizeof( nodes[0] ); i++ )
+ {
+ ERROR_CHECK_OBJECT( nodes[i] );
+ ERROR_CHECK_STATUS( vxReleaseNode( &nodes[i] ) );
+ }
+ }
+
+ // verify graph - only once
+ ERROR_CHECK_STATUS( vxVerifyGraph( graph ) );
+
+ Mat input, input_rgb;
+ cv::namedWindow("VX POP - LIVE", cv::WINDOW_GUI_EXPANDED);
+ VideoCapture cap(0);
+ if (!cap.isOpened()) {
+ printf("Unable to open camera\n");
+ return 0;
+ }
+ for(;;)
+ {
+ cap >> input;
+ resize(input, input, Size(width, height));
+ cvtColor(input, input_rgb, COLOR_BGR2RGB);
+ if(waitKey(30) >= 0) break;
+ vx_rectangle_t cv_rgb_image_region;
+ cv_rgb_image_region.start_x = 0;
+ cv_rgb_image_region.start_y = 0;
+ cv_rgb_image_region.end_x = width;
+ cv_rgb_image_region.end_y = height;
+ vx_imagepatch_addressing_t cv_rgb_image_layout{};
+ cv_rgb_image_layout.dim_x = input_rgb.cols;
+ cv_rgb_image_layout.dim_y = input_rgb.rows;
+ cv_rgb_image_layout.stride_x = input_rgb.elemSize();
+ cv_rgb_image_layout.stride_y = input_rgb.step;
+ vx_uint8 * cv_rgb_image_buffer = input_rgb.data;
+ ERROR_CHECK_STATUS( vxCopyImagePatch( input_rgb_image, &cv_rgb_image_region, 0,
+ &cv_rgb_image_layout, cv_rgb_image_buffer,
+ VX_WRITE_ONLY, VX_MEMORY_TYPE_HOST ) );
+ ERROR_CHECK_STATUS( vxProcessGraph( graph ) );
+ vx_rectangle_t rect = { 0, 0, (vx_uint32)width, (vx_uint32)height };
+ vx_map_id map_id;
+ vx_imagepatch_addressing_t addr;
+ void * ptr;
+ ERROR_CHECK_STATUS( vxMapImagePatch( output_pop_image, &rect, 0, &map_id, &addr, &ptr,
+ VX_READ_ONLY, VX_MEMORY_TYPE_HOST, VX_NOGAP_X ) );
+ Mat mat( height, width, CV_8U, ptr, addr.stride_y );
+ imshow( "VX POP - LIVE", mat );
+ if(waitKey(30) >= 0) break;
+ ERROR_CHECK_STATUS( vxUnmapImagePatch( output_pop_image, map_id ) );
+ }
+
+ // release objects
+ ERROR_CHECK_STATUS(vxReleaseGraph( &graph ) );
+ ERROR_CHECK_STATUS(vxReleaseThreshold( &hyst ));
+ ERROR_CHECK_STATUS(vxReleaseThreshold( &thresh95 ));
+ ERROR_CHECK_STATUS(vxReleaseThreshold( &thresh40 ));
+ ERROR_CHECK_STATUS(vxReleaseThreshold( &thresh20 ));
+ ERROR_CHECK_STATUS(vxReleaseThreshold( &thresh15 ));
+ ERROR_CHECK_STATUS(vxReleaseThreshold( &thresh0 ));
+ ERROR_CHECK_STATUS(vxReleaseImage( &yuv_image ) );
+ ERROR_CHECK_STATUS(vxReleaseImage( &luma_image ) );
+ ERROR_CHECK_STATUS(vxReleaseImage( &output_canny_image ) );
+ ERROR_CHECK_STATUS(vxReleaseImage( &input_rgb_image ) );
+ ERROR_CHECK_STATUS(vxReleaseImage( &R_image ));
+ ERROR_CHECK_STATUS(vxReleaseImage( &G_image ));
+ ERROR_CHECK_STATUS(vxReleaseImage( &B_image ));
+ ERROR_CHECK_STATUS(vxReleaseImage( &RmG_image ));
+ ERROR_CHECK_STATUS(vxReleaseImage( &RmB_image ));
+ ERROR_CHECK_STATUS(vxReleaseImage( &R95_image ));
+ ERROR_CHECK_STATUS(vxReleaseImage( &G40_image ));
+ ERROR_CHECK_STATUS(vxReleaseImage( &B20_image ));
+ ERROR_CHECK_STATUS(vxReleaseImage( &RmG15_image ));
+ ERROR_CHECK_STATUS(vxReleaseImage( &RmB0_image ));
+ ERROR_CHECK_STATUS(vxReleaseImage( &and1_image ));
+ ERROR_CHECK_STATUS(vxReleaseImage( &and2_image ));
+ ERROR_CHECK_STATUS(vxReleaseImage( &and3_image ));
+ ERROR_CHECK_STATUS(vxReleaseImage( &output_skinTone_image ));
+ ERROR_CHECK_STATUS(vxReleaseImage( &output_canny_skinTone_image ));
+ ERROR_CHECK_STATUS(vxReleaseImage( &output_pop_image ) );
+ ERROR_CHECK_STATUS(vxReleaseContext( &context ) );
+ return 0;
+}
diff --git a/samples/bubble-pop/source/internal_dataTranslator.cpp b/samples/bubble-pop/source/internal_dataTranslator.cpp
new file mode 100644
index 00000000..3f228515
--- /dev/null
+++ b/samples/bubble-pop/source/internal_dataTranslator.cpp
@@ -0,0 +1,299 @@
+/*
+Copyright (c) 2020 Advanced Micro Devices, Inc. All rights reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+
+#include"internal_opencvTunnel.h"
+
+/************************************************************************************************************
+Converting CV Pyramid into an OpenVX Pyramid
+*************************************************************************************************************/
+int CV_to_VX_Pyramid(vx_pyramid pyramid_vx, vector pyramid_cv)
+{
+ // vx_status status = VX_SUCCESS;
+ vx_size Level_vx = 0; vx_uint32 width = 0; vx_uint32 height = 0; vx_int32 i;
+
+ STATUS_ERROR_CHECK(vxQueryPyramid(pyramid_vx, VX_PYRAMID_ATTRIBUTE_LEVELS, &Level_vx, sizeof(Level_vx)));
+ for (i = 0; i < (int)Level_vx; i++)
+ {
+ vx_image this_level = vxGetPyramidLevel(pyramid_vx, i);
+ STATUS_ERROR_CHECK(vxQueryImage(this_level, VX_IMAGE_ATTRIBUTE_WIDTH, &width, sizeof(width)));
+ STATUS_ERROR_CHECK(vxQueryImage(this_level, VX_IMAGE_ATTRIBUTE_HEIGHT, &height, sizeof(height)));
+ if (width != (vx_uint32)pyramid_cv[i].cols && height != (vx_uint32)pyramid_cv[i].rows)
+ {
+ vxAddLogEntry((vx_reference)pyramid_vx, VX_ERROR_INVALID_DIMENSION, "CV_to_VX_Pyramid ERROR: Pyramid Image Mismatch\n"); return VX_ERROR_INVALID_DIMENSION;
+ }
+ Mat* pyr_level;
+ pyr_level = &pyramid_cv[i];
+ CV_to_VX_Image(this_level, pyr_level);
+ }
+ return 0;
+}
+
+/************************************************************************************************************
+Converting VX matrix into an OpenCV Mat
+*************************************************************************************************************/
+int VX_to_CV_MATRIX(Mat** mat, vx_matrix matrix_vx)
+{
+ vx_status status = VX_SUCCESS;
+ vx_size numRows = 0; vx_size numCols = 0; vx_enum type; int Type_CV = 0;
+
+ STATUS_ERROR_CHECK(vxQueryMatrix(matrix_vx, VX_MATRIX_ATTRIBUTE_ROWS, &numRows, sizeof(numRows)));
+ STATUS_ERROR_CHECK(vxQueryMatrix(matrix_vx, VX_MATRIX_ATTRIBUTE_COLUMNS, &numCols, sizeof(numCols)));
+ STATUS_ERROR_CHECK(vxQueryMatrix(matrix_vx, VX_MATRIX_ATTRIBUTE_TYPE, &type, sizeof(type)));
+
+ if (type == VX_TYPE_INT32)Type_CV = CV_32S;
+ if (type == VX_TYPE_FLOAT32)Type_CV = CV_32F;
+
+ if (type != VX_TYPE_FLOAT32 && type != VX_TYPE_INT32)
+ {
+ vxAddLogEntry((vx_reference)matrix_vx, VX_ERROR_INVALID_FORMAT, "VX_to_CV_MATRIX ERROR: Matrix type not Supported in this RELEASE\n"); return VX_ERROR_INVALID_FORMAT;
+ }
+
+ Mat * m_cv; m_cv = new Mat((int)numRows, (int)numCols, Type_CV); vx_size mat_size = numRows * numCols;
+ float *dyn_matrix = new float[mat_size]; int z = 0;
+
+ STATUS_ERROR_CHECK(vxReadMatrix(matrix_vx, (void *)dyn_matrix));
+ for (int i = 0; i < (int)numRows; i++)
+ for (int j = 0; j < (int)numCols; j++)
+ {
+ m_cv->at(i, j) = dyn_matrix[z]; z++;
+ }
+
+ *mat = m_cv;
+ return status;
+}
+
+/************************************************************************************************************
+Converting VX Image into an OpenCV Mat
+*************************************************************************************************************/
+int VX_to_CV_Image(Mat** mat, vx_image image)
+{
+ vx_status status = VX_SUCCESS;
+ vx_uint32 width = 0; vx_uint32 height = 0; vx_df_image format = VX_DF_IMAGE_VIRT; int CV_format = 0; vx_size planes = 0;
+
+ STATUS_ERROR_CHECK(vxQueryImage(image, VX_IMAGE_ATTRIBUTE_WIDTH, &width, sizeof(width)));
+ STATUS_ERROR_CHECK(vxQueryImage(image, VX_IMAGE_ATTRIBUTE_HEIGHT, &height, sizeof(height)));
+ STATUS_ERROR_CHECK(vxQueryImage(image, VX_IMAGE_ATTRIBUTE_FORMAT, &format, sizeof(format)));
+ STATUS_ERROR_CHECK(vxQueryImage(image, VX_IMAGE_ATTRIBUTE_PLANES, &planes, sizeof(planes)));
+
+ if (format == VX_DF_IMAGE_U8)CV_format = CV_8U;
+ if (format == VX_DF_IMAGE_S16)CV_format = CV_16S;
+ if (format == VX_DF_IMAGE_RGB)CV_format = CV_8UC3;
+
+ if (format != VX_DF_IMAGE_U8 && format != VX_DF_IMAGE_S16 && format != VX_DF_IMAGE_RGB)
+ {
+ vxAddLogEntry((vx_reference)image, VX_ERROR_INVALID_FORMAT, "VX_to_CV_Image ERROR: Image type not Supported in this RELEASE\n"); return VX_ERROR_INVALID_FORMAT;
+ }
+
+ Mat * m_cv; m_cv = new Mat(height, width, CV_format); Mat *pMat = (Mat *)m_cv;
+ vx_rectangle_t rect; rect.start_x = 0; rect.start_y = 0; rect.end_x = width; rect.end_y = height;
+
+ vx_uint8 *src[4] = { NULL, NULL, NULL, NULL }; vx_uint32 p; void *ptr = NULL;
+ vx_imagepatch_addressing_t addr[4] = {}; vx_uint32 y = 0u;
+
+ for (p = 0u; (p < planes); p++)
+ {
+ STATUS_ERROR_CHECK(vxAccessImagePatch(image, &rect, p, &addr[p], (void **)&src[p], VX_READ_ONLY));
+ size_t len = addr[p].stride_x * (addr[p].dim_x * addr[p].scale_x) / VX_SCALE_UNITY;
+ for (y = 0; y < height; y += addr[p].step_y)
+ {
+ ptr = vxFormatImagePatchAddress2d(src[p], 0, y - rect.start_y, &addr[p]);
+ memcpy(pMat->data + y * pMat->step, ptr, len);
+ }
+ }
+
+ for (p = 0u; p < planes; p++)
+ STATUS_ERROR_CHECK(vxCommitImagePatch(image, &rect, p, &addr[p], src[p]));
+
+ *mat = pMat;
+
+ return status;
+}
+
+/************************************************************************************************************
+Converting CV Image into an OpenVX Image
+*************************************************************************************************************/
+int CV_to_VX_Image(vx_image image, Mat* mat)
+{
+ vx_status status = VX_SUCCESS; vx_uint32 width = 0; vx_uint32 height = 0; vx_size planes = 0;
+
+ STATUS_ERROR_CHECK(vxQueryImage(image, VX_IMAGE_ATTRIBUTE_WIDTH, &width, sizeof(width)));
+ STATUS_ERROR_CHECK(vxQueryImage(image, VX_IMAGE_ATTRIBUTE_HEIGHT, &height, sizeof(height)));
+ STATUS_ERROR_CHECK(vxQueryImage(image, VX_IMAGE_ATTRIBUTE_PLANES, &planes, sizeof(planes)));
+
+ Mat *pMat = mat; vx_rectangle_t rect; rect.start_x = 0; rect.start_y = 0; rect.end_x = width; rect.end_y = height;
+
+ vx_uint8 *src[4] = { NULL, NULL, NULL, NULL }; vx_uint32 p; void *ptr = NULL;
+ vx_imagepatch_addressing_t addr[4] = {}; vx_uint32 y = 0u;
+
+ for (p = 0u; (p < planes); p++)
+ {
+ STATUS_ERROR_CHECK(vxAccessImagePatch(image, &rect, p, &addr[p], (void **)&src[p], VX_READ_ONLY));
+ size_t len = addr[p].stride_x * (addr[p].dim_x * addr[p].scale_x) / VX_SCALE_UNITY;
+ for (y = 0; y < height; y += addr[p].step_y)
+ {
+ ptr = vxFormatImagePatchAddress2d(src[p], 0, y - rect.start_y, &addr[p]);
+ memcpy(ptr, pMat->data + y * pMat->step, len);
+ }
+ }
+
+ for (p = 0u; p < planes; p++)
+ STATUS_ERROR_CHECK(vxCommitImagePatch(image, &rect, p, &addr[p], src[p]));
+
+ return status;
+}
+
+/************************************************************************************************************
+sort function.
+*************************************************************************************************************/
+bool sortbysize_CV(const KeyPoint &lhs, const KeyPoint &rhs)
+{
+ return lhs.size < rhs.size;
+}
+
+/************************************************************************************************************
+OpenCV Keypoints to OpenVX Keypoints
+*************************************************************************************************************/
+int CV_to_VX_keypoints(vector key_points, vx_array array)
+{
+
+ vx_status status = VX_SUCCESS;
+ vector Keypoint_VX;
+
+ float X, Y, K_Size, K_Angle, K_Response; int x, y, j = 0;
+ // void *ptr = NULL;
+ vx_size size = 0;
+
+ STATUS_ERROR_CHECK(vxQueryArray(array, VX_ARRAY_ATTRIBUTE_CAPACITY, &size, sizeof(size)));
+
+ size_t S = key_points.size(); Keypoint_VX.resize(S);
+ sort(key_points.begin(), key_points.end(), sortbysize_CV);
+ // vx_size stride = 0; void *base = NULL; vx_size L = 0;
+
+ for (vector::const_iterator i = key_points.begin(); i != key_points.end(); ++i)
+ {
+ X = key_points[j].pt.x; Y = key_points[j].pt.y;
+ K_Size = key_points[j].size; K_Angle = key_points[j].angle; K_Response = key_points[j].response;
+
+ if (fmod(X, 1) >= 0.5)x = (int)ceil(X); else x = (int)floor(X);
+ if (fmod(Y, 1) >= 0.5)y = (int)ceil(Y); else y = (int)floor(Y);
+
+ Keypoint_VX[j].x = x; Keypoint_VX[j].y = y;
+ Keypoint_VX[j].strength = K_Size; Keypoint_VX[j].orientation = K_Angle; Keypoint_VX[j].scale = K_Response;
+ Keypoint_VX[j].tracking_status = 1; Keypoint_VX[j].error = 0;
+ j++;
+ }
+
+ vx_keypoint_t * keypoint_ptr = &Keypoint_VX[0]; size = min(size, S);
+
+ status = vxTruncateArray(array, 0);
+ if (status){ vxAddLogEntry((vx_reference)array, status, "CV_to_VX_keypoints ERROR: vxTruncateArray failed\n"); return status; }
+
+ status = vxAddArrayItems(array, size, keypoint_ptr, sizeof(vx_keypoint_t));
+ if (status){ vxAddLogEntry((vx_reference)array, status, "CV_to_VX_keypoints ERROR: vxAddArrayItems failed\n"); return status; }
+
+ return status;
+}
+
+/************************************************************************************************************
+OpenCV Points to OpenVX Keypoints
+*************************************************************************************************************/
+int CVPoints2f_to_VX_keypoints(vector key_points, vx_array array)
+{
+ vx_status status = VX_SUCCESS;
+ vector Keypoint_VX; float X, Y; int x, y, j = 0;
+ // void *ptr = NULL;
+ vx_size size = 0;
+
+ STATUS_ERROR_CHECK(vxQueryArray(array, VX_ARRAY_ATTRIBUTE_CAPACITY, &size, sizeof(size)));
+
+ size_t S = key_points.size(); Keypoint_VX.resize(S);
+
+ for (int i = 0; i < (int)key_points.size(); ++i)
+ {
+ X = key_points[j].x; Y = key_points[j].y;
+
+ if (fmod(X, 1) >= 0.5)x = (int)ceil(X); else x = (int)floor(X);
+ if (fmod(Y, 1) >= 0.5)y = (int)ceil(Y); else y = (int)floor(Y);
+
+ Keypoint_VX[j].x = x; Keypoint_VX[j].y = y;
+ Keypoint_VX[j].strength = 0; Keypoint_VX[j].orientation = 0; Keypoint_VX[j].scale = 0;
+ Keypoint_VX[j].tracking_status = 0; Keypoint_VX[j].error = 0;
+
+ j++;
+ }
+
+ vx_keypoint_t * keypoint_ptr = &Keypoint_VX[0]; size = min(size, S);
+
+ status = vxTruncateArray(array, 0);
+ if (status){ vxAddLogEntry((vx_reference)array, status, "CVPoints2f_to_VX_keypoints ERROR: vxTruncateArray failed\n"); return status; }
+
+ status = vxAddArrayItems(array, size, keypoint_ptr, sizeof(vx_keypoint_t));
+ if (status){ vxAddLogEntry((vx_reference)array, status, "CVPoints2f_to_VX_keypoints ERROR: vxAddArrayItems failed\n"); return status; }
+
+ return status;
+
+}
+
+/************************************************************************************************************
+OpenCV Descriptors to OpenVX Descriptors
+*************************************************************************************************************/
+int CV_DESP_to_VX_DESP(Mat mat, vx_array array, int stride)
+{
+ vx_status status = VX_SUCCESS; vx_size size = 0;
+
+ STATUS_ERROR_CHECK(vxQueryArray(array, VX_ARRAY_ATTRIBUTE_CAPACITY, &size, sizeof(size)));
+
+ uchar *p = mat.data;
+
+ status = vxTruncateArray(array, 0);
+ if (status){ vxAddLogEntry((vx_reference)array, status, "CV_DESP_to_VX_DESP ERROR: vxTruncateArray failed\n"); return status; }
+
+ status = vxAddArrayItems(array, size, p, stride);
+ if (status){ vxAddLogEntry((vx_reference)array, status, "CV_DESP_to_VX_DESP ERROR: vxAddArrayItems failed\n"); return status; }
+
+ return status;
+}
+
+/************************************************************************************************************
+Match VX in and out image size
+*************************************************************************************************************/
+int match_vx_image_parameters(vx_image image1, vx_image image2)
+{
+ vx_status status = VX_SUCCESS;
+ vx_uint32 W1 = 0; vx_uint32 H1 = 0;
+ STATUS_ERROR_CHECK(vxQueryImage(image1, VX_IMAGE_ATTRIBUTE_WIDTH, &W1, sizeof(W1)));
+ STATUS_ERROR_CHECK(vxQueryImage(image1, VX_IMAGE_ATTRIBUTE_HEIGHT, &H1, sizeof(H1)));
+
+ vx_uint32 W2 = 0; vx_uint32 H2 = 0;
+ STATUS_ERROR_CHECK(vxQueryImage(image2, VX_IMAGE_ATTRIBUTE_WIDTH, &W2, sizeof(W2)));
+ STATUS_ERROR_CHECK(vxQueryImage(image2, VX_IMAGE_ATTRIBUTE_HEIGHT, &H2, sizeof(H2)));
+
+ //Input and Output image size match check
+ if (W1 != W2 || H1 != H2)
+ {
+ status = VX_ERROR_INVALID_DIMENSION;
+ vxAddLogEntry((vx_reference)image1, status, "match_vx_image_parameters ERROR: Image1 Height or Width Not Equal to Image2\n");
+ return status;
+ }
+
+ return status;
+}
diff --git a/samples/bubble-pop/source/internal_publishKernels.cpp b/samples/bubble-pop/source/internal_publishKernels.cpp
new file mode 100644
index 00000000..ccf74b0a
--- /dev/null
+++ b/samples/bubble-pop/source/internal_publishKernels.cpp
@@ -0,0 +1,63 @@
+/*
+Copyright (c) 2020 Advanced Micro Devices, Inc. All rights reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+
+#include "internal_publishKernels.h"
+
+#include "vx_ext_pop.h"
+
+/**********************************************************************
+ PUBLIC FUNCTION for VX POP user defined functions
+ **********************************************************************/
+extern "C" SHARED_PUBLIC vx_status VX_API_CALL vxPublishKernels(vx_context context)
+{
+ vx_status status = VX_SUCCESS;
+ printf("vxPublishKernels\n");
+
+ STATUS_ERROR_CHECK(get_kernels_to_publish());
+ STATUS_ERROR_CHECK(Kernel_List->PUBLISH(context));
+
+ return status;
+}
+
+/************************************************************************************************************
+Add All Kernels to the Kernel List
+*************************************************************************************************************/
+vx_status get_kernels_to_publish()
+{
+ vx_status status = VX_SUCCESS;
+
+ Kernel_List = new Kernellist(MAX_KERNELS);
+
+ STATUS_ERROR_CHECK(ADD_KERENEL(VX_bubbles_pop_Register));
+ STATUS_ERROR_CHECK(ADD_KERENEL(VX_donut_pop_Register));
+ return status;
+}
+
+/************************************************************************************************************
+Add Kernels to the Kernel List
+*************************************************************************************************************/
+vx_status ADD_KERENEL(std::function func)
+{
+ vx_status status = VX_SUCCESS;
+ STATUS_ERROR_CHECK(Kernel_List->ADD(func));
+ return status;
+}
\ No newline at end of file
diff --git a/samples/bubble-pop/source/internal_vxNodes.cpp b/samples/bubble-pop/source/internal_vxNodes.cpp
new file mode 100644
index 00000000..b562030b
--- /dev/null
+++ b/samples/bubble-pop/source/internal_vxNodes.cpp
@@ -0,0 +1,105 @@
+/*
+Copyright (c) 2020 Advanced Micro Devices, Inc. All rights reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+
+#include "internal_publishKernels.h"
+#include "vx_ext_pop.h"
+
+vx_node vxCreateNodeByStructure(vx_graph graph,
+ vx_enum kernelenum,
+ vx_reference params[],
+ vx_uint32 num)
+{
+ vx_status status = VX_SUCCESS;
+ vx_node node = 0;
+ vx_context context = vxGetContext((vx_reference)graph);
+ vx_kernel kernel = vxGetKernelByEnum(context, kernelenum);
+ if (kernel)
+ {
+ node = vxCreateGenericNode(graph, kernel);
+ if (node)
+ {
+ vx_uint32 p = 0;
+ for (p = 0; p < num; p++)
+ {
+ if (params[p])
+ {
+ status = vxSetParameterByIndex(node,
+ p,
+ params[p]);
+ if (status != VX_SUCCESS)
+ {
+ vxAddLogEntry((vx_reference)graph, status, "Kernel %d Parameter %u is invalid.\n", kernelenum, p);
+ vxReleaseNode(&node);
+ node = 0;
+ break;
+ }
+ }
+ }
+ }
+ else
+ {
+ vxAddLogEntry((vx_reference)graph, VX_ERROR_INVALID_PARAMETERS, "Failed to create node with kernel enum %d\n", kernelenum);
+ status = VX_ERROR_NO_MEMORY;
+ }
+ vxReleaseKernel(&kernel);
+ }
+ else
+ {
+ vxAddLogEntry((vx_reference)graph, VX_ERROR_INVALID_PARAMETERS, "failed to retrieve kernel enum %d\n", kernelenum);
+ status = VX_ERROR_NOT_SUPPORTED;
+ }
+ return node;
+}
+
+/*******************************************************************************************************************
+Bubble Pop C Function
+*******************************************************************************************************************/
+extern "C" SHARED_PUBLIC vx_node VX_API_CALL vxExtPopNode_bubblePop(vx_graph graph, vx_image input, vx_image output)
+{
+
+ vx_reference params[] = {
+ (vx_reference)input,
+ (vx_reference)output,
+ };
+
+ return vxCreateNodeByStructure(graph,
+ VX_KERNEL_EXT_POP_BUBBLE_POP,
+ params,
+ dimof(params));
+}
+
+/*******************************************************************************************************************
+Donut Pop C Function
+*******************************************************************************************************************/
+extern "C" SHARED_PUBLIC vx_node VX_API_CALL vxExtPopNode_donutPop(vx_graph graph, vx_image input, vx_image output)
+{
+
+ vx_reference params[] = {
+ (vx_reference)input,
+ (vx_reference)output,
+ };
+
+ return vxCreateNodeByStructure(graph,
+ VX_KERNEL_EXT_POP_DONUT_POP,
+ params,
+ dimof(params));
+}
\ No newline at end of file
diff --git a/samples/canny-edge-detector/BUILD b/samples/canny-edge-detector/BUILD
new file mode 100644
index 00000000..73434a1a
--- /dev/null
+++ b/samples/canny-edge-detector/BUILD
@@ -0,0 +1,21 @@
+
+cc_binary(
+ name = "canny-edge-detector",
+ srcs = [
+ "src/canny.cpp",
+ ],
+ deps = [
+ "//:corevx",
+ "@opencv",
+ "//targets/ai_server:imported_openvx_ai_server",
+ "//targets/c_model:imported_openvx_c_model",
+ "//targets/debug:imported_openvx_debug",
+ "//targets/extras:imported_openvx_extras",
+ "//targets/liteRT:imported_openvx_liteRT",
+ "//targets/opencl:imported_openvx_opencl",
+ "//targets/onnxRT:imported_openvx_onnxRT",
+ "//targets/executorch:imported_openvx_torch",
+ "//third_party:opencv-prebuilt",
+ ],
+ visibility = ["//visibility:public"],
+)
\ No newline at end of file
diff --git a/samples/canny-edge-detector/README.md b/samples/canny-edge-detector/README.md
new file mode 100644
index 00000000..44e61d55
--- /dev/null
+++ b/samples/canny-edge-detector/README.md
@@ -0,0 +1,64 @@
+## Canny Edge Detector Sample
+In this sample we will create an OpenVX graph to run canny edge detection on an image or a live camera. This sample application uses OpenCV to decode input image and display the output.
+
+ 
+
+### Prerequisites
+
+* [Conformant OpenVX Implementation](https://github.com/KhronosGroup/Khronosdotorg/blob/master/api/openvx/resources.md)
+
+* [OpenCV](https://github.com/opencv/opencv/releases/tag/3.4.0)
+
+### Steps to run the canny sample
+
+* **Step - 1:** Build and install [Conformant OpenVX Implementation](https://github.com/KhronosGroup/OpenVX-sample-impl). In this example we will use the OpenVX Sample Implementation available on [GitHub](https://github.com/KhronosGroup/OpenVX-sample-impl)
+
+```
+Build OpenVX on Linux
+
+* Git Clone project with a recursive flag to get submodules
+
+ git clone --recursive https://github.com/KhronosGroup/OpenVX-sample-impl.git
+
+* Use Build.py script
+
+ cd OpenVX-sample-impl/
+ python Build.py --os=Linux --arch=64 --conf=Debug --conf_vision --enh_vision --conf_nn
+```
+
+* **Step - 2:** Export OpenVX Directory Path
+
+```
+export OPENVX_DIR=$(pwd)/install/Linux/x64/Debug
+```
+
+* **Step - 3:** Clone the OpenVX Samples project and build the canny application
+
+```
+cd ~/ && mkdir OpenVXSample-canny
+cd OpenVXSample-canny/
+git clone https://github.com/kiritigowda/openvx-samples.git
+```
+
+* **Step - 4:** CMake and Build the canny application
+
+```
+mkdir canny-build && cd canny-build
+cmake -DOPENVX_INCLUDES=$OPENVX_DIR/include -DOPENVX_LIBRARIES=$OPENVX_DIR/bin/libopenvx.so ../openvx-samples/canny-edge-detector/
+make
+```
+
+* **Step - 5:** Run Canny application
+
+ * **Live**
+
+ ```
+ ./cannyEdgeDetector --live
+ ```
+
+ * **Image**
+
+ ````
+ ./cannyEdgeDetector --image ../openvx-samples/images/face.png
+ ````
+ 
diff --git a/samples/canny-edge-detector/src/canny.cpp b/samples/canny-edge-detector/src/canny.cpp
new file mode 100644
index 00000000..c8bf4466
--- /dev/null
+++ b/samples/canny-edge-detector/src/canny.cpp
@@ -0,0 +1,193 @@
+#include
+
+#include
+#include
+#include
+#include
+#include
+
+using namespace cv;
+using namespace std;
+
+#define ERROR_CHECK_STATUS(status) \
+ { \
+ vx_status status_ = (status); \
+ if (status_ != VX_SUCCESS) \
+ { \
+ printf("ERROR: failed with status = (%d) at " __FILE__ "#%d\n", status_, __LINE__); \
+ exit(1); \
+ } \
+ }
+
+#define ERROR_CHECK_OBJECT(obj) \
+ { \
+ vx_status status_ = vxGetStatus((vx_reference)(obj)); \
+ if (status_ != VX_SUCCESS) \
+ { \
+ printf("ERROR: failed with status = (%d) at " __FILE__ "#%d\n", status_, __LINE__); \
+ exit(1); \
+ } \
+ }
+
+static void VX_CALLBACK log_callback(vx_context context, vx_reference ref, vx_status status,
+ const vx_char string[])
+{
+ (void)context;
+ (void)ref;
+ (void)status;
+ size_t len = strlen(string);
+ if (len > 0)
+ {
+ printf("%s", string);
+ if (string[len - 1] != '\n') printf("\n");
+ fflush(stdout);
+ }
+}
+
+int main(int argc, char **argv)
+{
+ if (argc < 2)
+ {
+ printf(
+ "Usage:\n"
+ "./cannyDetect --image \n"
+ "./cannyDetect --live \n");
+ return 0;
+ }
+
+ int width = 480, height = 360;
+
+ vx_context context = vxCreateContext();
+ ERROR_CHECK_OBJECT(context);
+ vxRegisterLogCallback(context, log_callback, vx_false_e);
+
+ vx_graph graph = vxCreateGraph(context);
+ ERROR_CHECK_OBJECT(graph);
+
+ vx_image input_rgb_image = vxCreateImage(context, width, height, VX_DF_IMAGE_RGB);
+ vx_image output_filtered_image = vxCreateImage(context, width, height, VX_DF_IMAGE_U8);
+ ERROR_CHECK_OBJECT(input_rgb_image);
+ ERROR_CHECK_OBJECT(output_filtered_image);
+
+ vx_image yuv_image = vxCreateVirtualImage(graph, width, height, VX_DF_IMAGE_IYUV);
+ vx_image luma_image = vxCreateVirtualImage(graph, width, height, VX_DF_IMAGE_U8);
+ ERROR_CHECK_OBJECT(yuv_image);
+ ERROR_CHECK_OBJECT(luma_image);
+
+ vx_threshold hyst = vxCreateThreshold(context, VX_THRESHOLD_TYPE_RANGE, VX_TYPE_UINT8);
+ vx_int32 lower = 80, upper = 100;
+ vxSetThresholdAttribute(hyst, VX_THRESHOLD_ATTRIBUTE_THRESHOLD_LOWER, &lower, sizeof(lower));
+ vxSetThresholdAttribute(hyst, VX_THRESHOLD_ATTRIBUTE_THRESHOLD_UPPER, &upper, sizeof(upper));
+ ERROR_CHECK_OBJECT(hyst);
+ vx_int32 gradient_size = 3;
+
+ vx_node nodes[] = {vxColorConvertNode(graph, input_rgb_image, yuv_image),
+ vxChannelExtractNode(graph, yuv_image, VX_CHANNEL_Y, luma_image),
+ vxCannyEdgeDetectorNode(graph, luma_image, hyst, gradient_size, VX_NORM_L1,
+ output_filtered_image)};
+
+ for (vx_size i = 0; i < sizeof(nodes) / sizeof(nodes[0]); i++)
+ {
+ ERROR_CHECK_OBJECT(nodes[i]);
+ ERROR_CHECK_STATUS(vxReleaseNode(&nodes[i]));
+ }
+
+ ERROR_CHECK_STATUS(vxVerifyGraph(graph));
+
+ string option = argv[1];
+ Mat input;
+
+ if (option == "--image")
+ {
+ string imageLocation = argv[2];
+ input = imread(imageLocation.c_str());
+ if (input.empty())
+ {
+ printf("Image not found\n");
+ return 0;
+ }
+ resize(input, input, Size(width, height));
+ imshow("inputWindow", input);
+ vx_rectangle_t cv_rgb_image_region;
+ cv_rgb_image_region.start_x = 0;
+ cv_rgb_image_region.start_y = 0;
+ cv_rgb_image_region.end_x = width;
+ cv_rgb_image_region.end_y = height;
+ vx_imagepatch_addressing_t cv_rgb_image_layout{};
+ cv_rgb_image_layout.dim_x = input.cols;
+ cv_rgb_image_layout.dim_y = input.rows;
+ cv_rgb_image_layout.stride_x = input.elemSize();
+ cv_rgb_image_layout.stride_y = input.step;
+ vx_uint8 *cv_rgb_image_buffer = input.data;
+ ERROR_CHECK_STATUS(vxCopyImagePatch(input_rgb_image, &cv_rgb_image_region, 0,
+ &cv_rgb_image_layout, cv_rgb_image_buffer,
+ VX_WRITE_ONLY, VX_MEMORY_TYPE_HOST));
+ ERROR_CHECK_STATUS(vxProcessGraph(graph));
+ vx_rectangle_t rect = {0, 0, (vx_uint32)width, (vx_uint32)height};
+ vx_map_id map_id;
+ vx_imagepatch_addressing_t addr;
+ void *ptr;
+ ERROR_CHECK_STATUS(vxMapImagePatch(output_filtered_image, &rect, 0, &map_id, &addr, &ptr,
+ VX_READ_ONLY, VX_MEMORY_TYPE_HOST, VX_NOGAP_X));
+ Mat mat(height, width, CV_8U, ptr, addr.stride_y);
+ imshow("CannyDetect", mat);
+ waitKey(0);
+ ERROR_CHECK_STATUS(vxUnmapImagePatch(output_filtered_image, map_id));
+ }
+ else if (option == "--live")
+ {
+ VideoCapture cap(0);
+ if (!cap.isOpened())
+ {
+ printf("Unable to open camera\n");
+ return 0;
+ }
+ for (;;)
+ {
+ cap >> input;
+ resize(input, input, Size(width, height));
+ imshow("inputWindow", input);
+ if (waitKey(30) >= 0) break;
+ vx_rectangle_t cv_rgb_image_region;
+ cv_rgb_image_region.start_x = 0;
+ cv_rgb_image_region.start_y = 0;
+ cv_rgb_image_region.end_x = width;
+ cv_rgb_image_region.end_y = height;
+ vx_imagepatch_addressing_t cv_rgb_image_layout;
+ cv_rgb_image_layout.stride_x = 3;
+ cv_rgb_image_layout.stride_y = input.step;
+ vx_uint8 *cv_rgb_image_buffer = input.data;
+ ERROR_CHECK_STATUS(vxCopyImagePatch(input_rgb_image, &cv_rgb_image_region, 0,
+ &cv_rgb_image_layout, cv_rgb_image_buffer,
+ VX_WRITE_ONLY, VX_MEMORY_TYPE_HOST));
+ ERROR_CHECK_STATUS(vxProcessGraph(graph));
+ vx_rectangle_t rect = {0, 0, (vx_uint32)width, (vx_uint32)height};
+ vx_map_id map_id;
+ vx_imagepatch_addressing_t addr;
+ void *ptr;
+ ERROR_CHECK_STATUS(vxMapImagePatch(output_filtered_image, &rect, 0, &map_id, &addr,
+ &ptr, VX_READ_ONLY, VX_MEMORY_TYPE_HOST,
+ VX_NOGAP_X));
+ Mat mat(height, width, CV_8U, ptr, addr.stride_y);
+ imshow("CannyDetect", mat);
+ if (waitKey(30) >= 0) break;
+ ERROR_CHECK_STATUS(vxUnmapImagePatch(output_filtered_image, map_id));
+ }
+ }
+ else
+ {
+ printf(
+ "Usage:\n"
+ "./cannyDetect --image \n"
+ "./cannyDetect --live \n");
+ return 0;
+ }
+
+ ERROR_CHECK_STATUS(vxReleaseGraph(&graph));
+ ERROR_CHECK_STATUS(vxReleaseImage(&yuv_image));
+ ERROR_CHECK_STATUS(vxReleaseImage(&luma_image));
+ ERROR_CHECK_STATUS(vxReleaseImage(&input_rgb_image));
+ ERROR_CHECK_STATUS(vxReleaseImage(&output_filtered_image));
+ ERROR_CHECK_STATUS(vxReleaseContext(&context));
+ return 0;
+}
diff --git a/samples/images/canny-app.png b/samples/images/canny-app.png
new file mode 100644
index 00000000..dff4e8ee
Binary files /dev/null and b/samples/images/canny-app.png differ
diff --git a/samples/images/canny_image.PNG b/samples/images/canny_image.PNG
new file mode 100644
index 00000000..c67c2731
Binary files /dev/null and b/samples/images/canny_image.PNG differ
diff --git a/samples/images/face.png b/samples/images/face.png
new file mode 100644
index 00000000..5c1fd6a8
Binary files /dev/null and b/samples/images/face.png differ
diff --git a/samples/images/orb_kp.jpg b/samples/images/orb_kp.jpg
new file mode 100644
index 00000000..eb58247e
Binary files /dev/null and b/samples/images/orb_kp.jpg differ
diff --git a/samples/images/skintone-detect-app.png b/samples/images/skintone-detect-app.png
new file mode 100644
index 00000000..e0f3219c
Binary files /dev/null and b/samples/images/skintone-detect-app.png differ
diff --git a/samples/images/vx-pop-app.gif b/samples/images/vx-pop-app.gif
new file mode 100644
index 00000000..7ea1e305
Binary files /dev/null and b/samples/images/vx-pop-app.gif differ
diff --git a/samples/optical_flow/BUILD b/samples/optical_flow/BUILD
new file mode 100644
index 00000000..b7bf613b
--- /dev/null
+++ b/samples/optical_flow/BUILD
@@ -0,0 +1,22 @@
+
+
+cc_binary(
+ name = "optical_flow",
+ srcs = [
+ "source/optical_flow.cpp",
+ ],
+ deps = [
+ "//:corevx",
+ "@opencv",
+ "//targets/ai_server:imported_openvx_ai_server",
+ "//targets/c_model:imported_openvx_c_model",
+ "//targets/debug:imported_openvx_debug",
+ "//targets/extras:imported_openvx_extras",
+ "//targets/liteRT:imported_openvx_liteRT",
+ "//targets/opencl:imported_openvx_opencl",
+ "//targets/onnxRT:imported_openvx_onnxRT",
+ "//targets/executorch:imported_openvx_torch",
+ "//third_party:opencv-prebuilt",
+ ],
+ visibility = ["//visibility:public"],
+)
\ No newline at end of file
diff --git a/samples/optical_flow/README.md b/samples/optical_flow/README.md
new file mode 100644
index 00000000..4ccc5b80
--- /dev/null
+++ b/samples/optical_flow/README.md
@@ -0,0 +1,63 @@
+## Optical Flow Sample
+
+In this sample we will create an OpenVX graph to run Optical Flow on a video/live. This sample application uses OpenCV to decode input video and display the output.
+
+
+
+### Prerequisites
+
+* [Conformant OpenVX Implementation](https://github.com/ROCm/MIVisionX)
+
+* [OpenCV](https://github.com/opencv/opencv/releases/tag/3.4.0)
+
+
+### Steps to run the Optical Flow sample
+
+* **Step - 1:** Build and install [Conformant OpenVX Implementation](https://github.com/ROCm/MIVisionX).
+
+```
+Build OpenVX on Linux
+
+* Git Clone project
+
+ git clone https://github.com/ROCm/MIVisionX.git
+
+* Use CMake to build
+
+ mkdir build && cd build
+ cmake ../MIVisionX
+ make -j8
+ sudo make install
+```
+
+* **Step - 2:** Export OpenVX Directory Path
+
+```
+export OPENVX_DIR=/opt/rocm/
+```
+
+
+* **Step - 3:** CMake and Build the optical flow application
+
+```
+mkdir opticalFlow-build && cd opticalFlow-build
+cmake -DOPENVX_INCLUDES=$OPENVX_DIR/include/mivisionx -DOPENVX_LIBRARIES=$OPENVX_DIR/lib/libopenvx.so ../optical_flow
+make
+```
+
+* **Step - 4:** Run VX Optical Flow application
+
+ ```
+ Usage:
+ ./opticalFlow --video