Repository: nifi-minifi-cpp
Updated Branches:
  refs/heads/master 8e153bed7 -> dde50ecf5


MINIFICPP-416 Added crop properties to TFConvertImageToTensor

This closes #271.

Signed-off-by: Marc Parisi <phroc...@apache.org>


Project: http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/repo
Commit: http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/commit/dde50ecf
Tree: http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/tree/dde50ecf
Diff: http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/diff/dde50ecf

Branch: refs/heads/master
Commit: dde50ecf5d958847aaef24e8495a9895384770c4
Parents: 8e153be
Author: Andrew I. Christianson <a...@andyic.org>
Authored: Mon Feb 26 11:31:46 2018 -0500
Committer: Marc Parisi <phroc...@apache.org>
Committed: Tue Mar 6 09:43:36 2018 -0500

----------------------------------------------------------------------
 PROCESSORS.md                                   |  4 ++
 .../tensorflow/TFConvertImageToTensor.cpp       | 69 +++++++++++++++++++-
 extensions/tensorflow/TFConvertImageToTensor.h  |  9 +++
 3 files changed, 81 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/dde50ecf/PROCESSORS.md
----------------------------------------------------------------------
diff --git a/PROCESSORS.md b/PROCESSORS.md
index 307468e..e0e9f94 100644
--- a/PROCESSORS.md
+++ b/PROCESSORS.md
@@ -590,6 +590,10 @@ default values, and whether a property supports the NiFi 
Expression Language.
 | **Input Format** | | PNG, RAW | The format of the input image (PNG or RAW). 
RAW is RGB24. |
 | **Input Width** | | | The width, in pixels, of the input image. |
 | **Input Height** | | | The height, in pixels, of the input image. |
+| Crop Offset X | | | The X (horizontal) offset, in pixels, to crop the input 
image (relative to top-left corner). |
+| Crop Offset Y | | | The Y (vertical) offset, in pixels, to crop the input 
image (relative to top-left corner). |
+| Crop Size X | | | The X (horizontal) size, in pixels, to crop the input 
image. |
+| Crop Size Y | | | The Y (vertical) size, in pixels, to crop the input image. 
|
 | **Output Width** | | | The width, in pixels, of the output image. |
 | **Output Height** | | | The height, in pixels, of the output image. |
 | **Channels** | 3 | | The number of channels (e.g. 3 for RGB, 4 for RGBA) in 
