add some new python demos
This commit is contained in:
parent
d631c4d009
commit
c598b3aef4
23 changed files with 2174 additions and 11 deletions
|
|
@ -0,0 +1,106 @@
|
|||
|
||||
## Demo Run
|
||||
|
||||
### CPP
|
||||
|
||||
#### 1. Compile
|
||||
|
||||
**Prerequisites:**
|
||||
- Android NDK (r25e recommended)
|
||||
- `ANDROID_NDK_PATH` environment variable set
|
||||
|
||||
**Build:**
|
||||
```bash
|
||||
# Build for arm64-v8a
|
||||
cd examples/mobilenet/cpp
|
||||
./build-android.sh -a arm64-v8a
|
||||
```
|
||||
|
||||
The executable will be generated at `build/android/mobilenet_v2_demo` (Note: executable name may vary, verify in build folder).
|
||||
|
||||
#### 2. Run
|
||||
|
||||
```bash
|
||||
# Push executable to device
|
||||
adb push build/android/mobilenet_v2_demo /data/local/tmp/
|
||||
adb push model/mobilenet_v2_1.0_224_quant_A311D2.adla /data/local/tmp/
|
||||
adb push model/cat_224x224.jpg /data/local/tmp/
|
||||
adb push model/labels.txt /data/local/tmp/
|
||||
|
||||
# Run on device
|
||||
adb shell
|
||||
cd /data/local/tmp
|
||||
chmod +x mobilenet_v2_demo
|
||||
export LD_LIBRARY_PATH=/vendor/lib64 or (/vendor/lib)
|
||||
|
||||
# Usage: ./mobilenet_v2_demo <model_path> <image_path> <labels_path>
|
||||
./mobilenet_v2_demo mobilenet_v2_1.0_224_quant_A311D2.adla cat_224x224.jpg labels.txt
|
||||
```
|
||||
|
||||
**Note:** Replace `mobilenet_v2_1.0_224_quant_A311D2.adla` with your actual model file path.
|
||||
|
||||
### Python
|
||||
|
||||
**Prerequisites:**
|
||||
- Python 3.10
|
||||
- Required packages: `numpy`, `Pillow`, `amlnnlite`
|
||||
|
||||
**Install dependencies:**
|
||||
```bash
|
||||
pip install numpy Pillow amlnnlite-1.0.0-cp310-cp310-linux_aarch64.whl
|
||||
```
|
||||
|
||||
**Run on device:**
|
||||
```bash
|
||||
# Basic usage
|
||||
python mobilenetv2.py --model-path ./mobilenet_v2_1.0_224_quant_A311D2.adla
|
||||
|
||||
# Run with performance testing (100 cycles)
|
||||
python mobilenetv2.py --model-path ./mobilenet_v2_1.0_224_quant_A311D2.adla --run-cycles 100
|
||||
```
|
||||
|
||||
The script will automatically process all image files (`.jpg`, `.jpeg`, `.png`, `.bmp`) in the current directory and display top-5 classification results for each image.
|
||||
|
||||
## Results
|
||||
|
||||
The program will print the top-5 classification results with probabilities for each processed image.
|
||||
|
||||
**Example output:**
|
||||
```
|
||||
# python demo result
|
||||
============================================================
|
||||
Processing image 1/3: dog_224x224.jpg
|
||||
============================================================
|
||||
|
||||
Top-5 Classification Results:
|
||||
1. Shih-Tzu (probability: 0.9239)
|
||||
2. Pekinese (probability: 0.0476)
|
||||
3. Lhasa (probability: 0.0263)
|
||||
4. Brabancon griffon (probability: 0.0004)
|
||||
5. Dandie Dinmont (probability: 0.0003)
|
||||
|
||||
============================================================
|
||||
Processing image 2/3: cat_224x224.jpg
|
||||
============================================================
|
||||
|
||||
Top-5 Classification Results:
|
||||
1. tiger cat (probability: 0.4774)
|
||||
2. tabby (probability: 0.4324)
|
||||
3. Egyptian cat (probability: 0.0542)
|
||||
4. lynx (probability: 0.0150)
|
||||
5. Persian cat (probability: 0.0025)
|
||||
|
||||
============================================================
|
||||
Processing image 3/3: fish_224x224.jpeg
|
||||
============================================================
|
||||
|
||||
Top-5 Classification Results:
|
||||
1. goldfish (probability: 0.9998)
|
||||
2. conch (probability: 0.0001)
|
||||
3. trifle (probability: 0.0000)
|
||||
4. axolotl (probability: 0.0000)
|
||||
5. American lobster (probability: 0.0000)
|
||||
```
|
||||
|
||||
The classification results show the model's confidence scores (probabilities) for each detected class, with the highest probability indicating the most likely classification.
|
||||
|
||||
BIN
examples/mobilenet/model/cat_224x224.jpg
Executable file
BIN
examples/mobilenet/model/cat_224x224.jpg
Executable file
Binary file not shown.
|
After Width: | Height: | Size: 57 KiB |
BIN
examples/mobilenet/model/dog_224x224.jpg
Executable file
BIN
examples/mobilenet/model/dog_224x224.jpg
Executable file
Binary file not shown.
|
After Width: | Height: | Size: 18 KiB |
BIN
examples/mobilenet/model/fish_224x224.jpeg
Executable file
BIN
examples/mobilenet/model/fish_224x224.jpeg
Executable file
Binary file not shown.
|
After Width: | Height: | Size: 55 KiB |
1001
examples/mobilenet/model/labels.txt
Executable file
1001
examples/mobilenet/model/labels.txt
Executable file
File diff suppressed because it is too large
Load diff
158
examples/mobilenet/py/mobilenetv2.py
Executable file
158
examples/mobilenet/py/mobilenetv2.py
Executable file
|
|
@ -0,0 +1,158 @@
|
|||
import numpy as np
|
||||
import os
|
||||
import glob
|
||||
import argparse
|
||||
import time
|
||||
from PIL import Image
|
||||
from amlnnlite.api import AMLNNLite
|
||||
|
||||
|
||||
def preprocess(image_path: str) -> np.ndarray:
|
||||
"""
|
||||
Preprocess the input image for MobileNetV2 quantized model.
|
||||
|
||||
Steps:
|
||||
1. Load image and convert to RGB
|
||||
2. Resize to 224x224
|
||||
3. Normalize to [-1, 1]
|
||||
4. Quantize to uint8 with zero-point = 128, scale = 0.0078125
|
||||
|
||||
Args:
|
||||
image_path (str): Path to input image
|
||||
|
||||
Returns:
|
||||
np.ndarray: Preprocessed image data with shape (1, 224, 224, 3)
|
||||
"""
|
||||
img = Image.open(image_path).convert("RGB").resize((224, 224))
|
||||
img = np.array(img, dtype=np.float32)
|
||||
|
||||
# Normalize to [-1, 1]
|
||||
img = img / 127.5 - 1.0
|
||||
|
||||
# Expand batch dimension
|
||||
data = np.expand_dims(img, axis=0)
|
||||
|
||||
# Quantization (uint8)
|
||||
data = data / 0.0078125 + 128
|
||||
data = np.clip(data, 0, 255).astype(np.uint8)
|
||||
|
||||
return data
|
||||
|
||||
|
||||
def postprocess_topk(predictions: np.ndarray, labels_path: str, k: int = 5, use_softmax: bool = True) -> None:
|
||||
"""
|
||||
Postprocess model output and print top-K classification results.
|
||||
|
||||
Args:
|
||||
predictions (np.ndarray): Raw model output (logits)
|
||||
labels_path (str): Path to labels.txt
|
||||
k (int): Number of top results to display
|
||||
use_softmax (bool): If True, apply softmax to convert logits to probabilities
|
||||
"""
|
||||
predictions = predictions.reshape(-1).astype(np.float32)
|
||||
|
||||
if use_softmax:
|
||||
exp_predictions = np.exp(predictions - np.max(predictions))
|
||||
probabilities = exp_predictions / np.sum(exp_predictions)
|
||||
scores = probabilities
|
||||
score_label = "probability"
|
||||
else:
|
||||
scores = predictions
|
||||
score_label = "score"
|
||||
|
||||
# Load labels
|
||||
with open(labels_path, "r", encoding="utf-8") as f:
|
||||
labels = [line.strip() for line in f.readlines()]
|
||||
|
||||
# Get top-k indices based on scores
|
||||
top_indices = np.argsort(scores)[::-1][:k]
|
||||
|
||||
print(f"\nTop-{k} Classification Results:")
|
||||
for rank, idx in enumerate(top_indices, start=1):
|
||||
label = labels[idx] if idx < len(labels) else f"Class {idx}"
|
||||
score = scores[idx]
|
||||
if use_softmax:
|
||||
print(f" {rank}. {label:<25} ({score_label}: {score:.4f})")
|
||||
else:
|
||||
print(f" {rank}. {label:<25} ({score_label}: {score:.6f})")
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument('--model-path', default='./mobilenet_v2_1.0_224_quant.tflite')
|
||||
parser.add_argument('--run-cycles', type=int, default=1, help='Number of inference cycles to run (for performance testing)')
|
||||
args = parser.parse_args()
|
||||
|
||||
# Initialize AMLNNLite
|
||||
amlnn = AMLNNLite()
|
||||
amlnn.config(
|
||||
model_path=args.model_path # Model file path, Support ADLD and quantized TFlite models
|
||||
)
|
||||
amlnn.init()
|
||||
|
||||
# Find all image files in the 01_export_model directory
|
||||
image_dir = "./"
|
||||
image_extensions = ["*.jpg", "*.jpeg", "*.png", "*.bmp"]
|
||||
image_files = []
|
||||
for ext in image_extensions:
|
||||
image_files.extend(glob.glob(os.path.join(image_dir, ext)))
|
||||
image_files.extend(glob.glob(os.path.join(image_dir, ext.upper())))
|
||||
|
||||
if not image_files:
|
||||
print("No image files found in", image_dir)
|
||||
amlnn.uninit()
|
||||
return
|
||||
|
||||
print(f"Found {len(image_files)} image files to process:")
|
||||
for img_file in image_files:
|
||||
print(f" - {os.path.basename(img_file)}")
|
||||
print()
|
||||
|
||||
# Process each image
|
||||
for i, image_path in enumerate(image_files, 1):
|
||||
print(f"=" * 60)
|
||||
print(f"Processing image {i}/{len(image_files)}: {os.path.basename(image_path)}")
|
||||
print(f"=" * 60)
|
||||
|
||||
try:
|
||||
# Preprocess input
|
||||
input_data = preprocess(image_path)
|
||||
|
||||
# Run inference for specified cycles
|
||||
inference_times = []
|
||||
outputs = None
|
||||
for cycle in range(args.run_cycles):
|
||||
start_time = time.time()
|
||||
outputs = amlnn.inference(
|
||||
inputs=[input_data]
|
||||
)
|
||||
inference_time = (time.time() - start_time) * 1000 # Convert to milliseconds
|
||||
inference_times.append(inference_time)
|
||||
|
||||
# Print performance statistics if running multiple cycles
|
||||
if args.run_cycles > 1:
|
||||
avg_time = np.mean(inference_times)
|
||||
min_time = np.min(inference_times)
|
||||
max_time = np.max(inference_times)
|
||||
print(f"\nInference Performance ({args.run_cycles} cycles):")
|
||||
print(f" Average: {avg_time:.2f} ms")
|
||||
print(f" Min: {min_time:.2f} ms")
|
||||
print(f" Max: {max_time:.2f} ms")
|
||||
|
||||
# Postprocess results (only show results from last inference)
|
||||
postprocess_topk(outputs[0], "./labels.txt", k=5, use_softmax=True)
|
||||
|
||||
except Exception as e:
|
||||
print(f"Error processing {os.path.basename(image_path)}: {e}")
|
||||
|
||||
print()
|
||||
|
||||
# Optional visualization
|
||||
amlnn.visualize()
|
||||
|
||||
# Release resources
|
||||
amlnn.uninit()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Loading…
Add table
Add a link
Reference in a new issue