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_;