the input image. |

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/dde50ecf/extensions/tensorflow/TFConvertImageToTensor.cpp
----------------------------------------------------------------------
diff --git a/extensions/tensorflow/TFConvertImageToTensor.cpp 
b/extensions/tensorflow/TFConvertImageToTensor.cpp
index 803ea48..b6a1183 100644
--- a/extensions/tensorflow/TFConvertImageToTensor.cpp
+++ b/extensions/tensorflow/TFConvertImageToTensor.cpp
@@ -43,6 +43,18 @@ core::Property TFConvertImageToTensor::OutputHeight(  // 
NOLINT
 core::Property TFConvertImageToTensor::NumChannels(  // NOLINT
     "Channels",
     "The number of channels (e.g. 3 for RGB, 4 for RGBA) in the input image", 
"3");
+core::Property TFConvertImageToTensor::CropOffsetX(  // NOLINT
+    "Crop Offset X",
+    "The X (horizontal) offset, in pixels, to crop the input image (relative 
to top-left corner).", "");
+core::Property TFConvertImageToTensor::CropOffsetY(  // NOLINT
+    "Crop Offset Y",
+    "The Y (vertical) offset, in pixels, to crop the input image (relative to 
top-left corner).", "");
+core::Property TFConvertImageToTensor::CropSizeX(  // NOLINT
+    "Crop Size X",
+    "The X (horizontal) size, in pixels, to crop the input image.", "");
+core::Property TFConvertImageToTensor::CropSizeY(  // NOLINT
+    "Crop Size Y",
+    "The Y (vertical) size, in pixels, to crop the input image.", "");
 
 core::Relationship TFConvertImageToTensor::Success(  // NOLINT
     "success",
@@ -105,6 +117,40 @@ void 
TFConvertImageToTensor::onSchedule(core::ProcessContext *context, core::Pro
   } else {
     logger_->log_error("Invalid channel count");
   }
+
+  do_crop_ = true;
+
+  if (context->getProperty(CropOffsetX.getName(), val)) {
+    core::Property::StringToInt(val, crop_offset_x_);
+  } else {
+    do_crop_ = false;
+  }
+
+  if (context->getProperty(CropOffsetY.getName(), val)) {
+    core::Property::StringToInt(val, crop_offset_y_);
+  } else {
+    do_crop_ = false;
+  }
+
+  if (context->getProperty(CropSizeX.getName(), val)) {
+    core::Property::StringToInt(val, crop_size_x_);
+  } else {
+    do_crop_ = false;
+  }
+
+  if (context->getProperty(CropSizeY.getName(), val)) {
+    core::Property::StringToInt(val, crop_size_y_);
+  } else {
+    do_crop_ = false;
+  }
+
+  if (do_crop_) {
+    logger_->log_info("Input images will be cropped at %d, %d by %d, %d 
pixels",
+                      crop_offset_x_,
+                      crop_offset_y_,
+                      crop_size_x_,
+                      crop_size_y_);
+  }
 }
 
 void TFConvertImageToTensor::onTrigger(const 
std::shared_ptr<core::ProcessContext> &context,
@@ -138,8 +184,29 @@ void TFConvertImageToTensor::onTrigger(const 
std::shared_ptr<core::ProcessContex
       // Cast pixel values to floats
       auto float_caster = 
tensorflow::ops::Cast(root.WithOpName("float_caster"), input, 
tensorflow::DT_FLOAT);
 
+      int crop_offset_x = 0;
+      int crop_offset_y = 0;
+      int crop_size_x = input_width_;
+      int crop_size_y = input_height_;
+
+      if (do_crop_) {
+        crop_offset_x = crop_offset_x_;
+        crop_offset_y = crop_offset_y_;
+        crop_size_x = crop_size_x_;
+        crop_size_y = crop_size_y_;
+      }
+
+      tensorflow::ops::Slice cropped = 
tensorflow::ops::Slice(root.WithOpName("crop"),
+                                                              float_caster,
+                                                              {crop_offset_y,
+                                                               crop_offset_x,
+                                                               0},
+                                                              {crop_size_y,
+                                                               crop_size_x,
+                                                               num_channels_});
+
       // Expand into batches (of size 1)
-      auto dims_expander = tensorflow::ops::ExpandDims(root, float_caster, 0);
+      auto dims_expander = tensorflow::ops::ExpandDims(root, cropped, 0);
 
       // Resize tensor to output dimensions
       auto resize = tensorflow::ops::ResizeBilinear(

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/dde50ecf/extensions/tensorflow/TFConvertImageToTensor.h
----------------------------------------------------------------------
diff --git a/extensions/tensorflow/TFConvertImageToTensor.h 
b/extensions/tensorflow/TFConvertImageToTensor.h
index 63f889c..b28f620 100644
--- a/extensions/tensorflow/TFConvertImageToTensor.h
+++ b/extensions/tensorflow/TFConvertImageToTensor.h
@@ -44,6 +44,10 @@ class TFConvertImageToTensor : public core::Processor {
   static core::Property InputHeight;
   static core::Property OutputWidth;
   static core::Property OutputHeight;
+  static core::Property CropOffsetX;
+  static core::Property CropOffsetY;
+  static core::Property CropSizeX;
+  static core::Property CropSizeY;
 
   static core::Relationship Success;
   static core::Relationship Failure;
@@ -93,6 +97,11 @@ class TFConvertImageToTensor : public core::Processor {
   int output_width_;
   int output_height_;
   int num_channels_;
+  bool do_crop_ = false;
+  int crop_offset_x_ = 0;
+  int crop_offset_y_ = 0;
+  int crop_size_x_ = 0;
+  int crop_size_y_ = 0;
 
   std::shared_ptr<tensorflow::GraphDef> graph_def_;
   moodycamel::ConcurrentQueue<std::shared_ptr<TFContext>> tf_context_q_;

Reply via email to