diff --git a/src/TensorFlowNET.Core/APIs/tf.image.cs b/src/TensorFlowNET.Core/APIs/tf.image.cs
index 35fe2908..ff20ae22 100644
--- a/src/TensorFlowNET.Core/APIs/tf.image.cs
+++ b/src/TensorFlowNET.Core/APIs/tf.image.cs
@@ -16,6 +16,7 @@
using System.Collections.Generic;
using Tensorflow.IO;
+using static Tensorflow.Binding;
namespace Tensorflow
{
@@ -59,6 +60,10 @@ namespace Tensorflow
string name = null)
=> image_ops_impl.resize_images(images, size, method, preserve_aspect_ratio, antialias, name);
+ public Tensor resize_images_v2(Tensor images, TensorShape size, string method = ResizeMethod.BILINEAR, bool preserve_aspect_ratio = false, bool antialias = false,
+ string name = null)
+ => image_ops_impl.resize_images(images, tf.constant(size.dims), method, preserve_aspect_ratio, antialias, name);
+
public Tensor resize_images_with_pad(Tensor image, int target_height, int target_width, string method, bool antialias)
=> image_ops_impl.resize_images_with_pad(image, target_height, target_width, method, antialias);
@@ -160,7 +165,7 @@ namespace Tensorflow
int ratio = 1,
bool fancy_upscaling = true,
bool try_recover_truncated = false,
- float acceptable_fraction = 1,
+ int acceptable_fraction = 1,
string dct_method = "",
string name = null)
=> gen_image_ops.decode_jpeg(contents, channels: channels, ratio: ratio,
diff --git a/src/TensorFlowNET.Core/Eager/EagerRunner.TFE_FastPathExecute.cs b/src/TensorFlowNET.Core/Eager/EagerRunner.TFE_FastPathExecute.cs
index 82e29529..f5c0a8ee 100644
--- a/src/TensorFlowNET.Core/Eager/EagerRunner.TFE_FastPathExecute.cs
+++ b/src/TensorFlowNET.Core/Eager/EagerRunner.TFE_FastPathExecute.cs
@@ -376,6 +376,9 @@ namespace Tensorflow.Eager
case TF_AttrType.TF_ATTR_INT:
c_api.TFE_OpSetAttrInt(op, key, Convert.ToInt64(value));
break;
+ case TF_AttrType.TF_ATTR_FLOAT:
+ c_api.TFE_OpSetAttrFloat(op, key, Convert.ToSingle(value));
+ break;
case TF_AttrType.TF_ATTR_SHAPE:
var dims = (value as int[]).Select(x => (long)x).ToArray();
c_api.TFE_OpSetAttrShape(op, key, dims, dims.Length, status.Handle);
diff --git a/src/TensorFlowNET.Core/Eager/c_api.eager.cs b/src/TensorFlowNET.Core/Eager/c_api.eager.cs
index f5cc0fde..6a9073a1 100644
--- a/src/TensorFlowNET.Core/Eager/c_api.eager.cs
+++ b/src/TensorFlowNET.Core/Eager/c_api.eager.cs
@@ -176,6 +176,9 @@ namespace Tensorflow
[DllImport(TensorFlowLibName)]
public static extern void TFE_OpSetAttrInt(SafeOpHandle op, string attr_name, long value);
+ [DllImport(TensorFlowLibName)]
+ public static extern void TFE_OpSetAttrFloat(SafeOpHandle op, string attr_name, float value);
+
///
///
///
diff --git a/src/TensorFlowNET.Core/Keras/Preprocessings/DatasetUtils.get_training_or_validation_split.cs b/src/TensorFlowNET.Core/Keras/Preprocessings/DatasetUtils.get_training_or_validation_split.cs
new file mode 100644
index 00000000..a0969ea0
--- /dev/null
+++ b/src/TensorFlowNET.Core/Keras/Preprocessings/DatasetUtils.get_training_or_validation_split.cs
@@ -0,0 +1,43 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+
+namespace Tensorflow.Keras.Preprocessings
+{
+ public partial class DatasetUtils
+ {
+ ///
+ /// Potentially restict samples & labels to a training or validation split.
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public (T1[], T2[]) get_training_or_validation_split(T1[] samples,
+ T2[] labels,
+ float validation_split,
+ string subset)
+ {
+ var num_val_samples = Convert.ToInt32(samples.Length * validation_split);
+ if (subset == "training")
+ {
+ Console.WriteLine($"Using {samples.Length - num_val_samples} files for training.");
+ samples = samples[..^num_val_samples];
+ labels = labels[..^num_val_samples];
+ }
+ else if (subset == "validation")
+ {
+ Console.WriteLine($"Using {num_val_samples} files for validation.");
+ samples = samples[samples.Length..];
+ labels = labels[samples.Length..];
+ }
+ else
+ throw new NotImplementedException("");
+
+ return (samples, labels);
+ }
+ }
+}
diff --git a/src/TensorFlowNET.Core/Keras/Preprocessings/DatasetUtils.index_directory.cs b/src/TensorFlowNET.Core/Keras/Preprocessings/DatasetUtils.index_directory.cs
index 37893cfc..d3548c23 100644
--- a/src/TensorFlowNET.Core/Keras/Preprocessings/DatasetUtils.index_directory.cs
+++ b/src/TensorFlowNET.Core/Keras/Preprocessings/DatasetUtils.index_directory.cs
@@ -1,5 +1,8 @@
-using System;
+using NumSharp;
+using System;
using System.Collections.Generic;
+using System.IO;
+using System.Linq;
using System.Text;
namespace Tensorflow.Keras.Preprocessings
@@ -20,14 +23,45 @@ namespace Tensorflow.Keras.Preprocessings
/// file_paths, labels, class_names
///
public (string[], int[], string[]) index_directory(string directory,
- string labels,
- string[] formats,
- string class_names = null,
+ string[] formats = null,
+ string[] class_names = null,
bool shuffle = true,
int? seed = null,
bool follow_links = false)
{
- throw new NotImplementedException("");
+ var labels = new List();
+ var file_paths = new List();
+
+ var class_dirs = Directory.GetDirectories(directory);
+ class_names = class_dirs.Select(x => x.Split(Path.DirectorySeparatorChar)[^1]).ToArray();
+
+ for (var label = 0; label < class_dirs.Length; label++)
+ {
+ var files = Directory.GetFiles(class_dirs[label]);
+ file_paths.AddRange(files);
+ labels.AddRange(Enumerable.Range(0, files.Length).Select(x => label));
+ }
+
+ var return_labels = new int[labels.Count];
+ var return_file_paths = new string[file_paths.Count];
+
+ if (shuffle)
+ {
+ if (!seed.HasValue)
+ seed = np.random.randint((long)1e6);
+ var random_index = np.arange(labels.Count);
+ var rng = np.random.RandomState(seed.Value);
+ rng.shuffle(random_index);
+ var index = random_index.ToArray();
+
+ for (int i = 0; i< labels.Count; i++)
+ {
+ return_labels[i] = labels[index[i]];
+ return_file_paths[i] = file_paths[index[i]];
+ }
+ }
+
+ return (return_file_paths, return_labels, class_names);
}
}
}
diff --git a/src/TensorFlowNET.Core/Keras/Preprocessings/Preprocessing.image_dataset_from_directory.cs b/src/TensorFlowNET.Core/Keras/Preprocessings/Preprocessing.image_dataset_from_directory.cs
index 73191e06..6f84e7b6 100644
--- a/src/TensorFlowNET.Core/Keras/Preprocessings/Preprocessing.image_dataset_from_directory.cs
+++ b/src/TensorFlowNET.Core/Keras/Preprocessings/Preprocessing.image_dataset_from_directory.cs
@@ -28,7 +28,7 @@ namespace Tensorflow.Keras
public Tensor image_dataset_from_directory(string directory,
string labels = "inferred",
string label_mode = "int",
- string class_names = null,
+ string[] class_names = null,
string color_mode = "rgb",
int batch_size = 32,
TensorShape image_size = null,
@@ -44,13 +44,15 @@ namespace Tensorflow.Keras
num_channels = 3;
// C:/Users/haipi/.keras/datasets/flower_photos
var (image_paths, label_list, class_name_list) = tf.keras.preprocessing.dataset_utils.index_directory(directory,
- labels,
- WHITELIST_FORMATS,
+ formats: WHITELIST_FORMATS,
class_names: class_names,
shuffle: shuffle,
seed: seed,
follow_links: follow_links);
+ (image_paths, label_list) = tf.keras.preprocessing.dataset_utils.get_training_or_validation_split(image_paths, label_list, validation_split, subset);
+
+ paths_and_labels_to_dataset(image_paths, image_size, num_channels, label_list, label_mode, class_name_list.Length, interpolation);
throw new NotImplementedException("");
}
}
diff --git a/src/TensorFlowNET.Core/Keras/Preprocessings/Preprocessing.paths_and_labels_to_dataset.cs b/src/TensorFlowNET.Core/Keras/Preprocessings/Preprocessing.paths_and_labels_to_dataset.cs
new file mode 100644
index 00000000..795f4e3f
--- /dev/null
+++ b/src/TensorFlowNET.Core/Keras/Preprocessings/Preprocessing.paths_and_labels_to_dataset.cs
@@ -0,0 +1,32 @@
+using System;
+using System.Globalization;
+using static Tensorflow.Binding;
+
+namespace Tensorflow.Keras
+{
+ public partial class Preprocessing
+ {
+ public Tensor paths_and_labels_to_dataset(string[] image_paths,
+ TensorShape image_size,
+ int num_channels,
+ int[] labels,
+ string label_mode,
+ int num_classes,
+ string interpolation)
+ {
+ foreach (var image_path in image_paths)
+ path_to_image(image_path, image_size, num_channels, interpolation);
+
+ throw new NotImplementedException("");
+ }
+
+ Tensor path_to_image(string path, TensorShape image_size, int num_channels, string interpolation)
+ {
+ var img = tf.io.read_file(path);
+ img = tf.image.decode_image(
+ img, channels: num_channels, expand_animations: false);
+ img = tf.image.resize_images_v2(img, image_size, method: interpolation);
+ return img;
+ }
+ }
+}
diff --git a/src/TensorFlowNET.Core/Operations/control_flow_ops.cs b/src/TensorFlowNET.Core/Operations/control_flow_ops.cs
index 631c97e9..bdffcf2b 100644
--- a/src/TensorFlowNET.Core/Operations/control_flow_ops.cs
+++ b/src/TensorFlowNET.Core/Operations/control_flow_ops.cs
@@ -86,7 +86,7 @@ namespace Tensorflow
var guarded_assert = cond(condition, false_assert, true_assert, name: "AssertGuard");
- return guarded_assert[0].op;
+ return guarded_assert == null ? null : guarded_assert[0].op;
});
}
@@ -423,8 +423,6 @@ namespace Tensorflow
return true_fn() as Tensor;
else
return false_fn() as Tensor;
-
- return null;
}
// Add the Switch to the graph.
@@ -507,8 +505,6 @@ namespace Tensorflow
return true_fn() as Tensor[];
else
return false_fn() as Tensor[];
-
- return null;
}
// Add the Switch to the graph.
diff --git a/src/TensorFlowNET.Core/Operations/gen_image_ops.cs b/src/TensorFlowNET.Core/Operations/gen_image_ops.cs
index 06907f65..dc61f6b2 100644
--- a/src/TensorFlowNET.Core/Operations/gen_image_ops.cs
+++ b/src/TensorFlowNET.Core/Operations/gen_image_ops.cs
@@ -66,14 +66,24 @@ namespace Tensorflow
int ratio = 1,
bool fancy_upscaling = true,
bool try_recover_truncated = false,
- float acceptable_fraction = 1,
+ int acceptable_fraction = 1,
string dct_method = "",
string name = null)
{
// Add nodes to the TensorFlow graph.
if (tf.Context.executing_eagerly())
{
- throw new NotImplementedException("decode_jpeg");
+ var results = tf.Runner.TFE_FastPathExecute(tf.Context, tf.Context.DeviceName,
+ "DecodeJpeg", name,
+ null,
+ contents,
+ "channels", channels,
+ "ratio", ratio,
+ "fancy_upscaling", fancy_upscaling,
+ "try_recover_truncated", try_recover_truncated,
+ "acceptable_fraction", acceptable_fraction,
+ "dct_method", dct_method);
+ return results[0];
}
else
{
@@ -171,17 +181,42 @@ namespace Tensorflow
"half_pixel_centers", half_pixel_centers);
return results[0];
}
- else
+
+ var _op = tf.OpDefLib._apply_op_helper("ResizeBilinear", name: name, args: new
{
- var _op = tf.OpDefLib._apply_op_helper("ResizeBilinear", name: name, args: new
- {
- images,
- size,
- align_corners
- });
+ images,
+ size,
+ align_corners
+ });
- return _op.outputs[0];
+ return _op.outputs[0];
+ }
+
+ public static Tensor resize_bicubic(Tensor images,
+ Tensor size,
+ bool align_corners = false,
+ bool half_pixel_centers = false,
+ string name = null)
+ {
+ if (tf.Context.executing_eagerly())
+ {
+ var results = tf.Runner.TFE_FastPathExecute(tf.Context, tf.Context.DeviceName,
+ "ResizeBicubic", name,
+ null,
+ images, size,
+ "align_corners", align_corners,
+ "half_pixel_centers", half_pixel_centers);
+ return results[0];
}
+
+ var _op = tf.OpDefLib._apply_op_helper("ResizeBicubic", name: name, args: new
+ {
+ images,
+ size,
+ align_corners
+ });
+
+ return _op.outputs[0];
}
public static Tensor resize_nearest_neighbor(Tensor images, Tsize size, bool align_corners = false,
diff --git a/src/TensorFlowNET.Core/Operations/gen_ops.cs b/src/TensorFlowNET.Core/Operations/gen_ops.cs
index a2935b59..072e9739 100644
--- a/src/TensorFlowNET.Core/Operations/gen_ops.cs
+++ b/src/TensorFlowNET.Core/Operations/gen_ops.cs
@@ -24715,13 +24715,12 @@ namespace Tensorflow.Operations
///
/// Input images can be of different types but output images are always float.
///
- public static Tensor resize_bicubic (Tensor images, Tensor size, bool? align_corners = null, string name = "ResizeBicubic")
+ public static Tensor resize_bicubic (Tensor images, Tensor size, bool align_corners = false, bool half_pixel_centers = false, string name = "ResizeBicubic")
{
var dict = new Dictionary();
dict["images"] = images;
dict["size"] = size;
- if (align_corners.HasValue)
- dict["align_corners"] = align_corners.Value;
+ dict["align_corners"] = align_corners;
var op = tf.OpDefLib._apply_op_helper("ResizeBicubic", name: name, keywords: dict);
return op.output;
}
diff --git a/src/TensorFlowNET.Core/Operations/image_ops_impl.cs b/src/TensorFlowNET.Core/Operations/image_ops_impl.cs
index 11cc6740..abc00600 100644
--- a/src/TensorFlowNET.Core/Operations/image_ops_impl.cs
+++ b/src/TensorFlowNET.Core/Operations/image_ops_impl.cs
@@ -686,18 +686,20 @@ or rank = 4. Had rank = {0}", rank));
} else if (images.TensorShape.ndim != 4)
throw new ValueError("\'images\' must have either 3 or 4 dimensions.");
- var _hw_ = images.TensorShape.as_list();
+ var (height, width) = (images.dims[1], images.dims[2]);
try
{
size = ops.convert_to_tensor(size, dtypes.int32, name: "size");
- } catch (Exception ex)
+ }
+ catch (Exception ex)
{
if (ex is TypeError || ex is ValueError)
throw new ValueError("\'size\' must be a 1-D int32 Tensor");
else
throw;
}
+
if (!size.TensorShape.is_compatible_with(new [] {2}))
throw new ValueError(@"\'size\' must be a 1-D Tensor of 2 elements:
new_height, new_width");
@@ -736,9 +738,9 @@ new_height, new_width");
bool x_null = true;
if (skip_resize_if_same)
{
- foreach (int x in new [] {new_width_const, _hw_[2], new_height_const, _hw_[1]})
+ foreach (int x in new [] {new_width_const, width, new_height_const, height})
{
- if (_hw_[2] != new_width_const && _hw_[1] == new_height_const)
+ if (width != new_width_const && height == new_height_const)
{
break;
}
@@ -753,8 +755,8 @@ new_height, new_width");
}
images = resizer_fn(images, size);
-
- images.set_shape(new TensorShape(new int[] {0, new_height_const, new_width_const, 0}));
+
+ // images.set_shape(new TensorShape(new int[] { -1, new_height_const, new_width_const, -1 }));
if (!is_batch)
images = array_ops.squeeze(images, axis: new int[] {0});
@@ -792,17 +794,20 @@ new_height, new_width");
if (antialias)
return resize_with_scale_and_translate("triangle");
else
- return gen_image_ops.resize_bilinear(
- images_t, new_size, true);
+ return gen_image_ops.resize_bilinear(images_t,
+ new_size,
+ half_pixel_centers: true);
else if (method == ResizeMethod.NEAREST_NEIGHBOR)
- return gen_image_ops.resize_nearest_neighbor(
- images_t, new_size, true);
+ return gen_image_ops.resize_nearest_neighbor(images_t,
+ new_size,
+ half_pixel_centers: true);
else if (method == ResizeMethod.BICUBIC)
if (antialias)
return resize_with_scale_and_translate("keyscubic");
else
- return gen_ops.resize_bicubic(
- images_t, new_size, true);
+ return gen_image_ops.resize_bicubic(images_t,
+ new_size,
+ half_pixel_centers: true);
else if (method == ResizeMethod.AREA)
return gen_ops.resize_area(images_t, new_size);
else if (Array.Exists(scale_and_translate_methods, method => method == method))
@@ -2078,9 +2083,8 @@ new_height, new_width");
return tf_with(ops.name_scope(name, "is_jpeg"), scope =>
{
var substr = tf.strings.substr(contents, 0, 3);
- var jpg = Encoding.UTF8.GetString(new byte[] { 0xff, 0xd8, 0xff });
- var jpg_tensor = tf.constant(jpg);
- var result = math_ops.equal(substr, jpg_tensor, name: name);
+ var jpg = tf.constant(new byte[] { 0xff, 0xd8, 0xff }, TF_DataType.TF_STRING);
+ var result = math_ops.equal(substr, jpg, name: name);
return result;
});
}
diff --git a/src/TensorFlowNET.Core/Tensorflow.Binding.csproj b/src/TensorFlowNET.Core/Tensorflow.Binding.csproj
index f101418f..b90996d1 100644
--- a/src/TensorFlowNET.Core/Tensorflow.Binding.csproj
+++ b/src/TensorFlowNET.Core/Tensorflow.Binding.csproj
@@ -5,7 +5,7 @@
TensorFlow.NET
Tensorflow
2.2.0
- 0.20.0-preview4
+ 0.20.0-preview5
8.0
Haiping Chen, Meinrad Recheis, Eli Belash
SciSharp STACK
@@ -79,7 +79,7 @@ Please be patient, we're working hard on missing functions, providing full tenso
-
+
diff --git a/src/TensorFlowNET.Core/Tensors/TensorShape.cs b/src/TensorFlowNET.Core/Tensors/TensorShape.cs
index 48f19cfa..0bc783be 100644
--- a/src/TensorFlowNET.Core/Tensors/TensorShape.cs
+++ b/src/TensorFlowNET.Core/Tensors/TensorShape.cs
@@ -143,7 +143,13 @@ namespace Tensorflow
public bool is_compatible_with(TensorShape shape2)
{
- throw new NotImplementedException("TensorShape is_compatible_with");
+ if(dims != null && shape2.dims != null)
+ {
+ if (dims.Length != shape2.dims.Length)
+ return false;
+ }
+
+ return true;
}
public void assert_has_rank(int rank)
diff --git a/src/TensorFlowNET.Core/Tensors/tensor_util.cs b/src/TensorFlowNET.Core/Tensors/tensor_util.cs
index c50d807f..3d8b8270 100644
--- a/src/TensorFlowNET.Core/Tensors/tensor_util.cs
+++ b/src/TensorFlowNET.Core/Tensors/tensor_util.cs
@@ -231,17 +231,7 @@ namespace Tensorflow
if (tensor.GetType() == typeof(EagerTensor))
{
- int[] dims = {};
- foreach (int dim in tensor.numpy())
- if (dim != 1)
- {
- dims[dims.Length] = dim;
- } else
- {
- // -1 == Unknown
- dims[dims.Length] = -1;
- }
- return new TensorShape(dims);
+ return new TensorShape(tensor.numpy().ToArray());
}
if (tensor.TensorShape.ndim == 0)
diff --git a/test/TensorFlowNET.UnitTest/NameScopeTest.cs b/test/TensorFlowNET.UnitTest/NameScopeTest.cs
index f631f422..12d2f7b4 100644
--- a/test/TensorFlowNET.UnitTest/NameScopeTest.cs
+++ b/test/TensorFlowNET.UnitTest/NameScopeTest.cs
@@ -45,6 +45,19 @@ namespace TensorFlowNET.UnitTest.Basics
Assert.AreEqual("", g._name_stack);
}
+ [TestMethod]
+ public void NameScopeInEagerMode()
+ {
+ tf.enable_eager_execution();
+
+ tf_with(new ops.NameScope("scope"), scope =>
+ {
+ string name = scope;
+ });
+
+ tf.compat.v1.disable_eager_execution();
+ }
+
[TestMethod, Ignore("Unimplemented Usage")]
public void NestedNameScope_Using()
{
diff --git a/test/TensorFlowNET.UnitTest/Tensorflow.UnitTest.csproj b/test/TensorFlowNET.UnitTest/Tensorflow.UnitTest.csproj
index 0c52feb0..d5c854c0 100644
--- a/test/TensorFlowNET.UnitTest/Tensorflow.UnitTest.csproj
+++ b/test/TensorFlowNET.UnitTest/Tensorflow.UnitTest.csproj
@@ -46,7 +46,6 @@
-