Browse Source

Added the crop and resize method from the c++ library.

tags/v0.13
Mascha, Philipp Haiping Chen 5 years ago
parent
commit
884b9687ae
2 changed files with 86 additions and 16 deletions
  1. +33
    -16
      src/TensorFlowNET.Core/Operations/image_ops_impl.cs
  2. +53
    -0
      test/TensorFlowNET.UnitTest/img_test/TestCrop.cs

+ 33
- 16
src/TensorFlowNET.Core/Operations/image_ops_impl.cs View File

@@ -14,9 +14,11 @@
limitations under the License.
******************************************************************************/

using NumSharp;
using System;
using System.Collections.Generic;
using System.Text;
using Tensorflow.Operations;
using static Tensorflow.Binding;

namespace Tensorflow
@@ -102,6 +104,37 @@ namespace Tensorflow
});
}

internal static Tensor resize_images(Tensor images, Tensor size, ResizeMethod method, bool align_corners, bool preserve_aspect_ratio, string name)
{
throw new NotImplementedException();
}

/// <summary>
/// Extracts crops from the input image tensor and resizes them using bilinear sampling or nearest neighbor sampling (possibly with aspect ratio change) to a common output size specified by crop_size.
/// This is more general than the crop_to_bounding_box op which extracts a fixed size slice from the input image and does not allow resizing or aspect ratio change.
/// Returns a tensor with crops from the input image at positions defined at the bounding box locations in boxes.
/// The cropped boxes are all resized(with bilinear or nearest neighbor interpolation) to a fixed size = [crop_height, crop_width].
/// The result is a 4 - D tensor[num_boxes, crop_height, crop_width, depth].
/// The resizing is corner aligned. In particular, if boxes = [[0, 0, 1, 1]], the method will give identical results to using tf.image.resize_bilinear() or tf.image.resize_nearest_neighbor() (depends on the method argument) with align_corners = True.
/// </summary>
/// <param name="image">A 4-D tensor of shape [batch, image_height, image_width, depth]. Both image_height and image_width need to be positive.</param>
/// <param name="boxes">A 2-D tensor of shape [num_boxes, 4]. The i-th row of the tensor specifies the coordinates of a box in the box_ind[i] image and is specified in normalized coordinates [y1, x1, y2, x2]. A normalized coordinate value of y is mapped to the image coordinate at y * (image_height - 1), so as the [0, 1] interval of normalized image height is mapped to [0, image_height - 1] in image height coordinates. We do allow y1 > y2, in which case the sampled crop is an up-down flipped version of the original image. The width dimension is treated similarly. Normalized coordinates outside the [0, 1] range are allowed, in which case we use extrapolation_value to extrapolate the input image values.</param>
/// <param name="box_ind">A 1-D tensor of shape [num_boxes] with int32 values in [0, batch). The value of box_ind[i] specifies the image that the i-th box refers to.</param>
/// <param name="crop_size">A 1-D tensor of 2 elements, size = [crop_height, crop_width]. All cropped image patches are resized to this size. The aspect ratio of the image content is not preserved. Both crop_height and crop_width need to be positive.</param>
/// <returns>A 4-D tensor of shape [num_boxes, crop_height, crop_width, depth].</returns>
public static Tensor CropAndResize(Tensor image, Tensor boxes, Tensor box_ind, Tensor crop_size)
{
var _op = gen_nn_ops._op_def_lib._apply_op_helper("CropAndResize", name: null, args: new
{
image,
boxes,
box_ind,
crop_size
});

return _op.outputs[0];
}

public static Tensor is_jpeg(Tensor contents, string name = null)
{
return tf_with(ops.name_scope(name, "is_jpeg"), scope =>
@@ -129,22 +162,6 @@ namespace Tensorflow
throw new NotImplementedException("");
}

/// <summary>
/// Resize `images` to `size` using the specified `method`.
/// </summary>
/// <param name="images"></param>
/// <param name="size"></param>
/// <param name="method"></param>
/// <param name="align_corners"></param>
/// <param name="preserve_aspect_ratio"></param>
/// <param name="name"></param>
/// <returns></returns>
public static Tensor resize_images(Tensor images, Tensor size, ResizeMethod method = ResizeMethod.BILINEAR,
bool align_corners = false, bool preserve_aspect_ratio = false, string name = null)
{
throw new NotImplementedException("");
}

/// <summary>
/// Resize `images` to `size` using nearest neighbor interpolation.
/// </summary>


+ 53
- 0
test/TensorFlowNET.UnitTest/img_test/TestCrop.cs View File

@@ -0,0 +1,53 @@
using FluentAssertions;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using NumSharp;
using Tensorflow;
using static Tensorflow.Binding;

namespace TensorFlowNET.UnitTest.img_test
{
[TestClass]
public class TestCrop
{

[TestMethod]
public void TestCropAndResize()
{
// 3x3 'Image' with numbered coordinates
var input = np.array(0f, 1f, 2f, 3f, 4f, 5f, 6f, 7f, 8f);
var image = tf.reshape(input, new int[] { 1, 3, 3, 1 });

// 4x4 'Image' with numbered coordinates
var input2 = np.array(0f, 1f, 2f, 3f, 4f, 5f, 6f, 7f, 8f, 9f, 10f, 11f, 12f, 13f, 14f, 15f);
var image2 = tf.reshape(input2, new int[] { 1, 4, 4, 1 });
// create one box over the full image that flips it (y1 > y2)
var box = tf.reshape(np.array(1f, 0f, 0f, 1f), new int[] {1, 4});
var boxInd = tf.Variable(np.array(0));
// crop first 3x3 imageto size 1x1
var cropSize1_1 = tf.Variable(np.array(1, 1));
// don't crop second 4x4 image
var cropSize2_2 = tf.Variable(np.array(4, 4));
var init = tf.global_variables_initializer();
using (Session sess = tf.Session())
{
sess.run(init);

var cropped = image_ops_impl.CropAndResize(image, box, boxInd, cropSize1_1);
var result = sess.run(cropped);
// check if cropped to 1x1 center was succesfull
result.size.Should().Be(1);
result[0, 0, 0, 0].Should().Be(4f);

cropped = image_ops_impl.CropAndResize(image2, box, boxInd, cropSize2_2);
result = sess.run(cropped);
// check if flipped and no cropping occured
result.size.Should().Be(16);
result[0, 0, 0, 0].Should().Be(12f);
}

}

}
}

Loading…
Cancel
Save