diff options
author | Yuan Zhao | 2018-11-27 09:58:46 -0600 |
---|---|---|
committer | Yuan Zhao | 2018-11-27 13:16:32 -0600 |
commit | 782c7f753e775ffd56b067cb75ec95c931d8e11a (patch) | |
tree | 6d61a9dc92ef3dc1a97ccfb2dddca5657114da89 /examples | |
parent | b039c5c67501cb62d71a09305b734f0ff6676354 (diff) | |
download | tidl-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.cpp | 188 | ||||
-rwxr-xr-x | examples/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.bin | bin | 0 -> 483364 bytes | |||
-rw-r--r-- | examples/test/testvecs/config/tidl_models/tidl_param_mnist_lenet.bin | bin | 0 -> 432160 bytes | |||
-rw-r--r-- | examples/test/testvecs/input/digits10_images_28x28.y | bin | 0 -> 7840 bytes | |||
-rw-r--r-- | examples/test/testvecs/input/digits10_labels_10x1.y | bin | 0 -> 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 | |||
55 | using namespace std; | 50 | using namespace std; |
56 | using namespace tidl; | 51 | using namespace tidl; |
57 | using 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 | |
63 | const char *default_inputs[NUM_DEFAULT_INPUTS] = | 57 | uint32_t images_file_offset = 0; |
64 | { | 58 | uint32_t labels_file_offset = 0; |
65 | "../test/testvecs/input/digit_28x28.y" | 59 | uint32_t num_frames_file = 0; |
66 | }; | 60 | uint32_t num_wrong_results = 0; |
67 | 61 | ||
68 | 62 | ||
69 | Executor* CreateExecutor(DeviceType dt, uint32_t num, const Configuration& c); | 63 | Executor* CreateExecutor(DeviceType dt, uint32_t num, const Configuration& c); |
70 | bool RunConfiguration(cmdline_opts_t& opts); | 64 | bool RunConfiguration(cmdline_opts_t& opts); |
71 | bool ReadFrame(ExecutionObjectPipeline& eop, | 65 | bool 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); |
74 | bool WriteFrameOutput(const ExecutionObjectPipeline &eop); | 68 | bool WriteFrameOutput(const ExecutionObjectPipeline &eop, ifstream &ifs_labels); |
75 | void DisplayHelp(); | 69 | void 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 | ||
243 | bool ReadFrame(ExecutionObjectPipeline &eop, | 281 | bool 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 |
312 | bool WriteFrameOutput(const ExecutionObjectPipeline &eop) | 301 | bool 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 | ||
333 | void DisplayHelp() | 333 | void 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 @@ | |||
1 | numFrames = 1 | 1 | numFrames = 1 |
2 | preProcType = 0 | 2 | preProcType = 0 |
3 | inData = ../test/testvecs/input/digit_28x28.y | 3 | inData = ../test/testvecs/input/digits10_images_28x28.y |
4 | outData = "stats_tool_out.bin" | 4 | outData = "stats_tool_out.bin" |
5 | netBinFile = "../test/testvecs/config/tidl_models/tidl_net_mnist_cnn.bin" | 5 | netBinFile = "../test/testvecs/config/tidl_models/tidl_net_mnist_lenet.bin" |
6 | paramsBinFile = "../test/testvecs/config/tidl_models/tidl_param_mnist_cnn.bin" | 6 | paramsBinFile = "../test/testvecs/config/tidl_models/tidl_param_mnist_lenet.bin" |
7 | inWidth = 28 | 7 | inWidth = 28 |
8 | inHeight = 28 | 8 | inHeight = 28 |
9 | inNumChannels = 2 | 9 | inNumChannels = 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 | |||