Skip to content

Commit bd04f5b

Browse files
committed
run_bottleneck_on_image.resized_input_values
1 parent beda6c4 commit bd04f5b

6 files changed

Lines changed: 99 additions & 27 deletions

File tree

TensorFlow.NET.sln

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11

22
Microsoft Visual Studio Solution File, Format Version 12.00
3-
# Visual Studio 15
4-
VisualStudioVersion = 15.0.28307.168
3+
# Visual Studio Version 16
4+
VisualStudioVersion = 16.0.28803.452
55
MinimumVisualStudioVersion = 10.0.40219.1
66
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TensorFlowNET.UnitTest", "test\TensorFlowNET.UnitTest\TensorFlowNET.UnitTest.csproj", "{029A8CF1-CF95-4DCB-98AA-9D3D96A83B3E}"
77
EndProject
@@ -11,7 +11,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TensorFlowNET.Core", "src\T
1111
EndProject
1212
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Keras.Core", "src\KerasNET.Core\Keras.Core.csproj", "{902E188F-A953-43B4-9991-72BAB1697BC3}"
1313
EndProject
14-
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Keras.Example", "test\KerasNET.Example\Keras.Example.csproj", "{17E1AC16-9E0E-4545-905A-E92C6300C7AF}"
14+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Keras.Example", "test\KerasNET.Example\Keras.Example.csproj", "{17E1AC16-9E0E-4545-905A-E92C6300C7AF}"
1515
EndProject
1616
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Keras.UnitTest", "test\KerasNET.Test\Keras.UnitTest.csproj", "{A5839A45-A117-4BEA-898B-DE1ED6E0D58F}"
1717
EndProject

src/TensorFlowNET.Core/Sessions/BaseSession.cs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,9 @@ private NDArray _run(object fetches, FeedItem[] feed_dict = null)
9999
feed_dict_tensor[subfeed_t] = (NDArray)val;
100100
break;
101101
case byte[] val:
102+
feed_dict_tensor[subfeed_t] = np.array(val);
103+
break;
104+
case char[] val:
102105
feed_dict_tensor[subfeed_t] = (NDArray)val;
103106
break;
104107
case bool val:
@@ -130,7 +133,7 @@ private NDArray _run(object fetches, FeedItem[] feed_dict = null)
130133

131134
// We only want to really perform the run if fetches or targets are provided,
132135
// or if the call is a partial run that specifies feeds.
133-
var results = _do_run(final_targets.Select(x => (Operation)(object)x).ToList(), final_fetches, feed_dict_tensor);
136+
var results = _do_run(final_targets.Select(x => (Operation)x).ToList(), final_fetches, feed_dict_tensor);
134137

135138
return fetch_handler.build_results(this, results);
136139
}
@@ -161,7 +164,7 @@ private NDArray[] _do_run(List<Operation> target_list, List<Tensor> fetch_list,
161164
case Tensor t1:
162165
return new KeyValuePair<TF_Output, Tensor>(tensor._as_tf_output(), t1);
163166
case NDArray nd:
164-
return new KeyValuePair<TF_Output, Tensor>(tensor._as_tf_output(), new Tensor(nd));
167+
return new KeyValuePair<TF_Output, Tensor>(tensor._as_tf_output(), new Tensor(nd, tensor.dtype));
165168
case int intVal:
166169
return new KeyValuePair<TF_Output, Tensor>(tensor._as_tf_output(), new Tensor(intVal));
167170
case float floatVal:

src/TensorFlowNET.Core/Tensors/Tensor.Creation.cs

Lines changed: 9 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,9 @@ public Tensor(IntPtr handle)
2020
_handle = handle;
2121
}
2222

23-
public Tensor(NDArray nd)
23+
public Tensor(NDArray nd, TF_DataType? tensorDType = null)
2424
{
25-
_handle = Allocate(nd);
25+
_handle = Allocate(nd, tensorDType: tensorDType);
2626
}
2727

2828
public unsafe Tensor(byte[] buffer)
@@ -38,8 +38,14 @@ public unsafe Tensor(byte[] buffer)
3838
status.Check(true);
3939
}
4040

