| @@ -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, | public static Tensor decode_image(Tensor contents, int channels = 0, TF_DataType dtype = TF_DataType.TF_UINT8, | ||||
| string name = null, bool expand_animations = true) | 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; | |||||
| }); | }); | ||||
| } | } | ||||
| @@ -5,7 +5,7 @@ | |||||
| <AssemblyName>TensorFlow.NET</AssemblyName> | <AssemblyName>TensorFlow.NET</AssemblyName> | ||||
| <RootNamespace>Tensorflow</RootNamespace> | <RootNamespace>Tensorflow</RootNamespace> | ||||
| <TargetTensorFlow>2.2.0</TargetTensorFlow> | <TargetTensorFlow>2.2.0</TargetTensorFlow> | ||||
| <Version>0.31.1</Version> | |||||
| <Version>0.31.2</Version> | |||||
| <LangVersion>8.0</LangVersion> | <LangVersion>8.0</LangVersion> | ||||
| <Authors>Haiping Chen, Meinrad Recheis, Eli Belash</Authors> | <Authors>Haiping Chen, Meinrad Recheis, Eli Belash</Authors> | ||||
| <Company>SciSharp STACK</Company> | <Company>SciSharp STACK</Company> | ||||
| @@ -19,7 +19,7 @@ | |||||
| <Description>Google's TensorFlow full binding in .NET Standard. | <Description>Google's TensorFlow full binding in .NET Standard. | ||||
| Building, training and infering deep learning models. | Building, training and infering deep learning models. | ||||
| https://tensorflownet.readthedocs.io</Description> | 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. | <PackageReleaseNotes>tf.net 0.20.x and above are based on tensorflow native 2.x. | ||||
| * Eager Mode is added finally. | * 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: | TensorFlow .NET v0.30 is focused on making more Keras API work including: | ||||
| * tf.keras.datasets | * tf.keras.datasets | ||||
| * Building keras model in subclass, functional and sequential api</PackageReleaseNotes> | * 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> | <PackageLicenseFile>LICENSE</PackageLicenseFile> | ||||
| <PackageRequireLicenseAcceptance>true</PackageRequireLicenseAcceptance> | <PackageRequireLicenseAcceptance>true</PackageRequireLicenseAcceptance> | ||||
| <SignAssembly>true</SignAssembly> | <SignAssembly>true</SignAssembly> | ||||
| @@ -20,6 +20,7 @@ using System.Collections.Generic; | |||||
| using System.Linq; | using System.Linq; | ||||
| using System.Text; | using System.Text; | ||||
| using Tensorflow.Eager; | using Tensorflow.Eager; | ||||
| using static Tensorflow.Binding; | |||||
| namespace Tensorflow | namespace Tensorflow | ||||
| { | { | ||||
| @@ -410,14 +411,10 @@ would not be rank 1.", tensor.op.get_attr("axis"))); | |||||
| var value = constant_value(tensor); | var value = constant_value(tensor); | ||||
| if (!(value is null)) | 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_)); | ret = ret.merge_with(new TensorShape(d_)); | ||||
| } | } | ||||
| return ret; | return ret; | ||||
| @@ -40,8 +40,8 @@ namespace Tensorflow.Keras.Preprocessings | |||||
| labels.AddRange(Enumerable.Range(0, files.Length).Select(x => label)); | 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) | if (shuffle) | ||||
| { | { | ||||
| @@ -41,7 +41,7 @@ namespace Tensorflow.Keras | |||||
| int num_channels = 0; | int num_channels = 0; | ||||
| if (color_mode == "rgb") | if (color_mode == "rgb") | ||||
| num_channels = 3; | 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, | var (image_paths, label_list, class_name_list) = keras.preprocessing.dataset_utils.index_directory(directory, | ||||
| formats: WHITELIST_FORMATS, | formats: WHITELIST_FORMATS, | ||||
| class_names: class_names, | class_names: class_names, | ||||
| @@ -16,27 +16,11 @@ namespace Tensorflow.Keras | |||||
| var path_ds = tf.data.Dataset.from_tensor_slices(image_paths); | 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)); | 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") | 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); | img_ds = tf.data.Dataset.zip(img_ds, label_ds); | ||||
| } | } | ||||
| else*/ | |||||
| throw new NotImplementedException(""); | |||||
| return img_ds; | return img_ds; | ||||
| } | } | ||||
| @@ -47,6 +31,7 @@ namespace Tensorflow.Keras | |||||
| img = tf.image.decode_image( | img = tf.image.decode_image( | ||||
| img, channels: num_channels, expand_animations: false); | img, channels: num_channels, expand_animations: false); | ||||
| img = tf.image.resize_images_v2(img, image_size, method: interpolation); | img = tf.image.resize_images_v2(img, image_size, method: interpolation); | ||||
| img.set_shape((image_size[0], image_size[1], num_channels)); | |||||
| return img; | return img; | ||||
| } | } | ||||
| } | } | ||||
| @@ -6,7 +6,7 @@ | |||||
| <LangVersion>8.0</LangVersion> | <LangVersion>8.0</LangVersion> | ||||
| <RootNamespace>Tensorflow.Keras</RootNamespace> | <RootNamespace>Tensorflow.Keras</RootNamespace> | ||||
| <Platforms>AnyCPU;x64</Platforms> | <Platforms>AnyCPU;x64</Platforms> | ||||
| <Version>0.2.1</Version> | |||||
| <Version>0.3.0</Version> | |||||
| <Authors>Haiping Chen</Authors> | <Authors>Haiping Chen</Authors> | ||||
| <Product>Keras for .NET</Product> | <Product>Keras for .NET</Product> | ||||
| <Copyright>Apache 2.0, Haiping Chen 2020</Copyright> | <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> | <Company>SciSharp STACK</Company> | ||||
| <GeneratePackageOnBuild>true</GeneratePackageOnBuild> | <GeneratePackageOnBuild>true</GeneratePackageOnBuild> | ||||
| <PackageTags>tensorflow, keras, deep learning, machine learning</PackageTags> | <PackageTags>tensorflow, keras, deep learning, machine learning</PackageTags> | ||||
| <PackageRequireLicenseAcceptance>false</PackageRequireLicenseAcceptance> | |||||
| <PackageRequireLicenseAcceptance>true</PackageRequireLicenseAcceptance> | |||||
| <RepositoryType>Git</RepositoryType> | <RepositoryType>Git</RepositoryType> | ||||
| <SignAssembly>true</SignAssembly> | <SignAssembly>true</SignAssembly> | ||||
| <AssemblyOriginatorKeyFile>Open.snk</AssemblyOriginatorKeyFile> | <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> | ||||
| <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'"> | <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" /> | <ProjectReference Include="..\TensorFlowNET.Core\Tensorflow.Binding.csproj" /> | ||||
| </ItemGroup> | </ItemGroup> | ||||
| <ItemGroup> | |||||
| <None Include="..\..\LICENSE"> | |||||
| <Pack>True</Pack> | |||||
| <PackagePath></PackagePath> | |||||
| </None> | |||||
| </ItemGroup> | |||||
| </Project> | </Project> | ||||