Skip to content

Commit

Permalink
Create example for SSD detection. (#997)
Browse files Browse the repository at this point in the history
* Create example for SSD detection.

* Create script to convert PyTorch model to TinyDNN.

* Fix some bugs.

* Add README.
  • Loading branch information
hzxie authored and beru committed Oct 21, 2018
1 parent 5fb41f9 commit 4120498
Show file tree
Hide file tree
Showing 4 changed files with 549 additions and 1 deletion.
6 changes: 5 additions & 1 deletion examples/CMakeLists.txt
Expand Up @@ -36,7 +36,11 @@ if(USE_SERIALIZER)
target_link_libraries(example_deconv_train
${project_library_target_name} ${REQUIRED_LIBRARIES})

cotire(example_mnist_train example_mnist_test example_mnist_quantized_train example_deconv_train)
add_executable(example_ssd_test ssd_detection/test.cpp ${tiny_dnn_headers})
target_link_libraries(example_ssd_test
${project_library_target_name} ${REQUIRED_LIBRARIES})

cotire(example_mnist_train example_mnist_test example_mnist_quantized_train example_deconv_train example_ssd_test)
endif()

add_executable(example_deconv_visual deconv/visual.cpp ${tiny_dnn_headers})
Expand Down
47 changes: 47 additions & 0 deletions examples/ssd_detection/README.md
@@ -0,0 +1,47 @@
# Single Shot MultiBox Detector (SSD)

A TinyDNN implementation of [Single Shot MultiBox Detector](http://arxiv.org/abs/1512.02325) from the 2016 paper by Wei Liu, Dragomir Anguelov, Dumitru Erhan, Christian Szegedy, Scott Reed, Cheng-Yang, and Alexander C. Berg. The official and original Caffe code can be found [here](https://github.com/weiliu89/caffe/tree/ssd).

## Prerequisites for this example

- Download PyTorch pretrained models from [here](https://s3.amazonaws.com/amdegroot-models/ssd300_mAP_77.43_v2.pth)
- Convert PyTorch models to TinyDNN with following commands

```
mkdir models
python convert_models.py /path/to/model models
```

## Use SSD in Object Detection

```
./example_ssd_test /folder/to/models/ /path/to/image
```

You will get output similar to following:

```
Bounding box coordinates:
x_min = 19.6578, x_max = 66.2639, y_min = 240.801, y_max = 270.333, class = 1, score = 0.989524
x_min = -3.73388, x_max = 302.883, y_min = 43.5821, y_max = 202.043, class = 1, score = 0.900133
x_min = 17.771, x_max = 54.9812, y_min = 237.505, y_max = 259.987, class = 1, score = 0.660543
```

If you see the following message:

```
Failed to load weights from models/01.weights
Failed to load weights from models/02.weights
...
Failed to load weights from models/18.weights
```

Please make sure the path of weight files.

## Detection Results

Here's an example of object detection results produced by SSD.

![Airplane](https://user-images.githubusercontent.com/1730504/47263759-67bc1900-d53a-11e8-91cd-4bb4648668b7.png)

![Sofa](https://user-images.githubusercontent.com/1730504/47264055-d9976100-d540-11e8-98a5-0af7871374fd.png)
77 changes: 77 additions & 0 deletions examples/ssd_detection/convert_models.py
@@ -0,0 +1,77 @@
#!/usr/bin/python3
# -*- coding: utf-8 -*-

import os
import sys
import torch


nets = {
1: ["vgg.0", "vgg.2", "vgg.5", "vgg.7", "vgg.10", "vgg.12", "vgg.14", "vgg.17", "vgg.19", "vgg.21"],
2: ["vgg.24", "vgg.26", "vgg.28", "vgg.31", "vgg.33"],
3: ["extras.0", "extras.1"],
4: ["extras.2", "extras.3"],
5: ["extras.4", "extras.5"],
6: ["extras.6", "extras.7"],
7: ["loc.0"],
8: ["loc.1"],
9: ["loc.2"],
10: ["loc.3"],
11: ["loc.4"],
12: ["loc.5"],
13: ["conf.0"],
14: ["conf.1"],
15: ["conf.2"],
16: ["conf.3"],
17: ["conf.4"],
18: ["conf.5"],
}


def dump_layer_weights(f, weight, bias):
for i in range(weight.shape[0]):
for j in range(weight.shape[1]):
for k in range(weight.shape[2]):
for m in range(weight.shape[3]):
f.write('%.24f ' % weight[i][j][k][m])
_ = f.write('\n')
for i in range(bias.shape[0]):
f.write('%.24f ' % bias[i])
_ = f.write('\n')



def dump_net_weights(model_path, output_folder):
ckpt = torch.load(model_path)

for net_id in nets:
layers = nets[net_id]
output_file_path = os.path.join(output_folder, '%02d.weights' % net_id)

print('Saving weights to %s' % output_file_path)
with open(output_file_path, 'w') as f:
for layer in layers:
weight = ckpt['%s.weight' % layer]
bias = ckpt['%s.bias' % layer]
dump_layer_weights(f, weight, bias)


def main():
if not len(sys.argv) == 3:
print('python convert_models.py model_path output_folder')
sys.exit(1)

model_path = sys.argv[1]
output_folder = sys.argv[2]
if not os.path.exists(model_path) or os.path.isdir(model_path):
print('[ERROR] Model file not exists!')
sys.exit(2)
if not os.path.exists(output_folder) or not os.path.isdir(output_folder):
print('[ERROR] Output folder not exists!')
sys.exit(2)

dump_net_weights(model_path, output_folder)


if __name__ == '__main__':
main()

0 comments on commit 4120498

Please sign in to comment.