Full Code of simonwsw/deep-soli for AI

master e748041d59bb cached
26 files
61.3 KB
29.6k tokens
25 symbols
1 requests
Download .txt
Repository: simonwsw/deep-soli
Branch: master
Commit: e748041d59bb
Files: 26
Total size: 61.3 KB

Directory structure:
gitextract_2w_qnpkh/

├── .gitignore
├── LICENSE
├── README.md
├── cite.bib
├── config/
│   └── file_half.json
├── image/
│   ├── Makefile
│   ├── h5Data.cpp
│   ├── h5Data.hpp
│   ├── main.cpp
│   ├── seq.cpp
│   └── seq.hpp
├── net/
│   ├── data.lua
│   ├── imageseq.lua
│   ├── main.lua
│   ├── net.lua
│   ├── rnndata.lua
│   ├── rnntrain.lua
│   ├── seq.lua
│   ├── stat.lua
│   ├── train.lua
│   ├── uninet.lua
│   └── util.lua
└── pre/
    ├── image.py
    ├── main.py
    ├── op.py
    └── seq.py

================================================
FILE CONTENTS
================================================

================================================
FILE: .gitignore
================================================
# Mac
.DS_Store

# Matlab
*.m~
*.asv

# Vim
*~

# Python binary
*.pyc

# Temp dir
tmp

# Build and CMake
build

# openFrameworks
bin
obj


================================================
FILE: LICENSE
================================================
MIT License

Copyright (c) 2016 Saiwen Wang

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.


================================================
FILE: README.md
================================================
# deep-soli

Gesture Recognition Using Neural Networks with Google's Project Soli Sensor

## Update

Dataset and trained model are now available.

## Introduction

This is the open source evaluation code base of our paper:

**Interacting with Soli: Exploring Fine-Grained Dynamic Gesture Recognition
in the Radio-Frequency Spectrum** <br />
Saiwen Wang, Jie Song, Jamie Lien, Poupyrev Ivan, Otmar Hilliges <br />
(link to the [paper](http://bit.ly/2ftSRcn))

Please cite the paper if you find the code useful. Thank you.
([BibTex](https://github.com/simonwsw/deep-soli/blob/master/cite.bib))

This project uses Google's [Project Soli](atap.google.com/soli) sensor.

> Soli is a new sensing technology that uses miniature radar to
> detect touchless gesture interactions.
>
> ![Soli sensor image](http://bit.ly/2fbwLYm)
>
> Soli sensor technology works by emitting electromagnetic waves in a
> broad beam. Objects within the beam scatter this energy, reflecting
> some portion back towards the radar antenna. Properties of the
> reflected signal, such as energy, time delay, and frequency shift
> capture rich information about the object’s characteristics and
> dynamics, including size, shape, orientation, material, distance,
> and velocity.

Our paper uses a light-weight end-to-end trained Convolutional Neural Networks
and Recurrent Neural Networks architecture, recognizes 11 in-air gestures
with 87% per-frame accuracy, and can perform realtime predictions at 140Hz
on commodity hardware. (link to the [paper video](http://bit.ly/2fDd9iJ))

## Pre-request

- Python 2: HDF5, OpenCV 2 interfaces for python.
- C++: HDF5, OpenCV 2, Boost
- Lua JIT and Torch 7.
- Torch 7 packages: `class`, GPU support `cunn` and `cutorch`, Matlab
  support `mattorch`, JSON support `lunajson`, Torch image library `image`
- Please note that `mattorch` is an outdated packages which is no
  longer maintained.

## Quick start

- Make image binary

```
cd image
mkdir bin
make
```

- Preprocessing (HDF5 to images):

```
python pre/main.py --op image --file [dataset folder]
--target [target image folder] --channel 4 --originsize 32 --outsize 32
```

- Preprocessing (generate mean file):

```
python pre/main.py --op mean --file [image folder]
--target [mean file name] --channel 4 --outsize 32
```

- Load model and evaluate:

```
th net/main.lua --file [image folder] --list [train/test sequence split file]
--load [model file] --inputsize 32 --inputch 4 --label 13 --datasize 32
--datach 4 --batch 16 --maxseq 40 --cuda --cudnn
```

## Dataset

- Download [dataset](https://polybox.ethz.ch/index.php/s/wG93iTUdvRU8EaT)
  (please let me know when the link doesn't work).
- Train/test split file (in JSON format) we used is stored in the repo
  `config/file_half.json`.
- The dataset contains multiple preprocessed Range-Doppler Image sequences.
  Each sequence is saved as a single HDF5 format data file. File names are
  defined as `[gesture ID]_[session ID]_[instance ID].h5`. Range-Doppler Image
  data of a specific channel can be accessed by dataset name `ch[channel ID]`.
  Label can be accessed by dataset name `label`. Range-Doppler Image
  data array has shape of `[number of frame] * 1024` (can be reshape back to 2D Range-Doppler Image to `32 * 32`)
- Simple Python code to access the data:

```python
# Demo code to extract data in python
import h5py

use_channel = 0
with h5py.File(file_name, 'r') as f:
    # Data and label are numpy arrays
    data = f['ch{}'.format(use_channel)][()]
    label = f['label'][()]
```

- Dataset session arrangement for evaluation.
  - 11 (gestures) * 25 (instances) * 10 (users) for cross user evaluation:
    session 2 (25), 3 (25), 5 (25), 6 (25), 8 (25), 9 (25), 10 (25), 11 (25),
    12 (25), 13 (25).
  - 11 (gestures) * (50 (instances) * 4 (sessions) +
    25 (instances) * 2 (sessions)) for single user
    cross session evaluation: session 0 (50), 1 (50), 4 (50), 7 (50),
    13 (25), 14 (25).
  - Please refer to the paper for the gesture collecting
    campaign details.
- The gestures are listed in the table below. Each column represents
  one gesture and we snapshot three important steps for each gestures.
  The gesture label is indicated by the number in the circle above. Please
  notice that the gesture label order is different than the paper, as
  we regroup gestures in the paper. Sequences with gesture ID 11 are
  background signals with no presence of hand.

![gesture](http://bit.ly/2fHcMRX)

## Pre-trained model

- Download [model](https://polybox.ethz.ch/index.php/s/0SEdZqkn433dbEh)
- Trained proposed model, please refer to the paper for model detail.
- Simple Lua (Torch 7) code to load the model:

```
loadFile = 'uni_image_np_50.t7'
net = torch.load(loadFile)
print(net)
```

- The model uses layers support `cudnn`.

## Comments on the code base

This is a simplified version of the original code base we used for all the
experiments in the paper. The complex Torch based class hierarchies in
the `net` reflects varies model architectures we tried during the
experiments. For simplicity, we only make the evaluation part public.
The model detail can be found both in the paper and the model file.

## License

This project is licensed under the terms of the MIT license.


================================================
FILE: cite.bib
================================================
@inproceedings{wang2016interacting,
  title={Interacting with soli: Exploring fine-grained dynamic gesture recognition in the radio-frequency spectrum},
  author={Wang, Saiwen and Song, Jie and Lien, Jaime and Poupyrev, Ivan and Hilliges, Otmar},
  booktitle={Proceedings of the 29th Annual Symposium on User Interface Software and Technology},
  pages={851--860},
  year={2016},
  organization={ACM}
}


================================================
FILE: config/file_half.json
================================================
{"train": ["0_8_4", "0_3_1", "0_2_0", "0_13_5", "0_2_19", "0_3_2", "0_12_1", "0_9_7", "0_3_22", "0_2_2", "0_2_3", "0_5_8", "0_8_21", "0_9_4", "0_2_17", "0_13_13", "0_2_22", "0_9_15", "0_9_17", "0_11_14", "0_10_14", "0_2_16", "0_6_7", "0_2_10", "0_12_19", "0_8_24", "0_8_3", "0_11_4", "0_2_11", "0_3_3", "0_12_14", "0_5_7", "0_11_3", "0_10_1", "0_9_14", "0_11_23", "0_12_13", "0_8_19", "0_8_16", "0_10_16", "0_9_2", "0_8_13", "0_3_9", "0_9_12", "0_13_12", "0_5_15", "0_6_15", "0_6_0", "0_5_0", "0_10_7", "0_9_3", "0_3_11", "0_3_6", "0_13_18", "0_6_19", "0_9_5", "0_10_11", "0_12_7", "0_12_16", "0_11_16", "0_8_14", "0_11_20", "0_10_0", "0_10_13", "0_6_17", "0_6_11", "0_11_17", "0_10_2", "0_11_2", "0_12_18", "0_12_4", "0_11_9", "0_2_14", "0_6_6", "0_5_9", "0_10_8", "0_8_23", "0_11_0", "0_3_20", "0_11_7", "0_11_13", "0_2_7", "0_11_5", "0_8_12", "0_10_21", "0_2_9", "0_12_5", "0_3_23", "0_3_19", "0_8_7", "0_10_10", "0_5_2", "0_13_22", "0_8_5", "0_11_22", "0_11_24", "0_9_24", "0_3_12", "0_2_6", "0_8_20", "0_5_18", "0_5_3", "0_3_8", "0_9_9", "0_11_19", "0_13_23", "0_6_5", "0_11_18", "0_3_13", "0_3_16", "0_9_1", "0_3_4", "0_5_6", "0_6_22", "0_13_20", "0_9_10", "0_3_17", "0_6_10", "0_2_24", "0_10_3", "0_5_5", "0_6_18", "0_6_4", "0_2_1", "0_3_14", "0_10_5", "1_8_3", "1_2_24", "1_2_16", "1_9_12", "1_6_14", "1_13_24", "1_3_6", "1_3_1", "1_9_7", "1_3_24", "1_5_14", "1_9_6", "1_13_6", "1_13_3", "1_2_6", "1_6_10", "1_10_10", "1_2_12", "1_3_4", "1_5_12", "1_12_7", "1_12_24", "1_5_21", "1_12_12", "1_11_9", "1_11_10", "1_13_10", "1_11_19", "1_6_4", "1_5_1", "1_3_16", "1_5_6", "1_6_15", "1_5_18", "1_2_13", "1_9_21", "1_13_19", "1_3_0", "1_13_1", "1_10_12", "1_12_5", "1_9_13", "1_11_22", "1_3_10", "1_3_14", "1_8_11", "1_5_15", "1_6_2", "1_5_9", "1_9_24", "1_8_10", "1_5_10", "1_6_0", "1_10_8", "1_10_2", "1_8_19", "1_13_5", "1_12_11", "1_12_22", "1_9_17", "1_2_18", "1_11_4", "1_2_0", "1_5_22", "1_3_15", "1_10_20", "1_2_5", "1_2_8", "1_13_2", "1_10_5", "1_11_3", "1_10_24", "1_10_21", "1_6_11", "1_11_14", "1_9_1", "1_8_22", "1_13_21", "1_10_14", "1_9_19", "1_6_16", "1_2_10", "1_3_21", "1_8_14", "1_10_1", "1_12_14", "1_2_17", "1_5_19", "1_13_9", "1_8_12", "1_2_11", "1_13_11", "1_3_17", "1_11_17", "1_12_2", "1_12_15", "1_3_9", "1_10_6", "1_11_15", "1_2_23", "1_2_14", "1_8_16", "1_6_3", "1_3_5", "1_11_24", "1_13_14", "1_13_20", "1_3_2", "1_10_18", "1_9_16", "1_9_23", "1_8_2", "1_12_18", "1_3_8", "1_13_7", "1_2_4", "1_2_22", "1_5_8", "1_6_24", "1_2_9", "1_2_2", "1_11_12", "1_11_21", "1_11_8", "1_8_5", "1_11_18", "2_6_6", "2_9_20", "2_2_7", "2_3_16", "2_8_24", "2_8_9", "2_8_21", "2_11_17", "2_8_23", "2_9_8", "2_3_8", "2_2_11", "2_8_18", "2_13_11", "2_9_5", "2_11_14", "2_13_9", "2_12_14", "2_8_16", "2_10_21", "2_2_13", "2_13_18", "2_2_23", "2_12_15", "2_8_12", "2_11_0", "2_5_5", "2_5_19", "2_8_13", "2_5_12", "2_13_21", "2_3_13", "2_9_22", "2_2_9", "2_10_20", "2_6_2", "2_5_3", "2_10_17", "2_11_24", "2_10_12", "2_11_16", "2_11_5", "2_3_0", "2_12_19", "2_3_2", "2_10_0", "2_10_18", "2_13_2", "2_12_17", "2_12_11", "2_13_10", "2_5_17", "2_13_7", "2_11_8", "2_5_6", "2_13_20", "2_8_7", "2_6_7", "2_12_22", "2_6_16", "2_5_21", "2_3_5", "2_5_11", "2_13_17", "2_3_1", "2_6_12", "2_10_24", "2_3_3", "2_8_2", "2_10_23", "2_3_7", "2_5_1", "2_8_11", "2_5_15", "2_6_23", "2_2_5", "2_12_23", "2_5_23", "2_10_22", "2_2_3", "2_13_1", "2_9_7", "2_12_10", "2_12_9", "2_11_6", "2_2_18", "2_12_2", "2_10_10", "2_2_2", "2_11_2", "2_3_20", "2_13_6", "2_12_5", "2_11_18", "2_6_14", "2_5_20", "2_5_8", "2_8_3", "2_10_5", "2_8_4", "2_9_17", "2_2_14", "2_10_19", "2_2_22", "2_2_12", "2_11_21", "2_12_7", "2_6_5", "2_6_13", "2_12_24", "2_5_14", "2_6_8", "2_8_0", "2_8_1", "2_10_7", "2_12_3", "2_3_22", "2_9_24", "2_3_23", "2_12_20", "2_10_11", "2_3_19", "2_5_13", "2_11_9", "2_9_23", "2_2_20", "3_5_21", "3_8_14", "3_9_1", "3_10_21", "3_9_14", "3_12_1", "3_8_24", "3_3_4", "3_12_3", "3_9_24", "3_13_4", "3_2_2", "3_12_14", "3_8_4", "3_6_22", "3_10_16", "3_10_2", "3_5_4", "3_3_13", "3_2_21", "3_11_0", "3_6_16", "3_3_2", "3_8_12", "3_12_18", "3_5_2", "3_6_12", "3_11_13", "3_10_6", "3_6_8", "3_6_21", "3_10_19", "3_11_2", "3_3_5", "3_12_19", "3_13_18", "3_12_12", "3_13_22", "3_3_22", "3_10_8", "3_6_17", "3_11_10", "3_2_10", "3_5_14", "3_6_18", "3_2_9", "3_5_22", "3_9_3", "3_3_8", "3_12_20", "3_2_12", "3_10_1", "3_13_9", "3_13_12", "3_11_20", "3_12_10", "3_6_24", "3_13_2", "3_5_6", "3_12_21", "3_10_17", "3_10_18", "3_9_23", "3_3_12", "3_12_11", "3_8_17", "3_11_6", "3_8_8", "3_11_7", "3_3_19", "3_10_22", "3_10_14", "3_10_20", "3_13_15", "3_5_8", "3_3_10", "3_8_20", "3_11_9", "3_9_13", "3_6_11", "3_6_19", "3_11_18", "3_13_5", "3_8_9", "3_13_21", "3_9_21", "3_2_3", "3_9_7", "3_2_11", "3_3_20", "3_5_15", "3_12_7", "3_5_5", "3_3_17", "3_10_13", "3_11_19", "3_9_4", "3_3_14", "3_10_7", "3_9_11", "3_10_11", "3_10_10", "3_13_17", "3_5_19", "3_2_23", "3_6_5", "3_3_11", "3_13_14", "3_8_10", "3_5_11", "3_9_22", "3_13_13", "3_3_16", "3_11_5", "3_3_18", "3_6_23", "3_5_17", "3_13_1", "3_9_20", "3_5_24", "3_12_22", "3_6_6", "3_12_16", "3_12_15", "3_10_3", "3_5_16", "4_3_14", "4_3_7", "4_3_20", "4_3_5", "4_5_8", "4_2_15", "4_6_10", "4_13_9", "4_13_23", "4_10_16", "4_5_16", "4_10_3", "4_3_1", "4_10_24", "4_2_13", "4_5_11", "4_6_23", "4_9_1", "4_10_23", "4_6_20", "4_2_22", "4_11_18", "4_5_15", "4_9_22", "4_10_20", "4_11_7", "4_12_4", "4_3_0", "4_9_15", "4_9_17", "4_9_5", "4_9_21", "4_9_4", "4_13_24", "4_9_24", "4_10_11", "4_3_9", "4_6_2", "4_9_6", "4_3_3", "4_8_15", "4_3_18", "4_6_14", "4_13_11", "4_8_19", "4_5_4", "4_3_16", "4_6_6", "4_5_7", "4_8_14", "4_11_12", "4_12_14", "4_11_22", "4_11_17", "4_8_24", "4_6_1", "4_13_20", "4_12_21", "4_8_7", "4_3_22", "4_12_17", "4_10_9", "4_11_19", "4_3_17", "4_2_16", "4_10_19", "4_13_21", "4_9_20", "4_8_10", "4_5_2", "4_9_3", "4_9_16", "4_2_7", "4_13_3", "4_10_0", "4_8_22", "4_11_23", "4_5_0", "4_6_0", "4_11_6", "4_9_10", "4_2_6", "4_9_18", "4_8_23", "4_5_19", "4_2_14", "4_12_19", "4_11_4", "4_8_13", "4_8_2", "4_5_18", "4_13_15", "4_13_19", "4_8_5", "4_11_3", "4_3_19", "4_2_23", "4_2_8", "4_3_12", "4_6_18", "4_12_9", "4_2_4", "4_11_0", "4_12_5", "4_12_23", "4_6_15", "4_11_5", "4_3_13", "4_5_24", "4_12_18", "4_13_7", "4_5_12", "4_8_9", "4_6_8", "4_2_3", "4_10_17", "4_5_1", "4_6_24", "4_9_14", "4_3_8", "4_9_19", "4_10_18", "4_5_14", "4_10_1", "4_9_23", "4_12_13", "5_10_0", "5_3_24", "5_12_1", "5_12_4", "5_2_10", "5_8_22", "5_2_21", "5_9_7", "5_6_21", "5_12_14", "5_13_3", "5_12_5", "5_11_8", "5_10_11", "5_9_20", "5_11_1", "5_8_1", "5_12_9", "5_12_22", "5_5_17", "5_6_15", "5_9_23", "5_8_16", "5_6_19", "5_2_11", "5_13_4", "5_11_5", "5_3_20", "5_13_0", "5_8_13", "5_6_5", "5_2_19", "5_9_3", "5_5_10", "5_5_0", "5_9_16", "5_6_0", "5_2_15", "5_5_12", "5_2_4", "5_2_7", "5_3_2", "5_3_11", "5_11_11", "5_3_8", "5_11_13", "5_13_21", "5_5_15", "5_12_24", "5_3_7", "5_3_3", "5_5_21", "5_13_13", "5_10_9", "5_13_6", "5_9_17", "5_5_9", "5_10_20", "5_12_17", "5_11_18", "5_6_16", "5_9_11", "5_2_18", "5_2_9", "5_8_18", "5_13_18", "5_9_5", "5_3_18", "5_2_13", "5_12_3", "5_10_16", "5_3_13", "5_2_17", "5_10_8", "5_5_8", "5_13_2", "5_13_14", "5_13_5", "5_12_6", "5_6_1", "5_11_4", "5_3_5", "5_12_0", "5_6_2", "5_12_18", "5_6_13", "5_13_1", "5_9_13", "5_10_24", "5_3_6", "5_5_23", "5_12_15", "5_12_7", "5_13_9", "5_2_6", "5_10_14", "5_8_11", "5_10_15", "5_6_3", "5_9_0", "5_9_22", "5_8_10", "5_8_12", "5_8_19", "5_2_3", "5_2_2", "5_13_8", "5_10_2", "5_9_6", "5_8_4", "5_10_6", "5_6_14", "5_9_10", "5_3_21", "5_11_12", "5_8_5", "5_10_22", "5_13_12", "5_8_23", "5_5_4", "5_10_13", "5_5_19", "5_8_8", "5_6_17", "5_3_17", "5_5_11", "6_11_2", "6_11_21", "6_3_5", "6_6_19", "6_12_4", "6_3_24", "6_13_0", "6_6_16", "6_3_18", "6_3_13", "6_9_20", "6_9_24", "6_9_21", "6_2_12", "6_13_20", "6_6_22", "6_9_13", "6_8_3", "6_2_20", "6_2_4", "6_10_0", "6_9_6", "6_10_13", "6_3_11", "6_11_11", "6_8_13", "6_8_8", "6_9_9", "6_12_10", "6_10_7", "6_12_16", "6_3_14", "6_8_17", "6_6_11", "6_9_2", "6_8_0", "6_10_1", "6_5_5", "6_3_4", "6_2_16", "6_8_2", "6_6_2", "6_10_8", "6_9_3", "6_9_14", "6_10_12", "6_2_1", "6_9_0", "6_2_15", "6_9_15", "6_10_14", "6_5_13", "6_3_9", "6_12_24", "6_3_2", "6_6_10", "6_5_20", "6_9_22", "6_6_9", "6_9_1", "6_6_24", "6_13_7", "6_5_2", "6_10_20", "6_12_9", "6_10_3", "6_9_8", "6_2_8", "6_12_23", "6_10_5", "6_8_15", "6_13_12", "6_9_16", "6_10_10", "6_5_14", "6_13_1", "6_11_3", "6_13_13", "6_3_20", "6_9_11", "6_5_12", "6_12_11", "6_9_18", "6_6_21", "6_8_12", "6_5_10", "6_8_23", "6_3_6", "6_9_12", "6_8_9", "6_5_1", "6_6_20", "6_11_19", "6_10_19", "6_8_20", "6_5_11", "6_5_8", "6_9_4", "6_2_21", "6_11_1", "6_6_13", "6_10_15", "6_2_7", "6_8_14", "6_3_3", "6_9_10", "6_5_0", "6_6_5", "6_3_0", "6_10_4", "6_6_23", "6_12_12", "6_3_15", "6_8_11", "6_10_21", "6_3_10", "6_13_5", "6_6_15", "6_12_6", "6_10_9", "6_11_23", "6_5_4", "6_6_7", "6_8_21", "6_12_21", "6_8_18", "7_12_6", "7_8_1", "7_11_17", "7_2_3", "7_10_14", "7_6_9", "7_5_9", "7_6_23", "7_5_14", "7_3_13", "7_2_5", "7_13_20", "7_10_24", "7_13_21", "7_5_20", "7_8_20", "7_12_18", "7_8_18", "7_11_16", "7_3_17", "7_10_21", "7_5_13", "7_2_13", "7_11_3", "7_5_4", "7_2_20", "7_9_10", "7_6_24", "7_13_15", "7_2_21", "7_2_4", "7_8_7", "7_13_9", "7_8_4", "7_5_5", "7_13_8", "7_6_2", "7_13_10", "7_9_13", "7_8_23", "7_9_11", "7_8_11", "7_9_19", "7_3_12", "7_10_6", "7_8_10", "7_3_3", "7_11_15", "7_3_7", "7_6_14", "7_2_9", "7_11_13", "7_12_7", "7_3_10", "7_5_8", "7_2_24", "7_10_12", "7_11_7", "7_11_10", "7_13_16", "7_10_1", "7_6_15", "7_8_5", "7_3_20", "7_6_0", "7_9_8", "7_12_17", "7_12_24", "7_2_0", "7_10_20", "7_10_2", "7_9_1", "7_11_5", "7_12_16", "7_11_12", "7_9_9", "7_3_2", "7_6_21", "7_13_5", "7_10_23", "7_11_14", "7_9_3", "7_2_15", "7_6_7", "7_2_17", "7_6_3", "7_5_22", "7_9_21", "7_12_23", "7_10_18", "7_3_14", "7_8_2", "7_5_23", "7_12_5", "7_13_23", "7_2_16", "7_12_22", "7_9_4", "7_13_17", "7_6_4", "7_10_11", "7_10_7", "7_3_1", "7_5_15", "7_9_14", "7_2_1", "7_9_12", "7_5_11", "7_11_9", "7_6_20", "7_6_19", "7_12_0", "7_13_2", "7_6_1", "7_13_11", "7_11_21", "7_8_19", "7_11_23", "7_8_13", "7_12_20", "7_2_22", "7_11_22", "7_10_22", "7_9_0", "7_3_19", "7_3_5", "8_11_7", "8_3_20", "8_13_6", "8_2_5", "8_13_16", "8_13_2", "8_10_14", "8_13_20", "8_8_0", "8_2_20", "8_2_24", "8_2_7", "8_11_2", "8_2_12", "8_2_14", "8_2_17", "8_10_11", "8_6_22", "8_10_19", "8_12_17", "8_2_11", "8_9_9", "8_9_0", "8_11_11", "8_13_0", "8_11_6", "8_5_24", "8_10_5", "8_5_9", "8_13_4", "8_3_2", "8_6_16", "8_13_5", "8_8_11", "8_5_19", "8_10_7", "8_12_13", "8_13_14", "8_8_3", "8_12_18", "8_3_16", "8_12_23", "8_10_8", "8_11_17", "8_8_16", "8_3_9", "8_8_22", "8_11_3", "8_10_24", "8_3_23", "8_6_13", "8_5_17", "8_2_4", "8_13_21", "8_12_1", "8_10_17", "8_6_2", "8_6_7", "8_11_24", "8_3_10", "8_12_20", "8_3_3", "8_12_14", "8_5_6", "8_8_18", "8_11_13", "8_2_23", "8_2_1", "8_12_12", "8_8_6", "8_12_16", "8_5_4", "8_3_6", "8_12_2", "8_10_3", "8_5_23", "8_12_4", "8_11_12", "8_6_5", "8_13_24", "8_3_19", "8_10_18", "8_12_21", "8_9_16", "8_9_3", "8_3_22", "8_8_9", "8_3_17", "8_9_7", "8_5_22", "8_8_10", "8_9_11", "8_12_3", "8_9_22", "8_2_13", "8_6_23", "8_6_20", "8_6_18", "8_12_7", "8_10_0", "8_8_7", "8_12_19", "8_8_20", "8_12_9", "8_9_14", "8_12_15", "8_3_4", "8_11_1", "8_6_14", "8_6_15", "8_9_13", "8_10_10", "8_3_12", "8_5_12", "8_2_21", "8_13_7", "8_10_20", "8_6_3", "8_8_8", "8_6_12", "8_5_3", "8_6_8", "8_11_0", "8_8_19", "8_11_19", "8_9_5", "9_8_3", "9_9_18", "9_8_13", "9_9_16", "9_8_5", "9_11_23", "9_6_1", "9_9_17", "9_3_20", "9_2_23", "9_9_10", "9_12_21", "9_5_21", "9_10_10", "9_8_22", "9_6_7", "9_3_23", "9_9_21", "9_11_8", "9_2_17", "9_9_12", "9_11_15", "9_11_6", "9_2_21", "9_2_0", "9_13_1", "9_9_20", "9_5_22", "9_12_20", "9_2_14", "9_10_23", "9_5_7", "9_12_0", "9_3_11", "9_10_5", "9_2_16", "9_5_12", "9_8_16", "9_13_9", "9_12_15", "9_12_24", "9_5_14", "9_9_13", "9_13_0", "9_6_4", "9_9_23", "9_13_19", "9_13_12", "9_9_4", "9_9_5", "9_8_12", "9_13_23", "9_5_9", "9_8_14", "9_13_4", "9_3_10", "9_5_11", "9_3_9", "9_3_3", "9_11_14", "9_2_22", "9_9_15", "9_13_3", "9_10_19", "9_11_12", "9_12_22", "9_8_1", "9_11_5", "9_10_16", "9_3_21", "9_10_18", "9_12_17", "9_10_15", "9_3_7", "9_5_18", "9_5_19", "9_2_4", "9_12_3", "9_3_17", "9_2_5", "9_13_24", "9_6_17", "9_6_11", "9_11_21", "9_10_0", "9_11_18", "9_10_11", "9_8_24", "9_12_18", "9_10_2", "9_2_8", "9_9_3", "9_11_9", "9_5_23", "9_5_15", "9_12_6", "9_9_22", "9_2_10", "9_2_3", "9_10_12", "9_11_17", "9_3_14", "9_13_14", "9_8_0", "9_3_8", "9_5_1", "9_13_17", "9_12_12", "9_6_19", "9_3_15", "9_8_11", "9_3_4", "9_10_21", "9_6_21", "9_10_9", "9_8_2", "9_6_10", "9_8_4", "9_2_13", "9_3_1", "9_6_20", "9_10_14", "9_8_7", "9_3_13", "9_5_0", "9_5_17", "10_10_16", "10_10_7", "10_3_23", "10_5_0", "10_6_16", "10_10_11", "10_6_2", "10_5_9", "10_12_7", "10_10_19", "10_13_15", "10_10_3", "10_6_7", "10_11_17", "10_9_0", "10_6_5", "10_3_11", "10_13_0", "10_13_2", "10_10_13", "10_11_20", "10_3_19", "10_13_14", "10_5_15", "10_9_19", "10_9_22", "10_11_3", "10_2_1", "10_6_13", "10_12_11", "10_9_20", "10_8_6", "10_10_20", "10_8_2", "10_8_19", "10_9_14", "10_2_14", "10_13_18", "10_9_16", "10_2_13", "10_9_7", "10_3_1", "10_9_4", "10_2_15", "10_9_6", "10_8_4", "10_12_13", "10_13_10", "10_12_1", "10_12_2", "10_13_13", "10_8_0", "10_10_6", "10_12_20", "10_5_16", "10_2_20", "10_6_8", "10_12_15", "10_2_2", "10_9_1", "10_13_19", "10_9_15", "10_8_20", "10_8_22", "10_2_8", "10_2_7", "10_11_23", "10_10_1", "10_9_17", "10_10_5", "10_10_18", "10_11_8", "10_6_17", "10_11_12", "10_3_15", "10_13_20", "10_3_17", "10_11_0", "10_2_24", "10_12_12", "10_12_10", "10_13_4", "10_8_16", "10_8_11", "10_8_3", "10_6_18", "10_8_10", "10_5_14", "10_12_17", "10_6_23", "10_3_13", "10_13_12", "10_5_19", "10_6_20", "10_11_21", "10_11_7", "10_12_4", "10_13_5", "10_2_12", "10_11_6", "10_10_15", "10_2_19", "10_10_22", "10_13_9", "10_5_5", "10_5_1", "10_5_24", "10_2_9", "10_6_22", "10_12_16", "10_5_6", "10_13_11", "10_13_21", "10_10_0", "10_9_10", "10_10_8", "10_9_3", "10_5_12", "10_12_19", "10_8_9", "10_3_12", "10_11_11", "10_11_16", "10_5_4", "10_6_19", "10_3_7"], "eval": ["0_12_20", "0_10_18", "0_6_8", "0_3_0", "0_12_22", "0_13_10", "0_12_3", "0_5_14", "0_10_15", "0_2_5", "0_3_5", "0_3_18", "0_12_21", "0_5_21", "0_10_20", "0_8_22", "0_8_11", "0_13_6", "0_9_0", "0_3_7", "0_8_8", "0_5_10", "0_10_6", "0_9_20", "0_6_20", "0_13_15", "0_6_2", "0_9_13", "0_13_17", "0_12_23", "0_2_4", "0_12_10", "0_11_12", "0_13_21", "0_13_9", "0_12_6", "0_5_12", "0_9_16", "0_2_18", "0_13_4", "0_6_1", "0_10_12", "0_11_1", "0_11_6", "0_13_16", "0_2_13", "0_2_12", "0_5_16", "0_8_10", "0_13_19", "0_12_2", "0_12_17", "0_9_19", "0_6_3", "0_13_2", "0_9_6", "0_5_13", "0_12_9", "0_6_21", "0_5_19", "0_10_9", "0_9_23", "0_2_15", "0_9_22", "0_3_15", "0_11_21", "0_8_18", "0_12_12", "0_12_8", "0_5_22", "0_10_23", "0_5_17", "0_13_24", "0_6_12", "0_6_13", "0_10_24", "0_8_0", "0_5_24", "0_12_0", "0_8_6", "0_8_15", "0_5_11", "0_2_20", "0_8_2", "0_6_16", "0_9_21", "0_6_14", "0_3_21", "0_10_4", "0_13_8", "0_10_22", "0_9_18", "0_6_24", "0_13_1", "0_11_10", "0_5_4", "0_8_1", "0_13_11", "0_10_19", "0_2_23", "0_13_3", "0_11_8", "0_8_9", "0_12_15", "0_11_15", "0_3_24", "0_8_17", "0_3_10", "0_5_1", "0_2_21", "0_10_17", "0_2_8", "0_9_8", "0_13_7", "0_6_9", "0_5_20", "0_12_24", "0_12_11", "0_13_0", "0_9_11", "0_5_23", "0_11_11", "0_6_23", "0_13_14", "1_6_23", "1_9_5", "1_11_16", "1_10_16", "1_13_22", "1_3_18", "1_6_19", "1_8_23", "1_9_20", "1_8_9", "1_8_24", "1_9_15", "1_12_9", "1_5_2", "1_5_24", "1_6_17", "1_10_3", "1_10_22", "1_6_7", "1_12_1", "1_9_10", "1_12_10", "1_6_5", "1_8_21", "1_5_17", "1_3_20", "1_13_23", "1_2_15", "1_8_7", "1_11_1", "1_2_7", "1_11_23", "1_13_8", "1_6_13", "1_2_21", "1_3_13", "1_13_15", "1_6_18", "1_9_9", "1_2_19", "1_12_17", "1_11_11", "1_5_20", "1_5_16", "1_12_6", "1_3_7", "1_2_20", "1_11_7", "1_6_1", "1_9_22", "1_10_0", "1_6_22", "1_9_14", "1_2_3", "1_6_6", "1_8_17", "1_3_19", "1_11_0", "1_8_18", "1_10_15", "1_9_8", "1_9_18", "1_5_0", "1_10_23", "1_5_23", "1_10_13", "1_10_7", "1_6_8", "1_11_6", "1_8_0", "1_8_6", "1_13_17", "1_12_4", "1_13_13", "1_9_0", "1_6_20", "1_5_4", "1_3_3", "1_3_23", "1_12_20", "1_10_4", "1_11_2", "1_8_20", "1_12_3", "1_8_8", "1_12_8", "1_12_0", "1_5_11", "1_13_12", "1_9_11", "1_2_1", "1_12_13", "1_10_17", "1_3_22", "1_6_9", "1_3_12", "1_12_16", "1_8_15", "1_12_23", "1_5_5", "1_11_5", "1_11_20", "1_13_16", "1_8_4", "1_5_13", "1_13_18", "1_8_13", "1_8_1", "1_10_9", "1_13_4", "1_6_12", "1_5_7", "1_6_21", "1_9_2", "1_3_11", "1_5_3", "1_10_19", "1_9_4", "1_9_3", "1_13_0", "1_12_19", "1_10_11", "1_11_13", "1_12_21", "2_6_24", "2_10_13", "2_12_18", "2_5_2", "2_2_10", "2_12_4", "2_2_15", "2_10_14", "2_9_11", "2_9_19", "2_8_5", "2_9_14", "2_10_6", "2_3_18", "2_13_12", "2_2_0", "2_11_19", "2_12_21", "2_5_0", "2_8_19", "2_9_18", "2_13_5", "2_3_12", "2_3_6", "2_12_6", "2_9_21", "2_9_4", "2_3_14", "2_11_10", "2_11_1", "2_9_6", "2_2_17", "2_5_16", "2_6_9", "2_2_16", "2_6_11", "2_9_9", "2_9_12", "2_8_15", "2_2_1", "2_6_10", "2_13_16", "2_12_1", "2_9_13", "2_10_3", "2_6_4", "2_6_1", "2_11_12", "2_12_12", "2_11_7", "2_3_17", "2_6_17", "2_9_0", "2_2_8", "2_3_24", "2_9_3", "2_8_6", "2_13_0", "2_9_2", "2_5_10", "2_13_4", "2_3_10", "2_6_3", "2_9_1", "2_3_11", "2_9_10", "2_13_14", "2_5_7", "2_6_19", "2_13_19", "2_10_1", "2_2_19", "2_11_20", "2_13_24", "2_10_4", "2_6_18", "2_9_15", "2_6_15", "2_5_22", "2_13_3", "2_10_16", "2_11_11", "2_8_17", "2_10_2", "2_6_0", "2_3_21", "2_3_15", "2_13_8", "2_6_22", "2_10_9", "2_12_16", "2_5_18", "2_8_10", "2_10_15", "2_8_22", "2_13_13", "2_12_8", "2_13_15", "2_11_22", "2_2_4", "2_11_13", "2_3_4", "2_5_4", "2_11_4", "2_8_14", "2_2_6", "2_9_16", "2_11_23", "2_12_13", "2_3_9", "2_8_20", "2_6_20", "2_11_15", "2_6_21", "2_13_22", "2_5_9", "2_10_8", "2_12_0", "2_11_3", "2_2_24", "2_5_24", "2_13_23", "2_8_8", "2_2_21", "3_13_24", "3_2_17", "3_11_3", "3_5_9", "3_2_0", "3_3_23", "3_10_23", "3_3_6", "3_10_9", "3_8_18", "3_5_12", "3_11_17", "3_8_5", "3_2_15", "3_6_14", "3_9_12", "3_9_9", "3_13_10", "3_11_14", "3_8_3", "3_2_8", "3_11_8", "3_8_1", "3_3_15", "3_5_0", "3_13_0", "3_8_2", "3_6_7", "3_13_3", "3_11_1", "3_2_20", "3_8_16", "3_5_3", "3_2_13", "3_2_7", "3_2_4", "3_5_18", "3_6_3", "3_3_7", "3_9_18", "3_6_15", "3_9_15", "3_2_24", "3_11_22", "3_2_18", "3_10_12", "3_8_0", "3_8_13", "3_8_21", "3_9_6", "3_3_21", "3_12_13", "3_3_1", "3_8_15", "3_11_4", "3_3_0", "3_13_19", "3_11_16", "3_6_9", "3_2_19", "3_9_17", "3_13_11", "3_5_20", "3_13_7", "3_3_3", "3_13_23", "3_9_16", "3_9_8", "3_5_13", "3_5_23", "3_10_15", "3_8_19", "3_12_5", "3_12_4", "3_9_19", "3_6_20", "3_11_21", "3_6_1", "3_11_12", "3_2_22", "3_2_5", "3_6_13", "3_12_6", "3_2_16", "3_9_0", "3_8_23", "3_9_10", "3_6_0", "3_11_15", "3_12_9", "3_5_1", "3_13_20", "3_13_8", "3_13_6", "3_10_5", "3_10_24", "3_8_22", "3_6_10", "3_8_6", "3_8_7", "3_9_5", "3_11_11", "3_2_14", "3_6_2", "3_5_10", "3_11_23", "3_8_11", "3_10_0", "3_2_1", "3_11_24", "3_12_23", "3_12_17", "3_12_0", "3_12_24", "3_12_2", "3_9_2", "3_3_9", "3_5_7", "3_13_16", "3_10_4", "3_12_8", "3_6_4", "3_2_6", "3_3_24", "4_12_3", "4_6_12", "4_10_13", "4_3_21", "4_6_21", "4_3_15", "4_11_16", "4_13_5", "4_3_4", "4_10_2", "4_6_7", "4_9_11", "4_10_8", "4_2_20", "4_3_6", "4_3_2", "4_11_11", "4_8_16", "4_2_0", "4_2_2", "4_5_6", "4_12_1", "4_6_19", "4_8_0", "4_12_8", "4_13_10", "4_2_21", "4_3_24", "4_12_22", "4_11_8", "4_5_17", "4_13_4", "4_8_1", "4_11_14", "4_11_20", "4_10_21", "4_13_2", "4_13_1", "4_8_12", "4_9_0", "4_12_11", "4_12_2", "4_2_24", "4_3_11", "4_6_16", "4_12_7", "4_6_3", "4_9_13", "4_9_2", "4_13_6", "4_6_9", "4_8_18", "4_12_24", "4_2_11", "4_2_18", "4_9_8", "4_5_22", "4_5_10", "4_11_24", "4_13_22", "4_13_17", "4_8_11", "4_13_14", "4_8_20", "4_11_13", "4_2_1", "4_12_16", "4_11_15", "4_13_0", "4_2_5", "4_12_20", "4_5_5", "4_10_12", "4_8_21", "4_13_13", "4_10_6", "4_9_7", "4_2_19", "4_10_15", "4_10_22", "4_11_1", "4_10_7", "4_12_0", "4_2_12", "4_12_15", "4_9_9", "4_8_17", "4_8_8", "4_12_10", "4_3_23", "4_6_22", "4_8_4", "4_11_10", "4_2_9", "4_5_23", "4_6_4", "4_5_3", "4_13_12", "4_3_10", "4_10_4", "4_12_6", "4_6_13", "4_10_10", "4_9_12", "4_8_6", "4_13_16", "4_2_17", "4_2_10", "4_13_8", "4_11_21", "4_12_12", "4_11_9", "4_8_3", "4_13_18", "4_5_9", "4_5_20", "4_10_14", "4_6_5", "4_10_5", "4_11_2", "4_6_11", "4_5_13", "4_5_21", "4_6_17", "5_8_21", "5_10_19", "5_2_8", "5_5_16", "5_9_21", "5_2_20", "5_6_18", "5_6_8", "5_9_18", "5_12_11", "5_10_17", "5_13_11", "5_8_3", "5_5_13", "5_11_7", "5_12_8", "5_2_0", "5_3_23", "5_8_17", "5_5_6", "5_10_5", "5_8_9", "5_10_21", "5_12_10", "5_3_16", "5_5_14", "5_9_1", "5_11_21", "5_11_16", "5_5_22", "5_2_24", "5_13_15", "5_8_0", "5_10_1", "5_8_14", "5_8_20", "5_12_19", "5_8_6", "5_6_7", "5_5_1", "5_11_14", "5_3_19", "5_11_9", "5_5_24", "5_6_20", "5_8_24", "5_3_12", "5_12_2", "5_5_2", "5_12_16", "5_3_0", "5_11_10", "5_11_20", "5_13_19", "5_5_5", "5_3_15", "5_9_14", "5_9_24", "5_13_24", "5_11_23", "5_13_7", "5_13_23", "5_6_9", "5_6_24", "5_2_12", "5_5_7", "5_3_22", "5_12_12", "5_5_18", "5_12_23", "5_13_22", "5_2_23", "5_11_24", "5_11_17", "5_2_14", "5_3_4", "5_11_6", "5_11_0", "5_6_6", "5_10_4", "5_5_20", "5_11_15", "5_10_3", "5_3_10", "5_11_2", "5_9_4", "5_9_2", "5_3_14", "5_10_7", "5_10_23", "5_11_3", "5_6_4", "5_9_19", "5_9_8", "5_6_22", "5_8_7", "5_6_11", "5_9_9", "5_6_23", "5_9_15", "5_3_1", "5_12_20", "5_5_3", "5_12_21", "5_2_22", "5_13_16", "5_8_15", "5_10_18", "5_13_20", "5_9_12", "5_6_10", "5_10_10", "5_13_10", "5_8_2", "5_13_17", "5_10_12", "5_12_13", "5_3_9", "5_6_12", "5_2_16", "5_11_19", "5_2_5", "5_2_1", "5_11_22", "6_2_11", "6_2_17", "6_11_13", "6_2_24", "6_13_18", "6_5_19", "6_6_14", "6_12_1", "6_13_23", "6_5_15", "6_10_6", "6_12_19", "6_12_22", "6_6_12", "6_6_1", "6_10_17", "6_3_23", "6_13_9", "6_9_5", "6_13_19", "6_6_4", "6_5_22", "6_12_15", "6_5_21", "6_8_1", "6_12_7", "6_2_9", "6_11_16", "6_2_5", "6_2_18", "6_5_7", "6_6_6", "6_11_7", "6_11_6", "6_12_14", "6_11_9", "6_12_20", "6_8_16", "6_10_18", "6_2_19", "6_10_2", "6_2_22", "6_3_22", "6_6_18", "6_11_22", "6_13_22", "6_5_24", "6_3_19", "6_12_5", "6_5_17", "6_8_7", "6_8_19", "6_8_6", "6_13_8", "6_13_2", "6_9_19", "6_11_17", "6_11_4", "6_9_7", "6_13_21", "6_5_6", "6_11_0", "6_5_18", "6_2_10", "6_13_3", "6_13_24", "6_8_10", "6_12_0", "6_10_24", "6_13_11", "6_5_23", "6_2_3", "6_13_16", "6_13_6", "6_3_12", "6_12_17", "6_11_15", "6_11_24", "6_12_2", "6_3_21", "6_12_18", "6_9_23", "6_8_24", "6_2_13", "6_6_17", "6_6_0", "6_6_3", "6_6_8", "6_13_15", "6_3_8", "6_11_10", "6_10_16", "6_8_22", "6_2_2", "6_5_9", "6_8_5", "6_2_23", "6_11_20", "6_10_11", "6_11_14", "6_2_6", "6_2_0", "6_3_1", "6_3_17", "6_13_4", "6_13_10", "6_10_22", "6_11_8", "6_5_16", "6_8_4", "6_13_17", "6_2_14", "6_10_23", "6_5_3", "6_11_5", "6_12_8", "6_11_12", "6_13_14", "6_9_17", "6_11_18", "6_12_3", "6_12_13", "6_3_16", "6_3_7", "7_6_5", "7_12_19", "7_11_18", "7_2_6", "7_9_23", "7_3_21", "7_3_23", "7_12_2", "7_12_14", "7_6_16", "7_12_3", "7_8_9", "7_10_4", "7_2_12", "7_12_8", "7_5_12", "7_9_15", "7_9_16", "7_6_11", "7_9_5", "7_11_4", "7_8_0", "7_5_21", "7_5_19", "7_5_10", "7_9_7", "7_2_7", "7_8_22", "7_9_24", "7_10_5", "7_10_15", "7_5_7", "7_10_13", "7_6_17", "7_2_23", "7_9_20", "7_11_20", "7_13_14", "7_12_12", "7_9_2", "7_3_22", "7_3_18", "7_5_3", "7_9_6", "7_11_0", "7_8_15", "7_6_6", "7_5_1", "7_13_24", "7_3_4", "7_9_17", "7_5_2", "7_12_1", "7_13_0", "7_9_22", "7_12_9", "7_5_17", "7_12_10", "7_13_3", "7_2_10", "7_6_8", "7_2_18", "7_6_18", "7_13_13", "7_11_1", "7_12_21", "7_12_15", "7_13_18", "7_8_21", "7_13_7", "7_3_9", "7_3_8", "7_2_11", "7_8_12", "7_2_2", "7_12_4", "7_6_12", "7_10_16", "7_13_4", "7_5_16", "7_10_9", "7_11_19", "7_3_16", "7_3_15", "7_2_8", "7_11_2", "7_3_24", "7_6_13", "7_10_19", "7_10_0", "7_8_6", "7_10_17", "7_10_3", "7_8_14", "7_13_22", "7_2_19", "7_8_8", "7_3_11", "7_3_6", "7_5_24", "7_5_0", "7_3_0", "7_8_17", "7_12_11", "7_5_18", "7_11_6", "7_8_3", "7_6_22", "7_11_11", "7_9_18", "7_5_6", "7_13_19", "7_10_8", "7_11_24", "7_12_13", "7_8_24", "7_13_6", "7_13_12", "7_8_16", "7_10_10", "7_13_1", "7_6_10", "7_11_8", "7_2_14", "8_11_15", "8_12_10", "8_13_11", "8_10_6", "8_6_21", "8_5_10", "8_9_10", "8_13_17", "8_10_22", "8_9_20", "8_8_12", "8_8_2", "8_5_2", "8_11_23", "8_13_22", "8_3_21", "8_12_8", "8_2_16", "8_3_18", "8_8_17", "8_9_15", "8_2_10", "8_5_1", "8_9_23", "8_9_2", "8_8_1", "8_6_10", "8_5_11", "8_2_3", "8_5_7", "8_2_6", "8_11_8", "8_8_4", "8_6_9", "8_5_5", "8_9_8", "8_10_1", "8_13_1", "8_9_1", "8_3_0", "8_3_13", "8_11_21", "8_8_5", "8_13_13", "8_6_24", "8_6_11", "8_2_9", "8_5_15", "8_5_13", "8_2_8", "8_13_15", "8_10_12", "8_11_10", "8_10_2", "8_5_0", "8_9_24", "8_9_21", "8_3_15", "8_2_19", "8_2_22", "8_10_13", "8_5_8", "8_5_16", "8_9_6", "8_9_19", "8_6_17", "8_3_7", "8_11_5", "8_6_19", "8_12_0", "8_2_2", "8_2_0", "8_10_4", "8_8_23", "8_10_16", "8_11_18", "8_13_3", "8_11_9", "8_3_14", "8_3_5", "8_13_8", "8_5_18", "8_10_23", "8_2_18", "8_13_23", "8_9_18", "8_13_12", "8_8_14", "8_12_24", "8_12_5", "8_9_12", "8_3_1", "8_11_16", "8_6_6", "8_12_11", "8_8_15", "8_8_24", "8_6_4", "8_2_15", "8_11_20", "8_11_14", "8_13_19", "8_10_15", "8_10_9", "8_13_10", "8_12_22", "8_13_9", "8_11_22", "8_5_20", "8_11_4", "8_3_24", "8_8_13", "8_9_17", "8_6_0", "8_12_6", "8_3_11", "8_6_1", "8_9_4", "8_13_18", "8_5_14", "8_10_21", "8_8_21", "8_5_21", "8_3_8", "9_2_1", "9_9_14", "9_10_1", "9_9_1", "9_13_2", "9_3_0", "9_11_24", "9_11_0", "9_12_23", "9_2_24", "9_6_8", "9_11_3", "9_6_9", "9_2_18", "9_6_24", "9_11_16", "9_2_12", "9_2_15", "9_2_20", "9_13_13", "9_13_6", "9_6_14", "9_2_9", "9_2_11", "9_6_22", "9_3_16", "9_9_2", "9_9_19", "9_13_16", "9_9_8", "9_12_4", "9_13_7", "9_12_7", "9_13_10", "9_3_19", "9_8_10", "9_10_13", "9_13_15", "9_8_19", "9_12_1", "9_11_4", "9_12_10", "9_13_5", "9_10_3", "9_12_19", "9_3_18", "9_5_16", "9_3_22", "9_11_22", "9_5_8", "9_5_20", "9_13_22", "9_10_17", "9_12_16", "9_10_24", "9_13_8", "9_8_15", "9_13_18", "9_3_24", "9_2_2", "9_8_20", "9_8_17", "9_10_20", "9_11_2", "9_9_6", "9_8_9", "9_8_23", "9_5_10", "9_8_18", "9_12_9", "9_10_7", "9_3_2", "9_13_11", "9_6_3", "9_9_24", "9_6_18", "9_6_0", "9_10_8", "9_9_9", "9_6_6", "9_11_7", "9_6_5", "9_11_13", "9_13_20", "9_11_10", "9_9_11", "9_10_22", "9_11_19", "9_6_16", "9_12_13", "9_6_12", "9_12_5", "9_9_7", "9_5_6", "9_5_5", "9_12_14", "9_9_0", "9_6_23", "9_10_4", "9_3_5", "9_6_2", "9_3_6", "9_6_13", "9_11_11", "9_5_13", "9_2_19", "9_12_11", "9_11_20", "9_8_21", "9_11_1", "9_5_4", "9_2_6", "9_5_3", "9_5_2", "9_8_8", "9_6_15", "9_2_7", "9_5_24", "9_12_8", "9_13_21", "9_3_12", "9_8_6", "9_10_6", "9_12_2", "10_13_24", "10_13_16", "10_12_8", "10_3_2", "10_12_18", "10_12_3", "10_9_2", "10_10_4", "10_9_9", "10_9_5", "10_8_18", "10_2_6", "10_13_1", "10_9_21", "10_11_1", "10_10_17", "10_13_17", "10_2_17", "10_13_6", "10_12_24", "10_2_5", "10_9_11", "10_13_7", "10_9_8", "10_10_2", "10_5_8", "10_12_23", "10_6_11", "10_3_24", "10_5_3", "10_6_15", "10_11_22", "10_9_24", "10_10_23", "10_9_18", "10_8_23", "10_6_6", "10_2_21", "10_10_21", "10_8_12", "10_2_3", "10_8_7", "10_6_9", "10_8_14", "10_5_17", "10_3_16", "10_11_5", "10_8_8", "10_3_21", "10_3_18", "10_3_10", "10_2_10", "10_8_15", "10_8_5", "10_6_4", "10_10_14", "10_2_4", "10_3_0", "10_11_18", "10_9_12", "10_6_24", "10_12_5", "10_13_3", "10_3_8", "10_3_9", "10_12_0", "10_6_10", "10_2_23", "10_9_23", "10_11_10", "10_11_9", "10_11_14", "10_2_16", "10_13_8", "10_3_22", "10_5_13", "10_5_22", "10_12_9", "10_3_6", "10_5_21", "10_5_2", "10_10_9", "10_11_19", "10_5_20", "10_3_14", "10_5_10", "10_11_15", "10_10_10", "10_8_21", "10_12_22", "10_11_24", "10_6_14", "10_12_14", "10_5_7", "10_11_13", "10_8_24", "10_6_12", "10_6_21", "10_6_1", "10_5_23", "10_6_0", "10_5_18", "10_11_4", "10_12_21", "10_3_3", "10_2_11", "10_11_2", "10_5_11", "10_6_3", "10_10_24", "10_9_13", "10_8_13", "10_8_17", "10_3_20", "10_13_22", "10_2_22", "10_13_23", "10_8_1", "10_10_12", "10_2_18", "10_3_4", "10_2_0", "10_12_6", "10_3_5"]}


================================================
FILE: image/Makefile
================================================
CC=c++

# c flags
CFLAGS=-c -Wall -std=c++11 -O3
CFLAGS_BOOST=-DBOOST_SYSTEM_NO_DEPRECATED
CFLAGS_CV=`pkg-config --cflags opencv`
CFLAGS_H5=-I/usr/include -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE \
-D_BSD_SOURCE -D_FORTIFY_SOURCE=2 -g -fstack-protector \
--param=ssp-buffer-size=4 -Wformat -Werror=format-security

# linking flags
LDFLAGS_BOOST=-lboost_system -lboost_program_options
LDFLAGS_H5=-lhdf5 -lhdf5_cpp
LDFLAGS_CV=-L/usr/local/cuda-7.5/lib64 `pkg-config --libs opencv`

BIN=bin
SOURCES=$(wildcard *.cpp)
OBJECTS=$(patsubst %.cpp, %.o, $(SOURCES))
EXECUTABLE=$(BIN)/image

all: $(SOURCES) $(EXECUTABLE)

$(BIN)/image: $(BIN)/main.o $(BIN)/h5Data.o $(BIN)/seq.o
	$(CC) $(BIN)/main.o $(BIN)/h5Data.o $(BIN)/seq.o \
	$(LDFLAGS_BOOST) $(LDFLAGS_H5) $(LDFLAGS_CV) -o $@

$(BIN)/main.o: main.cpp
	$(CC) $(CFLAGS) $(CFLAGS_BOOST) $< -o $@

$(BIN)/h5Data.o: h5Data.cpp
	$(CC) $(CFLAGS) $(CFLAGS_H5) $< -o $@

$(BIN)/seq.o: seq.cpp
	$(CC) $(CFLAGS) $(CFLAGS_CV) $< -o $@

clean:
	rm -r -f $(BIN)/*


================================================
FILE: image/h5Data.cpp
================================================
#include "h5Data.hpp"

h5Data::h5Data(std::string f, int n) : fileName(f), numChannel(n) {
	// turn off the auto-printing when failure occurs
	dataFile = new H5::H5File(fileName, H5F_ACC_RDONLY);

	datasetLa = load(datasetNameLa, -1);
	for (int i = 0; i < numChannel; i++) {
		datasetCh[i] = load(datasetNameCh + std::to_string(i), i);
	}
}

h5Data::~h5Data() {
	// delete array of label and channels with []
	delete[] label;
	delete datasetLa;
	for (int i = 0; i < numChannel; i++) {
		delete[] ch[i];
		delete datasetCh[i];
	}

	delete dataFile;
}

H5::DataSet* h5Data::load(H5std_string datasetName, int whichCh) {
	// open dataset, dataspace and property list
	try {
		H5::Exception::dontPrint();
		hsize_t dimsr[2];
		H5::DataSet* dataset = new H5::DataSet(dataFile->openDataSet(datasetName));
		H5::DataSpace *filespace = new H5::DataSpace(dataset->getSpace());
		H5::DSetCreatPropList prop = dataset->getCreatePlist();

		// get information to obtain memory dataspace.
		int rank = filespace->getSimpleExtentNdims();
		filespace->getSimpleExtentDims(dimsr);
		H5::DataSpace* memspace = new H5::DataSpace(rank, dimsr, NULL);

		length = dimsr[0];

		// load labels and channels
		if (whichCh == -1) {
			label = new int[length];
			dataset->read(label, H5::PredType::NATIVE_INT, *memspace, *filespace);
		} else {
			ch[whichCh] = new float[length * dimsr[1]];
			dataset->read(ch[whichCh], H5::PredType::NATIVE_FLOAT, *memspace,
				*filespace);
		}

		prop.close();
		delete filespace;
		delete memspace;

		return dataset;
	} catch (H5::FileIException error) {
		error.printError();
		return NULL;
	} catch (H5::DataSetIException error) {
		error.printError();
		return NULL;
	} catch (H5::DataSpaceIException error) {
		error.printError();
		return NULL;
	}
}


================================================
FILE: image/h5Data.hpp
================================================
#ifndef H5DATA_H
#define H5DATA_H

#include <iostream>
#include <string>

// hdf5 includes
#include "H5Cpp.h"

// h5 tags
namespace {
	const H5std_string datasetNameLa = "label";
	const H5std_string datasetNameCh = "ch";

	const hsize_t dimsLa[2] = {1, 1};
	const hsize_t dimsCh[2] = {1, 32 * 32};

	const int backgroundClass = 0;
}

#endif

// data class for 5f file
class h5Data {
private:
	std::string fileName;
	int numChannel;
	int length;

	// store dataset
	H5::H5File *dataFile = NULL;
	H5::DataSet *datasetLa = NULL;
	H5::DataSet *datasetCh[8];

	// store label and channels data
	int *label;
	float *ch[8];

public:
	h5Data(std::string f, int n);
	~h5Data();

	H5::DataSet* load(H5std_string datasetName, int whichCh);

	inline float* getCh(int whichCh) { return ch[whichCh]; }
	inline int* getLa() { return label; }
	inline int getLength() { return length; }
};


================================================
FILE: image/main.cpp
================================================
#include <vector>
#include <string>

// boost options
#include <boost/program_options.hpp>
namespace po = boost::program_options;

#include "seq.hpp"

int main(int argc, char *argv[]) {
	try {
		// generate argument parser
		po::options_description desc("Image: allowed options");
		desc.add_options()
			("help", "Print help messages")
			("source", po::value<std::string>(), "h5 source file")
			("target", po::value<std::string>(), "Flow target directory")
			("channel", po::value<int>(), "Channel number")
			("origin", po::value<int>(), "Origin size")
			("out", po::value<int>(), "Output size")
			("label", po::value<bool>(), "Print label in output file name")
			("bound", po::value<double>(), "Bound for normalization");

		po::variables_map vm;
		po::store(po::parse_command_line(argc, argv, desc), vm);
		po::notify(vm);

		std::string source, target;
		int numChannel = 1, origin = 32, out = 32;
		bool label = false;
		double bound = 15.0;

		// assign argument to local variables
		if (vm.count("help")) {
			std::cout << "Image" << std::endl << desc << std::endl;
			return 0;
		} else {
			if (vm.count("source")) source = vm["source"].as<std::string>();
			if (vm.count("target")) target = vm["target"].as<std::string>();
			if (vm.count("channel")) numChannel = vm["channel"].as<int>();
			if (vm.count("origin")) origin = vm["origin"].as<int>();
			if (vm.count("out")) out = vm["out"].as<int>();
			if (vm.count("label")) label = vm["label"].as<bool>();
			if (vm.count("bound")) bound = vm["bound"].as<double>();

			// generate flow for different channels
			Seq seq = Seq(source, target, numChannel, label);
			for (int i = 0; i < numChannel; i++) {
				seq.flow(i, origin, origin, out, out, bound);
			}
		}
	} catch (std::exception& e) {
			std::cerr << "Error: " << e.what() << std::endl;
			return 1;
	} catch (...) {
			std::cerr << "Exception of unknown type" << std::endl;
			return 1;
	}

	return 0;
}


================================================
FILE: image/seq.cpp
================================================
#include "seq.hpp"

Seq::Seq(std::string s, std::string t, int n, bool l) :
		source(s), target(t), numChannel(n), printLabel(l) {
	// read h5 file and get the data
	h5file = new h5Data(source, numChannel);
	label = h5file->getLa();
	for (int i = 0; i < numChannel; i++) {
		ch[i] = h5file->getCh(i);
	}
	length = h5file->getLength();
}

Seq::~Seq() {
	// delete files with pointer at the end, release channel data in the end
	delete h5file;
}

// convert float (0-1) value images to int (0-255) images with bound limit
void Seq::float2Image(const cv::Mat &floatMat, cv::Mat &imageMat,
		double l, double u) {
	for (int i = 0; i < floatMat.rows; i++) {
		for (int j = 0; j < floatMat.cols; j++) {
			float x = floatMat.at<float>(i, j);
			imageMat.at<uchar>(i, j) = cast(x, l, u);
		}
	}
}

// load array data image with offset to int images with resize
cv::Mat Seq::loadOrigin(float *image, int originHeight, int originWidth,
		int outHeight, int outWidth) {
	// convert array data from float to int image
	cv::Mat originFloat = cv::Mat(originHeight, originWidth, CV_32F, image);
	cv::Mat originInt = cv::Mat(cv::Size(originWidth, originHeight), CV_8UC1);
	float2Image(originFloat, originInt, 0.0, 1.0);

	// resize image if necessary
	cv::Mat resize = cv::Mat(cv::Size(outWidth, outHeight), CV_8UC1);
	if (originHeight == outHeight && originWidth == outWidth) {
		originInt.copyTo(resize);
	} else {
		cv::resize(originInt, resize, cv::Size(outWidth, outHeight),
			0, 0, cv::INTER_LINEAR);
	}

	return resize;
}

// generate flow and original image
void Seq::flow(int whichCh, int originHeight, int originWidth,
		int outHeight, int outWidth, double bound) {
	// following frames (start with one to support original flow computation)
	for (int i = 1; i < length; i++) {
		// load next image
		std::string imageName;
		if (printLabel) {
			imageName = target + "/ch" + std::to_string(whichCh) + "_" +
				std::to_string(i - 1) + "_" + std::to_string(label[i - 1]) + "_";
		} else {
			imageName = target + "/ch" + std::to_string(whichCh) + "_" +
				std::to_string(i - 1) + "_";
		}

		// write the original image and save to file
		cv::Mat image = loadOrigin(ch[whichCh] + i * originHeight * originWidth,
			originHeight, originWidth, outHeight, outWidth); // resize image for out
		cv::imwrite(imageName + "image.jpg", image);
	}
}


================================================
FILE: image/seq.hpp
================================================
#ifndef SEQ_H
#define SEQ_H

#include <iostream>
#include <string>

// opencv
#include <opencv2/opencv.hpp>

#include "h5Data.hpp"

#endif

class Seq {
private:
	std::string source, target;
	int numChannel;
	int length;
	bool printLabel;

	// use file pointer to avoid call destructor of h5Data too soon
	h5Data *h5file = NULL;

	// not in charge of manage memory
	int *label;
	float *ch[8];

	void resize();
	// void flow();
public:
	Seq(std::string s, std::string t, int n, bool l);
	~Seq();

	inline float cast(float v, float l, float u) {
		if (v > u) return 255;
		else if (v < l) return 0;
		else return cvRound(255 * (v - l) / (u - l));
	}

	void float2Image(const cv::Mat &floatMat, cv::Mat &imageMat,
		double lBound, double uBound);
	cv::Mat loadOrigin(float *image, int originHeight, int originWidth,
		int outHeight, int outWidth);

	void flow(int whichCh, int originHeight, int originWidth,
		int outHeight, int outWidth, double bound);
};


================================================
FILE: net/data.lua
================================================
require 'class'
require 'paths'
require 'mattorch'
local json = require 'lunajson'

require 'net.util'

local Data = torch.class('Data')

function Data:__init(fileDir, listFile, meanFile, listType,
    inputSize, inputCh, labelSize, dataSize, dataCh, ch, useCuda)
  self.seqList = self:getSeq(fileDir, listFile, listType)
  self.mean = self:loadMean(meanFile)
  self.inputSize = inputSize
  self.inputCh = inputCh
  self.labelSize = labelSize
  self.dataSize = dataSize
  self.dataCh = dataCh
  self.ch = ch
  self.useCuda = useCuda
end

function Data:getSeq(fileDir, listFile, listType)
  -- read file into json
  local f = io.open(listFile, 'rb')
  local jsonString = f:read('*all')
  local jsonObject = json.decode(jsonString)
  f:close()
  -- arrange it according to different label
  local seqList = {}
  for i in pairs(jsonObject[listType]) do
    seqList[#seqList + 1] = paths.concat(fileDir, jsonObject[listType][i])
  end
  return seqList
end

-- random shuffle a list
function Data:shuffleList(list)
  local n, random = #list, math.random
  for i = 1, n do
    local j, k = random(n), random(n)
    list[j], list[k] = list[k], list[j]
  end
  return list
end

-- load mat mean file
function Data:loadMean(meanFile)
  return mattorch.load(meanFile)
end

function Data:initBatch(batchSize, seqLength)
  -- initialize inputs and targets, zero mask will ignore null target
  local inputs, targets = {}, {}
  for l = 1, seqLength do
    -- init with 4d data (cnn and uni)
    inputs[l] = torch.Tensor(batchSize,
      self.inputCh, self.inputSize, self.inputSize):zero()
    targets[l] = torch.Tensor(batchSize):fill(self.labelSize)
  end
  return inputs, targets
end


================================================
FILE: net/imageseq.lua
================================================
require 'class'
require 'paths'
require 'image'
local json = require 'lunajson'

require 'net.seq'
require 'net.util'

local ImageSeq = torch.class('ImageSeq', 'Seq')

function ImageSeq:__init(seqName, mean, dataSize, dataCh, ch, useCuda)
  Seq.__init(self, seqName, mean, dataSize, dataCh, ch, useCuda)
  self.info = self:getSeqInfo()
  -- load frame depends on image type, lib image support only float tensor
  -- reset tensor type back to float tensor when using cuda
  torch.setdefaulttensortype('torch.FloatTensor')
  self.imageFrame = self:loadFrame()
  -- set tensor type back to cuda tensor when using cuda
  if self.useCuda then
    torch.setdefaulttensortype('torch.CudaTensor')
  end
end

-- read label file
function ImageSeq:getSeqInfo()
  -- read file into json
  local f = io.open(paths.concat(self.name, 'label.json'), 'rb')
  local jsonString = f:read('*all')
  local jsonObject = json.decode(jsonString)
  f:close()
  -- convert into num based index, 0-based to 1-based
  -- label is also 1-based: 0-4 => 1-5
  local seqInfo = {}
  for i in pairs(jsonObject) do
    seqInfo[i + 1] = jsonObject[i] + 1
  end
  return seqInfo
end

function ImageSeq:loadFrame()
  local frame = {}
  local m = self.mean[string.format('ch%d_image', self.ch)]
    :permute(3, 2, 1) -- the matlab order is reversed
  -- access each frame, 1-based to 0-based image name
  for f = 1, #self.info do
    local name = string.format('ch%d_%d_image.jpg', self.ch, f - 1)
    -- for image tensor, first map from 0-1 to 0-255,
    -- then minus mean (also in 0-255)
    frame[#frame + 1] = (image.load(paths.concat(self.name, name), 1) * 256) - m
  end
  return frame
end

function ImageSeq:getImage(f)
  -- appending later frames
  local mat = self.imageFrame[f]
  for i = 1, self.dataCh - 1 do
    mat = torch.cat(mat, self.imageFrame[math.min(#self.info, f + i)], 1)
  end
  return mat
end

function ImageSeq:getFrame(f)
  -- load data depends on image or flow
  local matrix = self:getImage(f)
  return matrix
end


================================================
FILE: net/main.lua
================================================
require 'net.util'

-- parse cmd parameters
local cmd = torch.CmdLine()

cmd:option('--file', '../collect_image/origin_trans', 'Image dir')
cmd:option('--list', 'tmp/file.json', 'List file json')
cmd:option('--load', '', 'Load model file')

cmd:option('--inputsize', 32, 'Input size')
cmd:option('--inputch', 4, 'Input channel')
cmd:option('--label', 3, 'Label size')

cmd:option('--datasize', 32, 'Data size')
cmd:option('--datach', 4, 'Data channel (number of stack)')

cmd:option('--batch', 4, 'Batch size')
cmd:option('--maxseq', 40, 'Sequence length')

cmd:option('--cuda', false, 'Use CUDA')
cmd:option('--cudnn', false, 'Use CUDNN')
local opt = cmd:parse(arg or {})

--- other parameters
local meanFile = 'tmp/mean_32.mat'
local ch = 1

-- default tensor
if opt.cuda then
  require 'cutorch'
  require 'cunn'
  torch.setdefaulttensortype('torch.CudaTensor')
else
  torch.setdefaulttensortype('torch.FloatTensor')
end

-- train net, switch train type
local trainObject
require 'net.rnntrain'
trainObject = RnnTrain(opt.file, opt.list, meanFile,
  opt.inputsize, opt.inputch, opt.label,
  opt.datasize, opt.datach, ch,
  opt.load, opt.cuda, opt.cudnn)

trainObject:train(opt.batch, opt.maxseq)


================================================
FILE: net/net.lua
================================================
require 'class'

local Net = torch.class('Net')

function Net:__init(useCuda, useCudnn)
  -- cuda support
  self.useCuda = useCuda
  self.useCudnn = useCudnn
  if self.useCuda then
    require 'cutorch'
    require 'cunn'
    if self.useCudnn then
      require 'cudnn'
    end
  end
end

-- load already exist net
function Net:loadNet(loadFile)
  print('[net] loading model ' .. loadFile)
  net = torch.load(loadFile)
  print(net)
  return net
end

-- cuda and cudnn support
function Net:cudaNet(net)
  if self.useCuda then
    print('[net] with cuda')
    net = net:cuda()
    if self.useCudnn then
      print('[net] with cudnn')
      cudnn.convert(net, cudnn)
    end
  else
    print('[net] without cuda')
  end
  print(net)
  return net
end


================================================
FILE: net/rnndata.lua
================================================
require 'class'

require 'net.data'
require 'net.imageseq'

local RnnData = torch.class('RnnData', 'Data')

function RnnData:__init(fileDir, listFile, meanFile, listType,
    inputSize, inputCh, labelSize, dataSize, dataCh, ch, useCuda)
  Data.__init(self, fileDir, listFile, meanFile, listType,
    inputSize, inputCh, labelSize, dataSize, dataCh, ch, useCuda)
end

function RnnData:frameSeq(seq, maxSeq)
  -- load label for each frame, label is 1-based, f is frame id
  -- offset introduce zero paddings at the beginning of the sequence
  local frames = {}
  if #seq.info < maxSeq then
    local offset = maxSeq - #seq.info
    for f = 1, #seq.info do
      frames[offset + f] = f
    end
  else
    for f = 1, maxSeq do
      frames[f] = math.floor(f * (#seq.info / maxSeq))
    end
  end
  return frames
end

-- load batch to tensor
function RnnData:loadBatch(batchNum, batchSize, maxSeq)
  local inputs, targets = self:initBatch(batchSize, maxSeq)
  -- load data into inputs and targets
  local batchStart = (batchNum - 1) * batchSize
  for b = 1, batchSize do
    -- get seq info
    local seq
    seq = ImageSeq(self.seqList[batchStart + b], self.mean,
      self.dataSize, self.dataCh, self.ch, self.useCuda)
    -- generate frame sequence
    local frames = self:frameSeq(seq, maxSeq)
    for i, v in pairs(frames) do
      inputs[i][b] = seq:getFrame(v)
      targets[i][b] = seq.info[v]
    end
  end

  return inputs, targets
end


================================================
FILE: net/rnntrain.lua
================================================
require 'class'

require 'net.train'
require 'net.util'

local RnnTrain = torch.class('RnnTrain', 'Train')

function RnnTrain:__init(fileDir, listFile, meanFile,
    inputSize, inputCh, labelSize, dataSize, dataCh, ch,
    loadFile, useCuda, useCudnn)
  -- call base train constructor
  Train.__init(self, labelSize, useCuda, useCudnn)
  -- load data
  require 'net.rnndata'
  self.evalData = RnnData(fileDir, listFile, meanFile, 'eval',
    inputSize, inputCh, labelSize, dataSize, dataCh, ch, useCuda)
  print(string.format('[eval] data with %d seq', #self.evalData.seqList))
  -- build net
  local netObject
  require 'net.uninet'
  netObject = UniNet(useCuda, useCudnn)
  self.net = netObject:loadNet(loadFile)
end

function RnnTrain:batchEval(b, inputs)
  -- evaluate forward as whole sequence
  self.net:evaluate()
  local outputs = self.net:forward(self:convertCuda(inputs))
  self.net:forget()
  return outputs
end


================================================
FILE: net/seq.lua
================================================
require 'class'
require 'paths'
require 'image'
local json = require 'lunajson'

require 'net.util'

local Seq = torch.class('Seq')

function Seq:__init(seqName, mean, dataSize, dataCh, ch, useCuda)
  -- load info
  self.name = seqName
  self.mean = mean
  self.dataSize = dataSize
  self.dataCh = dataCh
  self.ch = ch
  self.useCuda = useCuda
end


================================================
FILE: net/stat.lua
================================================
require 'class'
local json = require 'lunajson'

local Stat = torch.class('Stat')

function Stat:__init(labelSize, batchSize, maxSeq)
  self.labelSize = labelSize
  self.batchSize = batchSize
  self.maxSeq = maxSeq
  -- init confusion matrix (correct label (size) * predict label (size))
  self.confus = self:initMat(labelSize, labelSize)
end

function Stat:initMat(height, width)
  local mat = {}
  for h = 1, height do
    mat[h] = {}
    for w = 1, width do
      mat[h][w] = 0
    end
  end
  return mat
end

function Stat:updateStat(outputs, targets)
  -- calculate one sequence by one sequence
  for o = 1, #outputs do
    local _, indices = torch.max(outputs[o], 2)
    for b = 1, self.batchSize do
      local right, pred = targets[o][b], indices[b][1]
      -- update confusion matrix
      self.confus[right][pred] = self.confus[right][pred] + 1
    end
  end
end

function Stat:sum(list, length)
  local result = 0
  -- ignore null label in sum
  for i = 1, length do
    result = result + list[i]
  end
  return result
end

-- calculate per label stat
function Stat:calPerLabel()
  local right, count = {}, {}
  -- iterate for all label
  for l = 1, self.labelSize do
    right[l] = self.confus[l][l]
    count[l] = self:sum(self.confus[l], #self.confus[l])
  end
  return right, count
end

-- print matrix
function Stat:printMat(str, right, count, matRight, matCount)
  for l = 1, #right do
    if count[l] > 0 then
      local accLine = right[l] * 100 / count[l]
      io.write(string.format('    %s %02d: %02.0f [', str, l, accLine))
      for ll = 1, #matRight[1] do
        -- print each element depends on the type and value
        if type(matCount[l]) == 'number' and matCount[l] > 0 then
          local acc = matRight[l][ll] * 100 / matCount[l]
          io.write(string.format(' %02.0f ', acc))
        else
          io.write(' -- ')
        end
      end
      io.write(']\n')
    else
      io.write(string.format('    %s %02d: --\n', str, l))
    end
  end
end

function Stat:print(type)
  local right, count = self:calPerLabel()
  -- calculate sum of label
  local accEpoch = self:sum(right, #right - 1) / self:sum(count, #count - 1)
  io.write(string.format('[%s] accuracy %f\n', type, accEpoch))
  -- print per label and confusion matrix
  self:printMat('label', right, count, self.confus, count)
  -- return accuracy for lr update
  return accEpoch
end


================================================
FILE: net/train.lua
================================================
require 'class'

local Train = torch.class('Train')

function Train:__init(labelSize, useCuda, useCudnn)
  -- require and cuda support
  require 'net.stat'
  self.useCuda = useCuda
  self.useCudnn = useCudnn
  if useCuda then
    require 'cutorch'
    require 'cunn'
  end
  -- other parameters
  self.labelSize = labelSize
end

-- one step of evaluate to all data
function Train:epochEval(batchSize, maxSeq)
  local stat = Stat(self.labelSize, batchSize, maxSeq)
  for b = 1, math.floor(#self.evalData.seqList / batchSize) do
    -- load data, start evaluating, depends on net type
    local inputs, targets = self.evalData:loadBatch(b, batchSize, maxSeq)
    local outputs = self:batchEval(b, inputs)
    -- update confusion matrix
    stat:updateStat(outputs, targets)
  end
  return stat:print('eval')
end

-- convert to cuda
function Train:convertCuda(list)
  if self.cuda then
    -- convert table one by one to cuda
    for l = 1, #list do
      list[l] = list[l]:cuda()
    end
    return list
  else
    return list
  end
end

function Train:train(batchSize, maxSeq)
  -- evaluate by epoch
  self:epochEval(batchSize, maxSeq)
  print('Finished')
end


================================================
FILE: net/uninet.lua
================================================
require 'class'
require 'rnn'

require 'net.net'

local UniNet = torch.class('UniNet', 'Net')

function UniNet:__init(useCuda, useCudnn)
  Net.__init(self, useCuda, useCudnn)
end


================================================
FILE: net/util.lua
================================================
-- helper function to check if string start with some sub-string
function string:startsWith(start)
  return string.sub(self, 1, string.len(start)) == start
end

function string:split(sep)
  local sep, fields = sep or ":", {}
  local pattern = string.format("([^%s]+)", sep)
  self:gsub(pattern, function(c) fields[#fields+1] = c end)
  return fields
end


================================================
FILE: pre/image.py
================================================
import cv2
import numpy as np

class image:
    def __init__(self, file_name):
        self.file_name = file_name

    # load image and resize image with size
    def load(self, height, width):
        frame = cv2.imread(self.file_name, cv2.IMREAD_GRAYSCALE)
        if height and width:
            frame = cv2.resize(frame, (width, height))
        frame = np.expand_dims(frame, axis=0).astype('float32')
        return frame


================================================
FILE: pre/main.py
================================================
import argparse

from seq import Seq

# call different method depends on op
def main(op, file_dir, target_dir, num_channel=1, redo=False,
        origin_size=32, out_size=32):
    s = Seq()

    if op == 'image':
        s.generate_image(file_dir, target_dir, num_channel,
            origin_size, out_size, redo)
    elif op == 'clean':
        s.clean_image(file_dir)
    elif op == 'mean':
        s.generate_mean(file_dir, target_dir, num_channel, out_size)
    else:
        raise NameError('The operation type {} is undefined'.format(op))

if __name__ == "__main__":
    parser = argparse.ArgumentParser(description="Generate image")
    parser.add_argument('--op', type=str)
    parser.add_argument('--file', type=str)
    parser.add_argument('--target', type=str)
    parser.add_argument('--channel', type=int)
    parser.add_argument('--redo',  action='store_true')
    parser.add_argument('--originsize', type=int)
    parser.add_argument('--outsize', type=int)

    args = parser.parse_args()

    main(args.op, args.file, args.target, args.channel, args.redo,
        args.originsize, args.outsize)


================================================
FILE: pre/op.py
================================================
import os, subprocess
import numpy as np
import h5py
import json

from image import image

class Operation:
    def __init__(self):
        pass

    # generate image for each sequence
    def generate_image(self, source, target, num_channel, origin_size=32,
            out_size=32, bound=15.0, bin_image='image/bin/image'):
        if not os.path.exists(target): os.makedirs(target)
        # run flow command
        p = subprocess.Popen([bin_image,
            '--source', source, '--target', target,
            '--channel', str(num_channel),
            '--origin', str(origin_size),
            '--out', str(out_size),
            '--bound', str(bound)])
        p.wait()
        # generate label file
        self._generate_label(source, target)

    # load labels
    def _generate_label(self, source, target, label_file='label.json'):
        with h5py.File(source, 'r') as hf:
            labels = [int(l) for l in hf['label'][()]]
        # save labels as a dict in json file
        labels_dict = {i: l
            for i, l in zip(range(len(labels) - 1), labels[1:])}
        with open(os.path.join(target, label_file), 'w') as jf:
            json.dump(labels_dict, jf)

    # delete generated image files
    def clean_image(self, file_dir, label_file='label.json'):
        print 'Cleaning', file_dir
        # delete images in dir
        image_files = [os.path.join(file_dir, f)
            for f in os.listdir(file_dir)
            if os.path.isfile(os.path.join(file_dir, f)) and 'jpg' in f]
        for image_file in image_files:
            try:
                os.remove(image_file)
            except Exception, e:
                print e
        # delete label file
        try:
            os.remove(os.path.join(file_dir, label_file))
        except Exception, e:
            print e
        # delete dir
        try:
            os.rmdir(file_dir)
        except Exception, e:
            print e

    # get frame count
    def _get_frame_num(self, source, label_file='label.json'):
        with open(os.path.join(source, label_file), 'r') as jf:
            labels_dict = json.load(jf)
        return len(labels_dict)

    # setup mean counter and accumulator at the beginning
    def setup_mean(self, num_channel, out_size):
        self.image_sums = {}
        self.count = 0.0
        for c in range(num_channel):
            self.image_sums['ch%i_image' % (c,)] = \
                np.zeros((1, out_size, out_size), dtype='float32')

    # accumulate mean for each sequence
    def accum_mean(self, source, num_channel, out_size):
        print 'Loading mean', source
        frame_num = self._get_frame_num(source)
        self.count += frame_num
        for c in range(num_channel):
            for i in range(frame_num):
                image_name = os.path.join(source,
                    'ch%i_%i_image.jpg' % (c, i))
                self.image_sums['ch%i_image' % (c,)] += \
                    image(image_name).load(out_size, out_size)

    # save accumulated mean to file
    def save_mean(self, mean_file, num_channel):
        # store file as hdf5
        if mean_file.endswith('h5'):
            print 'Save as hdf5'
            with h5py.File(mean_file, 'w') as f:
                for c in range(num_channel):
                    f.create_dataset('ch%i_image' % (c,),
                        data=self.image_sums['ch%i_image' % (c,)]
                            / self.count)
        # store file as matlab data
        elif mean_file.endswith('mat'):
            import scipy.io as sio
            print 'Save as mat'
            data = {}
            for c in range(num_channel):
                data['ch%i_image' % (c,)] = \
                    self.image_sums['ch%i_image' % (c,)] / self.count
            sio.savemat(mean_file, data)


================================================
FILE: pre/seq.py
================================================
import os, re
import numpy as np
import h5py

from op import Operation

class Seq:
    def __init__(self):
        pass

    # get files in label directories
    def get_h5(self, file_dir):
        return [os.path.join(file_dir, f)
            for f in os.listdir(file_dir)
            if os.path.isfile(os.path.join(file_dir, f)) and 'h5' in f]

    # get list of target image dir names
    def get_dir(self, file_dir):
        return [os.path.join(file_dir, d)
            for d in os.listdir(file_dir)
            if os.path.isdir(os.path.join(file_dir, d))]

    # generate image
    def generate_image(self, file_dir, target_dir, num_channel,
            origin_size, out_size, redo):
        source_files = self.get_h5(file_dir)
        o = Operation()
        for s in source_files:
            t = os.path.join(target_dir, re.sub('.h5', '',
                os.path.basename(s)))
            if redo or not os.path.exists(t):
                print 'Generating', s
                o.generate_image(s, t, num_channel, origin_size, out_size)

    # clean image
    def clean_image(self, file_dir):
        file_dirs = self.get_dir(file_dir)
        o = Operation()
        for d in file_dirs:
            o.clean_image(d)

    # generate mean
    def generate_mean(self, file_dir, target, num_channel, out_size):
        o = Operation()
        o.setup_mean(num_channel, out_size)
        source_dir = self.get_dir(file_dir)
        for s in source_dir:
            o.accum_mean(s, num_channel, out_size)
        o.save_mean(target, num_channel)
Download .txt
gitextract_2w_qnpkh/

├── .gitignore
├── LICENSE
├── README.md
├── cite.bib
├── config/
│   └── file_half.json
├── image/
│   ├── Makefile
│   ├── h5Data.cpp
│   ├── h5Data.hpp
│   ├── main.cpp
│   ├── seq.cpp
│   └── seq.hpp
├── net/
│   ├── data.lua
│   ├── imageseq.lua
│   ├── main.lua
│   ├── net.lua
│   ├── rnndata.lua
│   ├── rnntrain.lua
│   ├── seq.lua
│   ├── stat.lua
│   ├── train.lua
│   ├── uninet.lua
│   └── util.lua
└── pre/
    ├── image.py
    ├── main.py
    ├── op.py
    └── seq.py
Download .txt
SYMBOL INDEX (25 symbols across 7 files)

FILE: image/h5Data.hpp
  class h5Data (line 24) | class h5Data {
    method getLength (line 47) | inline int getLength() { return length; }

FILE: image/main.cpp
  function main (line 10) | int main(int argc, char *argv[]) {

FILE: image/seq.hpp
  class Seq (line 14) | class Seq {
    method cast (line 34) | inline float cast(float v, float l, float u) {

FILE: pre/image.py
  class image (line 4) | class image:
    method __init__ (line 5) | def __init__(self, file_name):
    method load (line 9) | def load(self, height, width):

FILE: pre/main.py
  function main (line 6) | def main(op, file_dir, target_dir, num_channel=1, redo=False,

FILE: pre/op.py
  class Operation (line 8) | class Operation:
    method __init__ (line 9) | def __init__(self):
    method generate_image (line 13) | def generate_image(self, source, target, num_channel, origin_size=32,
    method _generate_label (line 28) | def _generate_label(self, source, target, label_file='label.json'):
    method clean_image (line 38) | def clean_image(self, file_dir, label_file='label.json'):
    method _get_frame_num (line 61) | def _get_frame_num(self, source, label_file='label.json'):
    method setup_mean (line 67) | def setup_mean(self, num_channel, out_size):
    method accum_mean (line 75) | def accum_mean(self, source, num_channel, out_size):
    method save_mean (line 87) | def save_mean(self, mean_file, num_channel):

FILE: pre/seq.py
  class Seq (line 7) | class Seq:
    method __init__ (line 8) | def __init__(self):
    method get_h5 (line 12) | def get_h5(self, file_dir):
    method get_dir (line 18) | def get_dir(self, file_dir):
    method generate_image (line 24) | def generate_image(self, file_dir, target_dir, num_channel,
    method clean_image (line 36) | def clean_image(self, file_dir):
    method generate_mean (line 43) | def generate_mean(self, file_dir, target, num_channel, out_size):
Condensed preview — 26 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (71K chars).
[
  {
    "path": ".gitignore",
    "chars": 137,
    "preview": "# Mac\n.DS_Store\n\n# Matlab\n*.m~\n*.asv\n\n# Vim\n*~\n\n# Python binary\n*.pyc\n\n# Temp dir\ntmp\n\n# Build and CMake\nbuild\n\n# openFr"
  },
  {
    "path": "LICENSE",
    "chars": 1068,
    "preview": "MIT License\n\nCopyright (c) 2016 Saiwen Wang\n\nPermission is hereby granted, free of charge, to any person obtaining a cop"
  },
  {
    "path": "README.md",
    "chars": 5243,
    "preview": "# deep-soli\n\nGesture Recognition Using Neural Networks with Google's Project Soli Sensor\n\n## Update\n\nDataset and trained"
  },
  {
    "path": "cite.bib",
    "chars": 403,
    "preview": "@inproceedings{wang2016interacting,\n  title={Interacting with soli: Exploring fine-grained dynamic gesture recognition i"
  },
  {
    "path": "config/file_half.json",
    "chars": 27772,
    "preview": "{\"train\": [\"0_8_4\", \"0_3_1\", \"0_2_0\", \"0_13_5\", \"0_2_19\", \"0_3_2\", \"0_12_1\", \"0_9_7\", \"0_3_22\", \"0_2_2\", \"0_2_3\", \"0_5_8"
  },
  {
    "path": "image/Makefile",
    "chars": 999,
    "preview": "CC=c++\n\n# c flags\nCFLAGS=-c -Wall -std=c++11 -O3\nCFLAGS_BOOST=-DBOOST_SYSTEM_NO_DEPRECATED\nCFLAGS_CV=`pkg-config --cflag"
  },
  {
    "path": "image/h5Data.cpp",
    "chars": 1770,
    "preview": "#include \"h5Data.hpp\"\n\nh5Data::h5Data(std::string f, int n) : fileName(f), numChannel(n) {\n\t// turn off the auto-printin"
  },
  {
    "path": "image/h5Data.hpp",
    "chars": 873,
    "preview": "#ifndef H5DATA_H\n#define H5DATA_H\n\n#include <iostream>\n#include <string>\n\n// hdf5 includes\n#include \"H5Cpp.h\"\n\n// h5 tag"
  },
  {
    "path": "image/main.cpp",
    "chars": 1934,
    "preview": "#include <vector>\n#include <string>\n\n// boost options\n#include <boost/program_options.hpp>\nnamespace po = boost::program"
  },
  {
    "path": "image/seq.cpp",
    "chars": 2336,
    "preview": "#include \"seq.hpp\"\n\nSeq::Seq(std::string s, std::string t, int n, bool l) :\n\t\tsource(s), target(t), numChannel(n), print"
  },
  {
    "path": "image/seq.hpp",
    "chars": 953,
    "preview": "#ifndef SEQ_H\n#define SEQ_H\n\n#include <iostream>\n#include <string>\n\n// opencv\n#include <opencv2/opencv.hpp>\n\n#include \"h"
  },
  {
    "path": "net/data.lua",
    "chars": 1673,
    "preview": "require 'class'\nrequire 'paths'\nrequire 'mattorch'\nlocal json = require 'lunajson'\n\nrequire 'net.util'\n\nlocal Data = tor"
  },
  {
    "path": "net/imageseq.lua",
    "chars": 2003,
    "preview": "require 'class'\nrequire 'paths'\nrequire 'image'\nlocal json = require 'lunajson'\n\nrequire 'net.seq'\nrequire 'net.util'\n\nl"
  },
  {
    "path": "net/main.lua",
    "chars": 1199,
    "preview": "require 'net.util'\n\n-- parse cmd parameters\nlocal cmd = torch.CmdLine()\n\ncmd:option('--file', '../collect_image/origin_t"
  },
  {
    "path": "net/net.lua",
    "chars": 748,
    "preview": "require 'class'\n\nlocal Net = torch.class('Net')\n\nfunction Net:__init(useCuda, useCudnn)\n  -- cuda support\n  self.useCuda"
  },
  {
    "path": "net/rnndata.lua",
    "chars": 1442,
    "preview": "require 'class'\n\nrequire 'net.data'\nrequire 'net.imageseq'\n\nlocal RnnData = torch.class('RnnData', 'Data')\n\nfunction Rnn"
  },
  {
    "path": "net/rnntrain.lua",
    "chars": 923,
    "preview": "require 'class'\n\nrequire 'net.train'\nrequire 'net.util'\n\nlocal RnnTrain = torch.class('RnnTrain', 'Train')\n\nfunction Rnn"
  },
  {
    "path": "net/seq.lua",
    "chars": 349,
    "preview": "require 'class'\nrequire 'paths'\nrequire 'image'\nlocal json = require 'lunajson'\n\nrequire 'net.util'\n\nlocal Seq = torch.c"
  },
  {
    "path": "net/stat.lua",
    "chars": 2384,
    "preview": "require 'class'\nlocal json = require 'lunajson'\n\nlocal Stat = torch.class('Stat')\n\nfunction Stat:__init(labelSize, batch"
  },
  {
    "path": "net/train.lua",
    "chars": 1159,
    "preview": "require 'class'\n\nlocal Train = torch.class('Train')\n\nfunction Train:__init(labelSize, useCuda, useCudnn)\n  -- require an"
  },
  {
    "path": "net/uninet.lua",
    "chars": 179,
    "preview": "require 'class'\nrequire 'rnn'\n\nrequire 'net.net'\n\nlocal UniNet = torch.class('UniNet', 'Net')\n\nfunction UniNet:__init(us"
  },
  {
    "path": "net/util.lua",
    "chars": 354,
    "preview": "-- helper function to check if string start with some sub-string\nfunction string:startsWith(start)\n  return string.sub(s"
  },
  {
    "path": "pre/image.py",
    "chars": 428,
    "preview": "import cv2\nimport numpy as np\n\nclass image:\n    def __init__(self, file_name):\n        self.file_name = file_name\n\n    #"
  },
  {
    "path": "pre/main.py",
    "chars": 1111,
    "preview": "import argparse\n\nfrom seq import Seq\n\n# call different method depends on op\ndef main(op, file_dir, target_dir, num_chann"
  },
  {
    "path": "pre/op.py",
    "chars": 3786,
    "preview": "import os, subprocess\nimport numpy as np\nimport h5py\nimport json\n\nfrom image import image\n\nclass Operation:\n    def __in"
  },
  {
    "path": "pre/seq.py",
    "chars": 1550,
    "preview": "import os, re\nimport numpy as np\nimport h5py\n\nfrom op import Operation\n\nclass Seq:\n    def __init__(self):\n        pass\n"
  }
]

About this extraction

This page contains the full source code of the simonwsw/deep-soli GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 26 files (61.3 KB), approximately 29.6k tokens, and a symbol index with 25 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!