| |
| import argparse |
| import copy |
| import json |
| import sys |
| from pathlib import Path |
|
|
|
|
| FLATBUFFERS_PYTHON = ( |
| Path(__file__).resolve().parents[3] / "vendor" / "flatbuffers" / "python" |
| ) |
| sys.path.insert(0, str(FLATBUFFERS_PYTHON)) |
|
|
| from flatbuffers import flexbuffers |
|
|
|
|
| def base_model(custom_options: list[int], description: str) -> dict: |
| return { |
| "version": 3, |
| "operator_codes": [ |
| { |
| "builtin_code": "CUSTOM", |
| "custom_code": "TFLite_Detection_PostProcess", |
| "version": 1, |
| } |
| ], |
| "subgraphs": [ |
| { |
| "tensors": [ |
| { |
| "shape": [1, 6, 4], |
| "type": "UINT8", |
| "buffer": 0, |
| "name": "box_encodings", |
| "quantization": { |
| "min": [0.0], |
| "max": [255.0], |
| "scale": [1.0], |
| "zero_point": [1], |
| }, |
| }, |
| { |
| "shape": [1, 6, 3], |
| "type": "UINT8", |
| "buffer": 1, |
| "name": "scores", |
| "quantization": { |
| "min": [0.0], |
| "max": [255.0], |
| "scale": [0.01], |
| "zero_point": [0], |
| }, |
| }, |
| { |
| "shape": [6, 4], |
| "type": "UINT8", |
| "buffer": 2, |
| "name": "anchors", |
| "quantization": { |
| "min": [0.0], |
| "max": [255.0], |
| "scale": [0.5], |
| "zero_point": [0], |
| }, |
| }, |
| { |
| "type": "FLOAT32", |
| "buffer": 3, |
| "name": "detection_boxes", |
| "quantization": {}, |
| }, |
| { |
| "type": "FLOAT32", |
| "buffer": 4, |
| "name": "detection_classes", |
| "quantization": {}, |
| }, |
| { |
| "type": "FLOAT32", |
| "buffer": 5, |
| "name": "detection_scores", |
| "quantization": {}, |
| }, |
| { |
| "type": "FLOAT32", |
| "buffer": 6, |
| "name": "num_detections", |
| "quantization": {}, |
| }, |
| ], |
| "inputs": [0, 1, 2], |
| "outputs": [3, 4, 5, 6], |
| "operators": [ |
| { |
| "opcode_index": 0, |
| "inputs": [0, 1, 2], |
| "outputs": [3, 4, 5, 6], |
| "builtin_options_type": "NONE", |
| "custom_options": custom_options, |
| "custom_options_format": "FLEXBUFFERS", |
| } |
| ], |
| "name": "main", |
| } |
| ], |
| "description": description, |
| "buffers": [ |
| {}, |
| {}, |
| { |
| "data": [ |
| 1, |
| 1, |
| 2, |
| 2, |
| 1, |
| 1, |
| 2, |
| 2, |
| 1, |
| 1, |
| 2, |
| 2, |
| 1, |
| 21, |
| 2, |
| 2, |
| 1, |
| 21, |
| 2, |
| 2, |
| 1, |
| 201, |
| 2, |
| 2, |
| ] |
| }, |
| {}, |
| {}, |
| {}, |
| {}, |
| ], |
| } |
|
|
|
|
| def main() -> None: |
| parser = argparse.ArgumentParser() |
| parser.add_argument("--output-dir", type=Path, required=True) |
| args = parser.parse_args() |
|
|
| valid_options = flexbuffers.Dumps( |
| { |
| "use_regular_nms": True, |
| "max_detections": 3, |
| "max_classes_per_detection": 1, |
| "detections_per_class": 1, |
| "num_classes": 2, |
| "nms_score_threshold": 0.0, |
| "nms_iou_threshold": 0.5, |
| "h_scale": 5.0, |
| "w_scale": 5.0, |
| "x_scale": 10.0, |
| "y_scale": 10.0, |
| } |
| ) |
|
|
| control = base_model( |
| list(valid_options), |
| "Arm NN DetectionPostProcess valid FlexBuffer control", |
| ) |
| trigger = copy.deepcopy(control) |
| trigger["description"] = ( |
| "Arm NN DetectionPostProcess one-byte malformed FlexBuffer trigger" |
| ) |
| trigger["subgraphs"][0]["operators"][0]["custom_options"] = [0] |
|
|
| args.output_dir.mkdir(parents=True, exist_ok=True) |
| for name, model in (("control", control), ("trigger", trigger)): |
| path = args.output_dir / f"{name}.json" |
| path.write_text(json.dumps(model, indent=2) + "\n", encoding="utf-8") |
| print(f"{path}: custom_options={len(model['subgraphs'][0]['operators'][0]['custom_options'])}") |
|
|
|
|
| if __name__ == "__main__": |
| main() |
|
|