| @@ -42,6 +42,20 @@ namespace Tensorflow | |||||
| public Tensor convert_image_dtype(Tensor image, TF_DataType dtype, bool saturate = false, string name = null) | public Tensor convert_image_dtype(Tensor image, TF_DataType dtype, bool saturate = false, string name = null) | ||||
| => gen_image_ops.convert_image_dtype(image, dtype, saturate: saturate, name: name); | => gen_image_ops.convert_image_dtype(image, dtype, saturate: saturate, name: name); | ||||
| public Tensor decode_image(Tensor contents, int channels = 0, TF_DataType dtype = TF_DataType.TF_UINT8, | |||||
| string name = null, bool expand_animations = true) | |||||
| => image_ops_impl.decode_image(contents, channels: channels, dtype: dtype, | |||||
| name: name, expand_animations: expand_animations); | |||||
| /// <summary> | |||||
| /// Convenience function to check if the 'contents' encodes a JPEG image. | |||||
| /// </summary> | |||||
| /// <param name="contents"></param> | |||||
| /// <param name="name"></param> | |||||
| /// <returns></returns> | |||||
| public static Tensor is_jpeg(Tensor contents, string name = null) | |||||
| => image_ops_impl.is_jpeg(contents, name: name); | |||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| @@ -0,0 +1,32 @@ | |||||
| /***************************************************************************** | |||||
| Copyright 2018 The TensorFlow.NET Authors. All Rights Reserved. | |||||
| Licensed under the Apache License, Version 2.0 (the "License"); | |||||
| you may not use this file except in compliance with the License. | |||||
| You may obtain a copy of the License at | |||||
| http://www.apache.org/licenses/LICENSE-2.0 | |||||
| Unless required by applicable law or agreed to in writing, software | |||||
| distributed under the License is distributed on an "AS IS" BASIS, | |||||
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||||
| See the License for the specific language governing permissions and | |||||
| limitations under the License. | |||||
| ******************************************************************************/ | |||||
| using System.Collections.Generic; | |||||
| using Tensorflow.IO; | |||||
| namespace Tensorflow | |||||
| { | |||||
| public partial class tensorflow | |||||
| { | |||||
| public strings_internal strings = new strings_internal(); | |||||
| public class strings_internal | |||||
| { | |||||
| public Tensor substr(Tensor input, int pos, int len, | |||||
| string name = null, string @uint = "BYTE") | |||||
| => string_ops.substr(input, pos, len, name: name, @uint: @uint); | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -88,6 +88,69 @@ namespace Tensorflow | |||||
| } | } | ||||
| } | } | ||||
| public static Tensor decode_gif(Tensor contents, | |||||
| string name = null) | |||||
| { | |||||
| // Add nodes to the TensorFlow graph. | |||||
| if (tf.context.executing_eagerly()) | |||||
| { | |||||
| throw new NotImplementedException("decode_gif"); | |||||
| } | |||||
| else | |||||
| { | |||||
| var _op = _op_def_lib._apply_op_helper("DecodeGif", name: name, args: new | |||||
| { | |||||
| contents | |||||
| }); | |||||
| return _op.output; | |||||
| } | |||||
| } | |||||
| public static Tensor decode_png(Tensor contents, | |||||
| int channels = 0, | |||||
| TF_DataType dtype = TF_DataType.TF_UINT8, | |||||
| string name = null) | |||||
| { | |||||
| // Add nodes to the TensorFlow graph. | |||||
| if (tf.context.executing_eagerly()) | |||||
| { | |||||
| throw new NotImplementedException("decode_png"); | |||||
| } | |||||
| else | |||||
| { | |||||
| var _op = _op_def_lib._apply_op_helper("DecodePng", name: name, args: new | |||||
| { | |||||
| contents, | |||||
| channels, | |||||
| dtype | |||||
| }); | |||||
| return _op.output; | |||||
| } | |||||
| } | |||||
| public static Tensor decode_bmp(Tensor contents, | |||||
| int channels = 0, | |||||
| string name = null) | |||||
| { | |||||
| // Add nodes to the TensorFlow graph. | |||||
| if (tf.context.executing_eagerly()) | |||||
| { | |||||
| throw new NotImplementedException("decode_bmp"); | |||||
| } | |||||
| else | |||||
| { | |||||
| var _op = _op_def_lib._apply_op_helper("DecodeBmp", name: name, args: new | |||||
| { | |||||
| contents, | |||||
| channels | |||||
| }); | |||||
| return _op.output; | |||||
| } | |||||
| } | |||||
| public static Tensor resize_bilinear(Tensor images, Tensor size, bool align_corners = false, string name = null) | public static Tensor resize_bilinear(Tensor images, Tensor size, bool align_corners = false, string name = null) | ||||
| { | { | ||||
| if (tf.context.executing_eagerly()) | if (tf.context.executing_eagerly()) | ||||
| @@ -0,0 +1,42 @@ | |||||
| /***************************************************************************** | |||||
| Copyright 2018 The TensorFlow.NET Authors. All Rights Reserved. | |||||
| Licensed under the Apache License, Version 2.0 (the "License"); | |||||
| you may not use this file except in compliance with the License. | |||||
| You may obtain a copy of the License at | |||||
| http://www.apache.org/licenses/LICENSE-2.0 | |||||
| Unless required by applicable law or agreed to in writing, software | |||||
| distributed under the License is distributed on an "AS IS" BASIS, | |||||
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||||
| See the License for the specific language governing permissions and | |||||
| limitations under the License. | |||||
| ******************************************************************************/ | |||||
| using System; | |||||
| using System.Collections.Generic; | |||||
| using System.Text; | |||||
| namespace Tensorflow | |||||
| { | |||||
| public class gen_string_ops | |||||
| { | |||||
| static readonly OpDefLibrary _op_def_lib; | |||||
| static gen_string_ops() { _op_def_lib = new OpDefLibrary(); } | |||||
| public static Tensor substr(Tensor input, int pos, int len, | |||||
| string name = null, string @uint = "BYTE") | |||||
| { | |||||
| var _op = _op_def_lib._apply_op_helper("Substr", name: name, args: new | |||||
| { | |||||
| input, | |||||
| pos, | |||||
| len, | |||||
| unit = @uint | |||||
| }); | |||||
| return _op.output; | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -17,11 +17,116 @@ | |||||
| using System; | using System; | ||||
| using System.Collections.Generic; | using System.Collections.Generic; | ||||
| using System.Text; | using System.Text; | ||||
| using static Tensorflow.Binding; | |||||
| namespace Tensorflow | namespace Tensorflow | ||||
| { | { | ||||
| public class image_ops_impl | public class image_ops_impl | ||||
| { | { | ||||
| public static Tensor decode_image(Tensor contents, int channels = 0, TF_DataType dtype = TF_DataType.TF_UINT8, | |||||
| string name = null, bool expand_animations = true) | |||||
| { | |||||
| Tensor substr = null; | |||||
| Func<ITensorOrOperation> _jpeg = () => | |||||
| { | |||||
| 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 | |||||
| { | |||||
| var result = convert_image_dtype(gen_image_ops.decode_gif(contents), dtype); | |||||
| if (!expand_animations) | |||||
| // result = array_ops.gather(result, 0); | |||||
| throw new NotImplementedException(""); | |||||
| return result; | |||||
| }); | |||||
| }; | |||||
| Func<ITensorOrOperation> _bmp = () => | |||||
| { | |||||
| int bmp_channels = channels; | |||||
| var signature = string_ops.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> check_gif = () => | |||||
| { | |||||
| var is_gif = math_ops.equal(substr, "\x47\x49\x46", name: "is_gif"); | |||||
| 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"); | |||||
| }; | |||||
| return tf_with(ops.name_scope(name, "decode_image"), scope => | |||||
| { | |||||
| substr = string_ops.substr(contents, 0, 3); | |||||
| return control_flow_ops.cond(is_jpeg(contents), _jpeg, check_png, name: "cond_jpeg"); | |||||
| }); | |||||
| } | |||||
| public static Tensor is_jpeg(Tensor contents, string name = null) | |||||
| { | |||||
| return tf_with(ops.name_scope(name, "is_jpeg"), scope => | |||||
| { | |||||
| var substr = string_ops.substr(contents, 0, 3); | |||||
| return math_ops.equal(substr, "\xff\xd8\xff", name: name); | |||||
| }); | |||||
| } | |||||
| public static Tensor _is_png(Tensor contents, string name = null) | |||||
| { | |||||
| return tf_with(ops.name_scope(name, "is_png"), scope => | |||||
| { | |||||
| var substr = string_ops.substr(contents, 0, 3); | |||||
| return math_ops.equal(substr, @"\211PN", name: name); | |||||
| }); | |||||
| } | |||||
| public static Tensor convert_image_dtype(Tensor image, TF_DataType dtype, bool saturate = false, | |||||
| string name = null) | |||||
| { | |||||
| if (dtype == image.dtype) | |||||
| return array_ops.identity(image, name: name); | |||||
| throw new NotImplementedException(""); | |||||
| } | |||||
| } | } | ||||
| } | } | ||||
| @@ -168,6 +168,9 @@ namespace Tensorflow | |||||
| public static Tensor multiply<Tx, Ty>(Tx x, Ty y, string name = null) | public static Tensor multiply<Tx, Ty>(Tx x, Ty y, string name = null) | ||||
| => gen_math_ops.mul(x, y, name: name); | => gen_math_ops.mul(x, y, name: name); | ||||
| public static Tensor not_equal<Tx, Ty>(Tx x, Ty y, string name = null) | |||||
| => gen_math_ops.not_equal(x, y, name: name); | |||||
| public static Tensor mul_no_nan<Tx, Ty>(Tx x, Ty y, string name = null) | public static Tensor mul_no_nan<Tx, Ty>(Tx x, Ty y, string name = null) | ||||
| => gen_math_ops.mul_no_nan(x, y, name: name); | => gen_math_ops.mul_no_nan(x, y, name: name); | ||||
| @@ -264,6 +267,9 @@ namespace Tensorflow | |||||
| return gen_math_ops.log(x, name); | return gen_math_ops.log(x, name); | ||||
| } | } | ||||
| public static Tensor logical_and(Tensor x, Tensor y, string name = null) | |||||
| => gen_math_ops.logical_and(x, y, name: name); | |||||
| public static Tensor lgamma(Tensor x, string name = null) | public static Tensor lgamma(Tensor x, string name = null) | ||||
| => gen_math_ops.lgamma(x, name: name); | => gen_math_ops.lgamma(x, name: name); | ||||
| @@ -0,0 +1,38 @@ | |||||
| /***************************************************************************** | |||||
| Copyright 2018 The TensorFlow.NET Authors. All Rights Reserved. | |||||
| Licensed under the Apache License, Version 2.0 (the "License"); | |||||
| you may not use this file except in compliance with the License. | |||||
| You may obtain a copy of the License at | |||||
| http://www.apache.org/licenses/LICENSE-2.0 | |||||
| Unless required by applicable law or agreed to in writing, software | |||||
| distributed under the License is distributed on an "AS IS" BASIS, | |||||
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||||
| See the License for the specific language governing permissions and | |||||
| limitations under the License. | |||||
| ******************************************************************************/ | |||||
| using System; | |||||
| using System.Collections.Generic; | |||||
| using System.Text; | |||||
| namespace Tensorflow | |||||
| { | |||||
| public class string_ops | |||||
| { | |||||
| /// <summary> | |||||
| /// Return substrings from `Tensor` of strings. | |||||
| /// </summary> | |||||
| /// <param name="input"></param> | |||||
| /// <param name="pos"></param> | |||||
| /// <param name="len"></param> | |||||
| /// <param name="name"></param> | |||||
| /// <param name="uint"></param> | |||||
| /// <returns></returns> | |||||
| public static Tensor substr(Tensor input, int pos, int len, | |||||
| string name = null, string @uint = "BYTE") | |||||
| => gen_string_ops.substr(input, pos, len, name: name, @uint: @uint); | |||||
| } | |||||
| } | |||||
| @@ -416,12 +416,13 @@ namespace TensorFlowNET.UnitTest | |||||
| } | } | ||||
| [TestMethod] | |||||
| public void ImportGraphMeta() | public void ImportGraphMeta() | ||||
| { | { | ||||
| var dir = "my-save-dir/"; | var dir = "my-save-dir/"; | ||||
| using (var sess = tf.Session()) | using (var sess = tf.Session()) | ||||
| { | { | ||||
| var new_saver = tf.train.import_meta_graph(dir + "my-model-10000.meta"); | |||||
| var new_saver = tf.train.import_meta_graph(@"D:\tmp\resnet_v2_101_2017_04_14\eval.graph"); | |||||
| new_saver.restore(sess, dir + "my-model-10000"); | new_saver.restore(sess, dir + "my-model-10000"); | ||||
| var labels = tf.constant(0, dtype: tf.int32, shape: new int[] { 100 }, name: "labels"); | var labels = tf.constant(0, dtype: tf.int32, shape: new int[] { 100 }, name: "labels"); | ||||
| var batch_size = tf.size(labels); | var batch_size = tf.size(labels); | ||||
| @@ -0,0 +1,30 @@ | |||||
| using Microsoft.VisualStudio.TestTools.UnitTesting; | |||||
| using System; | |||||
| using System.Collections.Generic; | |||||
| using System.IO; | |||||
| using System.Text; | |||||
| using Tensorflow; | |||||
| using static Tensorflow.Binding; | |||||
| namespace TensorFlowNET.UnitTest | |||||
| { | |||||
| [TestClass] | |||||
| public class ImageTest | |||||
| { | |||||
| string imgPath = "../../../../../data/shasta-daisy.jpg"; | |||||
| Tensor contents; | |||||
| public ImageTest() | |||||
| { | |||||
| imgPath = Path.GetFullPath(imgPath); | |||||
| contents = tf.read_file(imgPath); | |||||
| } | |||||
| [TestMethod] | |||||
| public void decode_image() | |||||
| { | |||||
| var img = tf.image.decode_image(contents); | |||||
| Assert.AreEqual(img.name, "decode_image/cond_jpeg/Merge:0"); | |||||
| } | |||||
| } | |||||
| } | |||||