summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYuan Zhao2018-11-27 09:58:46 -0600
committerYuan Zhao2018-11-27 13:16:32 -0600
commit782c7f753e775ffd56b067cb75ec95c931d8e11a (patch)
tree6d61a9dc92ef3dc1a97ccfb2dddca5657114da89 /examples
parentb039c5c67501cb62d71a09305b734f0ff6676354 (diff)
downloadtidl-api-782c7f753e775ffd56b067cb75ec95c931d8e11a.tar.gz
tidl-api-782c7f753e775ffd56b067cb75ec95c931d8e11a.tar.xz
tidl-api-782c7f753e775ffd56b067cb75ec95c931d8e11a.zip
Add MNIST LeNet network model and test input
- Constrained to EVE only for now. - Add documentation for mnist example. - MCT-1083
Diffstat (limited to 'examples')
-rw-r--r--examples/mnist/main.cpp188
-rwxr-xr-xexamples/test/testvecs/config/infer/tidl_config_mnist_lenet.txt (renamed from examples/test/testvecs/config/infer/tidl_config_mnist.txt)6
-rw-r--r--examples/test/testvecs/config/tidl_models/tidl_net_mnist_lenet.binbin0 -> 483364 bytes
-rw-r--r--examples/test/testvecs/config/tidl_models/tidl_param_mnist_lenet.binbin0 -> 432160 bytes
-rw-r--r--examples/test/testvecs/input/digits10_images_28x28.ybin0 -> 7840 bytes
-rw-r--r--examples/test/testvecs/input/digits10_labels_10x1.ybin0 -> 10 bytes
6 files changed, 95 insertions, 99 deletions
diff --git a/examples/mnist/main.cpp b/examples/mnist/main.cpp
index 7794c51..d933ccc 100644
--- a/examples/mnist/main.cpp
+++ b/examples/mnist/main.cpp
@@ -47,31 +47,25 @@
47#include "imgutil.h" 47#include "imgutil.h"
48#include "../common/video_utils.h" 48#include "../common/video_utils.h"
49 49
50#include "opencv2/core.hpp"
51#include "opencv2/imgproc.hpp"
52#include "opencv2/highgui.hpp"
53#include "opencv2/videoio.hpp"
54
55using namespace std; 50using namespace std;
56using namespace tidl; 51using namespace tidl;
57using namespace cv;
58 52
59#define NUM_VIDEO_FRAMES 300 53#define DEFAULT_CONFIG "mnist_lenet"
60#define DEFAULT_CONFIG "mnist" 54#define DEFAULT_INPUT_IMAGES "../test/testvecs/input/digits10_images_28x28.y"
61#define NUM_DEFAULT_INPUTS 1 55#define DEFAULT_INPUT_LABELS "../test/testvecs/input/digits10_labels_10x1.y"
62#define DEFAULT_INPUT_FRAMES 1 56
63const char *default_inputs[NUM_DEFAULT_INPUTS] = 57uint32_t images_file_offset = 0;
64{ 58uint32_t labels_file_offset = 0;
65 "../test/testvecs/input/digit_28x28.y" 59uint32_t num_frames_file = 0;
66}; 60uint32_t num_wrong_results = 0;
67 61
68 62
69Executor* CreateExecutor(DeviceType dt, uint32_t num, const Configuration& c); 63Executor* CreateExecutor(DeviceType dt, uint32_t num, const Configuration& c);
70bool RunConfiguration(cmdline_opts_t& opts); 64bool RunConfiguration(cmdline_opts_t& opts);
71bool ReadFrame(ExecutionObjectPipeline& eop, 65bool ReadFrame(ExecutionObjectPipeline& eop,
72 uint32_t frame_idx, const Configuration& c, 66 uint32_t frame_idx, const Configuration& c,
73 const cmdline_opts_t& opts, VideoCapture &cap); 67 const cmdline_opts_t& opts, ifstream &ifs);
74bool WriteFrameOutput(const ExecutionObjectPipeline &eop); 68bool WriteFrameOutput(const ExecutionObjectPipeline &eop, ifstream &ifs_labels);
75void DisplayHelp(); 69void DisplayHelp();
76 70
77 71
@@ -101,13 +95,31 @@ int main(int argc, char *argv[])
101 exit(EXIT_SUCCESS); 95 exit(EXIT_SUCCESS);
102 } 96 }
103 assert(opts.num_dsps != 0 || opts.num_eves != 0); 97 assert(opts.num_dsps != 0 || opts.num_eves != 0);
104 if (opts.num_frames == 0) 98 if (opts.num_dsps != 0)
105 opts.num_frames = (opts.is_camera_input || opts.is_video_input) ? 99 {
106 NUM_VIDEO_FRAMES : 1; 100 cout << "MNIST network not supported on DSP yet." << endl;
101 exit(EXIT_SUCCESS);
102 }
103
107 if (opts.input_file.empty()) 104 if (opts.input_file.empty())
108 cout << "Input: " << default_inputs[0] << endl; 105 {
109 else 106 opts.input_file = DEFAULT_INPUT_IMAGES;
110 cout << "Input: " << opts.input_file << endl; 107 opts.object_classes_list_file = DEFAULT_INPUT_LABELS;
108 }
109
110 // if inputs are MNIST data set: skip MNIST header
111 string& s_images = opts.input_file;
112 if (s_images.size() > 10 &&
113 s_images.compare(s_images.size() - 10, 10, "idx3-ubyte") == 0)
114 images_file_offset = 16;
115 string& s_labels = opts.object_classes_list_file;
116 if (s_labels.size() > 10 &&
117 s_labels.compare(s_labels.size() - 10, 10, "idx1-ubyte") == 0)
118 labels_file_offset = 8;
119
120 cout << "Input images: " << opts.input_file << endl;
121 if (! opts.object_classes_list_file.empty())
122 cout << "Input labels: " << opts.object_classes_list_file << endl;
111 123
112 // Run network 124 // Run network
113 bool status = RunConfiguration(opts); 125 bool status = RunConfiguration(opts);
@@ -126,7 +138,7 @@ bool RunConfiguration(cmdline_opts_t& opts)
126 // Read the TI DL configuration file 138 // Read the TI DL configuration file
127 Configuration c; 139 Configuration c;
128 string config_file = "../test/testvecs/config/infer/tidl_config_" 140 string config_file = "../test/testvecs/config/infer/tidl_config_"
129 + opts.config + ".txt"; 141 + opts.config + ".txt";
130 bool status = c.ReadFromFile(config_file); 142 bool status = c.ReadFromFile(config_file);
131 if (!status) 143 if (!status)
132 { 144 {
@@ -135,9 +147,27 @@ bool RunConfiguration(cmdline_opts_t& opts)
135 } 147 }
136 c.enableApiTrace = opts.verbose; 148 c.enableApiTrace = opts.verbose;
137 149
138 // setup camera/video input/output 150 // setup images/labels input/output
139 VideoCapture cap; 151 ifstream ifs, ifs_labels;
140 if (! SetVideoInputOutput(cap, opts, "MNIST")) return false; 152 ifs.open(opts.input_file, ios::binary | ios::ate);
153 if (! ifs.good())
154 {
155 cerr << "Cannot open " << opts.input_file << endl;
156 return false;
157 }
158 num_frames_file = (((int) ifs.tellg()) - images_file_offset) /
159 (c.inWidth * c.inHeight);
160 if (opts.num_frames == 0)
161 opts.num_frames = num_frames_file;
162 if (! opts.object_classes_list_file.empty())
163 {
164 ifs_labels.open(opts.object_classes_list_file, ios::binary);
165 if (! ifs_labels.good())
166 {
167 cerr << "Cannot open " << opts.object_classes_list_file << endl;
168 return false;
169 }
170 }
141 171
142 try 172 try
143 { 173 {
@@ -198,11 +228,11 @@ bool RunConfiguration(cmdline_opts_t& opts)
198 { 228 {
199 device_time += 229 device_time +=
200 eos[frame_idx % num_eos]->GetProcessTimeInMilliSeconds(); 230 eos[frame_idx % num_eos]->GetProcessTimeInMilliSeconds();
201 WriteFrameOutput(*eop); 231 WriteFrameOutput(*eop, ifs_labels);
202 } 232 }
203 233
204 // Read a frame and start processing it with current eop 234 // Read a frame and start processing it with current eop
205 if (ReadFrame(*eop, frame_idx, c, opts, cap)) 235 if (ReadFrame(*eop, frame_idx, c, opts, ifs))
206 eop->ProcessFrameStartAsync(); 236 eop->ProcessFrameStartAsync();
207 } 237 }
208 238
@@ -210,9 +240,17 @@ bool RunConfiguration(cmdline_opts_t& opts)
210 chrono::duration<float> elapsed = tloop1 - tloop0; 240 chrono::duration<float> elapsed = tloop1 - tloop0;
211 cout << "Device total time: " << setw(6) << setprecision(4) 241 cout << "Device total time: " << setw(6) << setprecision(4)
212 << device_time << "ms" << endl; 242 << device_time << "ms" << endl;
213 cout << "Loop total time (including read/write/opencv/print/etc): " 243 cout << "Loop total time (including read/write/print/etc): "
214 << setw(6) << setprecision(4) 244 << setw(6) << setprecision(4)
215 << (elapsed.count() * 1000) << "ms" << endl; 245 << (elapsed.count() * 1000) << "ms" << endl;
246 if (opts.num_frames > 0 && ifs_labels.is_open())
247 {
248 cout << "Accuracy: " << setw(6) << setprecision(4)
249 << (opts.num_frames-num_wrong_results)*100.f / opts.num_frames
250 << "%" << endl;
251 if (opts.input_file == DEFAULT_INPUT_IMAGES && num_wrong_results >0)
252 status = false;
253 }
216 254
217 FreeMemory(eops); 255 FreeMemory(eops);
218 for (auto eop : eops) delete eop; 256 for (auto eop : eops) delete eop;
@@ -242,7 +280,7 @@ Executor* CreateExecutor(DeviceType dt, uint32_t num, const Configuration& c)
242 280
243bool ReadFrame(ExecutionObjectPipeline &eop, 281bool ReadFrame(ExecutionObjectPipeline &eop,
244 uint32_t frame_idx, const Configuration& c, 282 uint32_t frame_idx, const Configuration& c,
245 const cmdline_opts_t& opts, VideoCapture &cap) 283 const cmdline_opts_t& opts, ifstream &ifs)
246{ 284{
247 if (frame_idx >= opts.num_frames) 285 if (frame_idx >= opts.num_frames)
248 return false; 286 return false;
@@ -253,63 +291,14 @@ bool ReadFrame(ExecutionObjectPipeline &eop,
253 assert (frame_buffer != nullptr); 291 assert (frame_buffer != nullptr);
254 int channel_size = c.inWidth * c.inHeight; 292 int channel_size = c.inWidth * c.inHeight;
255 293
256 Mat image; 294 // already PreProc-ed white-on-black 28x28 frames
257 if (! opts.is_camera_input && ! opts.is_video_input) 295 ifs.seekg(images_file_offset + (frame_idx%num_frames_file) * channel_size);
258 { 296 ifs.read(frame_buffer, channel_size);
259 if (opts.input_file.empty()) 297 return ifs.good();
260 {
261 ifstream ifs(default_inputs[frame_idx % NUM_DEFAULT_INPUTS],
262 ios::binary);
263 ifs.seekg((frame_idx % DEFAULT_INPUT_FRAMES) * channel_size);
264 ifs.read(frame_buffer, channel_size);
265 memcpy(frame_buffer+channel_size, frame_buffer, channel_size);
266 bool ifs_status = ifs.good();
267 ifs.close();
268 return ifs_status; // already PreProc-ed
269 }
270 else
271 {
272 image = cv::imread(opts.input_file, CV_LOAD_IMAGE_COLOR);
273 if (image.empty())
274 {
275 cerr << "Unable to read input image" << endl;
276 return false;
277 }
278 }
279 }
280 else
281 {
282 Mat v_image;
283 if (! cap.grab()) return false;
284 if (! cap.retrieve(v_image)) return false;
285 #define DISPLAY_SIZE 112
286 int orig_width = v_image.cols;
287 int orig_height = v_image.rows;
288 // Crop camera/video input to center DISPLAY_SIZE x DISPLAY_SIZE input
289 if (orig_width > DISPLAY_SIZE && orig_height > DISPLAY_SIZE)
290 {
291 image = Mat(v_image, Rect((orig_width-DISPLAY_SIZE)/2,
292 (orig_height-DISPLAY_SIZE)/2,
293 DISPLAY_SIZE, DISPLAY_SIZE));
294 }
295 else
296 image = v_image;
297 cv::imshow("MNIST", image);
298 waitKey(2);
299 }
300
301 // Convert to Gray image, resize to 28x28, copy into frame_buffer
302 Mat s_image, bgr_frames[3];
303 cv::resize(image, s_image, Size(c.inWidth, c.inHeight),
304 0, 0, cv::INTER_AREA);
305 cv::split(s_image, bgr_frames);
306 memcpy(frame_buffer, bgr_frames[0].ptr(), channel_size);
307 memcpy(frame_buffer+1*channel_size, bgr_frames[1].ptr(), channel_size);
308 return true;
309} 298}
310 299
311// Display top 5 classified imagenet classes with probabilities 300// Display top 5 classified imagenet classes with probabilities
312bool WriteFrameOutput(const ExecutionObjectPipeline &eop) 301bool WriteFrameOutput(const ExecutionObjectPipeline &eop, ifstream &ifs_labels)
313{ 302{
314 unsigned char *out = (unsigned char *) eop.GetOutputBufferPtr(); 303 unsigned char *out = (unsigned char *) eop.GetOutputBufferPtr();
315 int out_size = eop.GetOutputBufferSizeInBytes(); 304 int out_size = eop.GetOutputBufferSizeInBytes();
@@ -318,7 +307,7 @@ bool WriteFrameOutput(const ExecutionObjectPipeline &eop)
318 int maxloc = -1; 307 int maxloc = -1;
319 for (int i = 0; i < out_size; i++) 308 for (int i = 0; i < out_size; i++)
320 { 309 {
321 // cout << (int) out[i] << " "; 310 // cout << (int) out[i] << " "; // 10 probability outputs
322 if (out[i] > maxval) 311 if (out[i] > maxval)
323 { 312 {
324 maxval = out[i]; 313 maxval = out[i];
@@ -327,25 +316,32 @@ bool WriteFrameOutput(const ExecutionObjectPipeline &eop)
327 } 316 }
328 cout << maxloc << endl; 317 cout << maxloc << endl;
329 318
319 // check inference result against pre-determined label
320 if (ifs_labels.is_open())
321 {
322 int frame_index = eop.GetFrameIndex();
323 char label = -1;
324 ifs_labels.seekg(labels_file_offset + (frame_index % num_frames_file));
325 ifs_labels.read(&label, 1);
326 if (maxloc != (int) label)
327 num_wrong_results += 1;
328 }
329
330 return true; 330 return true;
331} 331}
332 332
333void DisplayHelp() 333void DisplayHelp()
334{ 334{
335 cout << 335 cout <<
336 "Usage: imagenet\n" 336 "Usage: mnist\n"
337 " Will run imagenet network to predict top 5 object" 337 " Will run MNIST LeNet to predict the digit in a 28x28"
338 " classes for the input.\n Use -c to run a" 338 " white-on-black image.\n Use -c to run a"
339 " different imagenet network. Default is j11_v2.\n" 339 " different MNIST network. Default is mnist_lenet.\n"
340 "Optional arguments:\n" 340 "Optional arguments:\n"
341 " -c <config> Valid configs: j11_bn, j11_prelu, j11_v2\n" 341 " -c <config> Valid configs: mnist_lenet\n"
342 " -d <number> Number of dsp cores to use\n"
343 " -e <number> Number of eve cores to use\n" 342 " -e <number> Number of eve cores to use\n"
344 " -i <image> Path to the image file as input\n" 343 " -i <images> Path to the MNIST white-on-black images file\n"
345 " -i camera<number> Use camera as input\n" 344 " -l <labels> Path to the MNIST labels file\n"
346 " video input port: /dev/video<number>\n"
347 " -i <name>.{mp4,mov,avi} Use video file as input\n"
348 " -l <objects_list> Path to the object classes list file\n"
349 " -f <number> Number of frames to process\n" 345 " -f <number> Number of frames to process\n"
350 " -v Verbose output during execution\n" 346 " -v Verbose output during execution\n"
351 " -h Help\n"; 347 " -h Help\n";
diff --git a/examples/test/testvecs/config/infer/tidl_config_mnist.txt b/examples/test/testvecs/config/infer/tidl_config_mnist_lenet.txt
index b62b859..f4b0b7f 100755
--- a/examples/test/testvecs/config/infer/tidl_config_mnist.txt
+++ b/examples/test/testvecs/config/infer/tidl_config_mnist_lenet.txt
@@ -1,9 +1,9 @@
1numFrames = 1 1numFrames = 1
2preProcType = 0 2preProcType = 0
3inData = ../test/testvecs/input/digit_28x28.y 3inData = ../test/testvecs/input/digits10_images_28x28.y
4outData = "stats_tool_out.bin" 4outData = "stats_tool_out.bin"
5netBinFile = "../test/testvecs/config/tidl_models/tidl_net_mnist_cnn.bin" 5netBinFile = "../test/testvecs/config/tidl_models/tidl_net_mnist_lenet.bin"
6paramsBinFile = "../test/testvecs/config/tidl_models/tidl_param_mnist_cnn.bin" 6paramsBinFile = "../test/testvecs/config/tidl_models/tidl_param_mnist_lenet.bin"
7inWidth = 28 7inWidth = 28
8inHeight = 28 8inHeight = 28
9inNumChannels = 2 9inNumChannels = 2
diff --git a/examples/test/testvecs/config/tidl_models/tidl_net_mnist_lenet.bin b/examples/test/testvecs/config/tidl_models/tidl_net_mnist_lenet.bin
new file mode 100644
index 0000000..ea9ac6c
--- /dev/null
+++ b/examples/test/testvecs/config/tidl_models/tidl_net_mnist_lenet.bin
Binary files differ
diff --git a/examples/test/testvecs/config/tidl_models/tidl_param_mnist_lenet.bin b/examples/test/testvecs/config/tidl_models/tidl_param_mnist_lenet.bin
new file mode 100644
index 0000000..66cc8a6
--- /dev/null
+++ b/examples/test/testvecs/config/tidl_models/tidl_param_mnist_lenet.bin
Binary files differ
diff --git a/examples/test/testvecs/input/digits10_images_28x28.y b/examples/test/testvecs/input/digits10_images_28x28.y
new file mode 100644
index 0000000..8799ea3
--- /dev/null
+++ b/examples/test/testvecs/input/digits10_images_28x28.y
Binary files differ
diff --git a/examples/test/testvecs/input/digits10_labels_10x1.y b/examples/test/testvecs/input/digits10_labels_10x1.y
new file mode 100644
index 0000000..df93f5f
--- /dev/null
+++ b/examples/test/testvecs/input/digits10_labels_10x1.y
Binary files differ