41-
private IntPtr Allocate(NDArray nd)
41+
private IntPtr Allocate(NDArray nd, TF_DataType? tensorDType = null)
4242
{
43+
if (tensorDType == TF_DataType.TF_STRING &&
44+
nd.dtype.Name == "Byte")
45+
{
46+
return new Tensor(nd.Data<byte>());
47+
}
48+
4349
IntPtr dotHandle = IntPtr.Zero;
4450
ulong size = 0;
4551

@@ -73,23 +79,6 @@ private IntPtr Allocate(NDArray nd)
7379
break;
7480
case "Byte":
7581
Marshal.Copy(nd1.Data<byte>(), 0, dotHandle, nd.size);
76-
/*var bb = nd.Data<byte>();
77-
var bytes = Marshal.AllocHGlobal(bb.Length);
78-
Marshal.Copy(bb, 0, bytes, bb.Length);
79-
ulong bytes_len = c_api.TF_StringEncodedSize((ulong)bb.Length);
80-
var dataTypeByte = ToTFDataType(nd.dtype);
81-
// shape
82-
var dims2 = nd.shape.Select(x => (long)x).ToArray();
83-
84-
var tfHandle2 = c_api.TF_AllocateTensor(dataTypeByte,
85-
dims2,
86-
nd.ndim,
87-
bytes_len + sizeof(Int64));
88-
89-
dotHandle = c_api.TF_TensorData(tfHandle2);
90-
Marshal.WriteInt64(dotHandle, 0);
91-
c_api.TF_StringEncode(bytes, (ulong)bb.Length, dotHandle + sizeof(Int64), bytes_len, status);
92-
return tfHandle2;*/
9382
break;
9483
//case "String":
9584
/*string ss = nd.Data<string>()[0];

src/TensorFlowNET.Core/Tensors/Tensor.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,8 @@ public TF_DataType ToTFDataType(Type type)
187187
{
188188
switch (type.Name)
189189
{
190+
case "Char":
191+
return TF_DataType.TF_UINT8;
190192
case "Int16":
191193
return TF_DataType.TF_INT16;
192194
case "Int32":

src/TensorFlowNET.Core/tf.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ namespace Tensorflow
88
{
99
public static partial class tf
1010
{
11+
public static TF_DataType bytes = TF_DataType.TF_STRING;
1112
public static TF_DataType int16 = TF_DataType.TF_INT16;
1213
public static TF_DataType int32 = TF_DataType.TF_INT32;
1314
public static TF_DataType float16 = TF_DataType.TF_HALF;

test/TensorFlowNET.Examples/ImageProcess/RetrainImageClassifier.cs

Lines changed: 79 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
using System;
1+
using NumSharp;
2+
using System;
23
using System.Collections.Generic;
34
using System.Diagnostics;
45
using System.IO;
@@ -105,7 +106,83 @@ private void get_or_create_bottleneck(Session sess, Dictionary<string, Dictionar
105106
Tensor bottleneck_tensor, string module_name)
106107
{
107108
var label_lists = image_lists[label_name];
108-
var sub_dir_path = Path.Join(image_dir, label_name);
109+
var sub_dir_path = Path.Join(bottleneck_dir, label_name);
110+
Directory.CreateDirectory(sub_dir_path);
111+
string bottleneck_path = get_bottleneck_path(image_lists, label_name, index,
112+
bottleneck_dir, category, module_name);
113+
114+
if (!File.Exists(bottleneck_path))
115+
create_bottleneck_file(bottleneck_path, image_lists, label_name, index,
116+
image_dir, category, sess, jpeg_data_tensor,
117+
decoded_image_tensor, resized_input_tensor,
118+
bottleneck_tensor);
119+
}
120+
121+
private void create_bottleneck_file(string bottleneck_path, Dictionary<string, Dictionary<string, string[]>> image_lists,
122+
string label_name, int index, string image_dir, string category, Session sess,
123+
Tensor jpeg_data_tensor, Tensor decoded_image_tensor, Tensor resized_input_tensor, Tensor bottleneck_tensor)
124+
{
125+
// Create a single bottleneck file.
126+
print("Creating bottleneck at " + bottleneck_path);
127+
var image_path = get_image_path(image_lists, label_name, index, image_dir, category);
128+
if (!File.Exists(image_path))
129+
print($"File does not exist {image_path}");
130+
131+
var image_data = File.ReadAllBytes(image_path);
132+
var bottleneck_values = run_bottleneck_on_image(
133+
sess, image_data, jpeg_data_tensor, decoded_image_tensor,
134+
resized_input_tensor, bottleneck_tensor);
135+
}
136+
137+
/// <summary>
138+
/// Runs inference on an image to extract the 'bottleneck' summary layer.
139+
/// </summary>
140+
/// <param name="sess">Current active TensorFlow Session.</param>
141+
/// <param name="image_path">Path of raw JPEG data.</param>
142+
/// <param name="image_data_tensor">Input data layer in the graph.</param>
143+
/// <param name="decoded_image_tensor">Output of initial image resizing and preprocessing.</param>
144+
/// <param name="resized_input_tensor">The input node of the recognition graph.</param>
145+
/// <param name="bottleneck_tensor">Layer before the final softmax.</param>
146+
/// <returns></returns>
147+
private NDArray run_bottleneck_on_image(Session sess, byte[] image_data, Tensor image_data_tensor,
148+
Tensor decoded_image_tensor, Tensor resized_input_tensor, Tensor bottleneck_tensor)
149+
{
150+
// First decode the JPEG image, resize it, and rescale the pixel values.
151+
var resized_input_values = sess.run(decoded_image_tensor, new FeedItem(image_data_tensor, image_data));
152+
// Then run it through the recognition network.
153+
var bottleneck_values = sess.run(bottleneck_tensor, new FeedItem(resized_input_tensor, resized_input_values));
154+
bottleneck_values = np.squeeze(bottleneck_values);
155+
return bottleneck_values;
156+
}
157+
158+
private string get_bottleneck_path(Dictionary<string, Dictionary<string, string[]>> image_lists, string label_name, int index,
159+
string bottleneck_dir, string category, string module_name)
160+
{
161+
module_name = (module_name.Replace("://", "~") // URL scheme.
162+
.Replace('/', '~') // URL and Unix paths.
163+
.Replace(':', '~').Replace('\\', '~')); // Windows paths.
164+
return get_image_path(image_lists, label_name, index, bottleneck_dir,
165+
category) + "_" + module_name + ".txt";
166+
}
167+
168+
private string get_image_path(Dictionary<string, Dictionary<string, string[]>> image_lists, string label_name,
169+
int index, string image_dir, string category)
170+
{
171+
if (!image_lists.ContainsKey(label_name))
172+
print($"Label does not exist {label_name}");
173+
174+
var label_lists = image_lists[label_name];
175+
if (!label_lists.ContainsKey(category))
176+
print($"Category does not exist {category}");
177+
var category_list = label_lists[category];
178+
if (category_list.Length == 0)
179+
print($"Label {label_name} has no images in the category {category}.");
180+
181+
var mod_index = index % len(category_list);
182+
var base_name = category_list[mod_index].Split(Path.DirectorySeparatorChar).Last();
183+
var sub_dir = label_name;
184+
var full_path = Path.Join(image_dir, sub_dir, base_name);
185+
return full_path;
109186
}
110187

111188
public void PrepareData()

0 commit comments

Comments
 (0)