Browse Source

Fix image_dataset_from_directory #666

tags/keras_v0.3.0
Oceania2018 4 years ago
parent
commit
8c0feae8bf
7 changed files with 88 additions and 92 deletions
  1. +63
    -58
      src/TensorFlowNET.Core/Operations/image_ops_impl.cs
  2. +3
    -3
      src/TensorFlowNET.Core/Tensorflow.Binding.csproj
  3. +5
    -8
      src/TensorFlowNET.Core/Tensors/tensor_util.cs
  4. +2
    -2
      src/TensorFlowNET.Keras/Preprocessings/DatasetUtils.index_directory.cs
  5. +1
    -1
      src/TensorFlowNET.Keras/Preprocessings/Preprocessing.image_dataset_from_directory.cs
  6. +2
    -17
      src/TensorFlowNET.Keras/Preprocessings/Preprocessing.paths_and_labels_to_dataset.cs
  7. +12
    -3
      src/TensorFlowNET.Keras/Tensorflow.Keras.csproj

+ 63
- 58
src/TensorFlowNET.Core/Operations/image_ops_impl.cs View File

@@ -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<ITensorOrOperation> _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<ITensorOrOperation> _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<ITensorOrOperation> _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<ITensorOrOperation> _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<ITensorOrOperation> _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<ITensorOrOperation> _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<ITensorOrOperation> _png = () =>
{
return convert_image_dtype(gen_image_ops.decode_png(
contents,
channels,
dtype: dtype),
dtype);
};
Func<ITensorOrOperation> _png = () =>
{
return convert_image_dtype(gen_image_ops.decode_png(
contents,
channels,
dtype: dtype),
dtype);
};

Func<ITensorOrOperation> check_gif = () =>
{
return control_flow_ops.cond(is_gif(contents), _gif, _bmp, name: "cond_gif");
};
Func<ITensorOrOperation> 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<ITensorOrOperation> check_png = () =>
{
return control_flow_ops.cond(is_png(contents), _png, check_gif, name: "cond_png");
};
Func<ITensorOrOperation> 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;
});
}



+ 3
- 3
src/TensorFlowNET.Core/Tensorflow.Binding.csproj View File

@@ -5,7 +5,7 @@
<AssemblyName>TensorFlow.NET</AssemblyName>
<RootNamespace>Tensorflow</RootNamespace>
<TargetTensorFlow>2.2.0</TargetTensorFlow>
<Version>0.31.1</Version>
<Version>0.31.2</Version>
<LangVersion>8.0</LangVersion>
<Authors>Haiping Chen, Meinrad Recheis, Eli Belash</Authors>
<Company>SciSharp STACK</Company>
@@ -19,7 +19,7 @@
<Description>Google's TensorFlow full binding in .NET Standard.
Building, training and infering deep learning models.
https://tensorflownet.readthedocs.io</Description>
<AssemblyVersion>0.31.1.0</AssemblyVersion>
<AssemblyVersion>0.31.2.0</AssemblyVersion>
<PackageReleaseNotes>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</Description>
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</PackageReleaseNotes>
<FileVersion>0.31.1.0</FileVersion>
<FileVersion>0.31.2.0</FileVersion>
<PackageLicenseFile>LICENSE</PackageLicenseFile>
<PackageRequireLicenseAcceptance>true</PackageRequireLicenseAcceptance>
<SignAssembly>true</SignAssembly>


+ 5
- 8
src/TensorFlowNET.Core/Tensors/tensor_util.cs View File

@@ -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<int>()))
d_[index] = d >= 0 ? d : -1;
ret = ret.merge_with(new TensorShape(d_));
}
return ret;


+ 2
- 2
src/TensorFlowNET.Keras/Preprocessings/DatasetUtils.index_directory.cs View File

@@ -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)
{


+ 1
- 1
src/TensorFlowNET.Keras/Preprocessings/Preprocessing.image_dataset_from_directory.cs View File

@@ -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,


+ 2
- 17
src/TensorFlowNET.Keras/Preprocessings/Preprocessing.paths_and_labels_to_dataset.cs View File

@@ -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;
}
}


+ 12
- 3
src/TensorFlowNET.Keras/Tensorflow.Keras.csproj View File

@@ -6,7 +6,7 @@
<LangVersion>8.0</LangVersion>
<RootNamespace>Tensorflow.Keras</RootNamespace>
<Platforms>AnyCPU;x64</Platforms>
<Version>0.2.1</Version>
<Version>0.3.0</Version>
<Authors>Haiping Chen</Authors>
<Product>Keras for .NET</Product>
<Copyright>Apache 2.0, Haiping Chen 2020</Copyright>
@@ -25,11 +25,13 @@ Keras is an API designed for human beings, not machines. Keras follows best prac
<Company>SciSharp STACK</Company>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<PackageTags>tensorflow, keras, deep learning, machine learning</PackageTags>
<PackageRequireLicenseAcceptance>false</PackageRequireLicenseAcceptance>
<PackageRequireLicenseAcceptance>true</PackageRequireLicenseAcceptance>
<RepositoryType>Git</RepositoryType>
<SignAssembly>true</SignAssembly>
<AssemblyOriginatorKeyFile>Open.snk</AssemblyOriginatorKeyFile>
<AssemblyVersion>0.2.1.0</AssemblyVersion>
<AssemblyVersion>0.3.0.0</AssemblyVersion>
<FileVersion>0.3.0.0</FileVersion>
<PackageLicenseFile>LICENSE</PackageLicenseFile>
</PropertyGroup>

<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
@@ -55,4 +57,11 @@ Keras is an API designed for human beings, not machines. Keras follows best prac
<ProjectReference Include="..\TensorFlowNET.Core\Tensorflow.Binding.csproj" />
</ItemGroup>

<ItemGroup>
<None Include="..\..\LICENSE">
<Pack>True</Pack>
<PackagePath></PackagePath>
</None>
</ItemGroup>

</Project>

Loading…
Cancel
Save