rknncli 0.2.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- rknncli-0.2.0/PKG-INFO +69 -0
- rknncli-0.2.0/README.md +51 -0
- rknncli-0.2.0/pyproject.toml +47 -0
- rknncli-0.2.0/rknncli/__init__.py +3 -0
- rknncli-0.2.0/rknncli/cli.py +229 -0
- rknncli-0.2.0/rknncli/parser.py +320 -0
- rknncli-0.2.0/rknncli/schema/rknn/Graph.py +371 -0
- rknncli-0.2.0/rknncli/schema/rknn/Model.py +422 -0
- rknncli-0.2.0/rknncli/schema/rknn/Node.py +380 -0
- rknncli-0.2.0/rknncli/schema/rknn/Tensor.py +697 -0
- rknncli-0.2.0/rknncli/schema/rknn/Type1.py +94 -0
- rknncli-0.2.0/rknncli/schema/rknn/Type2.py +255 -0
- rknncli-0.2.0/rknncli/schema/rknn/Type3.py +94 -0
- rknncli-0.2.0/rknncli/schema/rknn/__init__.py +0 -0
- rknncli-0.2.0/rknncli.egg-info/PKG-INFO +69 -0
- rknncli-0.2.0/rknncli.egg-info/SOURCES.txt +18 -0
- rknncli-0.2.0/rknncli.egg-info/dependency_links.txt +1 -0
- rknncli-0.2.0/rknncli.egg-info/entry_points.txt +2 -0
- rknncli-0.2.0/rknncli.egg-info/top_level.txt +1 -0
- rknncli-0.2.0/setup.cfg +4 -0
rknncli-0.2.0/PKG-INFO
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: rknncli
|
|
3
|
+
Version: 0.2.0
|
|
4
|
+
Summary: A command line tool for parsing and displaying RKNN model information
|
|
5
|
+
Author: rknncli
|
|
6
|
+
License: MIT
|
|
7
|
+
Classifier: Development Status :: 3 - Alpha
|
|
8
|
+
Classifier: Intended Audience :: Developers
|
|
9
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
10
|
+
Classifier: Programming Language :: Python :: 3
|
|
11
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
16
|
+
Requires-Python: >=3.8
|
|
17
|
+
Description-Content-Type: text/markdown
|
|
18
|
+
|
|
19
|
+
# RKNN CLI
|
|
20
|
+
|
|
21
|
+
A command line tool for parsing and displaying RKNN model information.
|
|
22
|
+
|
|
23
|
+
## Installation
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
pip install -e .
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## Usage
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
rknncli <path-to-rknn-model>
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Example:
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
rknncli assets/yolov5s-640-640.rknn
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## Output Format
|
|
42
|
+
|
|
43
|
+
The tool prints model information in the following format:
|
|
44
|
+
|
|
45
|
+
```
|
|
46
|
+
Model: rknn model
|
|
47
|
+
Version: 1.6.2-source_code
|
|
48
|
+
Target Platform: rk3588
|
|
49
|
+
|
|
50
|
+
Input information
|
|
51
|
+
--------------------------------------------------------------------------------
|
|
52
|
+
ValueInfo "images": type INT8, shape ['batch', 3, 'height', 'width'],
|
|
53
|
+
|
|
54
|
+
Output information
|
|
55
|
+
--------------------------------------------------------------------------------
|
|
56
|
+
ValueInfo "output0": type INT8, shape ['batch', 255, 80, 80],
|
|
57
|
+
ValueInfo "286": type INT8, shape ['batch', 255, 40, 40],
|
|
58
|
+
ValueInfo "288": type INT8, shape ['batch', 255, 20, 20'],
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## Development
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
# Install in development mode
|
|
65
|
+
pip install -e .
|
|
66
|
+
|
|
67
|
+
# Run the CLI
|
|
68
|
+
python -m rknncli.cli assets/yolov5s-640-640.rknn
|
|
69
|
+
```
|
rknncli-0.2.0/README.md
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# RKNN CLI
|
|
2
|
+
|
|
3
|
+
A command line tool for parsing and displaying RKNN model information.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pip install -e .
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Usage
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
rknncli <path-to-rknn-model>
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
Example:
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
rknncli assets/yolov5s-640-640.rknn
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Output Format
|
|
24
|
+
|
|
25
|
+
The tool prints model information in the following format:
|
|
26
|
+
|
|
27
|
+
```
|
|
28
|
+
Model: rknn model
|
|
29
|
+
Version: 1.6.2-source_code
|
|
30
|
+
Target Platform: rk3588
|
|
31
|
+
|
|
32
|
+
Input information
|
|
33
|
+
--------------------------------------------------------------------------------
|
|
34
|
+
ValueInfo "images": type INT8, shape ['batch', 3, 'height', 'width'],
|
|
35
|
+
|
|
36
|
+
Output information
|
|
37
|
+
--------------------------------------------------------------------------------
|
|
38
|
+
ValueInfo "output0": type INT8, shape ['batch', 255, 80, 80],
|
|
39
|
+
ValueInfo "286": type INT8, shape ['batch', 255, 40, 40],
|
|
40
|
+
ValueInfo "288": type INT8, shape ['batch', 255, 20, 20'],
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## Development
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
# Install in development mode
|
|
47
|
+
pip install -e .
|
|
48
|
+
|
|
49
|
+
# Run the CLI
|
|
50
|
+
python -m rknncli.cli assets/yolov5s-640-640.rknn
|
|
51
|
+
```
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "rknncli"
|
|
3
|
+
version = "0.2.0"
|
|
4
|
+
description = "A command line tool for parsing and displaying RKNN model information"
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
requires-python = ">=3.8"
|
|
7
|
+
license = {text = "MIT"}
|
|
8
|
+
authors = [
|
|
9
|
+
{name = "rknncli"},
|
|
10
|
+
]
|
|
11
|
+
classifiers = [
|
|
12
|
+
"Development Status :: 3 - Alpha",
|
|
13
|
+
"Intended Audience :: Developers",
|
|
14
|
+
"License :: OSI Approved :: MIT License",
|
|
15
|
+
"Programming Language :: Python :: 3",
|
|
16
|
+
"Programming Language :: Python :: 3.8",
|
|
17
|
+
"Programming Language :: Python :: 3.9",
|
|
18
|
+
"Programming Language :: Python :: 3.10",
|
|
19
|
+
"Programming Language :: Python :: 3.11",
|
|
20
|
+
"Programming Language :: Python :: 3.12",
|
|
21
|
+
]
|
|
22
|
+
|
|
23
|
+
[project.scripts]
|
|
24
|
+
rknncli = "rknncli.cli:main"
|
|
25
|
+
|
|
26
|
+
[build-system]
|
|
27
|
+
requires = ["setuptools>=45", "wheel"]
|
|
28
|
+
build-backend = "setuptools.build_meta"
|
|
29
|
+
|
|
30
|
+
[tool.setuptools.packages.find]
|
|
31
|
+
where = ["."]
|
|
32
|
+
include = ["rknncli*"]
|
|
33
|
+
|
|
34
|
+
[tool.black]
|
|
35
|
+
line-length = 100
|
|
36
|
+
target-version = ['py38']
|
|
37
|
+
|
|
38
|
+
[tool.ruff]
|
|
39
|
+
line-length = 100
|
|
40
|
+
select = ["E", "F", "I", "N", "W"]
|
|
41
|
+
ignore = ["E501"]
|
|
42
|
+
|
|
43
|
+
[tool.mypy]
|
|
44
|
+
python_version = "3.8"
|
|
45
|
+
warn_return_any = true
|
|
46
|
+
warn_unused_configs = true
|
|
47
|
+
disallow_untyped_defs = true
|
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
"""RKNN CLI - Command line interface for parsing RKNN models."""
|
|
2
|
+
|
|
3
|
+
import argparse
|
|
4
|
+
import sys
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
from typing import List, Dict, Any
|
|
7
|
+
|
|
8
|
+
from rknncli.parser import RKNNParser
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def format_shape(size: List) -> List:
|
|
12
|
+
"""Format tensor shape with dimension names.
|
|
13
|
+
|
|
14
|
+
Args:
|
|
15
|
+
size: List of dimension sizes.
|
|
16
|
+
|
|
17
|
+
Returns:
|
|
18
|
+
List of dimension names (strings) or dimension values.
|
|
19
|
+
"""
|
|
20
|
+
return size
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def get_dtype_str(dtype_info: Dict) -> str:
|
|
24
|
+
"""Get data type string from dtype info.
|
|
25
|
+
|
|
26
|
+
Args:
|
|
27
|
+
dtype_info: Dictionary containing dtype information.
|
|
28
|
+
|
|
29
|
+
Returns:
|
|
30
|
+
String representation of the data type.
|
|
31
|
+
"""
|
|
32
|
+
if isinstance(dtype_info, dict):
|
|
33
|
+
# Try vx_type first, then qnt_type
|
|
34
|
+
vx_type = dtype_info.get("vx_type", "").strip()
|
|
35
|
+
if vx_type:
|
|
36
|
+
return vx_type.upper()
|
|
37
|
+
qnt_type = dtype_info.get("qnt_type", "").strip()
|
|
38
|
+
if qnt_type:
|
|
39
|
+
return qnt_type.upper()
|
|
40
|
+
return "FLOAT"
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def print_merged_model_info(parser: RKNNParser) -> None:
|
|
46
|
+
"""Print merged model information from both FlatBuffers and JSON.
|
|
47
|
+
|
|
48
|
+
Args:
|
|
49
|
+
parser: RKNNParser instance with FlatBuffers support.
|
|
50
|
+
"""
|
|
51
|
+
# Get basic model info from JSON
|
|
52
|
+
print(f"Model: {parser.get_model_name()}")
|
|
53
|
+
platforms = parser.get_target_platform()
|
|
54
|
+
if platforms:
|
|
55
|
+
print(f"Target Platform: {', '.join(platforms)}")
|
|
56
|
+
|
|
57
|
+
# Get FlatBuffers info
|
|
58
|
+
fb_info = parser.get_flatbuffers_info()
|
|
59
|
+
if fb_info:
|
|
60
|
+
print(f"Format: {fb_info.get('format', 'Unknown')}")
|
|
61
|
+
print(f"Source: {fb_info.get('source', 'Unknown')}")
|
|
62
|
+
print(f"Compiler: {fb_info.get('compiler', 'Unknown')}")
|
|
63
|
+
print(f"Runtime: {fb_info.get('runtime', 'Unknown')}")
|
|
64
|
+
|
|
65
|
+
if fb_info.get("num_graphs", 0) > 0:
|
|
66
|
+
print(f"Number of graphs: {fb_info['num_graphs']}")
|
|
67
|
+
|
|
68
|
+
print()
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def print_merged_io_info(parser: RKNNParser) -> None:
|
|
72
|
+
"""Print merged input/output information from both FlatBuffers and JSON.
|
|
73
|
+
|
|
74
|
+
Args:
|
|
75
|
+
parser: RKNNParser instance with FlatBuffers support.
|
|
76
|
+
"""
|
|
77
|
+
# Get merged IO info
|
|
78
|
+
inputs, outputs = parser.get_merged_io_info()
|
|
79
|
+
|
|
80
|
+
# Print input information
|
|
81
|
+
print("Input information")
|
|
82
|
+
print("-" * 80)
|
|
83
|
+
|
|
84
|
+
for tensor in inputs:
|
|
85
|
+
name = tensor.get("url", f"tensor_{tensor.get('tensor_id', 0)}")
|
|
86
|
+
dtype = tensor.get("dtype", {})
|
|
87
|
+
|
|
88
|
+
# Get dtype string
|
|
89
|
+
if isinstance(dtype, dict):
|
|
90
|
+
dtype_str = get_dtype_str(dtype)
|
|
91
|
+
else:
|
|
92
|
+
dtype_str = str(dtype).upper()
|
|
93
|
+
|
|
94
|
+
size = tensor.get("size", [])
|
|
95
|
+
shape = format_shape(size)
|
|
96
|
+
shape_str = "[" + ", ".join(f"'{s}'" if isinstance(s, str) else str(s) for s in shape) + "]"
|
|
97
|
+
|
|
98
|
+
# Build the base output string
|
|
99
|
+
output_parts = [f' ValueInfo "{name}": type {dtype_str}, shape {shape_str}']
|
|
100
|
+
|
|
101
|
+
# Add layout info from FlatBuffers
|
|
102
|
+
if "layout" in tensor and tensor["layout"]:
|
|
103
|
+
layout = tensor["layout"].upper()
|
|
104
|
+
layout_ori = tensor.get("layout_ori", "").upper()
|
|
105
|
+
if layout_ori and layout_ori != layout:
|
|
106
|
+
output_parts.append(f"layout {layout}(ori:{layout_ori})")
|
|
107
|
+
else:
|
|
108
|
+
output_parts.append(f"layout {layout}")
|
|
109
|
+
|
|
110
|
+
# Add quantization info from FlatBuffers
|
|
111
|
+
if "quant_info" in tensor:
|
|
112
|
+
quant = tensor["quant_info"]
|
|
113
|
+
if quant.get("qmethod") or quant.get("qtype"):
|
|
114
|
+
output_parts.append(f"quant {quant['qmethod']} {quant['qtype']}")
|
|
115
|
+
|
|
116
|
+
# Print the merged info on one line
|
|
117
|
+
print(", ".join(output_parts) + ",")
|
|
118
|
+
|
|
119
|
+
print()
|
|
120
|
+
|
|
121
|
+
# Print output information
|
|
122
|
+
print("Output information")
|
|
123
|
+
print("-" * 80)
|
|
124
|
+
|
|
125
|
+
for tensor in outputs:
|
|
126
|
+
name = tensor.get("url", f"tensor_{tensor.get('tensor_id', 0)}")
|
|
127
|
+
dtype = tensor.get("dtype", {})
|
|
128
|
+
|
|
129
|
+
# Get dtype string
|
|
130
|
+
if isinstance(dtype, dict):
|
|
131
|
+
dtype_str = get_dtype_str(dtype)
|
|
132
|
+
else:
|
|
133
|
+
dtype_str = str(dtype).upper()
|
|
134
|
+
|
|
135
|
+
size = tensor.get("size", [])
|
|
136
|
+
shape = format_shape(size)
|
|
137
|
+
shape_str = "[" + ", ".join(f"'{s}'" if isinstance(s, str) else str(s) for s in shape) + "]"
|
|
138
|
+
|
|
139
|
+
# Build the base output string
|
|
140
|
+
output_parts = [f' ValueInfo "{name}": type {dtype_str}, shape {shape_str}']
|
|
141
|
+
|
|
142
|
+
# Add layout info from FlatBuffers
|
|
143
|
+
if "layout" in tensor and tensor["layout"]:
|
|
144
|
+
layout = tensor["layout"].upper()
|
|
145
|
+
layout_ori = tensor.get("layout_ori", "").upper()
|
|
146
|
+
if layout_ori and layout_ori != layout:
|
|
147
|
+
output_parts.append(f"layout {layout}(ori:{layout_ori})")
|
|
148
|
+
else:
|
|
149
|
+
output_parts.append(f"layout {layout}")
|
|
150
|
+
|
|
151
|
+
# Add quantization info from FlatBuffers
|
|
152
|
+
if "quant_info" in tensor:
|
|
153
|
+
quant = tensor["quant_info"]
|
|
154
|
+
if quant.get("qmethod") or quant.get("qtype"):
|
|
155
|
+
output_parts.append(f"quant {quant['qmethod']} {quant['qtype']}")
|
|
156
|
+
|
|
157
|
+
# Print the merged info on one line
|
|
158
|
+
print(", ".join(output_parts) + ",")
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
def print_model_summary(parser) -> None:
|
|
162
|
+
"""Print model summary information.
|
|
163
|
+
|
|
164
|
+
Args:
|
|
165
|
+
parser: RKNNParser instance.
|
|
166
|
+
"""
|
|
167
|
+
print(f"Model: {parser.get_model_name()}")
|
|
168
|
+
print(f"Version: {parser.get_version()}")
|
|
169
|
+
platforms = parser.get_target_platform()
|
|
170
|
+
if platforms:
|
|
171
|
+
print(f"Target Platform: {', '.join(platforms)}")
|
|
172
|
+
print()
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
def main() -> int:
|
|
178
|
+
"""Main entry point.
|
|
179
|
+
|
|
180
|
+
Returns:
|
|
181
|
+
Exit code (0 for success, non-zero for error).
|
|
182
|
+
"""
|
|
183
|
+
parser = argparse.ArgumentParser(
|
|
184
|
+
prog="rknncli",
|
|
185
|
+
description="A command line tool for parsing and displaying RKNN model information.",
|
|
186
|
+
)
|
|
187
|
+
parser.add_argument(
|
|
188
|
+
"model",
|
|
189
|
+
type=str,
|
|
190
|
+
help="Path to the RKNN model file",
|
|
191
|
+
)
|
|
192
|
+
parser.add_argument(
|
|
193
|
+
"-v", "--version",
|
|
194
|
+
action="version",
|
|
195
|
+
version="%(prog)s 0.1.0",
|
|
196
|
+
)
|
|
197
|
+
|
|
198
|
+
args = parser.parse_args()
|
|
199
|
+
|
|
200
|
+
model_path = Path(args.model)
|
|
201
|
+
if not model_path.exists():
|
|
202
|
+
print(f"Error: File not found: {model_path}", file=sys.stderr)
|
|
203
|
+
return 1
|
|
204
|
+
|
|
205
|
+
if not model_path.is_file():
|
|
206
|
+
print(f"Error: Not a file: {model_path}", file=sys.stderr)
|
|
207
|
+
return 1
|
|
208
|
+
|
|
209
|
+
try:
|
|
210
|
+
# Always parse both FlatBuffers and JSON data
|
|
211
|
+
rknn_parser = RKNNParser(model_path, parse_flatbuffers=True)
|
|
212
|
+
|
|
213
|
+
# Print merged model information
|
|
214
|
+
print_merged_model_info(rknn_parser)
|
|
215
|
+
|
|
216
|
+
# Print merged IO information
|
|
217
|
+
print_merged_io_info(rknn_parser)
|
|
218
|
+
except ValueError as e:
|
|
219
|
+
print(f"Error: Failed to parse RKNN file: {e}", file=sys.stderr)
|
|
220
|
+
return 1
|
|
221
|
+
except Exception as e:
|
|
222
|
+
print(f"Error: {e}", file=sys.stderr)
|
|
223
|
+
return 1
|
|
224
|
+
|
|
225
|
+
return 0
|
|
226
|
+
|
|
227
|
+
|
|
228
|
+
if __name__ == "__main__":
|
|
229
|
+
sys.exit(main())
|