From 2041d7efc95901cf929176307203b94c4c2678f1 Mon Sep 17 00:00:00 2001 From: dogvane Date: Wed, 26 Jul 2023 15:16:49 +0800 Subject: [PATCH 1/5] add tf.reverse_v2 function tf.reverse param2 is "dims" type DT_BOOL, tf.reverse_v2 params2 is "axis" type Tidx --- src/TensorFlowNET.Core/APIs/tf.array.cs | 14 ++ .../ManagedAPI/ArrayOpsTest.cs | 157 ++++++++++++++++++ 2 files changed, 171 insertions(+) diff --git a/src/TensorFlowNET.Core/APIs/tf.array.cs b/src/TensorFlowNET.Core/APIs/tf.array.cs index 4d9c3da5..2b49a92b 100644 --- a/src/TensorFlowNET.Core/APIs/tf.array.cs +++ b/src/TensorFlowNET.Core/APIs/tf.array.cs @@ -174,6 +174,20 @@ namespace Tensorflow return array_ops.reverse(tensor, axis, name: name); } + + /// + /// Reverses specific dimensions of a tensor. + /// + /// + /// + /// + /// + 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); + /// /// Returns the rank of a tensor. /// diff --git a/test/TensorFlowNET.UnitTest/ManagedAPI/ArrayOpsTest.cs b/test/TensorFlowNET.UnitTest/ManagedAPI/ArrayOpsTest.cs index 675689bb..5b538d26 100644 --- a/test/TensorFlowNET.UnitTest/ManagedAPI/ArrayOpsTest.cs +++ b/test/TensorFlowNET.UnitTest/ManagedAPI/ArrayOpsTest.cs @@ -4,6 +4,163 @@ using Tensorflow; using static Tensorflow.Binding; using System.Linq; +namespace TensorFlowNET.UnitTest.ManagedAPI +{ + [TestClass] + public class ArrayOpsTest : EagerModeTestBase + { + /// + /// https://www.tensorflow.org/api_docs/python/tf/slice + /// + [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); + } + + /// + /// https://www.tensorflow.org/api_docs/python/tf/gather + /// + [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); + } + + /// + /// https://www.tensorflow.org/api_docs/python/tf/TensorArray + /// + [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); + } + + /// + /// + /// + [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 { [TestClass] From f99c9be9493912e7ac0be7b2164cf75e18efde99 Mon Sep 17 00:00:00 2001 From: dogvane Date: Wed, 26 Jul 2023 22:37:32 +0800 Subject: [PATCH 2/5] add image save as jpg and png funcion and testunit --- data/img001.bmp | Bin 0 -> 178662 bytes src/TensorFlowNET.Core/APIs/tf.image.cs | 7 +++++ src/TensorFlowNET.Core/APIs/tf.io.cs | 7 +++++ src/TensorFlowNET.Core/Operations/gen_ops.cs | 5 ++-- .../Operations/image_ops_impl.cs | 16 ++++++++++ .../TensorFlowNET.Graph.UnitTest/ImageTest.cs | 28 ++++++++++++++++++ 6 files changed, 61 insertions(+), 2 deletions(-) create mode 100644 data/img001.bmp diff --git a/data/img001.bmp b/data/img001.bmp new file mode 100644 index 0000000000000000000000000000000000000000..86cfa972f9d1620eb234ae74a55b6f98bce5f9e2 GIT binary patch literal 178662 zcmeI5L5}7+8AS_L!GIwHR=@(7vq@IKlno&!%$S2AEi1AU=ZpQ>zK&0+`zdj3$M@V* zf0xux@BR5N|M>fFfByINr||oa;rG9P{r=6*@50s3&)^>N;Wm8X_PT{~@`FGwHg4m_2MFAW9inaW zx&76co98NsjoX{Mv2^^h*torPxjP^JQEc4aS&wzIUy2>#1fS1e>jo^J{G2gdmnZXd zAp&<|hX|XLzDdl5oOC&AL2TT1AlA@E9U+-^b5+K~j_ijCVN+u>c+1S-VF?P}UA97do{ zY}_7J5HG4DP%SoY*8ykM00Ng*he7+RH~AMWHi>EPU3_M{*dgF1rEd~b+*srBT*St0 zBW#+izQ7zB_?VV&k@ZQ*8K(KtHi@`&AK4_9f6&Y~1!Oi{0!5dW((Q_AZ#|NML~2 zxb4^%TNw$A5gWISbui6~z%a3K+p9A6u@D$3Hf~!QVU7!d!D8dKOKWWMNMO9!xcyiP z6WR$(5gWJLi&Ng=55NDHjuC)%{+@i5@j@QX2ijCV|B~IMOsB7J{mRxhi z#_g8w=B}-CwR+Xtu+zoH?YEUF%&+#deW5YFg4noiEK6kCTRDx#_T5%QY}_`sKYf}} zKbLd1yh}%H+;)+n>n0Y{IvwEctEI%o?M_yBZCkd>>n)G_SdO74b_lh}f81cjm<6LA zZR|0ja2`Rial3~DE_>dIV8Y&A!WtJ?SAdo z?Hrv+F6wscx+2W zsKgz^Fn;-o9p|fMku5zEbGeX>nfu_9x5p-Bv5z`y9=fxe4|} zgJ)XAK8~alO0#tL;sj&rIPgf@F1D23f~7yAu9zSgGjY2j)PNIqUYr<>N`GWtJwYet^u`|T<%|usWq*!tol^iJ8>x70_!RN3oA1P0XuP zx>q}w`-sF$iVnAzr=2zEE_MhqF|tVMz1tLtnH1eS^{f4Rh5u%|Cn&_6(r+2v7_o7?+(P5i>24=thug+P?aPOWeH=9*(0=~M z9j2H5ctV#6(_@Zrw#;p?*x@ka2~01&T!Giq=`qJQTR=BnY}_u?(fA0rBfu$Q<96il zeu3Ku(ph5XZihd}+*?jIoL+izo=&%OV~YGhGEwZK*1;U+mfp$aeA~G(2X~ss4 zJJ-@>WUkv|YF$h0@b_6R%@#J9UV7ndj*q6t?EP1h;$nv?dlSfQnO=H+q#h&FV|Hy; zUu@j&VfC@+huvO6Y~0?*ZLgm;R}mYxKkRmoauK^M%=AC3%g6J2su0unNA88h?(uzX z5ksML%Q+k8D8x+MZuzlfEwORC(cbcM1-HE_UR~^#Z|ZW($y1TilT*3hio{Glx+`KX zCw9o#p1J~5SRzt--Qn%4L}Df_zx@RJfY@&%+bhmzijcmXCwtS9VS{()(nG9H75!UfkI;A^?%D0k=`Kocm&f7GONR@6pbHy~N zn0B|<6+3ifk6BTuWr>W$c50%(@*l`ifh8#B=xv14WJ z7qX?dM?3Ez8}sb;_r#v{)5uZ1Z0Tn++pm>l9(p5od&|iV%B3eqZMhYXiP$aW-mMic z{qERr$CYDViXDGed7E_n{CL#!#rR|7Z&WTlKW+7hY|OIQhb`5qdoMi8e7^4eUgQ3< zr5n$0oTeGmBDSpFXPM8}#zqEA(=6RRxM0jnu|x2)C&{%tmg)_YgT>qG4SOsUEPaQV zcVfrv(U$xo&Y5zNpC^t?IZxrGxLttL>CvOu$9tnQmlvJRR@nCP7{_2?)x<}*Js7@G z?Bi4gokmJkKE_~x_SfOIomKnHS7OK4mDLJQ<4oU+$M^PowM!7(cEM=bq)zN(XNzWD zrj2};gIO>%A7Y zs|h1^HM%hial4K)V%KpSxeB){Xd`w7wDC)D`z>?CeoJiDeB6FT9Zd+Qov^or0)-q=n0o;BhkJyihG$-J8xfjGP^HF|^+l6*6#V*X}krV;kzN-VV z@5rn&j@y?_A@(JfwFYrJ?+dYWCM%BMcG4PRCqUM{#qD! image_ops_impl.decode_image(contents, channels: channels, dtype: dtype, 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); + + /// /// Convenience function to check if the 'contents' encodes a JPEG image. /// diff --git a/src/TensorFlowNET.Core/APIs/tf.io.cs b/src/TensorFlowNET.Core/APIs/tf.io.cs index be1e86e6..4cb18070 100644 --- a/src/TensorFlowNET.Core/APIs/tf.io.cs +++ b/src/TensorFlowNET.Core/APIs/tf.io.cs @@ -16,6 +16,7 @@ using System.Collections.Generic; using Tensorflow.IO; +using Tensorflow.Operations; namespace Tensorflow { @@ -46,6 +47,12 @@ namespace Tensorflow public Tensor[] restore_v2(Tensor prefix, string[] tensor_names, string[] shape_and_slices, TF_DataType[] dtypes, string name = null) => 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(); diff --git a/src/TensorFlowNET.Core/Operations/gen_ops.cs b/src/TensorFlowNET.Core/Operations/gen_ops.cs index 5fa4c97d..ed756740 100644 --- a/src/TensorFlowNET.Core/Operations/gen_ops.cs +++ b/src/TensorFlowNET.Core/Operations/gen_ops.cs @@ -39083,13 +39083,14 @@ namespace Tensorflow.Operations /// /// creates directory if not existing. /// - 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(); dict["filename"] = filename; dict["contents"] = contents; var op = tf.OpDefLib._apply_op_helper("WriteFile", name: name, keywords: dict); - return op; + op.run(); + return op.output; } /// diff --git a/src/TensorFlowNET.Core/Operations/image_ops_impl.cs b/src/TensorFlowNET.Core/Operations/image_ops_impl.cs index 318b8b14..0c827b7f 100644 --- a/src/TensorFlowNET.Core/Operations/image_ops_impl.cs +++ b/src/TensorFlowNET.Core/Operations/image_ops_impl.cs @@ -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) { return tf_with(ops.name_scope(name, "is_jpeg"), scope => diff --git a/test/TensorFlowNET.Graph.UnitTest/ImageTest.cs b/test/TensorFlowNET.Graph.UnitTest/ImageTest.cs index d671b609..6a430443 100644 --- a/test/TensorFlowNET.Graph.UnitTest/ImageTest.cs +++ b/test/TensorFlowNET.Graph.UnitTest/ImageTest.cs @@ -4,6 +4,7 @@ using System.Linq; using Tensorflow; using static Tensorflow.Binding; using System; +using System.IO; namespace TensorFlowNET.UnitTest { @@ -164,5 +165,32 @@ namespace TensorFlowNET.UnitTest Assert.AreEqual(result.size, 16ul); 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); + } } } From 960b0ab3278d3d8e94355f661fbd8d9b79745ef0 Mon Sep 17 00:00:00 2001 From: Dogvane Huang Date: Wed, 26 Jul 2023 22:39:34 +0800 Subject: [PATCH 3/5] Merge branch 'SciSharp:master' into master --- src/TensorFlowNET.Core/APIs/tf.array.cs | 14 ++ .../ManagedAPI/ArrayOpsTest.cs | 157 ++++++++++++++++++ 2 files changed, 171 insertions(+) diff --git a/src/TensorFlowNET.Core/APIs/tf.array.cs b/src/TensorFlowNET.Core/APIs/tf.array.cs index 4d9c3da5..2b49a92b 100644 --- a/src/TensorFlowNET.Core/APIs/tf.array.cs +++ b/src/TensorFlowNET.Core/APIs/tf.array.cs @@ -174,6 +174,20 @@ namespace Tensorflow return array_ops.reverse(tensor, axis, name: name); } + + /// + /// Reverses specific dimensions of a tensor. + /// + /// + /// + /// + /// + 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); + /// /// Returns the rank of a tensor. /// diff --git a/test/TensorFlowNET.UnitTest/ManagedAPI/ArrayOpsTest.cs b/test/TensorFlowNET.UnitTest/ManagedAPI/ArrayOpsTest.cs index 675689bb..5b538d26 100644 --- a/test/TensorFlowNET.UnitTest/ManagedAPI/ArrayOpsTest.cs +++ b/test/TensorFlowNET.UnitTest/ManagedAPI/ArrayOpsTest.cs @@ -4,6 +4,163 @@ using Tensorflow; using static Tensorflow.Binding; using System.Linq; +namespace TensorFlowNET.UnitTest.ManagedAPI +{ + [TestClass] + public class ArrayOpsTest : EagerModeTestBase + { + /// + /// https://www.tensorflow.org/api_docs/python/tf/slice + /// + [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); + } + + /// + /// https://www.tensorflow.org/api_docs/python/tf/gather + /// + [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); + } + + /// + /// https://www.tensorflow.org/api_docs/python/tf/TensorArray + /// + [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); + } + + /// + /// + /// + [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 { [TestClass]