diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 81acbae..4bb70f7 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -22,7 +22,7 @@ jobs: build: name: Build from OpenVINO source - runs-on: ubuntu-latest + runs-on: ubuntu-18.04 steps: - uses: actions/checkout@v2 with: diff --git a/crates/openvino/tests/classify-inception.rs b/crates/openvino/tests/classify-inception.rs index 65dfafc..784cd2d 100644 --- a/crates/openvino/tests/classify-inception.rs +++ b/crates/openvino/tests/classify-inception.rs @@ -9,7 +9,7 @@ use std::fs; #[test] fn classify_inception() { let mut core = Core::new(None).unwrap(); - let mut network = core + let network = core .read_network_from_file( &Fixture::graph().to_string_lossy(), &Fixture::weights().to_string_lossy(), @@ -17,30 +17,17 @@ fn classify_inception() { .unwrap(); let input_name = &network.get_input_name(0).unwrap(); - assert_eq!(input_name, "image_tensor"); + assert_eq!(input_name, "input"); let output_name = &network.get_output_name(0).unwrap(); - assert_eq!(output_name, "DetectionOutput"); - - // Prepare inputs and outputs for resizing, since our input tensor is not the size the model expects. - network - .set_input_resize_algorithm(input_name, ResizeAlgorithm::RESIZE_BILINEAR) - .unwrap(); - network.set_input_layout(input_name, Layout::NHWC).unwrap(); - network - .set_input_precision(input_name, Precision::U8) - .unwrap(); - network - .set_output_precision(output_name, Precision::FP32) - .unwrap(); + assert_eq!(output_name, "InceptionV3/Predictions/Softmax"); // Load the network. let mut executable_network = core.load_network(&network, "CPU").unwrap(); let mut infer_request = executable_network.create_infer_request().unwrap(); - // TODO eventually, this should not panic: infer_request.set_batch_size(1).unwrap(); // Read the image. let tensor_data = fs::read(Fixture::tensor()).unwrap(); - let tensor_desc = TensorDesc::new(Layout::NHWC, &[1, 3, 481, 640], Precision::U8); + let tensor_desc = TensorDesc::new(Layout::NHWC, &[1, 3, 299, 299], Precision::FP32); let blob = Blob::new(tensor_desc, &tensor_data).unwrap(); // Execute inference. @@ -60,30 +47,31 @@ fn classify_inception() { assert_eq!( &results[..5], &[ - Result(15, 59.0), - Result(1, 1.0), - Result(8, 1.0), - Result(12, 1.0), - Result(16, 0.9939936), + Result(964, 0.9648312), + Result(763, 0.0015633557), + Result(412, 0.0007776478), + Result(814, 0.0006391522), + Result(924, 0.0006150733), ][..] ) - // This above results match the output of running OpenVINO's `hello_classification` with the same inputs: - // $ bin/intel64/Debug/hello_classification /tmp/fixture/frozen_inference_graph.xml /tmp/fixture/000000062808.jpg CPU + // The results above almost match the output of OpenVINO's `hello_classification` with similar + // inputs: + // $ bin/intel64/Debug/hello_classification ../inception.xml ../pizza.jpg CPU // Top 10 results: - // Image /tmp/fixture/000000062808.jpg + // Image ../pizza.jpg // classid probability // ------- ----------- - // 15 59.0000000 - // 1 1.0000000 - // 12 1.0000000 - // 8 1.0000000 - // 16 0.9939936 - // 2 0.9750488 - // 9 0.9535966 - // 20 0.8796915 - // 13 0.8178773 - // 6 0.8092338 + // 964 0.9656160 + // 763 0.0015505 + // 412 0.0007806 + // 924 0.0006135 + // 814 0.0006102 + // 966 0.0005903 + // 960 0.0004972 + // 522 0.0003951 + // 927 0.0003644 + // 923 0.0002908 } /// A structure for holding the `(category, probability)` pair extracted from the output tensor of diff --git a/crates/openvino/tests/detect-inception.rs b/crates/openvino/tests/detect-inception.rs new file mode 100644 index 0000000..4d6b4ac --- /dev/null +++ b/crates/openvino/tests/detect-inception.rs @@ -0,0 +1,110 @@ +//! Demonstrates using `openvino-rs` to classify an image using an Inception SSD model and a prepared input tensor. See +//! [README](fixtures/inception/README.md) for details on how this test fixture was prepared. +mod fixtures; + +use fixtures::inception_ssd::Fixture; +use openvino::{Blob, Core, Layout, Precision, ResizeAlgorithm, TensorDesc}; +use std::fs; + +#[test] +fn detect_inception() { + let mut core = Core::new(None).unwrap(); + let mut network = core + .read_network_from_file( + &Fixture::graph().to_string_lossy(), + &Fixture::weights().to_string_lossy(), + ) + .unwrap(); + + let input_name = &network.get_input_name(0).unwrap(); + assert_eq!(input_name, "image_tensor"); + let output_name = &network.get_output_name(0).unwrap(); + assert_eq!(output_name, "DetectionOutput"); + + // Prepare inputs and outputs for resizing, since our input tensor is not the size the model expects. + network + .set_input_resize_algorithm(input_name, ResizeAlgorithm::RESIZE_BILINEAR) + .unwrap(); + network.set_input_layout(input_name, Layout::NHWC).unwrap(); + network + .set_input_precision(input_name, Precision::U8) + .unwrap(); + network + .set_output_precision(output_name, Precision::FP32) + .unwrap(); + + // Load the network. + let mut executable_network = core.load_network(&network, "CPU").unwrap(); + let mut infer_request = executable_network.create_infer_request().unwrap(); + + // Read the image. + let tensor_data = fs::read(Fixture::tensor()).unwrap(); + let tensor_desc = TensorDesc::new(Layout::NHWC, &[1, 3, 481, 640], Precision::U8); + let blob = Blob::new(tensor_desc, &tensor_data).unwrap(); + + // Execute inference. + infer_request.set_blob(input_name, blob).unwrap(); + infer_request.infer().unwrap(); + let mut results = infer_request.get_blob(output_name).unwrap(); + let buffer = unsafe { results.buffer_mut_as_type::().unwrap().to_vec() }; + + // Sort results (TODO extract bounding boxes instead). + let mut results: Results = buffer + .iter() + .enumerate() + .map(|(c, p)| Result(c, *p)) + .collect(); + results.sort_by(|a, b| b.1.partial_cmp(&a.1).unwrap()); + + assert_eq!( + &results[..5], + &[ + Result(15, 59.0), + Result(1, 1.0), + Result(8, 1.0), + Result(12, 1.0), + Result(16, 0.9939936), + ][..] + ) + + // This above results should match the output of running OpenVINO's + // `object_detection_sample_ssd` with the same inputs. This test incorrectly uses result + // sorting instead of extracting the bounding boxes like `object_detection_sample_ssd` does + // (FIXME): + // $ bin/intel64/Debug/object_detection_sample_ssd -m ../inception-ssd.xml -i ../pizza.jpg + // [ INFO ] InferenceEngine: + // API version ............ 2.1 + // Build .................. custom_master_a1d858c5028c1a26d37286913d64028849454b75 + // Description ....... API + // Parsing input parameters + // [ INFO ] Files were added: 1 + // [ INFO ] ../pizza.jpg + // [ INFO ] Loading Inference Engine + // [ INFO ] Device info: + // CPU + // MKLDNNPlugin version ......... 2.1 + // Build ........... custom_master_a1d858c5028c1a26d37286913d64028849454b75 + // [ INFO ] Loading network files: + // ../inception-ssd.xml + // [ INFO ] Preparing input blobs + // [ INFO ] Batch size is 1 + // [ INFO ] Preparing output blobs + // [ INFO ] Loading model to the device + // [ INFO ] Create infer request + // [ WARNING ] Image is resized from (640, 481) to (300, 300) + // [ INFO ] Batch size is 1 + // [ INFO ] Start inference + // [ INFO ] Processing output blobs + // [0,1] element, prob = 0.975312 (1,19)-(270,389) batch id : 0 WILL BE PRINTED! + // [1,1] element, prob = 0.953244 (368,17)-(640,393) batch id : 0 WILL BE PRINTED! + // [2,59] element, prob = 0.993812 (143,280)-(502,423) batch id : 0 WILL BE PRINTED! + // [3,67] element, prob = 0.301402 (5,369)-(582,480) batch id : 0 + // [ INFO ] Image out_0.bmp created! + // [ INFO ] Execution successful +} + +/// A structure for holding the `(category, probability)` pair extracted from the output tensor of +/// the OpenVINO classification. +#[derive(Debug, PartialEq)] +struct Result(usize, f32); +type Results = Vec; diff --git a/crates/openvino/tests/fixtures/inception/README.md b/crates/openvino/tests/fixtures/inception/README.md index c759cdc..9f58e53 100644 --- a/crates/openvino/tests/fixtures/inception/README.md +++ b/crates/openvino/tests/fixtures/inception/README.md @@ -1,9 +1,11 @@ # Inception SSD Test Fixture -In order to test the use of `openvino-rs` in the real world, here we include the necessary files for performing the -classification in [classify-inception.rs](../classify-inception.rs). The artifacts are included in-tree and can be -rebuilt using the [build.sh] script (with the right system dependencies). The artifacts include: - - the Inception SSD inference model, converted to OpenVINO IR format (`*.bin`, `*.mapping`, `*.xml`) +In order to test the use of `openvino-rs` in the real world, here we include the necessary files for +performing the classification in [classify-inception.rs](../classify-inception.rs). The artifacts +are included in-tree and can be rebuilt using the [build.sh] script (with the right system +dependencies). The artifacts include: + - the Inception v3 classification model, converted to OpenVINO IR format (`*.bin`, `*.mapping`, + `*.xml`) - an image from the COCO dataset transformed into the correct tensor format (`tensor-*.bgr`) -The [mod.sh] `Fixture` provides the correct artifact paths in Rust. \ No newline at end of file +The [mod.sh] `Fixture` provides the correct artifact paths in Rust. diff --git a/crates/openvino/tests/fixtures/inception/build.sh b/crates/openvino/tests/fixtures/inception/build.sh index df3b91a..3501f39 100755 --- a/crates/openvino/tests/fixtures/inception/build.sh +++ b/crates/openvino/tests/fixtures/inception/build.sh @@ -10,20 +10,24 @@ OPENVINO_DIR=${OPENVINO_DIR:-$(realpath $FIXTURE_DIR/../../../../../../openvino) PYTHON=${PYTHON:-python3} pushd $TMP_DIR -# Retrieve the MobileNet model from the TensorFlow -wget --no-clobber http://download.tensorflow.org/models/object_detection/ssd_inception_v2_coco_2018_01_28.tar.gz -tar xzvf ssd_*.tar.gz -ln -sf ssd_inception_v2_coco_2018_01_28 model +# Retrieve the Inception model from the TensorFlow +wget --no-clobber https://storage.googleapis.com/download.tensorflow.org/models/inception_v3_2016_08_28_frozen.pb.tar.gz +tar xzvf inception_*.tar.gz -# Convert the model to OpenVINO IR using the model-optimizer. +# Convert the model to OpenVINO IR using the model-optimizer; see +# https://github.com/openvinotoolkit/open_model_zoo/blob/master/models/public/googlenet-v3/model.yml. pip install --user -r $OPENVINO_DIR/model-optimizer/requirements_tf.txt $PYTHON $OPENVINO_DIR/model-optimizer/mo_tf.py \ - --input_model model/frozen_inference_graph.pb \ - --transformations_config $OPENVINO_DIR/model-optimizer/extensions/front/tf/ssd_v2_support.json \ - --tensorflow_object_detection_api_pipeline_config model/pipeline.config -cp $TMP_DIR/frozen_inference_graph.bin $FIXTURE_DIR/inception-ssd.bin -cp $TMP_DIR/frozen_inference_graph.mapping $FIXTURE_DIR/inception-ssd.mapping -cp $TMP_DIR/frozen_inference_graph.xml $FIXTURE_DIR/inception-ssd.xml + --reverse_input_channels \ + --input_shape=[1,299,299,3] \ + --input=input \ + --mean_values=input[127.5,127.5,127.5] \ + --scale_values=input[127.5] \ + --output=InceptionV3/Predictions/Softmax \ + --input_model=inception_v3_2016_08_28_frozen.pb +cp $TMP_DIR/inception_v3_2016_08_28_frozen.bin $FIXTURE_DIR/inception.bin +cp $TMP_DIR/inception_v3_2016_08_28_frozen.mapping $FIXTURE_DIR/inception.mapping +cp $TMP_DIR/inception_v3_2016_08_28_frozen.xml $FIXTURE_DIR/inception.xml # Retrieve the first 10 images of the COCO dataset. wget --no-clobber http://images.cocodataset.org/zips/val2017.zip @@ -32,7 +36,7 @@ unzip -Z1 val2017.zip | head -n 10 | xargs unzip val2017.zip popd # Convert an image to raw tensor format -cargo run -p openvino-tensor-converter -- $TMP_DIR/val2017/000000062808.jpg $FIXTURE_DIR/tensor-1x3x640x481-u8.bgr 481x640x3xu8 +cargo run -p openvino-tensor-converter -- $TMP_DIR/val2017/000000062808.jpg $FIXTURE_DIR/tensor-1x3x299x299-fp32.bgr 299x299x3xfp32 # Clean up. rm -rf $TMP_DIR diff --git a/crates/openvino/tests/fixtures/inception/inception.bin b/crates/openvino/tests/fixtures/inception/inception.bin new file mode 100644 index 0000000..fa50baf --- /dev/null +++ b/crates/openvino/tests/fixtures/inception/inception.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:bbc900d6bcbd83e48d98569cc471fa2c1439c02b5c67454670a2bd679e4b8080 +size 95277684 diff --git a/crates/openvino/tests/fixtures/inception/inception.mapping b/crates/openvino/tests/fixtures/inception/inception.mapping new file mode 100644 index 0000000..772375f --- /dev/null +++ b/crates/openvino/tests/fixtures/inception/inception.mapping @@ -0,0 +1,2039 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/crates/openvino/tests/fixtures/inception/inception.xml b/crates/openvino/tests/fixtures/inception/inception.xml new file mode 100644 index 0000000..f0080f0 --- /dev/null +++ b/crates/openvino/tests/fixtures/inception/inception.xml @@ -0,0 +1,10072 @@ + + + + + + + + 1 + 3 + 299 + 299 + + + + + + + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 3 + 299 + 299 + + + 1 + 1 + 1 + 1 + + + + + 1 + 3 + 299 + 299 + + + + + + + + 1 + 3 + 1 + 1 + + + + + + + + 1 + 3 + 299 + 299 + + + 1 + 3 + 1 + 1 + + + + + 1 + 3 + 299 + 299 + + + + + + + + 32 + 3 + 3 + 3 + + + + + + + + 1 + 3 + 299 + 299 + + + 32 + 3 + 3 + 3 + + + + + 1 + 32 + 149 + 149 + + + + + + + + 1 + 32 + 1 + 1 + + + + + + + + 1 + 32 + 149 + 149 + + + 1 + 32 + 1 + 1 + + + + + 1 + 32 + 149 + 149 + + + + + + + 1 + 32 + 149 + 149 + + + + + 1 + 32 + 149 + 149 + + + + + + + + 32 + 32 + 3 + 3 + + + + + + + + 1 + 32 + 149 + 149 + + + 32 + 32 + 3 + 3 + + + + + 1 + 32 + 147 + 147 + + + + + + + + 1 + 32 + 1 + 1 + + + + + + + + 1 + 32 + 147 + 147 + + + 1 + 32 + 1 + 1 + + + + + 1 + 32 + 147 + 147 + + + + + + + 1 + 32 + 147 + 147 + + + + + 1 + 32 + 147 + 147 + + + + + + + + 64 + 32 + 3 + 3 + + + + + + + + 1 + 32 + 147 + 147 + + + 64 + 32 + 3 + 3 + + + + + 1 + 64 + 147 + 147 + + + + + + + + 1 + 64 + 1 + 1 + + + + + + + + 1 + 64 + 147 + 147 + + + 1 + 64 + 1 + 1 + + + + + 1 + 64 + 147 + 147 + + + + + + + 1 + 64 + 147 + 147 + + + + + 1 + 64 + 147 + 147 + + + + + + + + 1 + 64 + 147 + 147 + + + + + 1 + 64 + 73 + 73 + + + + + + + + 80 + 64 + 1 + 1 + + + + + + + + 1 + 64 + 73 + 73 + + + 80 + 64 + 1 + 1 + + + + + 1 + 80 + 73 + 73 + + + + + + + + 1 + 80 + 1 + 1 + + + + + + + + 1 + 80 + 73 + 73 + + + 1 + 80 + 1 + 1 + + + + + 1 + 80 + 73 + 73 + + + + + + + 1 + 80 + 73 + 73 + + + + + 1 + 80 + 73 + 73 + + + + + + + + 192 + 80 + 3 + 3 + + + + + + + + 1 + 80 + 73 + 73 + + + 192 + 80 + 3 + 3 + + + + + 1 + 192 + 71 + 71 + + + + + + + + 1 + 192 + 1 + 1 + + + + + + + + 1 + 192 + 71 + 71 + + + 1 + 192 + 1 + 1 + + + + + 1 + 192 + 71 + 71 + + + + + + + 1 + 192 + 71 + 71 + + + + + 1 + 192 + 71 + 71 + + + + + + + + 1 + 192 + 71 + 71 + + + + + 1 + 192 + 35 + 35 + + + + + + + + 64 + 192 + 1 + 1 + + + + + + + + 1 + 192 + 35 + 35 + + + 64 + 192 + 1 + 1 + + + + + 1 + 64 + 35 + 35 + + + + + + + + 1 + 64 + 1 + 1 + + + + + + + + 1 + 64 + 35 + 35 + + + 1 + 64 + 1 + 1 + + + + + 1 + 64 + 35 + 35 + + + + + + + 1 + 64 + 35 + 35 + + + + + 1 + 64 + 35 + 35 + + + + + + + + 48 + 192 + 1 + 1 + + + + + + + + 1 + 192 + 35 + 35 + + + 48 + 192 + 1 + 1 + + + + + 1 + 48 + 35 + 35 + + + + + + + + 1 + 48 + 1 + 1 + + + + + + + + 1 + 48 + 35 + 35 + + + 1 + 48 + 1 + 1 + + + + + 1 + 48 + 35 + 35 + + + + + + + 1 + 48 + 35 + 35 + + + + + 1 + 48 + 35 + 35 + + + + + + + + 64 + 48 + 5 + 5 + + + + + + + + 1 + 48 + 35 + 35 + + + 64 + 48 + 5 + 5 + + + + + 1 + 64 + 35 + 35 + + + + + + + + 1 + 64 + 1 + 1 + + + + + + + + 1 + 64 + 35 + 35 + + + 1 + 64 + 1 + 1 + + + + + 1 + 64 + 35 + 35 + + + + + + + 1 + 64 + 35 + 35 + + + + + 1 + 64 + 35 + 35 + + + + + + + + 64 + 192 + 1 + 1 + + + + + + + + 1 + 192 + 35 + 35 + + + 64 + 192 + 1 + 1 + + + + + 1 + 64 + 35 + 35 + + + + + + + + 1 + 64 + 1 + 1 + + + + + + + + 1 + 64 + 35 + 35 + + + 1 + 64 + 1 + 1 + + + + + 1 + 64 + 35 + 35 + + + + + + + 1 + 64 + 35 + 35 + + + + + 1 + 64 + 35 + 35 + + + + + + + + 96 + 64 + 3 + 3 + + + + + + + + 1 + 64 + 35 + 35 + + + 96 + 64 + 3 + 3 + + + + + 1 + 96 + 35 + 35 + + + + + + + + 1 + 96 + 1 + 1 + + + + + + + + 1 + 96 + 35 + 35 + + + 1 + 96 + 1 + 1 + + + + + 1 + 96 + 35 + 35 + + + + + + + 1 + 96 + 35 + 35 + + + + + 1 + 96 + 35 + 35 + + + + + + + + 96 + 96 + 3 + 3 + + + + + + + + 1 + 96 + 35 + 35 + + + 96 + 96 + 3 + 3 + + + + + 1 + 96 + 35 + 35 + + + + + + + + 1 + 96 + 1 + 1 + + + + + + + + 1 + 96 + 35 + 35 + + + 1 + 96 + 1 + 1 + + + + + 1 + 96 + 35 + 35 + + + + + + + 1 + 96 + 35 + 35 + + + + + 1 + 96 + 35 + 35 + + + + + + + + 1 + 192 + 35 + 35 + + + + + 1 + 192 + 35 + 35 + + + + + + + + 32 + 192 + 1 + 1 + + + + + + + + 1 + 192 + 35 + 35 + + + 32 + 192 + 1 + 1 + + + + + 1 + 32 + 35 + 35 + + + + + + + + 1 + 32 + 1 + 1 + + + + + + + + 1 + 32 + 35 + 35 + + + 1 + 32 + 1 + 1 + + + + + 1 + 32 + 35 + 35 + + + + + + + 1 + 32 + 35 + 35 + + + + + 1 + 32 + 35 + 35 + + + + + + + + 1 + 64 + 35 + 35 + + + 1 + 64 + 35 + 35 + + + 1 + 96 + 35 + 35 + + + 1 + 32 + 35 + 35 + + + + + 1 + 256 + 35 + 35 + + + + + + + + 64 + 256 + 1 + 1 + + + + + + + + 1 + 256 + 35 + 35 + + + 64 + 256 + 1 + 1 + + + + + 1 + 64 + 35 + 35 + + + + + + + + 1 + 64 + 1 + 1 + + + + + + + + 1 + 64 + 35 + 35 + + + 1 + 64 + 1 + 1 + + + + + 1 + 64 + 35 + 35 + + + + + + + 1 + 64 + 35 + 35 + + + + + 1 + 64 + 35 + 35 + + + + + + + + 48 + 256 + 1 + 1 + + + + + + + + 1 + 256 + 35 + 35 + + + 48 + 256 + 1 + 1 + + + + + 1 + 48 + 35 + 35 + + + + + + + + 1 + 48 + 1 + 1 + + + + + + + + 1 + 48 + 35 + 35 + + + 1 + 48 + 1 + 1 + + + + + 1 + 48 + 35 + 35 + + + + + + + 1 + 48 + 35 + 35 + + + + + 1 + 48 + 35 + 35 + + + + + + + + 64 + 48 + 5 + 5 + + + + + + + + 1 + 48 + 35 + 35 + + + 64 + 48 + 5 + 5 + + + + + 1 + 64 + 35 + 35 + + + + + + + + 1 + 64 + 1 + 1 + + + + + + + + 1 + 64 + 35 + 35 + + + 1 + 64 + 1 + 1 + + + + + 1 + 64 + 35 + 35 + + + + + + + 1 + 64 + 35 + 35 + + + + + 1 + 64 + 35 + 35 + + + + + + + + 64 + 256 + 1 + 1 + + + + + + + + 1 + 256 + 35 + 35 + + + 64 + 256 + 1 + 1 + + + + + 1 + 64 + 35 + 35 + + + + + + + + 1 + 64 + 1 + 1 + + + + + + + + 1 + 64 + 35 + 35 + + + 1 + 64 + 1 + 1 + + + + + 1 + 64 + 35 + 35 + + + + + + + 1 + 64 + 35 + 35 + + + + + 1 + 64 + 35 + 35 + + + + + + + + 96 + 64 + 3 + 3 + + + + + + + + 1 + 64 + 35 + 35 + + + 96 + 64 + 3 + 3 + + + + + 1 + 96 + 35 + 35 + + + + + + + + 1 + 96 + 1 + 1 + + + + + + + + 1 + 96 + 35 + 35 + + + 1 + 96 + 1 + 1 + + + + + 1 + 96 + 35 + 35 + + + + + + + 1 + 96 + 35 + 35 + + + + + 1 + 96 + 35 + 35 + + + + + + + + 96 + 96 + 3 + 3 + + + + + + + + 1 + 96 + 35 + 35 + + + 96 + 96 + 3 + 3 + + + + + 1 + 96 + 35 + 35 + + + + + + + + 1 + 96 + 1 + 1 + + + + + + + + 1 + 96 + 35 + 35 + + + 1 + 96 + 1 + 1 + + + + + 1 + 96 + 35 + 35 + + + + + + + 1 + 96 + 35 + 35 + + + + + 1 + 96 + 35 + 35 + + + + + + + + 1 + 256 + 35 + 35 + + + + + 1 + 256 + 35 + 35 + + + + + + + + 64 + 256 + 1 + 1 + + + + + + + + 1 + 256 + 35 + 35 + + + 64 + 256 + 1 + 1 + + + + + 1 + 64 + 35 + 35 + + + + + + + + 1 + 64 + 1 + 1 + + + + + + + + 1 + 64 + 35 + 35 + + + 1 + 64 + 1 + 1 + + + + + 1 + 64 + 35 + 35 + + + + + + + 1 + 64 + 35 + 35 + + + + + 1 + 64 + 35 + 35 + + + + + + + + 1 + 64 + 35 + 35 + + + 1 + 64 + 35 + 35 + + + 1 + 96 + 35 + 35 + + + 1 + 64 + 35 + 35 + + + + + 1 + 288 + 35 + 35 + + + + + + + + 64 + 288 + 1 + 1 + + + + + + + + 1 + 288 + 35 + 35 + + + 64 + 288 + 1 + 1 + + + + + 1 + 64 + 35 + 35 + + + + + + + + 1 + 64 + 1 + 1 + + + + + + + + 1 + 64 + 35 + 35 + + + 1 + 64 + 1 + 1 + + + + + 1 + 64 + 35 + 35 + + + + + + + 1 + 64 + 35 + 35 + + + + + 1 + 64 + 35 + 35 + + + + + + + + 48 + 288 + 1 + 1 + + + + + + + + 1 + 288 + 35 + 35 + + + 48 + 288 + 1 + 1 + + + + + 1 + 48 + 35 + 35 + + + + + + + + 1 + 48 + 1 + 1 + + + + + + + + 1 + 48 + 35 + 35 + + + 1 + 48 + 1 + 1 + + + + + 1 + 48 + 35 + 35 + + + + + + + 1 + 48 + 35 + 35 + + + + + 1 + 48 + 35 + 35 + + + + + + + + 64 + 48 + 5 + 5 + + + + + + + + 1 + 48 + 35 + 35 + + + 64 + 48 + 5 + 5 + + + + + 1 + 64 + 35 + 35 + + + + + + + + 1 + 64 + 1 + 1 + + + + + + + + 1 + 64 + 35 + 35 + + + 1 + 64 + 1 + 1 + + + + + 1 + 64 + 35 + 35 + + + + + + + 1 + 64 + 35 + 35 + + + + + 1 + 64 + 35 + 35 + + + + + + + + 64 + 288 + 1 + 1 + + + + + + + + 1 + 288 + 35 + 35 + + + 64 + 288 + 1 + 1 + + + + + 1 + 64 + 35 + 35 + + + + + + + + 1 + 64 + 1 + 1 + + + + + + + + 1 + 64 + 35 + 35 + + + 1 + 64 + 1 + 1 + + + + + 1 + 64 + 35 + 35 + + + + + + + 1 + 64 + 35 + 35 + + + + + 1 + 64 + 35 + 35 + + + + + + + + 96 + 64 + 3 + 3 + + + + + + + + 1 + 64 + 35 + 35 + + + 96 + 64 + 3 + 3 + + + + + 1 + 96 + 35 + 35 + + + + + + + + 1 + 96 + 1 + 1 + + + + + + + + 1 + 96 + 35 + 35 + + + 1 + 96 + 1 + 1 + + + + + 1 + 96 + 35 + 35 + + + + + + + 1 + 96 + 35 + 35 + + + + + 1 + 96 + 35 + 35 + + + + + + + + 96 + 96 + 3 + 3 + + + + + + + + 1 + 96 + 35 + 35 + + + 96 + 96 + 3 + 3 + + + + + 1 + 96 + 35 + 35 + + + + + + + + 1 + 96 + 1 + 1 + + + + + + + + 1 + 96 + 35 + 35 + + + 1 + 96 + 1 + 1 + + + + + 1 + 96 + 35 + 35 + + + + + + + 1 + 96 + 35 + 35 + + + + + 1 + 96 + 35 + 35 + + + + + + + + 1 + 288 + 35 + 35 + + + + + 1 + 288 + 35 + 35 + + + + + + + + 64 + 288 + 1 + 1 + + + + + + + + 1 + 288 + 35 + 35 + + + 64 + 288 + 1 + 1 + + + + + 1 + 64 + 35 + 35 + + + + + + + + 1 + 64 + 1 + 1 + + + + + + + + 1 + 64 + 35 + 35 + + + 1 + 64 + 1 + 1 + + + + + 1 + 64 + 35 + 35 + + + + + + + 1 + 64 + 35 + 35 + + + + + 1 + 64 + 35 + 35 + + + + + + + + 1 + 64 + 35 + 35 + + + 1 + 64 + 35 + 35 + + + 1 + 96 + 35 + 35 + + + 1 + 64 + 35 + 35 + + + + + 1 + 288 + 35 + 35 + + + + + + + + 384 + 288 + 3 + 3 + + + + + + + + 1 + 288 + 35 + 35 + + + 384 + 288 + 3 + 3 + + + + + 1 + 384 + 17 + 17 + + + + + + + + 1 + 384 + 1 + 1 + + + + + + + + 1 + 384 + 17 + 17 + + + 1 + 384 + 1 + 1 + + + + + 1 + 384 + 17 + 17 + + + + + + + 1 + 384 + 17 + 17 + + + + + 1 + 384 + 17 + 17 + + + + + + + + 64 + 288 + 1 + 1 + + + + + + + + 1 + 288 + 35 + 35 + + + 64 + 288 + 1 + 1 + + + + + 1 + 64 + 35 + 35 + + + + + + + + 1 + 64 + 1 + 1 + + + + + + + + 1 + 64 + 35 + 35 + + + 1 + 64 + 1 + 1 + + + + + 1 + 64 + 35 + 35 + + + + + + + 1 + 64 + 35 + 35 + + + + + 1 + 64 + 35 + 35 + + + + + + + + 96 + 64 + 3 + 3 + + + + + + + + 1 + 64 + 35 + 35 + + + 96 + 64 + 3 + 3 + + + + + 1 + 96 + 35 + 35 + + + + + + + + 1 + 96 + 1 + 1 + + + + + + + + 1 + 96 + 35 + 35 + + + 1 + 96 + 1 + 1 + + + + + 1 + 96 + 35 + 35 + + + + + + + 1 + 96 + 35 + 35 + + + + + 1 + 96 + 35 + 35 + + + + + + + + 96 + 96 + 3 + 3 + + + + + + + + 1 + 96 + 35 + 35 + + + 96 + 96 + 3 + 3 + + + + + 1 + 96 + 17 + 17 + + + + + + + + 1 + 96 + 1 + 1 + + + + + + + + 1 + 96 + 17 + 17 + + + 1 + 96 + 1 + 1 + + + + + 1 + 96 + 17 + 17 + + + + + + + 1 + 96 + 17 + 17 + + + + + 1 + 96 + 17 + 17 + + + + + + + + 1 + 288 + 35 + 35 + + + + + 1 + 288 + 17 + 17 + + + + + + + + 1 + 384 + 17 + 17 + + + 1 + 96 + 17 + 17 + + + 1 + 288 + 17 + 17 + + + + + 1 + 768 + 17 + 17 + + + + + + + + 192 + 768 + 1 + 1 + + + + + + + + 1 + 768 + 17 + 17 + + + 192 + 768 + 1 + 1 + + + + + 1 + 192 + 17 + 17 + + + + + + + + 1 + 192 + 1 + 1 + + + + + + + + 1 + 192 + 17 + 17 + + + 1 + 192 + 1 + 1 + + + + + 1 + 192 + 17 + 17 + + + + + + + 1 + 192 + 17 + 17 + + + + + 1 + 192 + 17 + 17 + + + + + + + + 128 + 768 + 1 + 1 + + + + + + + + 1 + 768 + 17 + 17 + + + 128 + 768 + 1 + 1 + + + + + 1 + 128 + 17 + 17 + + + + + + + + 1 + 128 + 1 + 1 + + + + + + + + 1 + 128 + 17 + 17 + + + 1 + 128 + 1 + 1 + + + + + 1 + 128 + 17 + 17 + + + + + + + 1 + 128 + 17 + 17 + + + + + 1 + 128 + 17 + 17 + + + + + + + + 128 + 128 + 1 + 7 + + + + + + + + 1 + 128 + 17 + 17 + + + 128 + 128 + 1 + 7 + + + + + 1 + 128 + 17 + 17 + + + + + + + + 1 + 128 + 1 + 1 + + + + + + + + 1 + 128 + 17 + 17 + + + 1 + 128 + 1 + 1 + + + + + 1 + 128 + 17 + 17 + + + + + + + 1 + 128 + 17 + 17 + + + + + 1 + 128 + 17 + 17 + + + + + + + + 192 + 128 + 7 + 1 + + + + + + + + 1 + 128 + 17 + 17 + + + 192 + 128 + 7 + 1 + + + + + 1 + 192 + 17 + 17 + + + + + + + + 1 + 192 + 1 + 1 + + + + + + + + 1 + 192 + 17 + 17 + + + 1 + 192 + 1 + 1 + + + + + 1 + 192 + 17 + 17 + + + + + + + 1 + 192 + 17 + 17 + + + + + 1 + 192 + 17 + 17 + + + + + + + + 128 + 768 + 1 + 1 + + + + + + + + 1 + 768 + 17 + 17 + + + 128 + 768 + 1 + 1 + + + + + 1 + 128 + 17 + 17 + + + + + + + + 1 + 128 + 1 + 1 + + + + + + + + 1 + 128 + 17 + 17 + + + 1 + 128 + 1 + 1 + + + + + 1 + 128 + 17 + 17 + + + + + + + 1 + 128 + 17 + 17 + + + + + 1 + 128 + 17 + 17 + + + + + + + + 128 + 128 + 7 + 1 + + + + + + + + 1 + 128 + 17 + 17 + + + 128 + 128 + 7 + 1 + + + + + 1 + 128 + 17 + 17 + + + + + + + + 1 + 128 + 1 + 1 + + + + + + + + 1 + 128 + 17 + 17 + + + 1 + 128 + 1 + 1 + + + + + 1 + 128 + 17 + 17 + + + + + + + 1 + 128 + 17 + 17 + + + + + 1 + 128 + 17 + 17 + + + + + + + + 128 + 128 + 1 + 7 + + + + + + + + 1 + 128 + 17 + 17 + + + 128 + 128 + 1 + 7 + + + + + 1 + 128 + 17 + 17 + + + + + + + + 1 + 128 + 1 + 1 + + + + + + + + 1 + 128 + 17 + 17 + + + 1 + 128 + 1 + 1 + + + + + 1 + 128 + 17 + 17 + + + + + + + 1 + 128 + 17 + 17 + + + + + 1 + 128 + 17 + 17 + + + + + + + + 128 + 128 + 7 + 1 + + + + + + + + 1 + 128 + 17 + 17 + + + 128 + 128 + 7 + 1 + + + + + 1 + 128 + 17 + 17 + + + + + + + + 1 + 128 + 1 + 1 + + + + + + + + 1 + 128 + 17 + 17 + + + 1 + 128 + 1 + 1 + + + + + 1 + 128 + 17 + 17 + + + + + + + 1 + 128 + 17 + 17 + + + + + 1 + 128 + 17 + 17 + + + + + + + + 192 + 128 + 1 + 7 + + + + + + + + 1 + 128 + 17 + 17 + + + 192 + 128 + 1 + 7 + + + + + 1 + 192 + 17 + 17 + + + + + + + + 1 + 192 + 1 + 1 + + + + + + + + 1 + 192 + 17 + 17 + + + 1 + 192 + 1 + 1 + + + + + 1 + 192 + 17 + 17 + + + + + + + 1 + 192 + 17 + 17 + + + + + 1 + 192 + 17 + 17 + + + + + + + + 1 + 768 + 17 + 17 + + + + + 1 + 768 + 17 + 17 + + + + + + + + 192 + 768 + 1 + 1 + + + + + + + + 1 + 768 + 17 + 17 + + + 192 + 768 + 1 + 1 + + + + + 1 + 192 + 17 + 17 + + + + + + + + 1 + 192 + 1 + 1 + + + + + + + + 1 + 192 + 17 + 17 + + + 1 + 192 + 1 + 1 + + + + + 1 + 192 + 17 + 17 + + + + + + + 1 + 192 + 17 + 17 + + + + + 1 + 192 + 17 + 17 + + + + + + + + 1 + 192 + 17 + 17 + + + 1 + 192 + 17 + 17 + + + 1 + 192 + 17 + 17 + + + 1 + 192 + 17 + 17 + + + + + 1 + 768 + 17 + 17 + + + + + + + + 192 + 768 + 1 + 1 + + + + + + + + 1 + 768 + 17 + 17 + + + 192 + 768 + 1 + 1 + + + + + 1 + 192 + 17 + 17 + + + + + + + + 1 + 192 + 1 + 1 + + + + + + + + 1 + 192 + 17 + 17 + + + 1 + 192 + 1 + 1 + + + + + 1 + 192 + 17 + 17 + + + + + + + 1 + 192 + 17 + 17 + + + + + 1 + 192 + 17 + 17 + + + + + + + + 160 + 768 + 1 + 1 + + + + + + + + 1 + 768 + 17 + 17 + + + 160 + 768 + 1 + 1 + + + + + 1 + 160 + 17 + 17 + + + + + + + + 1 + 160 + 1 + 1 + + + + + + + + 1 + 160 + 17 + 17 + + + 1 + 160 + 1 + 1 + + + + + 1 + 160 + 17 + 17 + + + + + + + 1 + 160 + 17 + 17 + + + + + 1 + 160 + 17 + 17 + + + + + + + + 160 + 160 + 1 + 7 + + + + + + + + 1 + 160 + 17 + 17 + + + 160 + 160 + 1 + 7 + + + + + 1 + 160 + 17 + 17 + + + + + + + + 1 + 160 + 1 + 1 + + + + + + + + 1 + 160 + 17 + 17 + + + 1 + 160 + 1 + 1 + + + + + 1 + 160 + 17 + 17 + + + + + + + 1 + 160 + 17 + 17 + + + + + 1 + 160 + 17 + 17 + + + + + + + + 192 + 160 + 7 + 1 + + + + + + + + 1 + 160 + 17 + 17 + + + 192 + 160 + 7 + 1 + + + + + 1 + 192 + 17 + 17 + + + + + + + + 1 + 192 + 1 + 1 + + + + + + + + 1 + 192 + 17 + 17 + + + 1 + 192 + 1 + 1 + + + + + 1 + 192 + 17 + 17 + + + + + + + 1 + 192 + 17 + 17 + + + + + 1 + 192 + 17 + 17 + + + + + + + + 160 + 768 + 1 + 1 + + + + + + + + 1 + 768 + 17 + 17 + + + 160 + 768 + 1 + 1 + + + + + 1 + 160 + 17 + 17 + + + + + + + + 1 + 160 + 1 + 1 + + + + + + + + 1 + 160 + 17 + 17 + + + 1 + 160 + 1 + 1 + + + + + 1 + 160 + 17 + 17 + + + + + + + 1 + 160 + 17 + 17 + + + + + 1 + 160 + 17 + 17 + + + + + + + + 160 + 160 + 7 + 1 + + + + + + + + 1 + 160 + 17 + 17 + + + 160 + 160 + 7 + 1 + + + + + 1 + 160 + 17 + 17 + + + + + + + + 1 + 160 + 1 + 1 + + + + + + + + 1 + 160 + 17 + 17 + + + 1 + 160 + 1 + 1 + + + + + 1 + 160 + 17 + 17 + + + + + + + 1 + 160 + 17 + 17 + + + + + 1 + 160 + 17 + 17 + + + + + + + + 160 + 160 + 1 + 7 + + + + + + + + 1 + 160 + 17 + 17 + + + 160 + 160 + 1 + 7 + + + + + 1 + 160 + 17 + 17 + + + + + + + + 1 + 160 + 1 + 1 + + + + + + + + 1 + 160 + 17 + 17 + + + 1 + 160 + 1 + 1 + + + + + 1 + 160 + 17 + 17 + + + + + + + 1 + 160 + 17 + 17 + + + + + 1 + 160 + 17 + 17 + + + + + + + + 160 + 160 + 7 + 1 + + + + + + + + 1 + 160 + 17 + 17 + + + 160 + 160 + 7 + 1 + + + + + 1 + 160 + 17 + 17 + + + + + + + + 1 + 160 + 1 + 1 + + + + + + + + 1 + 160 + 17 + 17 + + + 1 + 160 + 1 + 1 + + + + + 1 + 160 + 17 + 17 + + + + + + + 1 + 160 + 17 + 17 + + + + + 1 + 160 + 17 + 17 + + + + + + + + 192 + 160 + 1 + 7 + + + + + + + + 1 + 160 + 17 + 17 + + + 192 + 160 + 1 + 7 + + + + + 1 + 192 + 17 + 17 + + + + + + + + 1 + 192 + 1 + 1 + + + + + + + + 1 + 192 + 17 + 17 + + + 1 + 192 + 1 + 1 + + + + + 1 + 192 + 17 + 17 + + + + + + + 1 + 192 + 17 + 17 + + + + + 1 + 192 + 17 + 17 + + + + + + + + 1 + 768 + 17 + 17 + + + + + 1 + 768 + 17 + 17 + + + + + + + + 192 + 768 + 1 + 1 + + + + + + + + 1 + 768 + 17 + 17 + + + 192 + 768 + 1 + 1 + + + + + 1 + 192 + 17 + 17 + + + + + + + + 1 + 192 + 1 + 1 + + + + + + + + 1 + 192 + 17 + 17 + + + 1 + 192 + 1 + 1 + + + + + 1 + 192 + 17 + 17 + + + + + + + 1 + 192 + 17 + 17 + + + + + 1 + 192 + 17 + 17 + + + + + + + + 1 + 192 + 17 + 17 + + + 1 + 192 + 17 + 17 + + + 1 + 192 + 17 + 17 + + + 1 + 192 + 17 + 17 + + + + + 1 + 768 + 17 + 17 + + + + + + + + 192 + 768 + 1 + 1 + + + + + + + + 1 + 768 + 17 + 17 + + + 192 + 768 + 1 + 1 + + + + + 1 + 192 + 17 + 17 + + + + + + + + 1 + 192 + 1 + 1 + + + + + + + + 1 + 192 + 17 + 17 + + + 1 + 192 + 1 + 1 + + + + + 1 + 192 + 17 + 17 + + + + + + + 1 + 192 + 17 + 17 + + + + + 1 + 192 + 17 + 17 + + + + + + + + 160 + 768 + 1 + 1 + + + + + + + + 1 + 768 + 17 + 17 + + + 160 + 768 + 1 + 1 + + + + + 1 + 160 + 17 + 17 + + + + + + + + 1 + 160 + 1 + 1 + + + + + + + + 1 + 160 + 17 + 17 + + + 1 + 160 + 1 + 1 + + + + + 1 + 160 + 17 + 17 + + + + + + + 1 + 160 + 17 + 17 + + + + + 1 + 160 + 17 + 17 + + + + + + + + 160 + 160 + 1 + 7 + + + + + + + + 1 + 160 + 17 + 17 + + + 160 + 160 + 1 + 7 + + + + + 1 + 160 + 17 + 17 + + + + + + + + 1 + 160 + 1 + 1 + + + + + + + + 1 + 160 + 17 + 17 + + + 1 + 160 + 1 + 1 + + + + + 1 + 160 + 17 + 17 + + + + + + + 1 + 160 + 17 + 17 + + + + + 1 + 160 + 17 + 17 + + + + + + + + 192 + 160 + 7 + 1 + + + + + + + + 1 + 160 + 17 + 17 + + + 192 + 160 + 7 + 1 + + + + + 1 + 192 + 17 + 17 + + + + + + + + 1 + 192 + 1 + 1 + + + + + + + + 1 + 192 + 17 + 17 + + + 1 + 192 + 1 + 1 + + + + + 1 + 192 + 17 + 17 + + + + + + + 1 + 192 + 17 + 17 + + + + + 1 + 192 + 17 + 17 + + + + + + + + 160 + 768 + 1 + 1 + + + + + + + + 1 + 768 + 17 + 17 + + + 160 + 768 + 1 + 1 + + + + + 1 + 160 + 17 + 17 + + + + + + + + 1 + 160 + 1 + 1 + + + + + + + + 1 + 160 + 17 + 17 + + + 1 + 160 + 1 + 1 + + + + + 1 + 160 + 17 + 17 + + + + + + + 1 + 160 + 17 + 17 + + + + + 1 + 160 + 17 + 17 + + + + + + + + 160 + 160 + 7 + 1 + + + + + + + + 1 + 160 + 17 + 17 + + + 160 + 160 + 7 + 1 + + + + + 1 + 160 + 17 + 17 + + + + + + + + 1 + 160 + 1 + 1 + + + + + + + + 1 + 160 + 17 + 17 + + + 1 + 160 + 1 + 1 + + + + + 1 + 160 + 17 + 17 + + + + + + + 1 + 160 + 17 + 17 + + + + + 1 + 160 + 17 + 17 + + + + + + + + 160 + 160 + 1 + 7 + + + + + + + + 1 + 160 + 17 + 17 + + + 160 + 160 + 1 + 7 + + + + + 1 + 160 + 17 + 17 + + + + + + + + 1 + 160 + 1 + 1 + + + + + + + + 1 + 160 + 17 + 17 + + + 1 + 160 + 1 + 1 + + + + + 1 + 160 + 17 + 17 + + + + + + + 1 + 160 + 17 + 17 + + + + + 1 + 160 + 17 + 17 + + + + + + + + 160 + 160 + 7 + 1 + + + + + + + + 1 + 160 + 17 + 17 + + + 160 + 160 + 7 + 1 + + + + + 1 + 160 + 17 + 17 + + + + + + + + 1 + 160 + 1 + 1 + + + + + + + + 1 + 160 + 17 + 17 + + + 1 + 160 + 1 + 1 + + + + + 1 + 160 + 17 + 17 + + + + + + + 1 + 160 + 17 + 17 + + + + + 1 + 160 + 17 + 17 + + + + + + + + 192 + 160 + 1 + 7 + + + + + + + + 1 + 160 + 17 + 17 + + + 192 + 160 + 1 + 7 + + + + + 1 + 192 + 17 + 17 + + + + + + + + 1 + 192 + 1 + 1 + + + + + + + + 1 + 192 + 17 + 17 + + + 1 + 192 + 1 + 1 + + + + + 1 + 192 + 17 + 17 + + + + + + + 1 + 192 + 17 + 17 + + + + + 1 + 192 + 17 + 17 + + + + + + + + 1 + 768 + 17 + 17 + + + + + 1 + 768 + 17 + 17 + + + + + + + + 192 + 768 + 1 + 1 + + + + + + + + 1 + 768 + 17 + 17 + + + 192 + 768 + 1 + 1 + + + + + 1 + 192 + 17 + 17 + + + + + + + + 1 + 192 + 1 + 1 + + + + + + + + 1 + 192 + 17 + 17 + + + 1 + 192 + 1 + 1 + + + + + 1 + 192 + 17 + 17 + + + + + + + 1 + 192 + 17 + 17 + + + + + 1 + 192 + 17 + 17 + + + + + + + + 1 + 192 + 17 + 17 + + + 1 + 192 + 17 + 17 + + + 1 + 192 + 17 + 17 + + + 1 + 192 + 17 + 17 + + + + + 1 + 768 + 17 + 17 + + + + + + + + 192 + 768 + 1 + 1 + + + + + + + + 1 + 768 + 17 + 17 + + + 192 + 768 + 1 + 1 + + + + + 1 + 192 + 17 + 17 + + + + + + + + 1 + 192 + 1 + 1 + + + + + + + + 1 + 192 + 17 + 17 + + + 1 + 192 + 1 + 1 + + + + + 1 + 192 + 17 + 17 + + + + + + + 1 + 192 + 17 + 17 + + + + + 1 + 192 + 17 + 17 + + + + + + + + 192 + 768 + 1 + 1 + + + + + + + + 1 + 768 + 17 + 17 + + + 192 + 768 + 1 + 1 + + + + + 1 + 192 + 17 + 17 + + + + + + + + 1 + 192 + 1 + 1 + + + + + + + + 1 + 192 + 17 + 17 + + + 1 + 192 + 1 + 1 + + + + + 1 + 192 + 17 + 17 + + + + + + + 1 + 192 + 17 + 17 + + + + + 1 + 192 + 17 + 17 + + + + + + + + 192 + 192 + 1 + 7 + + + + + + + + 1 + 192 + 17 + 17 + + + 192 + 192 + 1 + 7 + + + + + 1 + 192 + 17 + 17 + + + + + + + + 1 + 192 + 1 + 1 + + + + + + + + 1 + 192 + 17 + 17 + + + 1 + 192 + 1 + 1 + + + + + 1 + 192 + 17 + 17 + + + + + + + 1 + 192 + 17 + 17 + + + + + 1 + 192 + 17 + 17 + + + + + + + + 192 + 192 + 7 + 1 + + + + + + + + 1 + 192 + 17 + 17 + + + 192 + 192 + 7 + 1 + + + + + 1 + 192 + 17 + 17 + + + + + + + + 1 + 192 + 1 + 1 + + + + + + + + 1 + 192 + 17 + 17 + + + 1 + 192 + 1 + 1 + + + + + 1 + 192 + 17 + 17 + + + + + + + 1 + 192 + 17 + 17 + + + + + 1 + 192 + 17 + 17 + + + + + + + + 192 + 768 + 1 + 1 + + + + + + + + 1 + 768 + 17 + 17 + + + 192 + 768 + 1 + 1 + + + + + 1 + 192 + 17 + 17 + + + + + + + + 1 + 192 + 1 + 1 + + + + + + + + 1 + 192 + 17 + 17 + + + 1 + 192 + 1 + 1 + + + + + 1 + 192 + 17 + 17 + + + + + + + 1 + 192 + 17 + 17 + + + + + 1 + 192 + 17 + 17 + + + + + + + + 192 + 192 + 7 + 1 + + + + + + + + 1 + 192 + 17 + 17 + + + 192 + 192 + 7 + 1 + + + + + 1 + 192 + 17 + 17 + + + + + + + + 1 + 192 + 1 + 1 + + + + + + + + 1 + 192 + 17 + 17 + + + 1 + 192 + 1 + 1 + + + + + 1 + 192 + 17 + 17 + + + + + + + 1 + 192 + 17 + 17 + + + + + 1 + 192 + 17 + 17 + + + + + + + + 192 + 192 + 1 + 7 + + + + + + + + 1 + 192 + 17 + 17 + + + 192 + 192 + 1 + 7 + + + + + 1 + 192 + 17 + 17 + + + + + + + + 1 + 192 + 1 + 1 + + + + + + + + 1 + 192 + 17 + 17 + + + 1 + 192 + 1 + 1 + + + + + 1 + 192 + 17 + 17 + + + + + + + 1 + 192 + 17 + 17 + + + + + 1 + 192 + 17 + 17 + + + + + + + + 192 + 192 + 7 + 1 + + + + + + + + 1 + 192 + 17 + 17 + + + 192 + 192 + 7 + 1 + + + + + 1 + 192 + 17 + 17 + + + + + + + + 1 + 192 + 1 + 1 + + + + + + + + 1 + 192 + 17 + 17 + + + 1 + 192 + 1 + 1 + + + + + 1 + 192 + 17 + 17 + + + + + + + 1 + 192 + 17 + 17 + + + + + 1 + 192 + 17 + 17 + + + + + + + + 192 + 192 + 1 + 7 + + + + + + + + 1 + 192 + 17 + 17 + + + 192 + 192 + 1 + 7 + + + + + 1 + 192 + 17 + 17 + + + + + + + + 1 + 192 + 1 + 1 + + + + + + + + 1 + 192 + 17 + 17 + + + 1 + 192 + 1 + 1 + + + + + 1 + 192 + 17 + 17 + + + + + + + 1 + 192 + 17 + 17 + + + + + 1 + 192 + 17 + 17 + + + + + + + + 1 + 768 + 17 + 17 + + + + + 1 + 768 + 17 + 17 + + + + + + + + 192 + 768 + 1 + 1 + + + + + + + + 1 + 768 + 17 + 17 + + + 192 + 768 + 1 + 1 + + + + + 1 + 192 + 17 + 17 + + + + + + + + 1 + 192 + 1 + 1 + + + + + + + + 1 + 192 + 17 + 17 + + + 1 + 192 + 1 + 1 + + + + + 1 + 192 + 17 + 17 + + + + + + + 1 + 192 + 17 + 17 + + + + + 1 + 192 + 17 + 17 + + + + + + + + 1 + 192 + 17 + 17 + + + 1 + 192 + 17 + 17 + + + 1 + 192 + 17 + 17 + + + 1 + 192 + 17 + 17 + + + + + 1 + 768 + 17 + 17 + + + + + + + + 192 + 768 + 1 + 1 + + + + + + + + 1 + 768 + 17 + 17 + + + 192 + 768 + 1 + 1 + + + + + 1 + 192 + 17 + 17 + + + + + + + + 1 + 192 + 1 + 1 + + + + + + + + 1 + 192 + 17 + 17 + + + 1 + 192 + 1 + 1 + + + + + 1 + 192 + 17 + 17 + + + + + + + 1 + 192 + 17 + 17 + + + + + 1 + 192 + 17 + 17 + + + + + + + + 320 + 192 + 3 + 3 + + + + + + + + 1 + 192 + 17 + 17 + + + 320 + 192 + 3 + 3 + + + + + 1 + 320 + 8 + 8 + + + + + + + + 1 + 320 + 1 + 1 + + + + + + + + 1 + 320 + 8 + 8 + + + 1 + 320 + 1 + 1 + + + + + 1 + 320 + 8 + 8 + + + + + + + 1 + 320 + 8 + 8 + + + + + 1 + 320 + 8 + 8 + + + + + + + + 192 + 768 + 1 + 1 + + + + + + + + 1 + 768 + 17 + 17 + + + 192 + 768 + 1 + 1 + + + + + 1 + 192 + 17 + 17 + + + + + + + + 1 + 192 + 1 + 1 + + + + + + + + 1 + 192 + 17 + 17 + + + 1 + 192 + 1 + 1 + + + + + 1 + 192 + 17 + 17 + + + + + + + 1 + 192 + 17 + 17 + + + + + 1 + 192 + 17 + 17 + + + + + + + + 192 + 192 + 1 + 7 + + + + + + + + 1 + 192 + 17 + 17 + + + 192 + 192 + 1 + 7 + + + + + 1 + 192 + 17 + 17 + + + + + + + + 1 + 192 + 1 + 1 + + + + + + + + 1 + 192 + 17 + 17 + + + 1 + 192 + 1 + 1 + + + + + 1 + 192 + 17 + 17 + + + + + + + 1 + 192 + 17 + 17 + + + + + 1 + 192 + 17 + 17 + + + + + + + + 192 + 192 + 7 + 1 + + + + + + + + 1 + 192 + 17 + 17 + + + 192 + 192 + 7 + 1 + + + + + 1 + 192 + 17 + 17 + + + + + + + + 1 + 192 + 1 + 1 + + + + + + + + 1 + 192 + 17 + 17 + + + 1 + 192 + 1 + 1 + + + + + 1 + 192 + 17 + 17 + + + + + + + 1 + 192 + 17 + 17 + + + + + 1 + 192 + 17 + 17 + + + + + + + + 192 + 192 + 3 + 3 + + + + + + + + 1 + 192 + 17 + 17 + + + 192 + 192 + 3 + 3 + + + + + 1 + 192 + 8 + 8 + + + + + + + + 1 + 192 + 1 + 1 + + + + + + + + 1 + 192 + 8 + 8 + + + 1 + 192 + 1 + 1 + + + + + 1 + 192 + 8 + 8 + + + + + + + 1 + 192 + 8 + 8 + + + + + 1 + 192 + 8 + 8 + + + + + + + + 1 + 768 + 17 + 17 + + + + + 1 + 768 + 8 + 8 + + + + + + + + 1 + 320 + 8 + 8 + + + 1 + 192 + 8 + 8 + + + 1 + 768 + 8 + 8 + + + + + 1 + 1280 + 8 + 8 + + + + + + + + 320 + 1280 + 1 + 1 + + + + + + + + 1 + 1280 + 8 + 8 + + + 320 + 1280 + 1 + 1 + + + + + 1 + 320 + 8 + 8 + + + + + + + + 1 + 320 + 1 + 1 + + + + + + + + 1 + 320 + 8 + 8 + + + 1 + 320 + 1 + 1 + + + + + 1 + 320 + 8 + 8 + + + + + + + 1 + 320 + 8 + 8 + + + + + 1 + 320 + 8 + 8 + + + + + + + + 384 + 1280 + 1 + 1 + + + + + + + + 1 + 1280 + 8 + 8 + + + 384 + 1280 + 1 + 1 + + + + + 1 + 384 + 8 + 8 + + + + + + + + 1 + 384 + 1 + 1 + + + + + + + + 1 + 384 + 8 + 8 + + + 1 + 384 + 1 + 1 + + + + + 1 + 384 + 8 + 8 + + + + + + + 1 + 384 + 8 + 8 + + + + + 1 + 384 + 8 + 8 + + + + + + + + 384 + 384 + 1 + 3 + + + + + + + + 1 + 384 + 8 + 8 + + + 384 + 384 + 1 + 3 + + + + + 1 + 384 + 8 + 8 + + + + + + + + 1 + 384 + 1 + 1 + + + + + + + + 1 + 384 + 8 + 8 + + + 1 + 384 + 1 + 1 + + + + + 1 + 384 + 8 + 8 + + + + + + + 1 + 384 + 8 + 8 + + + + + 1 + 384 + 8 + 8 + + + + + + + + 384 + 384 + 3 + 1 + + + + + + + + 1 + 384 + 8 + 8 + + + 384 + 384 + 3 + 1 + + + + + 1 + 384 + 8 + 8 + + + + + + + + 1 + 384 + 1 + 1 + + + + + + + + 1 + 384 + 8 + 8 + + + 1 + 384 + 1 + 1 + + + + + 1 + 384 + 8 + 8 + + + + + + + 1 + 384 + 8 + 8 + + + + + 1 + 384 + 8 + 8 + + + + + + + + 1 + 384 + 8 + 8 + + + 1 + 384 + 8 + 8 + + + + + 1 + 768 + 8 + 8 + + + + + + + + 448 + 1280 + 1 + 1 + + + + + + + + 1 + 1280 + 8 + 8 + + + 448 + 1280 + 1 + 1 + + + + + 1 + 448 + 8 + 8 + + + + + + + + 1 + 448 + 1 + 1 + + + + + + + + 1 + 448 + 8 + 8 + + + 1 + 448 + 1 + 1 + + + + + 1 + 448 + 8 + 8 + + + + + + + 1 + 448 + 8 + 8 + + + + + 1 + 448 + 8 + 8 + + + + + + + + 384 + 448 + 3 + 3 + + + + + + + + 1 + 448 + 8 + 8 + + + 384 + 448 + 3 + 3 + + + + + 1 + 384 + 8 + 8 + + + + + + + + 1 + 384 + 1 + 1 + + + + + + + + 1 + 384 + 8 + 8 + + + 1 + 384 + 1 + 1 + + + + + 1 + 384 + 8 + 8 + + + + + + + 1 + 384 + 8 + 8 + + + + + 1 + 384 + 8 + 8 + + + + + + + + 384 + 384 + 1 + 3 + + + + + + + + 1 + 384 + 8 + 8 + + + 384 + 384 + 1 + 3 + + + + + 1 + 384 + 8 + 8 + + + + + + + + 1 + 384 + 1 + 1 + + + + + + + + 1 + 384 + 8 + 8 + + + 1 + 384 + 1 + 1 + + + + + 1 + 384 + 8 + 8 + + + + + + + 1 + 384 + 8 + 8 + + + + + 1 + 384 + 8 + 8 + + + + + + + + 384 + 384 + 3 + 1 + + + + + + + + 1 + 384 + 8 + 8 + + + 384 + 384 + 3 + 1 + + + + + 1 + 384 + 8 + 8 + + + + + + + + 1 + 384 + 1 + 1 + + + + + + + + 1 + 384 + 8 + 8 + + + 1 + 384 + 1 + 1 + + + + + 1 + 384 + 8 + 8 + + + + + + + 1 + 384 + 8 + 8 + + + + + 1 + 384 + 8 + 8 + + + + + + + + 1 + 384 + 8 + 8 + + + 1 + 384 + 8 + 8 + + + + + 1 + 768 + 8 + 8 + + + + + + + + 1 + 1280 + 8 + 8 + + + + + 1 + 1280 + 8 + 8 + + + + + + + + 192 + 1280 + 1 + 1 + + + + + + + + 1 + 1280 + 8 + 8 + + + 192 + 1280 + 1 + 1 + + + + + 1 + 192 + 8 + 8 + + + + + + + + 1 + 192 + 1 + 1 + + + + + + + + 1 + 192 + 8 + 8 + + + 1 + 192 + 1 + 1 + + + + + 1 + 192 + 8 + 8 + + + + + + + 1 + 192 + 8 + 8 + + + + + 1 + 192 + 8 + 8 + + + + + + + + 1 + 320 + 8 + 8 + + + 1 + 768 + 8 + 8 + + + 1 + 768 + 8 + 8 + + + 1 + 192 + 8 + 8 + + + + + 1 + 2048 + 8 + 8 + + + + + + + + 320 + 2048 + 1 + 1 + + + + + + + + 1 + 2048 + 8 + 8 + + + 320 + 2048 + 1 + 1 + + + + + 1 + 320 + 8 + 8 + + + + + + + + 1 + 320 + 1 + 1 + + + + + + + + 1 + 320 + 8 + 8 + + + 1 + 320 + 1 + 1 + + + + + 1 + 320 + 8 + 8 + + + + + + + 1 + 320 + 8 + 8 + + + + + 1 + 320 + 8 + 8 + + + + + + + + 384 + 2048 + 1 + 1 + + + + + + + + 1 + 2048 + 8 + 8 + + + 384 + 2048 + 1 + 1 + + + + + 1 + 384 + 8 + 8 + + + + + + + + 1 + 384 + 1 + 1 + + + + + + + + 1 + 384 + 8 + 8 + + + 1 + 384 + 1 + 1 + + + + + 1 + 384 + 8 + 8 + + + + + + + 1 + 384 + 8 + 8 + + + + + 1 + 384 + 8 + 8 + + + + + + + + 384 + 384 + 1 + 3 + + + + + + + + 1 + 384 + 8 + 8 + + + 384 + 384 + 1 + 3 + + + + + 1 + 384 + 8 + 8 + + + + + + + + 1 + 384 + 1 + 1 + + + + + + + + 1 + 384 + 8 + 8 + + + 1 + 384 + 1 + 1 + + + + + 1 + 384 + 8 + 8 + + + + + + + 1 + 384 + 8 + 8 + + + + + 1 + 384 + 8 + 8 + + + + + + + + 384 + 384 + 3 + 1 + + + + + + + + 1 + 384 + 8 + 8 + + + 384 + 384 + 3 + 1 + + + + + 1 + 384 + 8 + 8 + + + + + + + + 1 + 384 + 1 + 1 + + + + + + + + 1 + 384 + 8 + 8 + + + 1 + 384 + 1 + 1 + + + + + 1 + 384 + 8 + 8 + + + + + + + 1 + 384 + 8 + 8 + + + + + 1 + 384 + 8 + 8 + + + + + + + + 1 + 384 + 8 + 8 + + + 1 + 384 + 8 + 8 + + + + + 1 + 768 + 8 + 8 + + + + + + + + 448 + 2048 + 1 + 1 + + + + + + + + 1 + 2048 + 8 + 8 + + + 448 + 2048 + 1 + 1 + + + + + 1 + 448 + 8 + 8 + + + + + + + + 1 + 448 + 1 + 1 + + + + + + + + 1 + 448 + 8 + 8 + + + 1 + 448 + 1 + 1 + + + + + 1 + 448 + 8 + 8 + + + + + + + 1 + 448 + 8 + 8 + + + + + 1 + 448 + 8 + 8 + + + + + + + + 384 + 448 + 3 + 3 + + + + + + + + 1 + 448 + 8 + 8 + + + 384 + 448 + 3 + 3 + + + + + 1 + 384 + 8 + 8 + + + + + + + + 1 + 384 + 1 + 1 + + + + + + + + 1 + 384 + 8 + 8 + + + 1 + 384 + 1 + 1 + + + + + 1 + 384 + 8 + 8 + + + + + + + 1 + 384 + 8 + 8 + + + + + 1 + 384 + 8 + 8 + + + + + + + + 384 + 384 + 1 + 3 + + + + + + + + 1 + 384 + 8 + 8 + + + 384 + 384 + 1 + 3 + + + + + 1 + 384 + 8 + 8 + + + + + + + + 1 + 384 + 1 + 1 + + + + + + + + 1 + 384 + 8 + 8 + + + 1 + 384 + 1 + 1 + + + + + 1 + 384 + 8 + 8 + + + + + + + 1 + 384 + 8 + 8 + + + + + 1 + 384 + 8 + 8 + + + + + + + + 384 + 384 + 3 + 1 + + + + + + + + 1 + 384 + 8 + 8 + + + 384 + 384 + 3 + 1 + + + + + 1 + 384 + 8 + 8 + + + + + + + + 1 + 384 + 1 + 1 + + + + + + + + 1 + 384 + 8 + 8 + + + 1 + 384 + 1 + 1 + + + + + 1 + 384 + 8 + 8 + + + + + + + 1 + 384 + 8 + 8 + + + + + 1 + 384 + 8 + 8 + + + + + + + + 1 + 384 + 8 + 8 + + + 1 + 384 + 8 + 8 + + + + + 1 + 768 + 8 + 8 + + + + + + + + 1 + 2048 + 8 + 8 + + + + + 1 + 2048 + 8 + 8 + + + + + + + + 192 + 2048 + 1 + 1 + + + + + + + + 1 + 2048 + 8 + 8 + + + 192 + 2048 + 1 + 1 + + + + + 1 + 192 + 8 + 8 + + + + + + + + 1 + 192 + 1 + 1 + + + + + + + + 1 + 192 + 8 + 8 + + + 1 + 192 + 1 + 1 + + + + + 1 + 192 + 8 + 8 + + + + + + + 1 + 192 + 8 + 8 + + + + + 1 + 192 + 8 + 8 + + + + + + + + 1 + 320 + 8 + 8 + + + 1 + 768 + 8 + 8 + + + 1 + 768 + 8 + 8 + + + 1 + 192 + 8 + 8 + + + + + 1 + 2048 + 8 + 8 + + + + + + + + 1 + 2048 + 8 + 8 + + + + + 1 + 2048 + 1 + 1 + + + + + + + + 1001 + 2048 + 1 + 1 + + + + + + + + 1 + 2048 + 1 + 1 + + + 1001 + 2048 + 1 + 1 + + + + + 1 + 1001 + 1 + 1 + + + + + + + + 1 + 1001 + 1 + 1 + + + + + + + + 1 + 1001 + 1 + 1 + + + 1 + 1001 + 1 + 1 + + + + + 1 + 1001 + 1 + 1 + + + + + + + + 4 + + + + + + + 1 + 1001 + 1 + 1 + + + 4 + + + + + 1 + 1 + 1 + 1001 + + + + + + + + 2 + + + + + + + 1 + 1 + 1 + 1001 + + + 2 + + + + + 1 + 1001 + + + + + + + + 2 + + + + + + + + 1 + 1001 + + + 2 + + + + + 1 + 1001 + + + + + + + + 1 + 1001 + + + + + 1 + 1001 + + + + + + + 1 + 1001 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/crates/openvino/tests/fixtures/inception/mod.rs b/crates/openvino/tests/fixtures/inception/mod.rs index e31b8bf..0e07edc 100644 --- a/crates/openvino/tests/fixtures/inception/mod.rs +++ b/crates/openvino/tests/fixtures/inception/mod.rs @@ -11,12 +11,12 @@ impl Fixture { .unwrap() } pub fn graph() -> PathBuf { - Fixture::dir().join("inception-ssd.xml") + Fixture::dir().join("inception.xml") } pub fn weights() -> PathBuf { - Fixture::dir().join("inception-ssd.bin") + Fixture::dir().join("inception.bin") } pub fn tensor() -> PathBuf { - Fixture::dir().join("tensor-1x3x640x481-u8.bgr") + Fixture::dir().join("tensor-1x3x299x299-fp32.bgr") } } diff --git a/crates/openvino/tests/fixtures/inception/tensor-1x3x299x299-fp32.bgr b/crates/openvino/tests/fixtures/inception/tensor-1x3x299x299-fp32.bgr new file mode 100644 index 0000000..6e47ad0 Binary files /dev/null and b/crates/openvino/tests/fixtures/inception/tensor-1x3x299x299-fp32.bgr differ diff --git a/crates/openvino/tests/fixtures/inception_ssd/README.md b/crates/openvino/tests/fixtures/inception_ssd/README.md new file mode 100644 index 0000000..47bf2e2 --- /dev/null +++ b/crates/openvino/tests/fixtures/inception_ssd/README.md @@ -0,0 +1,10 @@ +# Inception SSD Test Fixture + +In order to test the use of `openvino-rs` in the real world, here we include the necessary files for +performing single-shot detection (SSD) in [detect-inception.rs](../detect-inception.rs). The +artifacts are included in-tree and can be rebuilt using the [build.sh] script (with the right system +dependencies). The artifacts include: + - the Inception SSD inference model, converted to OpenVINO IR format (`*.bin`, `*.mapping`, `*.xml`) + - an image from the COCO dataset transformed into the correct tensor format (`tensor-*.bgr`) + +The [mod.sh] `Fixture` provides the correct artifact paths in Rust. diff --git a/crates/openvino/tests/fixtures/inception_ssd/build.sh b/crates/openvino/tests/fixtures/inception_ssd/build.sh new file mode 100755 index 0000000..fd0bb73 --- /dev/null +++ b/crates/openvino/tests/fixtures/inception_ssd/build.sh @@ -0,0 +1,38 @@ +#!/bin/bash + +# The following script rebuilds the test fixture committed in this directory. It relies on external tools that not all +# systems will have readily available and as such it should be used mainly as an example script. The artifacts created +# are checked in to save future users the setup time. +set -e +TMP_DIR=${1:-$(mktemp -d -t ci-XXXXXXXXXX)} +FIXTURE_DIR=$(dirname "$0" | xargs realpath) +OPENVINO_DIR=${OPENVINO_DIR:-$(realpath $FIXTURE_DIR/../../../../../../openvino)} +PYTHON=${PYTHON:-python3} +pushd $TMP_DIR + +# Retrieve the Inception model from the TensorFlow +wget --no-clobber http://download.tensorflow.org/models/object_detection/ssd_inception_v2_coco_2018_01_28.tar.gz +tar xzvf ssd_*.tar.gz +ln -sf ssd_inception_v2_coco_2018_01_28 model + +# Convert the model to OpenVINO IR using the model-optimizer. +pip install --user -r $OPENVINO_DIR/model-optimizer/requirements_tf.txt +$PYTHON $OPENVINO_DIR/model-optimizer/mo_tf.py \ + --input_model model/frozen_inference_graph.pb \ + --transformations_config $OPENVINO_DIR/model-optimizer/extensions/front/tf/ssd_v2_support.json \ + --tensorflow_object_detection_api_pipeline_config model/pipeline.config +cp $TMP_DIR/frozen_inference_graph.bin $FIXTURE_DIR/inception-ssd.bin +cp $TMP_DIR/frozen_inference_graph.mapping $FIXTURE_DIR/inception-ssd.mapping +cp $TMP_DIR/frozen_inference_graph.xml $FIXTURE_DIR/inception-ssd.xml + +# Retrieve the first 10 images of the COCO dataset. +wget --no-clobber http://images.cocodataset.org/zips/val2017.zip +rm -rf val2017 +unzip -Z1 val2017.zip | head -n 10 | xargs unzip val2017.zip +popd + +# Convert an image to raw tensor format +cargo run -p openvino-tensor-converter -- $TMP_DIR/val2017/000000062808.jpg $FIXTURE_DIR/tensor-1x3x640x481-u8.bgr 481x640x3xu8 + +# Clean up. +rm -rf $TMP_DIR diff --git a/crates/openvino/tests/fixtures/inception/inception-ssd.bin b/crates/openvino/tests/fixtures/inception_ssd/inception-ssd.bin similarity index 100% rename from crates/openvino/tests/fixtures/inception/inception-ssd.bin rename to crates/openvino/tests/fixtures/inception_ssd/inception-ssd.bin diff --git a/crates/openvino/tests/fixtures/inception/inception-ssd.mapping b/crates/openvino/tests/fixtures/inception_ssd/inception-ssd.mapping similarity index 100% rename from crates/openvino/tests/fixtures/inception/inception-ssd.mapping rename to crates/openvino/tests/fixtures/inception_ssd/inception-ssd.mapping diff --git a/crates/openvino/tests/fixtures/inception/inception-ssd.xml b/crates/openvino/tests/fixtures/inception_ssd/inception-ssd.xml similarity index 100% rename from crates/openvino/tests/fixtures/inception/inception-ssd.xml rename to crates/openvino/tests/fixtures/inception_ssd/inception-ssd.xml diff --git a/crates/openvino/tests/fixtures/inception_ssd/mod.rs b/crates/openvino/tests/fixtures/inception_ssd/mod.rs new file mode 100644 index 0000000..e940cbc --- /dev/null +++ b/crates/openvino/tests/fixtures/inception_ssd/mod.rs @@ -0,0 +1,22 @@ +use std::path::PathBuf; + +/// This structure encodes the paths necessary for running the SSD test. +pub struct Fixture; +#[allow(dead_code)] +impl Fixture { + fn dir() -> PathBuf { + PathBuf::from(env!("CARGO_MANIFEST_DIR")) + .join("tests/fixtures/inception_ssd") + .canonicalize() + .unwrap() + } + pub fn graph() -> PathBuf { + Fixture::dir().join("inception-ssd.xml") + } + pub fn weights() -> PathBuf { + Fixture::dir().join("inception-ssd.bin") + } + pub fn tensor() -> PathBuf { + Fixture::dir().join("tensor-1x3x640x481-u8.bgr") + } +} diff --git a/crates/openvino/tests/fixtures/inception/tensor-1x3x640x481-u8.bgr b/crates/openvino/tests/fixtures/inception_ssd/tensor-1x3x640x481-u8.bgr similarity index 100% rename from crates/openvino/tests/fixtures/inception/tensor-1x3x640x481-u8.bgr rename to crates/openvino/tests/fixtures/inception_ssd/tensor-1x3x640x481-u8.bgr diff --git a/crates/openvino/tests/fixtures/mod.rs b/crates/openvino/tests/fixtures/mod.rs index 250fb4a..48687c2 100644 --- a/crates/openvino/tests/fixtures/mod.rs +++ b/crates/openvino/tests/fixtures/mod.rs @@ -1,3 +1,4 @@ pub mod alexnet; pub mod inception; +pub mod inception_ssd; pub mod mobilenet;