| @@ -174,6 +174,20 @@ namespace Tensorflow | |||||
| return array_ops.reverse(tensor, axis, name: name); | return array_ops.reverse(tensor, axis, name: name); | ||||
| } | } | ||||
| /// <summary> | |||||
| /// Reverses specific dimensions of a tensor. | |||||
| /// </summary> | |||||
| /// <param name="tensor"></param> | |||||
| /// <param name="axis"></param> | |||||
| /// <param name="name"></param> | |||||
| /// <returns></returns> | |||||
| public Tensor reverse_v2(Tensor tensor, int[] axis, string name = null) | |||||
| => gen_array_ops.reverse_v2(tensor, ops.convert_to_tensor(axis), name: name); | |||||
| public Tensor reverse_v2(Tensor tensor, Tensor axis, string name = null) | |||||
| => gen_array_ops.reverse_v2(tensor, axis, name: name); | |||||
| /// <summary> | /// <summary> | ||||
| /// Returns the rank of a tensor. | /// Returns the rank of a tensor. | ||||
| /// </summary> | /// </summary> | ||||
| @@ -339,6 +339,13 @@ namespace Tensorflow | |||||
| => image_ops_impl.decode_image(contents, channels: channels, dtype: dtype, | => image_ops_impl.decode_image(contents, channels: channels, dtype: dtype, | ||||
| name: name, expand_animations: expand_animations); | name: name, expand_animations: expand_animations); | ||||
| public Tensor encode_png(Tensor contents, string name = null) | |||||
| => image_ops_impl.encode_png(contents, name: name); | |||||
| public Tensor encode_jpeg(Tensor contents, string name = null) | |||||
| => image_ops_impl.encode_jpeg(contents, name: name); | |||||
| /// <summary> | /// <summary> | ||||
| /// Convenience function to check if the 'contents' encodes a JPEG image. | /// Convenience function to check if the 'contents' encodes a JPEG image. | ||||
| /// </summary> | /// </summary> | ||||
| @@ -16,6 +16,7 @@ | |||||
| using System.Collections.Generic; | using System.Collections.Generic; | ||||
| using Tensorflow.IO; | using Tensorflow.IO; | ||||
| using Tensorflow.Operations; | |||||
| namespace Tensorflow | namespace Tensorflow | ||||
| { | { | ||||
| @@ -46,6 +47,12 @@ namespace Tensorflow | |||||
| public Tensor[] restore_v2(Tensor prefix, string[] tensor_names, | public Tensor[] restore_v2(Tensor prefix, string[] tensor_names, | ||||
| string[] shape_and_slices, TF_DataType[] dtypes, string name = null) | string[] shape_and_slices, TF_DataType[] dtypes, string name = null) | ||||
| => ops.restore_v2(prefix, tensor_names, shape_and_slices, dtypes, name: name); | => ops.restore_v2(prefix, tensor_names, shape_and_slices, dtypes, name: name); | ||||
| public void write_file(string filename, Tensor conentes, string name = null) | |||||
| => write_file(Tensorflow.ops.convert_to_tensor(filename, TF_DataType.TF_STRING), conentes, name); | |||||
| public void write_file(Tensor filename, Tensor conentes, string name = null) | |||||
| => gen_ops.write_file(filename, conentes, name); | |||||
| } | } | ||||
| public GFile gfile = new GFile(); | public GFile gfile = new GFile(); | ||||
| @@ -39083,13 +39083,14 @@ namespace Tensorflow.Operations | |||||
| /// <remarks> | /// <remarks> | ||||
| /// creates directory if not existing. | /// creates directory if not existing. | ||||
| /// </remarks> | /// </remarks> | ||||
| public static Operation write_file(Tensor filename, Tensor contents, string name = "WriteFile") | |||||
| public static Tensor write_file(Tensor filename, Tensor contents, string name = "WriteFile") | |||||
| { | { | ||||
| var dict = new Dictionary<string, object>(); | var dict = new Dictionary<string, object>(); | ||||
| dict["filename"] = filename; | dict["filename"] = filename; | ||||
| dict["contents"] = contents; | dict["contents"] = contents; | ||||
| var op = tf.OpDefLib._apply_op_helper("WriteFile", name: name, keywords: dict); | var op = tf.OpDefLib._apply_op_helper("WriteFile", name: name, keywords: dict); | ||||
| return op; | |||||
| op.run(); | |||||
| return op.output; | |||||
| } | } | ||||
| /// <summary> | /// <summary> | ||||
| @@ -2047,6 +2047,22 @@ new_height, new_width"); | |||||
| }); | }); | ||||
| } | } | ||||
| public static Tensor encode_jpeg(Tensor contents, string name = null) | |||||
| { | |||||
| return tf_with(ops.name_scope(name, "encode_jpeg"), scope => | |||||
| { | |||||
| return gen_ops.encode_jpeg(contents, name:name); | |||||
| }); | |||||
| } | |||||
| public static Tensor encode_png(Tensor contents, string name = null) | |||||
| { | |||||
| return tf_with(ops.name_scope(name, "encode_png"), scope => | |||||
| { | |||||
| return gen_ops.encode_png(contents, name: name); | |||||
| }); | |||||
| } | |||||
| public static Tensor is_jpeg(Tensor contents, string name = null) | public static Tensor is_jpeg(Tensor contents, string name = null) | ||||
| { | { | ||||
| return tf_with(ops.name_scope(name, "is_jpeg"), scope => | return tf_with(ops.name_scope(name, "is_jpeg"), scope => | ||||
| @@ -4,6 +4,7 @@ using System.Linq; | |||||
| using Tensorflow; | using Tensorflow; | ||||
| using static Tensorflow.Binding; | using static Tensorflow.Binding; | ||||
| using System; | using System; | ||||
| using System.IO; | |||||
| namespace TensorFlowNET.UnitTest | namespace TensorFlowNET.UnitTest | ||||
| { | { | ||||
| @@ -164,5 +165,32 @@ namespace TensorFlowNET.UnitTest | |||||
| Assert.AreEqual(result.size, 16ul); | Assert.AreEqual(result.size, 16ul); | ||||
| Assert.AreEqual(result[0, 0, 0, 0], 12f); | Assert.AreEqual(result[0, 0, 0, 0], 12f); | ||||
| } | } | ||||
| [TestMethod] | |||||
| public void ImageSaveTest() | |||||
| { | |||||
| var imgPath = TestHelper.GetFullPathFromDataDir("img001.bmp"); | |||||
| var jpegImgPath = TestHelper.GetFullPathFromDataDir("img001.jpeg"); | |||||
| var pngImgPath = TestHelper.GetFullPathFromDataDir("img001.png"); | |||||
| File.Delete(jpegImgPath); | |||||
| File.Delete(pngImgPath); | |||||
| var contents = tf.io.read_file(imgPath); | |||||
| var bmp = tf.image.decode_image(contents); | |||||
| Assert.AreEqual(bmp.name, "decode_image/DecodeImage:0"); | |||||
| var jpeg = tf.image.encode_jpeg(bmp); | |||||
| tf.io.write_file(jpegImgPath, jpeg); | |||||
| Assert.IsTrue(File.Exists(jpegImgPath)); | |||||
| var png = tf.image.encode_png(bmp); | |||||
| tf.io.write_file(pngImgPath, png); | |||||
| Assert.IsTrue(File.Exists(pngImgPath)); | |||||
| // 如果要测试图片正确性,可以注释下面两行代码 | |||||
| File.Delete(jpegImgPath); | |||||
| File.Delete(pngImgPath); | |||||
| } | |||||
| } | } | ||||
| } | } | ||||
| @@ -4,6 +4,163 @@ using Tensorflow; | |||||
| using static Tensorflow.Binding; | using static Tensorflow.Binding; | ||||
| using System.Linq; | using System.Linq; | ||||
| namespace TensorFlowNET.UnitTest.ManagedAPI | |||||
| { | |||||
| [TestClass] | |||||
| public class ArrayOpsTest : EagerModeTestBase | |||||
| { | |||||
| /// <summary> | |||||
| /// https://www.tensorflow.org/api_docs/python/tf/slice | |||||
| /// </summary> | |||||
| [TestMethod] | |||||
| public void Slice() | |||||
| { | |||||
| // Tests based on example code in TF documentation | |||||
| var input_array = tf.constant(np.array(new int[] { 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5, 6, 6, 6 }).reshape((3, 2, 3))); | |||||
| var indices = tf.constant(np.array(new int[] { 0, 2 })); | |||||
| var r1 = array_ops.slice(input_array, ops.convert_n_to_tensor(new object[] { 1, 0, 0 }), ops.convert_n_to_tensor(new object[] { 1, 1, 3 })); | |||||
| Assert.AreEqual(new Shape(1, 1, 3), r1.shape); | |||||
| var r1np = r1.numpy(); | |||||
| Assert.AreEqual(r1np[0, 0, 0], 3); | |||||
| Assert.AreEqual(r1np[0, 0, 1], 3); | |||||
| Assert.AreEqual(r1np[0, 0, 2], 3); | |||||
| var r2 = array_ops.slice(input_array, ops.convert_n_to_tensor(new object[] { 1, 0, 0 }), ops.convert_n_to_tensor(new object[] { 1, 2, 3 })); | |||||
| Assert.AreEqual(new Shape(1, 2, 3), r2.shape); | |||||
| var r2np = r2.numpy(); | |||||
| Assert.AreEqual(r2np[0, 0, 0], 3); | |||||
| Assert.AreEqual(r2np[0, 0, 1], 3); | |||||
| Assert.AreEqual(r2np[0, 0, 2], 3); | |||||
| Assert.AreEqual(r2np[0, 1, 0], 4); | |||||
| Assert.AreEqual(r2np[0, 1, 1], 4); | |||||
| Assert.AreEqual(r2np[0, 1, 2], 4); | |||||
| var r3 = array_ops.slice(input_array, ops.convert_n_to_tensor(new object[] { 1, 0, 0 }), ops.convert_n_to_tensor(new object[] { 2, 1, 3 })); | |||||
| Assert.AreEqual(new Shape(2, 1, 3), r3.shape); | |||||
| var r3np = r3.numpy(); | |||||
| Assert.AreEqual(r3np[0, 0, 0], 3); | |||||
| Assert.AreEqual(r3np[0, 0, 1], 3); | |||||
| Assert.AreEqual(r3np[0, 0, 2], 3); | |||||
| Assert.AreEqual(r3np[1, 0, 0], 5); | |||||
| Assert.AreEqual(r3np[1, 0, 1], 5); | |||||
| Assert.AreEqual(r3np[1, 0, 2], 5); | |||||
| } | |||||
| /// <summary> | |||||
| /// https://www.tensorflow.org/api_docs/python/tf/gather | |||||
| /// </summary> | |||||
| [TestMethod] | |||||
| public void Gather() | |||||
| { | |||||
| var input_array = tf.constant(np.arange(12).reshape((3, 4)).astype(np.float32)); | |||||
| var indices = tf.constant(np.array(new int[] { 0, 2 })); | |||||
| var result = array_ops.gather(input_array, indices); | |||||
| Assert.AreEqual(new Shape(2, 4), result.shape); | |||||
| Assert.AreEqual(result.numpy()[0, 0], 0.0f); | |||||
| Assert.AreEqual(result.numpy()[0, 1], 1.0f); | |||||
| Assert.AreEqual(result.numpy()[1, 3], 11.0f); | |||||
| // Tests based on example code in Python doc string for tf.gather() | |||||
| var p1 = tf.random.normal(new Shape(5, 6, 7, 8)); | |||||
| var i1 = tf.random_uniform(new Shape(10, 11), maxval: 7, dtype: tf.int32); | |||||
| var r1 = tf.gather(p1, i1, axis: 2); | |||||
| Assert.AreEqual(new Shape(5, 6, 10, 11, 8), r1.shape); | |||||
| var p2 = tf.random.normal(new Shape(4, 3)); | |||||
| var i2 = tf.constant(new int[,] { { 0, 2 } }); | |||||
| var r2 = tf.gather(p2, i2, axis: 0); | |||||
| Assert.AreEqual(new Shape(1, 2, 3), r2.shape); | |||||
| var r3 = tf.gather(p2, i2, axis: 1); | |||||
| Assert.AreEqual(new Shape(4, 1, 2), r3.shape); | |||||
| } | |||||
| /// <summary> | |||||
| /// https://www.tensorflow.org/api_docs/python/tf/TensorArray | |||||
| /// </summary> | |||||
| [TestMethod] | |||||
| public void TensorArray() | |||||
| { | |||||
| var ta = tf.TensorArray(tf.float32, size: 0, dynamic_size: true, clear_after_read: false); | |||||
| ta.write(0, 10); | |||||
| ta.write(1, 20); | |||||
| ta.write(2, 30); | |||||
| Assert.AreEqual(ta.read(0).numpy(), 10f); | |||||
| Assert.AreEqual(ta.read(1).numpy(), 20f); | |||||
| Assert.AreEqual(ta.read(2).numpy(), 30f); | |||||
| } | |||||
| /// <summary> | |||||
| /// | |||||
| /// </summary> | |||||
| [TestMethod] | |||||
| public void Reverse() | |||||
| { | |||||
| /* | |||||
| * python run get test data code: | |||||
| import tensorflow as tf | |||||
| data=[[1, 2, 3], [4, 5, 6], [7,8,9]] | |||||
| data2 = tf.constant(data) | |||||
| print('test data shaper:', data2.shape) | |||||
| print('test data:', data2) | |||||
| axis = [-2,-1,0,1] | |||||
| for i in axis: | |||||
| print('') | |||||
| print('axis:', i) | |||||
| ax = tf.constant([i]) | |||||
| datar = tf.reverse(data2, ax) | |||||
| datar2 = array_ops.reverse(data2, ax) | |||||
| print(datar) | |||||
| print(datar2) | |||||
| * */ | |||||
| var inputData = np.array(new int[,] { { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9 } }); | |||||
| var expectedOutput = new[] { | |||||
| // np.array(new int[,] { { 7, 8, 9 }, { 4, 5, 6 }, { 1, 2, 3 } }), | |||||
| np.array(new int[,] { { 3, 2, 1 }, { 6, 5, 4 }, { 9, 8, 7 } }), | |||||
| np.array(new int[,] { { 7, 8, 9 }, { 4, 5, 6 }, { 1, 2, 3 } }), | |||||
| np.array(new int[,] { { 3, 2, 1 }, { 6, 5, 4 }, { 9, 8, 7 } }) | |||||
| }; | |||||
| var axes = new int [] { | |||||
| -1, | |||||
| 0, | |||||
| 1 }; | |||||
| for (var i = 0; i < axes.Length; i++) | |||||
| { | |||||
| var axis = axes[i]; | |||||
| var expected = tf.constant(expectedOutput[i]).numpy(); | |||||
| var inputTensor = tf.constant(inputData); | |||||
| var axisTrensor = tf.constant(new[] { axis }); | |||||
| var outputTensor = tf.reverse_v2(inputTensor, axisTrensor); | |||||
| var npout = outputTensor.numpy(); | |||||
| Assert.IsTrue(Enumerable.SequenceEqual(npout, expected), $"axis:{axis}"); | |||||
| var outputTensor2 = tf.reverse_v2(inputTensor, new[] { axis } ); | |||||
| var npout2 = outputTensor2.numpy(); | |||||
| Assert.IsTrue(Enumerable.SequenceEqual(npout2, expected), $"axis:{axis}"); | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| using Microsoft.VisualStudio.TestTools.UnitTesting; | |||||
| using Tensorflow.NumPy; | |||||
| using Tensorflow; | |||||
| using static Tensorflow.Binding; | |||||
| using System.Linq; | |||||
| namespace TensorFlowNET.UnitTest.ManagedAPI | namespace TensorFlowNET.UnitTest.ManagedAPI | ||||
| { | { | ||||
| [TestClass] | [TestClass] | ||||