diff --git a/src/TensorFlowNET.Core/Operations/image_ops_impl.cs b/src/TensorFlowNET.Core/Operations/image_ops_impl.cs index 014e376a..e48cb031 100644 --- a/src/TensorFlowNET.Core/Operations/image_ops_impl.cs +++ b/src/TensorFlowNET.Core/Operations/image_ops_impl.cs @@ -1702,74 +1702,79 @@ new_height, new_width"); public static Tensor decode_image(Tensor contents, int channels = 0, TF_DataType dtype = TF_DataType.TF_UINT8, string name = null, bool expand_animations = true) { - Func _jpeg = () => + return tf_with(ops.name_scope(name, "decode_image"), scope => { - int jpeg_channels = channels; - var good_channels = math_ops.not_equal(jpeg_channels, 4, name: "check_jpeg_channels"); - string channels_msg = "Channels must be in (None, 0, 1, 3) when decoding JPEG 'images'"; - var assert_channels = control_flow_ops.Assert(good_channels, new string[] { channels_msg }); - return tf_with(ops.control_dependencies(new[] { assert_channels }), delegate + var substr = tf.strings.substr(contents, 0, 3); + + Func _jpeg = () => { - return convert_image_dtype(gen_image_ops.decode_jpeg(contents, channels), dtype); - }); - }; + int jpeg_channels = channels; + var good_channels = math_ops.not_equal(jpeg_channels, 4, name: "check_jpeg_channels"); + string channels_msg = "Channels must be in (None, 0, 1, 3) when decoding JPEG 'images'"; + var assert_channels = control_flow_ops.Assert(good_channels, new string[] { channels_msg }); + return tf_with(ops.control_dependencies(new[] { assert_channels }), delegate + { + return convert_image_dtype(gen_image_ops.decode_jpeg(contents, channels), dtype); + }); + }; - Func _gif = () => - { - int gif_channels = channels; - var good_channels = math_ops.logical_and( - math_ops.not_equal(gif_channels, 1, name: "check_gif_channels"), - math_ops.not_equal(gif_channels, 4, name: "check_gif_channels")); - - string channels_msg = "Channels must be in (None, 0, 3) when decoding GIF images"; - var assert_channels = control_flow_ops.Assert(good_channels, new string[] { channels_msg }); - return tf_with(ops.control_dependencies(new[] { assert_channels }), delegate + /*Func _gif = () => { - var result = convert_image_dtype(gen_image_ops.decode_gif(contents), dtype); - if (!expand_animations) - result = array_ops.gather(result, 0); - return result; - }); - }; + int gif_channels = channels; + var good_channels = math_ops.logical_and( + math_ops.not_equal(gif_channels, 1, name: "check_gif_channels"), + math_ops.not_equal(gif_channels, 4, name: "check_gif_channels")); + + string channels_msg = "Channels must be in (None, 0, 3) when decoding GIF images"; + var assert_channels = control_flow_ops.Assert(good_channels, new string[] { channels_msg }); + return tf_with(ops.control_dependencies(new[] { assert_channels }), delegate + { + var result = convert_image_dtype(gen_image_ops.decode_gif(contents), dtype); + if (!expand_animations) + result = array_ops.gather(result, 0); + return result; + }); + }; - Func _bmp = () => - { - int bmp_channels = channels; - var signature = tf.strings.substr(contents, 0, 2); - var is_bmp = math_ops.equal(signature, "BM", name: "is_bmp"); - string decode_msg = "Unable to decode bytes as JPEG, PNG, GIF, or BMP"; - var assert_decode = control_flow_ops.Assert(is_bmp, new string[] { decode_msg }); - var good_channels = math_ops.not_equal(bmp_channels, 1, name: "check_channels"); - string channels_msg = "Channels must be in (None, 0, 3) when decoding BMP images"; - var assert_channels = control_flow_ops.Assert(good_channels, new string[] { channels_msg }); - return tf_with(ops.control_dependencies(new[] { assert_decode, assert_channels }), delegate + Func _bmp = () => { - return convert_image_dtype(gen_image_ops.decode_bmp(contents), dtype); - }); - }; + int bmp_channels = channels; + var signature = tf.strings.substr(contents, 0, 2); + var is_bmp = math_ops.equal(signature, "BM", name: "is_bmp"); + string decode_msg = "Unable to decode bytes as JPEG, PNG, GIF, or BMP"; + var assert_decode = control_flow_ops.Assert(is_bmp, new string[] { decode_msg }); + var good_channels = math_ops.not_equal(bmp_channels, 1, name: "check_channels"); + string channels_msg = "Channels must be in (None, 0, 3) when decoding BMP images"; + var assert_channels = control_flow_ops.Assert(good_channels, new string[] { channels_msg }); + return tf_with(ops.control_dependencies(new[] { assert_decode, assert_channels }), delegate + { + return convert_image_dtype(gen_image_ops.decode_bmp(contents), dtype); + }); + }; - Func _png = () => - { - return convert_image_dtype(gen_image_ops.decode_png( - contents, - channels, - dtype: dtype), - dtype); - }; + Func _png = () => + { + return convert_image_dtype(gen_image_ops.decode_png( + contents, + channels, + dtype: dtype), + dtype); + }; - Func check_gif = () => - { - return control_flow_ops.cond(is_gif(contents), _gif, _bmp, name: "cond_gif"); - }; + Func check_gif = () => + { + var gif = tf.constant(new byte[] { 0x47, 0x49, 0x46 }, TF_DataType.TF_STRING); + var is_gif = math_ops.equal(substr, gif, name: name); + return control_flow_ops.cond(is_gif, _gif, _bmp, name: "cond_gif"); + }; - Func check_png = () => - { - return control_flow_ops.cond(is_png(contents), _png, check_gif, name: "cond_png"); - }; + Func check_png = () => + { + return control_flow_ops.cond(is_png(contents), _png, check_gif, name: "cond_png"); + };*/ - return tf_with(ops.name_scope(name, "decode_image"), scope => - { - return control_flow_ops.cond(is_jpeg(contents), _jpeg, check_png, name: "cond_jpeg"); + // return control_flow_ops.cond(is_jpeg(contents), _jpeg, check_png, name: "cond_jpeg"); + return _jpeg() as Tensor; }); } diff --git a/src/TensorFlowNET.Core/Tensorflow.Binding.csproj b/src/TensorFlowNET.Core/Tensorflow.Binding.csproj index 4ea95719..bc0af8ff 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.31.1 + 0.31.2 8.0 Haiping Chen, Meinrad Recheis, Eli Belash SciSharp STACK @@ -19,7 +19,7 @@ Google's TensorFlow full binding in .NET Standard. Building, training and infering deep learning models. https://tensorflownet.readthedocs.io - 0.31.1.0 + 0.31.2.0 tf.net 0.20.x and above are based on tensorflow native 2.x. * Eager Mode is added finally. @@ -30,7 +30,7 @@ https://tensorflownet.readthedocs.io TensorFlow .NET v0.30 is focused on making more Keras API work including: * tf.keras.datasets * Building keras model in subclass, functional and sequential api - 0.31.1.0 + 0.31.2.0 LICENSE true true diff --git a/src/TensorFlowNET.Core/Tensors/tensor_util.cs b/src/TensorFlowNET.Core/Tensors/tensor_util.cs index 7a665c23..b17ee329 100644 --- a/src/TensorFlowNET.Core/Tensors/tensor_util.cs +++ b/src/TensorFlowNET.Core/Tensors/tensor_util.cs @@ -20,6 +20,7 @@ using System.Collections.Generic; using System.Linq; using System.Text; using Tensorflow.Eager; +using static Tensorflow.Binding; namespace Tensorflow { @@ -410,14 +411,10 @@ would not be rank 1.", tensor.op.get_attr("axis"))); var value = constant_value(tensor); if (!(value is null)) { - int[] d_ = { }; - foreach (int d in value) - { - if (d >= 0) - d_[d_.Length] = d; - else - d_[d_.Length] = -1; // None - } + var d_ = new int[value.size]; + foreach (var (index, d) in enumerate(value.ToArray())) + d_[index] = d >= 0 ? d : -1; + ret = ret.merge_with(new TensorShape(d_)); } return ret; diff --git a/src/TensorFlowNET.Keras/Preprocessings/DatasetUtils.index_directory.cs b/src/TensorFlowNET.Keras/Preprocessings/DatasetUtils.index_directory.cs index 33754b00..cf7ef12c 100644 --- a/src/TensorFlowNET.Keras/Preprocessings/DatasetUtils.index_directory.cs +++ b/src/TensorFlowNET.Keras/Preprocessings/DatasetUtils.index_directory.cs @@ -40,8 +40,8 @@ namespace Tensorflow.Keras.Preprocessings 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]; + var return_labels = labels.Select(x => x).ToArray(); + var return_file_paths = file_paths.Select(x => x).ToArray(); if (shuffle) { diff --git a/src/TensorFlowNET.Keras/Preprocessings/Preprocessing.image_dataset_from_directory.cs b/src/TensorFlowNET.Keras/Preprocessings/Preprocessing.image_dataset_from_directory.cs index c9af1915..a57ac73e 100644 --- a/src/TensorFlowNET.Keras/Preprocessings/Preprocessing.image_dataset_from_directory.cs +++ b/src/TensorFlowNET.Keras/Preprocessings/Preprocessing.image_dataset_from_directory.cs @@ -41,7 +41,7 @@ namespace Tensorflow.Keras int num_channels = 0; if (color_mode == "rgb") num_channels = 3; - // C:/Users/haipi/.keras/datasets/flower_photos + var (image_paths, label_list, class_name_list) = keras.preprocessing.dataset_utils.index_directory(directory, formats: WHITELIST_FORMATS, class_names: class_names, diff --git a/src/TensorFlowNET.Keras/Preprocessings/Preprocessing.paths_and_labels_to_dataset.cs b/src/TensorFlowNET.Keras/Preprocessings/Preprocessing.paths_and_labels_to_dataset.cs index ad950fc9..d1bf1d97 100644 --- a/src/TensorFlowNET.Keras/Preprocessings/Preprocessing.paths_and_labels_to_dataset.cs +++ b/src/TensorFlowNET.Keras/Preprocessings/Preprocessing.paths_and_labels_to_dataset.cs @@ -16,27 +16,11 @@ namespace Tensorflow.Keras var path_ds = tf.data.Dataset.from_tensor_slices(image_paths); var img_ds = path_ds.map(x => path_to_image(x, image_size, num_channels, interpolation)); - /*Shape shape = (image_paths.Length, image_size.dims[0], image_size.dims[1], num_channels); - Console.WriteLine($"Allocating memory for shape{shape}, {NPTypeCode.Float}"); - var data = np.zeros(shape, NPTypeCode.Float); - - for (var i = 0; i < image_paths.Length; i++) - { - var image = path_to_image(image_paths[i], image_size, num_channels, interpolation); - data[i] = image.numpy(); - if (i % 100 == 0) - Console.WriteLine($"Filled {i}/{image_paths.Length} data into ndarray."); - } - - var img_ds = tf.data.Dataset.from_tensor_slices(data); - if (label_mode == "int") { - var label_ds = tf.keras.preprocessing.dataset_utils.labels_to_dataset(labels, label_mode, num_classes); + var label_ds = dataset_utils.labels_to_dataset(labels, label_mode, num_classes); img_ds = tf.data.Dataset.zip(img_ds, label_ds); } - else*/ - throw new NotImplementedException(""); return img_ds; } @@ -47,6 +31,7 @@ namespace Tensorflow.Keras img = tf.image.decode_image( img, channels: num_channels, expand_animations: false); img = tf.image.resize_images_v2(img, image_size, method: interpolation); + img.set_shape((image_size[0], image_size[1], num_channels)); return img; } } diff --git a/src/TensorFlowNET.Keras/Tensorflow.Keras.csproj b/src/TensorFlowNET.Keras/Tensorflow.Keras.csproj index aec973ad..b97fdb8d 100644 --- a/src/TensorFlowNET.Keras/Tensorflow.Keras.csproj +++ b/src/TensorFlowNET.Keras/Tensorflow.Keras.csproj @@ -6,7 +6,7 @@ 8.0 Tensorflow.Keras AnyCPU;x64 - 0.2.1 + 0.3.0 Haiping Chen Keras for .NET Apache 2.0, Haiping Chen 2020 @@ -25,11 +25,13 @@ Keras is an API designed for human beings, not machines. Keras follows best prac SciSharp STACK true tensorflow, keras, deep learning, machine learning - false + true Git true Open.snk - 0.2.1.0 + 0.3.0.0 + 0.3.0.0 + LICENSE @@ -55,4 +57,11 @@ Keras is an API designed for human beings, not machines. Keras follows best prac + + + True + + + +