@@ -42,6 +42,20 @@ namespace Tensorflow | |||
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); | |||
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) | |||
{ | |||
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.Collections.Generic; | |||
using System.Text; | |||
using static Tensorflow.Binding; | |||
namespace Tensorflow | |||
{ | |||
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) | |||
=> 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) | |||
=> gen_math_ops.mul_no_nan(x, y, name: name); | |||
@@ -264,6 +267,9 @@ namespace Tensorflow | |||
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) | |||
=> 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() | |||
{ | |||
var dir = "my-save-dir/"; | |||
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"); | |||
var labels = tf.constant(0, dtype: tf.int32, shape: new int[] { 100 }, name: "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"); | |||
} | |||
} | |||
} |