From 66b9adbf2dc94cd6a834aa89bf0611efb84acb01 Mon Sep 17 00:00:00 2001 From: agsantos <aline.gondimsantos@savoirfairelinux.com> Date: Tue, 23 Jun 2020 10:40:48 -0400 Subject: [PATCH] adds gpu options for desktop Change-Id: Ica7c2a2892919ee1f81fd9f96c174f7448ae4d3a --- ForegroundSegmentation/TFInference.cpp | 28 ++++++--- ForegroundSegmentation/TFInference.h | 30 +++++----- ForegroundSegmentation/buildtfcc.sh | 70 ++++++++++++++++++++++ ForegroundSegmentation/pluginInference.cpp | 44 +++++++------- ForegroundSegmentation/pluginParameters.h | 4 +- ForegroundSegmentation/videoSubscriber.cpp | 10 ++-- README.md | 16 ++--- 7 files changed, 143 insertions(+), 59 deletions(-) create mode 100644 ForegroundSegmentation/buildtfcc.sh diff --git a/ForegroundSegmentation/TFInference.cpp b/ForegroundSegmentation/TFInference.cpp index 7590dd7..8e32995 100644 --- a/ForegroundSegmentation/TFInference.cpp +++ b/ForegroundSegmentation/TFInference.cpp @@ -23,14 +23,14 @@ const char sep = separator(); const std::string TAG = "FORESEG"; -namespace jami +namespace jami { TensorflowInference::TensorflowInference(TFModel tfModel) : tfModel(tfModel) {} - TensorflowInference::~TensorflowInference() + TensorflowInference::~TensorflowInference() { } - bool TensorflowInference::isAllocated() const + bool TensorflowInference::isAllocated() const { return allocated; } @@ -211,7 +211,7 @@ namespace jami #else // Reads a model graph definition from disk, and creates a session object you // can use to run it. - void TensorflowInference::LoadGraph() + void TensorflowInference::LoadGraph() { tensorflow::GraphDef graph_def; tensorflow::Status load_graph_status = tensorflow::ReadBinaryProto(tensorflow::Env::Default(), tfModel.modelPath, &graph_def); @@ -219,11 +219,21 @@ namespace jami return ; //tensorflow::errors::NotFound("Failed to load compute graph at '", //tfModel.modelPath.c_str(), "'"); } - (&session)->reset(tensorflow::NewSession(tensorflow::SessionOptions())); + + PluginParameters* parameters = getGlobalPluginParameters(); + + tensorflow::SessionOptions options; + if(parameters->useGPU) + { + options.config.mutable_gpu_options()->set_allow_growth(true); + options.config.mutable_gpu_options()->set_per_process_gpu_memory_fraction(0.5); + } + (&session)->reset(tensorflow::NewSession(options)); tensorflow::Status session_create_status = session->Create(graph_def); if (!session_create_status.ok()) { return ; } + allocated = true; } @@ -233,7 +243,7 @@ namespace jami { // Actually run the image through the model. tensorflow::Status run_status = session->Run({{tfModel.inputLayer, imageTensor}}, {tfModel.outputLayer}, {}, &outputs); - if (!run_status.ok()) + if (!run_status.ok()) { Plog::log(Plog::LogPriority::INFO, "RUN GRAPH", "A problem occured when running the graph"); } @@ -244,12 +254,12 @@ namespace jami } } - void TensorflowInference::init() + void TensorflowInference::init() { // Loading the model Plog::log(Plog::LogPriority::INFO, "TENSOR", "INSIDE THE INIT" ); LoadGraph(); - } + } #endif - + } diff --git a/ForegroundSegmentation/TFInference.h b/ForegroundSegmentation/TFInference.h index 4ffaab2..5ecb67f 100644 --- a/ForegroundSegmentation/TFInference.h +++ b/ForegroundSegmentation/TFInference.h @@ -9,10 +9,10 @@ #include <vector> #ifdef TFLITE - #include <tensorflow/lite/interpreter.h> - #include <tensorflow/lite/delegates/nnapi/nnapi_delegate.h> +#include <tensorflow/lite/interpreter.h> +#include <tensorflow/lite/delegates/nnapi/nnapi_delegate.h> -namespace tflite +namespace tflite { class FlatBufferModel; class Interpreter; @@ -20,29 +20,31 @@ namespace tflite } // namespace tflite #else - #include <tensorflow/core/lib/core/status.h> - #include <tensorflow/core/public/session.h> - #include <tensorflow/core/framework/tensor.h> - #include <tensorflow/core/framework/types.pb.h> - #include <tensorflow/core/platform/init_main.h> - -namespace tensorflow +#include <tensorflow/core/lib/core/status.h> +#include <tensorflow/core/public/session.h> +#include <tensorflow/core/framework/tensor.h> +#include <tensorflow/core/framework/types.pb.h> +#include <tensorflow/core/platform/init_main.h> +#include <tensorflow/core/protobuf/config.pb.h> + +namespace tensorflow { class Tensor; class Status; class GraphDef; class Session; + struct SessionOptions; class TensorShape; class Env; enum DataType:int; -} // namespace namespace tensorflow +} // namespace namespace tensorflow #endif -namespace jami +namespace jami { - class TensorflowInference + class TensorflowInference { public: /** @@ -112,7 +114,7 @@ namespace jami std::unique_ptr<tflite::Interpreter> interpreter; #else std::unique_ptr<tensorflow::Session> session; - std::vector<tensorflow::Tensor> outputs; + std::vector<tensorflow::Tensor> outputs; #endif TFModel tfModel; std::vector<std::string> labels; diff --git a/ForegroundSegmentation/buildtfcc.sh b/ForegroundSegmentation/buildtfcc.sh new file mode 100644 index 0000000..d65588f --- /dev/null +++ b/ForegroundSegmentation/buildtfcc.sh @@ -0,0 +1,70 @@ +#! /bin/bash +# Build the plugin for the project +if [ -z $DAEMON ]; then + DAEMON="./../../daemon" + echo "DAEMON not provided, building for ${DAEMON}" +fi + +PLUGIN_NAME="foregroundsegmentation" +JPL_FILE_NAME=${PLUGIN_NAME}".jpl" +SO_FILE_NAME="lib"${PLUGIN_NAME}".so" +DAEMON_SRC="${DAEMON}/src" +CONTRIB_PATH="${DAEMON}/contrib" +DESTINATION_PATH="./../build/" +PLUGINS_LIB="../lib" +LIBS_DIR="/home/${USER}/Libs" + + +CONTRIB_PLATFORM_CURT=x86_64 +CONTRIB_PLATFORM=${CONTRIB_PLATFORM_CURT}-linux-gnu + +mkdir -p lib/${CONTRIB_PLATFORM_CURT} +mkdir -p ${DESTINATION_PATH}/${CONTRIB_PLATFORM}/jpl + +# Compile +clang++ -std=c++14 -shared -fPIC \ +-Wl,-Bsymbolic,-rpath,"\${ORIGIN}" \ +-Wall -Wextra \ +-Wno-unused-variable \ +-Wno-unused-function \ +-Wno-unused-parameter \ +-I"." \ +-I${DAEMON_SRC} \ +-I"${CONTRIB_PATH}/${CONTRIB_PLATFORM}/include" \ +-I"${CONTRIB_PATH}/${CONTRIB_PLATFORM}/include/opencv4" \ +-I${LIBS_DIR}/_tensorflow_cc/include \ +-I${LIBS_DIR}/_tensorflow_cc/include/third_party/eigen3 \ +-I${PLUGINS_LIB} \ +main.cpp \ +videoSubscriber.cpp \ +pluginProcessor.cpp \ +pluginMediaHandler.cpp \ +TFInference.cpp \ +pluginInference.cpp \ +pluginParameters.cpp \ +-L${CONTRIB_PATH}/${CONTRIB_PLATFORM}/lib/ \ +-L${CONTRIB_PATH}/${CONTRIB_PLATFORM}/lib/opencv4/3rdparty/ \ +-L${LIBS_DIR}/_tensorflow_cc/lib/${CONTRIB_PLATFORM}-gpu61/ \ +-lswscale \ +-lavutil \ +-lopencv_imgcodecs \ +-lopencv_imgproc \ +-lopencv_core \ +-ltensorflow_cc \ +-lpng \ +-o lib/${CONTRIB_PLATFORM_CURT}/${SO_FILE_NAME} +# (above) Always put opencv_core after all other opencv libs +# (above) Always put avutil after all other ffmpeg libs +# (above) Always put png after all other libs + +cp ${LIBS_DIR}/_tensorflow_cc/lib/${CONTRIB_PLATFORM}-gpu61/libtensorflow_cc.so lib/$CONTRIB_PLATFORM_CURT/libtensorflow_cc.so.2 +cp /usr/lib/${CONTRIB_PLATFORM}/libswscale.so.4 lib/$CONTRIB_PLATFORM_CURT +cp /usr/lib/${CONTRIB_PLATFORM}/libavutil.so.55 lib/$CONTRIB_PLATFORM_CURT +cp /usr/lib/${CONTRIB_PLATFORM}/libpng16.so.16 lib/$CONTRIB_PLATFORM_CURT + +zip -r ${JPL_FILE_NAME} data manifest.json lib +mv ${JPL_FILE_NAME} ${DESTINATION_PATH}/${CONTRIB_PLATFORM}/jpl/ + +# Cleanup +# Remove lib after compilation +rm -rf lib diff --git a/ForegroundSegmentation/pluginInference.cpp b/ForegroundSegmentation/pluginInference.cpp index 1c84407..3d950a2 100644 --- a/ForegroundSegmentation/pluginInference.cpp +++ b/ForegroundSegmentation/pluginInference.cpp @@ -9,9 +9,9 @@ const std::string TAG = "FORESEG"; namespace jami { - PluginInference::PluginInference(TFModel model) : TensorflowInference(model) + PluginInference::PluginInference(TFModel model) : TensorflowInference(model) { -#ifndef TFLITE +#ifndef TFLITE //Initialize TENSORFLOW_CC lib static const char* kFakeName = "fake program name"; int argc = 1; @@ -22,7 +22,7 @@ namespace jami Plog::log(Plog::LogPriority::INFO, "TENSORFLOW INIT", "Unknown argument " ); } free(fake_name_copy); -#endif //TFLITE +#endif //TFLITE } PluginInference::~PluginInference(){} @@ -111,7 +111,7 @@ namespace jami // Given an image file name, read in the data, try to decode it as an image, // resize it to the requested size, and then scale the values as desired. void PluginInference::ReadTensorFromMat(const cv::Mat& image) - { + { // std::ostringstream oss; // oss << image.rows; // Plog::log(Plog::LogPriority::INFO, "ReadTensorFromMat", oss.str()); @@ -148,32 +148,32 @@ namespace jami case tensorflow::DataType::DT_INT32: { for (int offset = 0; offset < flatSize; offset++) - { + { // Get vaule through .flat() - out.push_back(static_cast<float> (outputs[0].flat<tensorflow::int32>()(offset))); + out.push_back(static_cast<float> (outputs[0].flat<tensorflow::int32>()(offset))); } break; } case tensorflow::DataType::DT_INT64: { for (int offset = 0; offset < flatSize; offset++) - { + { // Get vaule through .flat() - if (outputs[0].flat<tensorflow::int64>()(offset) == 15 or outputs[0].flat<tensorflow::int64>()(offset) == 1) - { - oss << " " << outputs[0].flat<tensorflow::int64>()(offset); - Plog::log(Plog::LogPriority::INFO, "masksPredictions", oss.str()); - } - out.push_back(static_cast<float> (outputs[0].flat<tensorflow::int64>()(offset))); + // if (outputs[0].flat<tensorflow::int64>()(offset) == 15 or outputs[0].flat<tensorflow::int64>()(offset) == 1) + // { + // oss << " " << outputs[0].flat<tensorflow::int64>()(offset); + // Plog::log(Plog::LogPriority::INFO, "masksPredictions", oss.str()); + // } + out.push_back(static_cast<float> (outputs[0].flat<tensorflow::int64>()(offset))); } break; } default: { for (int offset = 0; offset < flatSize; offset++) - { + { // Get vaule through .flat() - out.push_back(0); + out.push_back(0); } break; } @@ -182,9 +182,9 @@ namespace jami return out; } - void PluginInference::setExpectedImageDimensions() + void PluginInference::setExpectedImageDimensions() { - + if (tfModel.dims[1] != 0) { imageWidth = tfModel.dims[1]; @@ -196,23 +196,23 @@ namespace jami if (tfModel.dims[3] != 0) { imageNbChannels = tfModel.dims[3]; - } + } } #endif - int PluginInference::getImageWidth() const + int PluginInference::getImageWidth() const { // Plog::log(Plog::LogPriority::INFO, TAG, "inside getImageWidth()"); return imageWidth; } - int PluginInference::getImageHeight() const + int PluginInference::getImageHeight() const { // Plog::log(Plog::LogPriority::INFO, TAG, "inside getImageHeight()"); - return imageHeight; + return imageHeight; } - int PluginInference::getImageNbChannels() const + int PluginInference::getImageNbChannels() const { // Plog::log(Plog::LogPriority::INFO, TAG, "inside getImageNbChannels()"); return imageNbChannels; diff --git a/ForegroundSegmentation/pluginParameters.h b/ForegroundSegmentation/pluginParameters.h index ec38f22..acf49e2 100644 --- a/ForegroundSegmentation/pluginParameters.h +++ b/ForegroundSegmentation/pluginParameters.h @@ -8,12 +8,14 @@ struct PluginParameters { std::string stream = "out"; #ifdef TFLITE + bool useGPU = false; //only used when on desktop #ifdef __ANDROID std::string model = "model_256_Qlatency.tflite"; #else std::string model = "model_256_F_16.tflite"; -#endif +#endif #else + bool useGPU = true; //only used when on desktop std::string model = "frozen_inference_graph.pb"; #endif //TFLITE std::string image = "background2.png"; diff --git a/ForegroundSegmentation/videoSubscriber.cpp b/ForegroundSegmentation/videoSubscriber.cpp index 77659fd..b92cf3e 100644 --- a/ForegroundSegmentation/videoSubscriber.cpp +++ b/ForegroundSegmentation/videoSubscriber.cpp @@ -60,7 +60,6 @@ namespace jami // Plog::log(Plog::LogPriority::INFO, TAG, "inside update()"); if (isAttached) { - std::ostringstream oss; //====================================================================================== // GET FRAME ROTATION AVFrameSideData *side_data = @@ -73,6 +72,7 @@ namespace jami angle = static_cast<int>(av_display_rotation_get(matrix_rotation)); } + std::ostringstream oss; // Plog::log(Plog::LogPriority::INFO, TAG, "step GET RAW FRAME"); //====================================================================================== // GET RAW FRAME @@ -93,8 +93,8 @@ namespace jami cv::Mat clone = frame.clone(); //====================================================================================== // ROTATE THE FRAME - // rotateFrame(angle, clone); - // rotateFrame(angle, frame); + rotateFrame(angle, clone); + rotateFrame(angle, frame); if (firstRun) { @@ -129,8 +129,8 @@ namespace jami //====================================================================================== // REPLACE AVFRAME DATA WITH FRAME DATA - // rotateFrame(-angle, clone); - // rotateFrame(-angle, frame); + rotateFrame(-angle, clone); + rotateFrame(-angle, frame); // Plog::log(Plog::LogPriority::INFO, TAG, "step REPLACE AVFRAME DATA WITH FRAME DATA"); if (bgrFrame && bgrFrame->data[0]) diff --git a/README.md b/README.md index 0cea3fa..04bf28e 100644 --- a/README.md +++ b/README.md @@ -50,7 +50,7 @@ For Android: (Tensorflow Lite) Dependencies: 1 - Android NDK 18r - $ ./configure + $ ./configure >> Do you wish to build TensorFlow with XLA JIT support? [Y/n]: n >> Do you wish to download a fresh release of clang? (Experimental) [y/N]: y >> Would you like to interactively configure ./WORKSPACE for Android builds? [y/N]: y @@ -58,19 +58,19 @@ For Android: (Tensorflow Lite) $ bazel build //tensorflow/lite:libtensorflowlite.so --crosstool_top=//external:android/crosstool --cpu=armeabi-v7a --host_crosstool_top=@bazel_tools//tools/cpp:toolchain --cxxopt="-std=c++11" - $ bazel build //tensorflow/lite:libtensorflowlite.so --crosstool_top=//external:android/crosstool --cpu=arm64-v8a --host_crosstool_top=@bazel_tools//tools/cpp:toolchain --cxxopt="-std=c++11" + $ bazel build //tensorflow/lite:libtensorflowlite.so --crosstool_top=//external:android/crosstool --cpu=arm64-v8a --host_crosstool_top=@bazel_tools//tools/cpp:toolchain --cxxopt="-std=c++11" $ bazel build //tensorflow/lite:libtensorflowlite.so --crosstool_top=//external:android/crosstool --cpu=x86_64 --host_crosstool_top=@bazel_tools//tools/cpp:toolchain --cxxopt="-std=c++11" For Linux: - $ ./configure + $ ./configure For TFLite: - $ bazel build --config=v1 --define framework_shared_object=false //tensorflow:libtensorflow_cc.so + $ bazel build //tensorflow/lite:libtensorflowlite.so or For Tensorflow C++ API: - $ bazel build //tensorflow/lite:libtensorflowlite.so + $ bazel build --config=v1 --define framework_shared_object=false //tensorflow:libtensorflow_cc.so OBS.: If you want to build Tensorflow C++ API with GPU suport, be sure to have a CUDA capable GPU and that you have followed all installation steps for the Nvidia drivers, CUDA Toolkit, CUDNN, Tensor RT, that their versions @@ -87,7 +87,7 @@ TENSORFLOWLITE INCLUDES ASSEMBLE INSTRUCTIONS "<tensorflow>/bazel-genfiles/tensorflow/lite/" or at: "<tensorflow>/bazel-out/<cpu>-opt/bin/tensorflow/lite/" - (cpu may be "armeabi-v7a", "arm64-v8a", "x86_64" or "k8" depending on the build realized) + (cpu may be "armeabi-v7a", "arm64-v8a", "x86_64", "x86" or "k8" depending on the build realized) The lib in the first folder is overwritten after each build. The lib in the second folder is not. @@ -185,7 +185,7 @@ TENSORFLOW C++ API INCLUDES ASSEMBLE INSTRUCTIONS core/ -> keep folder structure and copy all header files from "<tensorflow>/ tensorflow/core" - -> copy all proto header files (.pb.h) from + -> copy all proto header files (.pb.h) from "<tensorflow>/bazel-genfiles/tensorflow/core/" absl/ -> keep folder structure and copy all header and .inc files from "<tensorflow>/ @@ -202,6 +202,6 @@ TENSORFLOW C++ API INCLUDES ASSEMBLE INSTRUCTIONS -> keep folder structure and copy all files from "<tensorflow>/bazel-tensorflow/external/eigen_archive/unsupported/Eigen/" CXX11/ -> copy "<tensorflow>/third_party/eigen3/unsupported/Eigen/CXX11/FixedPoint" - -> copy "<tensorflow>/third_party/eigen3/unsupported/Eigen/CXX11/src/" + -> copy "<tensorflow>/third_party/eigen3/unsupported/Eigen/CXX11/src/" --> Be aware to apply any needed changes to the build.sh file so that the plugin can be build against the standart tensorflow_cc library. -- GitLab