diff --git a/examples/clip/README.md b/examples/clip/README.md index e69de29..b49050d 100644 --- a/examples/clip/README.md +++ b/examples/clip/README.md @@ -0,0 +1,95 @@ +## Demo Run + +### CPP + +#### 1. Compile + +**Prerequisites:** +- Android NDK (r25e recommended) +- `ANDROID_NDK_PATH` environment variable set + +**Build:** +```bash +# Build for arm64-v8a +cd examples/clip/cpp +./build-android.sh -a arm64-v8a +``` + +The executable will be generated at `build/android_arm64-v8a/clip_demo` (Note: executable name may vary, verify in build folder). + +#### 2. Run + +```bash +# Push executable to device +adb push build/android_arm64-v8a/clip_demo /data/local/tmp/ +adb push model/vision_model_int8_A311D2.adla /data/local/tmp/ +adb push clip_datasets/ /data/local/tmp/ +adb push test_hat_0.jpg /data/local/tmp/ + +# Run on device +adb shell +cd /data/local/tmp +chmod +x clip_demo +export LD_LIBRARY_PATH=/vendor/lib64 or (/vendor/lib) + +# Usage: ./clip_demo [base_dir] [json_filename] +./clip_demo vision_model_int8_A311D2.adla ./clip_datasets/ clip_text_res.json +``` + +**Note:** +- Replace `vision_model_int8_A311D2.adla` with your actual model file path. +- The `base_dir` and `json_filename` parameters are optional. You can also use environment variables `CLIP_BASE_DIR` and `CLIP_JSON_FILENAME`. +- The program will prompt you to enter image paths interactively. Enter "exit" to quit. + +### 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 (process current directory) +python clip.py --model-path ./vision_model_int8_A311D2.adla + +# Specify image directory or file +python clip.py --model-path ./vision_model_int8_A311D2.adla --image-dir ./ + +# Specify base directory and JSON filename +python clip.py --model-path ./vision_model_int8_A311D2.adla --base-dir ./clip_datasets/ --json-filename clip_text_res.json +``` + +The script will automatically process all image files (`.jpg`, `.jpeg`, `.png`, `.bmp`) in the specified directory or process a single image file, and display the best matching dataset for each image. + +5. Results + +The program will print the best matching dataset path for each processed image. The program searches through all dataset folders in the base directory and finds the text feature with the highest similarity to the input image. + +**Example output:** +``` +# python demo result +Model initialized successfully. + +Found 2 image file(s) to process +Searching in base directory: ./clip_datasets/ + +Processing image: test_jacket_0.jpg + Best matching dataset: ./clip_datasets/shirt10_jacket7 +Searching in base directory: ./clip_datasets/ + +Processing image: test_hat_0.jpg + Best matching dataset: ./clip_datasets/hat1_jd + +Total results: 2 +Index[0]: ./clip_datasets/shirt10_jacket7 +Index[1]: ./clip_datasets/hat1_jd + +Done. +``` + +The program returns the dataset folder path that contains the text feature with the highest similarity to the input image. Each result represents the best matching dataset for the corresponding input image. diff --git a/examples/clip/py/clip.py b/examples/clip/py/clip.py new file mode 100755 index 0000000..9373e18 --- /dev/null +++ b/examples/clip/py/clip.py @@ -0,0 +1,304 @@ +import numpy as np +import os +import argparse +import json +import re +from PIL import Image +from amlnnlite.api import AMLNNLite + + +def preprocess_image(image_path: str, target_size: int = 224) -> np.ndarray: + """ + Preprocess image for CLIP model. + + Steps: + 1. Load image and convert to RGB + 2. Scale the shorter side to target_size + 3. Center crop to target_size x target_size + 4. Normalize with CLIP mean and std + + Args: + image_path (str): Path to input image + target_size (int): Target image size (default: 224) + + Returns: + np.ndarray: Preprocessed image data with shape (target_size, target_size, 3) + """ + # Load image + img = Image.open(image_path).convert("RGB") + width, height = img.size + + # Scale the shorter side + scale = target_size / min(width, height) + new_w = int(round(width * scale)) + new_h = int(round(height * scale)) + + # Resize + img = img.resize((new_w, new_h), Image.BILINEAR) + + # Center crop + left = (new_w - target_size) // 2 + top = (new_h - target_size) // 2 + img = img.crop((left, top, left + target_size, top + target_size)) + + # Convert to numpy array and normalize to [0, 1] + img_array = np.array(img, dtype=np.float32) / 255.0 + + # CLIP normalization + mean = np.array([0.48145466, 0.4578275, 0.40821073], dtype=np.float32) + std = np.array([0.26862954, 0.26130258, 0.27577711], dtype=np.float32) + + # Normalize: (x - mean) / std + img_array = (img_array - mean) / std + + # Return in NHWC format + return img_array + + +def post_process( + image_features: np.ndarray, + text_features: np.ndarray, + scale: float = 100.00000762939453, + use_cosine: bool = True, + apply_scale: bool = True, +) -> float: + """ + Calculate similarity between image and text features. + + Args: + image_features (np.ndarray): Image feature vector + text_features (np.ndarray): Text feature vector + scale (float): Scale factor for similarity calculation + use_cosine (bool): If True, L2-normalize both vectors before dot product (cosine similarity) + apply_scale (bool): If True, multiply by scale after dot product + + Returns: + float: Similarity score + """ + img_vec = image_features.flatten().astype(np.float32) + txt_vec = np.array(text_features, dtype=np.float32).flatten() + + if len(img_vec) != len(txt_vec): + raise ValueError(f"Feature dimension mismatch: image={len(img_vec)}, text={len(txt_vec)}") + + if use_cosine: + img_norm = np.linalg.norm(img_vec) + 1e-8 + txt_norm = np.linalg.norm(txt_vec) + 1e-8 + img_vec = img_vec / img_norm + txt_vec = txt_vec / txt_norm + + dot_product = np.dot(img_vec, txt_vec) + + similarity = dot_product * scale if apply_scale else dot_product + + return float(similarity) + + +def extract_index(filename: str) -> int: + """ + Extract index from filename pattern: test_xxx_index.jpg + + Args: + filename (str): Filename to extract index from + + Returns: + int: Extracted index, or -1 if pattern doesn't match + """ + pattern = r"test_\w+_(\d+)\.jpg" + match = re.match(pattern, filename) + if match: + return int(match.group(1)) + return -1 + + +def process_image_dir( + amlnn: AMLNNLite, + image_dir_path: str, + base_dir: str = "", + json_filename: str = "" +) -> list: + """ + Process image directory and find best matching text dataset. + + Args: + amlnn: AMLNNLite instance + image_dir_path (str): Path to directory containing test images + base_dir (str): Base directory for clip datasets (optional, can use CLIP_BASE_DIR env var) + json_filename (str): JSON filename in each dataset folder (optional, can use CLIP_JSON_FILENAME env var) + + Returns: + list: List of best matching dataset paths + """ + results = [] + file_pattern = re.compile(r"test_(\w+)_\d+\.jpg") + image_extensions = {'.jpg', '.jpeg', '.png', '.bmp', '.JPG', '.JPEG', '.PNG', '.BMP'} + + if not base_dir: + base_dir = os.getenv("CLIP_BASE_DIR", "./clip_datasets/") + + if not json_filename: + json_filename = os.getenv("CLIP_JSON_FILENAME", "clip_text_res.json") + + matched_files = [] + if os.path.isdir(image_dir_path): + for filename in os.listdir(image_dir_path): + filepath = os.path.join(image_dir_path, filename) + if os.path.isfile(filepath): + if file_pattern.match(filename): + matched_files.append((filename, filepath, True)) + elif any(filename.lower().endswith(ext) for ext in image_extensions): + matched_files.append((filename, filepath, False)) + elif os.path.isfile(image_dir_path): + filename = os.path.basename(image_dir_path) + if any(filename.lower().endswith(ext) for ext in image_extensions): + has_pattern = bool(file_pattern.match(filename)) + matched_files.append((filename, image_dir_path, has_pattern)) + else: + print(f"Error: {image_dir_path} is not a valid image file") + return results + else: + print(f"Error: {image_dir_path} is not a valid directory or file") + return results + + if not matched_files: + print(f"Warning: No image files found in {image_dir_path}") + return results + + print(f"Found {len(matched_files)} image file(s) to process") + + matched_files.sort(key=lambda x: extract_index(x[0]) if x[2] else 999999) + + # Process each image + for filename, filepath, has_pattern in matched_files: + if has_pattern: + match = file_pattern.match(filename) + if match: + name = match.group(1) + else: + name = "" + else: + name = "" + + # Preprocess image + try: + input_data = preprocess_image(filepath) + input_data = np.expand_dims(input_data, axis=0) + except Exception as e: + print(f"Error preprocessing image {filename}: {e}") + continue + + # Run inference + try: + outputs = amlnn.inference(inputs=[input_data]) + model_output = outputs[0] + if isinstance(model_output, np.ndarray): + model_output = model_output.astype(np.float32) + else: + model_output = np.array(model_output, dtype=np.float32) + model_output = model_output.flatten() + except Exception as e: + print(f"Error running inference on {filename}: {e}") + continue + + max_sim = float('-inf') + best_key = "" + best_id = "" + + if not os.path.isdir(base_dir): + print(f"Error: Base directory does not exist: {base_dir}") + continue + + print(f"Searching in base directory: {base_dir}") + folder_count = 0 + for folder_name in os.listdir(base_dir): + folder_path = os.path.join(base_dir, folder_name) + if not os.path.isdir(folder_path): + continue + + if has_pattern and name and name not in folder_name: + continue + + folder_count += 1 + + vit_res_path = os.path.join(folder_path, json_filename) + if not os.path.isfile(vit_res_path): + print(f"Warning: JSON file not found: {vit_res_path}") + continue + + try: + with open(vit_res_path, 'r', encoding='utf-8') as f: + vit_json = json.load(f) + + for key, text_vec in vit_json.items(): + if isinstance(text_vec, list): + text_features = np.array(text_vec, dtype=np.float32) + sim_scaled = post_process( + model_output, + text_features, + use_cosine=True, + apply_scale=True, + ) + + if sim_scaled > max_sim: + max_sim = sim_scaled + best_key = key + best_id = folder_name + except Exception as e: + print(f"Error loading JSON file {vit_res_path}: {e}") + continue + + if best_key and best_id: + best_path = os.path.join(base_dir, best_id) + results.append(best_path) + print(f"\nProcessing image: {filename}") + print(f" Best matching dataset: {best_path}") + else: + print(f"\nProcessing image: {filename}") + print(f" No matching dataset found (searched {folder_count} folder(s))") + + return results + + +def main(): + parser = argparse.ArgumentParser(description='CLIP Image-Text Matching Demo') + parser.add_argument('--model-path', required=True, help='Path to the CLIP model file') + parser.add_argument('--base-dir', default='./clip_datasets/', help='Base directory for clip datasets (can also use CLIP_BASE_DIR env var)') + parser.add_argument('--json-filename', default='clip_text_res.json', help='JSON filename in each dataset folder (can also use CLIP_JSON_FILENAME env var, default: clip_text_res.json)') + parser.add_argument('--image-dir', default='./', help='Image directory or single image file to process (optional, will prompt if not provided)') + args = parser.parse_args() + + # Initialize AMLNNLite + print("Initializing model...") + amlnn = AMLNNLite() + amlnn.config(model_path=args.model_path) + amlnn.init() + print("Model initialized successfully.\n") + + # Process images + if args.image_dir: + results = process_image_dir(amlnn, args.image_dir, args.base_dir, args.json_filename) + print(f"\nTotal results: {len(results)}") + for i, result in enumerate(results): + print(f"Index[{i}]: {result}") + else: + while True: + image_path = input("\nPlease enter the JPG image path or directory (enter 'exit' to quit):\n").strip() + + if image_path.lower() == 'exit': + break + + if not image_path: + print("The path cannot be empty.") + continue + + results = process_image_dir(amlnn, image_path, args.base_dir, args.json_filename) + + for i, result in enumerate(results): + print(f"Index[{i}]: {result}") + + amlnn.uninit() + print("\nDone.") + + +if __name__ == "__main__": + main() diff --git a/examples/mobilenet/README.md b/examples/mobilenet/README.md index e69de29..5af7226 100644 --- a/examples/mobilenet/README.md +++ b/examples/mobilenet/README.md @@ -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 +./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. + diff --git a/examples/mobilenet/model/cat_224x224.jpg b/examples/mobilenet/model/cat_224x224.jpg new file mode 100755 index 0000000..11c5ba4 Binary files /dev/null and b/examples/mobilenet/model/cat_224x224.jpg differ diff --git a/examples/mobilenet/model/dog_224x224.jpg b/examples/mobilenet/model/dog_224x224.jpg new file mode 100755 index 0000000..4f46457 Binary files /dev/null and b/examples/mobilenet/model/dog_224x224.jpg differ diff --git a/examples/mobilenet/model/fish_224x224.jpeg b/examples/mobilenet/model/fish_224x224.jpeg new file mode 100755 index 0000000..4b6f038 Binary files /dev/null and b/examples/mobilenet/model/fish_224x224.jpeg differ diff --git a/examples/mobilenet/model/labels.txt b/examples/mobilenet/model/labels.txt new file mode 100755 index 0000000..fe81123 --- /dev/null +++ b/examples/mobilenet/model/labels.txt @@ -0,0 +1,1001 @@ +background +tench +goldfish +great white shark +tiger shark +hammerhead +electric ray +stingray +cock +hen +ostrich +brambling +goldfinch +house finch +junco +indigo bunting +robin +bulbul +jay +magpie +chickadee +water ouzel +kite +bald eagle +vulture +great grey owl +European fire salamander +common newt +eft +spotted salamander +axolotl +bullfrog +tree frog +tailed frog +loggerhead +leatherback turtle +mud turtle +terrapin +box turtle +banded gecko +common iguana +American chameleon +whiptail +agama +frilled lizard +alligator lizard +Gila monster +green lizard +African chameleon +Komodo dragon +African crocodile +American alligator +triceratops +thunder snake +ringneck snake +hognose snake +green snake +king snake +garter snake +water snake +vine snake +night snake +boa constrictor +rock python +Indian cobra +green mamba +sea snake +horned viper +diamondback +sidewinder +trilobite +harvestman +scorpion +black and gold garden spider +barn spider +garden spider +black widow +tarantula +wolf spider +tick +centipede +black grouse +ptarmigan +ruffed grouse +prairie chicken +peacock +quail +partridge +African grey +macaw +sulphur-crested cockatoo +lorikeet +coucal +bee eater +hornbill +hummingbird +jacamar +toucan +drake +red-breasted merganser +goose +black swan +tusker +echidna +platypus +wallaby +koala +wombat +jellyfish +sea anemone +brain coral +flatworm +nematode +conch +snail +slug +sea slug +chiton +chambered nautilus +Dungeness crab +rock crab +fiddler crab +king crab +American lobster +spiny lobster +crayfish +hermit crab +isopod +white stork +black stork +spoonbill +flamingo +little blue heron +American egret +bittern +crane +limpkin +European gallinule +American coot +bustard +ruddy turnstone +red-backed sandpiper +redshank +dowitcher +oystercatcher +pelican +king penguin +albatross +grey whale +killer whale +dugong +sea lion +Chihuahua +Japanese spaniel +Maltese dog +Pekinese +Shih-Tzu +Blenheim spaniel +papillon +toy terrier +Rhodesian ridgeback +Afghan hound +basset +beagle +bloodhound +bluetick +black-and-tan coonhound +Walker hound +English foxhound +redbone +borzoi +Irish wolfhound +Italian greyhound +whippet +Ibizan hound +Norwegian elkhound +otterhound +Saluki +Scottish deerhound +Weimaraner +Staffordshire bullterrier +American Staffordshire terrier +Bedlington terrier +Border terrier +Kerry blue terrier +Irish terrier +Norfolk terrier +Norwich terrier +Yorkshire terrier +wire-haired fox terrier +Lakeland terrier +Sealyham terrier +Airedale +cairn +Australian terrier +Dandie Dinmont +Boston bull +miniature schnauzer +giant schnauzer +standard schnauzer +Scotch terrier +Tibetan terrier +silky terrier +soft-coated wheaten terrier +West Highland white terrier +Lhasa +flat-coated retriever +curly-coated retriever +golden retriever +Labrador retriever +Chesapeake Bay retriever +German short-haired pointer +vizsla +English setter +Irish setter +Gordon setter +Brittany spaniel +clumber +English springer +Welsh springer spaniel +cocker spaniel +Sussex spaniel +Irish water spaniel +kuvasz +schipperke +groenendael +malinois +briard +kelpie +komondor +Old English sheepdog +Shetland sheepdog +collie +Border collie +Bouvier des Flandres +Rottweiler +German shepherd +Doberman +miniature pinscher +Greater Swiss Mountain dog +Bernese mountain dog +Appenzeller +EntleBucher +boxer +bull mastiff +Tibetan mastiff +French bulldog +Great Dane +Saint Bernard +Eskimo dog +malamute +Siberian husky +dalmatian +affenpinscher +basenji +pug +Leonberg +Newfoundland +Great Pyrenees +Samoyed +Pomeranian +chow +keeshond +Brabancon griffon +Pembroke +Cardigan +toy poodle +miniature poodle +standard poodle +Mexican hairless +timber wolf +white wolf +red wolf +coyote +dingo +dhole +African hunting dog +hyena +red fox +kit fox +Arctic fox +grey fox +tabby +tiger cat +Persian cat +Siamese cat +Egyptian cat +cougar +lynx +leopard +snow leopard +jaguar +lion +tiger +cheetah +brown bear +American black bear +ice bear +sloth bear +mongoose +meerkat +tiger beetle +ladybug +ground beetle +long-horned beetle +leaf beetle +dung beetle +rhinoceros beetle +weevil +fly +bee +ant +grasshopper +cricket +walking stick +cockroach +mantis +cicada +leafhopper +lacewing +dragonfly +damselfly +admiral +ringlet +monarch +cabbage butterfly +sulphur butterfly +lycaenid +starfish +sea urchin +sea cucumber +wood rabbit +hare +Angora +hamster +porcupine +fox squirrel +marmot +beaver +guinea pig +sorrel +zebra +hog +wild boar +warthog +hippopotamus +ox +water buffalo +bison +ram +bighorn +ibex +hartebeest +impala +gazelle +Arabian camel +llama +weasel +mink +polecat +black-footed ferret +otter +skunk +badger +armadillo +three-toed sloth +orangutan +gorilla +chimpanzee +gibbon +siamang +guenon +patas +baboon +macaque +langur +colobus +proboscis monkey +marmoset +capuchin +howler monkey +titi +spider monkey +squirrel monkey +Madagascar cat +indri +Indian elephant +African elephant +lesser panda +giant panda +barracouta +eel +coho +rock beauty +anemone fish +sturgeon +gar +lionfish +puffer +abacus +abaya +academic gown +accordion +acoustic guitar +aircraft carrier +airliner +airship +altar +ambulance +amphibian +analog clock +apiary +apron +ashcan +assault rifle +backpack +bakery +balance beam +balloon +ballpoint +Band Aid +banjo +bannister +barbell +barber chair +barbershop +barn +barometer +barrel +barrow +baseball +basketball +bassinet +bassoon +bathing cap +bath towel +bathtub +beach wagon +beacon +beaker +bearskin +beer bottle +beer glass +bell cote +bib +bicycle-built-for-two +bikini +binder +binoculars +birdhouse +boathouse +bobsled +bolo tie +bonnet +bookcase +bookshop +bottlecap +bow +bow tie +brass +brassiere +breakwater +breastplate +broom +bucket +buckle +bulletproof vest +bullet train +butcher shop +cab +caldron +candle +cannon +canoe +can opener +cardigan +car mirror +carousel +carpenter's kit +carton +car wheel +cash machine +cassette +cassette player +castle +catamaran +CD player +cello +cellular telephone +chain +chainlink fence +chain mail +chain saw +chest +chiffonier +chime +china cabinet +Christmas stocking +church +cinema +cleaver +cliff dwelling +cloak +clog +cocktail shaker +coffee mug +coffeepot +coil +combination lock +computer keyboard +confectionery +container ship +convertible +corkscrew +cornet +cowboy boot +cowboy hat +cradle +crane +crash helmet +crate +crib +Crock Pot +croquet ball +crutch +cuirass +dam +desk +desktop computer +dial telephone +diaper +digital clock +digital watch +dining table +dishrag +dishwasher +disk brake +dock +dogsled +dome +doormat +drilling platform +drum +drumstick +dumbbell +Dutch oven +electric fan +electric guitar +electric locomotive +entertainment center +envelope +espresso maker +face powder +feather boa +file +fireboat +fire engine +fire screen +flagpole +flute +folding chair +football helmet +forklift +fountain +fountain pen +four-poster +freight car +French horn +frying pan +fur coat +garbage truck +gasmask +gas pump +goblet +go-kart +golf ball +golfcart +gondola +gong +gown +grand piano +greenhouse +grille +grocery store +guillotine +hair slide +hair spray +half track +hammer +hamper +hand blower +hand-held computer +handkerchief +hard disc +harmonica +harp +harvester +hatchet +holster +home theater +honeycomb +hook +hoopskirt +horizontal bar +horse cart +hourglass +iPod +iron +jack-o'-lantern +jean +jeep +jersey +jigsaw puzzle +jinrikisha +joystick +kimono +knee pad +knot +lab coat +ladle +lampshade +laptop +lawn mower +lens cap +letter opener +library +lifeboat +lighter +limousine +liner +lipstick +Loafer +lotion +loudspeaker +loupe +lumbermill +magnetic compass +mailbag +mailbox +maillot +maillot +manhole cover +maraca +marimba +mask +matchstick +maypole +maze +measuring cup +medicine chest +megalith +microphone +microwave +military uniform +milk can +minibus +miniskirt +minivan +missile +mitten +mixing bowl +mobile home +Model T +modem +monastery +monitor +moped +mortar +mortarboard +mosque +mosquito net +motor scooter +mountain bike +mountain tent +mouse +mousetrap +moving van +muzzle +nail +neck brace +necklace +nipple +notebook +obelisk +oboe +ocarina +odometer +oil filter +organ +oscilloscope +overskirt +oxcart +oxygen mask +packet +paddle +paddlewheel +padlock +paintbrush +pajama +palace +panpipe +paper towel +parachute +parallel bars +park bench +parking meter +passenger car +patio +pay-phone +pedestal +pencil box +pencil sharpener +perfume +Petri dish +photocopier +pick +pickelhaube +picket fence +pickup +pier +piggy bank +pill bottle +pillow +ping-pong ball +pinwheel +pirate +pitcher +plane +planetarium +plastic bag +plate rack +plow +plunger +Polaroid camera +pole +police van +poncho +pool table +pop bottle +pot +potter's wheel +power drill +prayer rug +printer +prison +projectile +projector +puck +punching bag +purse +quill +quilt +racer +racket +radiator +radio +radio telescope +rain barrel +recreational vehicle +reel +reflex camera +refrigerator +remote control +restaurant +revolver +rifle +rocking chair +rotisserie +rubber eraser +rugby ball +rule +running shoe +safe +safety pin +saltshaker +sandal +sarong +sax +scabbard +scale +school bus +schooner +scoreboard +screen +screw +screwdriver +seat belt +sewing machine +shield +shoe shop +shoji +shopping basket +shopping cart +shovel +shower cap +shower curtain +ski +ski mask +sleeping bag +slide rule +sliding door +slot +snorkel +snowmobile +snowplow +soap dispenser +soccer ball +sock +solar dish +sombrero +soup bowl +space bar +space heater +space shuttle +spatula +speedboat +spider web +spindle +sports car +spotlight +stage +steam locomotive +steel arch bridge +steel drum +stethoscope +stole +stone wall +stopwatch +stove +strainer +streetcar +stretcher +studio couch +stupa +submarine +suit +sundial +sunglass +sunglasses +sunscreen +suspension bridge +swab +sweatshirt +swimming trunks +swing +switch +syringe +table lamp +tank +tape player +teapot +teddy +television +tennis ball +thatch +theater curtain +thimble +thresher +throne +tile roof +toaster +tobacco shop +toilet seat +torch +totem pole +tow truck +toyshop +tractor +trailer truck +tray +trench coat +tricycle +trimaran +tripod +triumphal arch +trolleybus +trombone +tub +turnstile +typewriter keyboard +umbrella +unicycle +upright +vacuum +vase +vault +velvet +vending machine +vestment +viaduct +violin +volleyball +waffle iron +wall clock +wallet +wardrobe +warplane +washbasin +washer +water bottle +water jug +water tower +whiskey jug +whistle +wig +window screen +window shade +Windsor tie +wine bottle +wing +wok +wooden spoon +wool +worm fence +wreck +yawl +yurt +web site +comic book +crossword puzzle +street sign +traffic light +book jacket +menu +plate +guacamole +consomme +hot pot +trifle +ice cream +ice lolly +French loaf +bagel +pretzel +cheeseburger +hotdog +mashed potato +head cabbage +broccoli +cauliflower +zucchini +spaghetti squash +acorn squash +butternut squash +cucumber +artichoke +bell pepper +cardoon +mushroom +Granny Smith +strawberry +orange +lemon +fig +pineapple +banana +jackfruit +custard apple +pomegranate +hay +carbonara +chocolate sauce +dough +meat loaf +pizza +potpie +burrito +red wine +espresso +cup +eggnog +alp +bubble +cliff +coral reef +geyser +lakeside +promontory +sandbar +seashore +valley +volcano +ballplayer +groom +scuba diver +rapeseed +daisy +yellow lady's slipper +corn +acorn +hip +buckeye +coral fungus +agaric +gyromitra +stinkhorn +earthstar +hen-of-the-woods +bolete +ear +toilet tissue diff --git a/examples/mobilenet/py/mobilenetv2.py b/examples/mobilenet/py/mobilenetv2.py new file mode 100755 index 0000000..58b5742 --- /dev/null +++ b/examples/mobilenet/py/mobilenetv2.py @@ -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() diff --git a/examples/resnet/README.md b/examples/resnet/README.md index e69de29..c996c26 100755 --- a/examples/resnet/README.md +++ b/examples/resnet/README.md @@ -0,0 +1,165 @@ +# resnet + +## 1.Overview + + + +## 2.Model Download + +- **Open Source model** + + - **Open Source projects:** + + - **Export Model Step:** + + - **Install ultralytics** + + pip install torch==2.4.1 + + pip install torchvision==0.19.1 + + pip install ultralytics==8.3.0 + + - **Download weights** + + + + - **Export Model** + + ``` + + ``` + + +- **Exported Model** + + ​ link to amlogic server( **onnx model or quantized tflite**) + + + +## 3. Model Conversion + +``` +cd model +Usage: ./adla_covnert.sh model_path adla_tookkit_path target_platform + +example + +``` + +| Parameter | Discription | +| ----------------- | ------------------------------------------------------------ | +| model_path | onnx model path | +| adla_tookkit_path | path to adla_toolkit | +| target_platform | Specify target platform. for A311D2 : PRODUCT_PID0XA003. for S905X5: PRODUCT_PID0XA005 | + + + +## 4. Demo Run + +### CPP + +#### 1. Compile + +**Prerequisites:** +- Android NDK (r25e recommended) +- `ANDROID_NDK_PATH` environment variable set + +**Build:** +```bash +# Build for arm64-v8a +cd examples/resnet/cpp +./build-android.sh -a arm64-v8a +``` + +The executable will be generated at `build/android/resnet_demo` (Note: executable name may vary, verify in build folder). + +#### 2. Run + +```bash +# Push executable to device +adb push build/android/resnet_demo /data/local/tmp/ +adb push model/res2net50_int8_A311D2.adla /data/local/tmp/ +adb push imgs /data/local/tmp/ +adb push labels.txt /data/local/tmp/ + +# Run on device +adb shell +cd /data/local/tmp +chmod +x resnet_demo +export LD_LIBRARY_PATH=/vendor/lib64 or (/vendor/lib) + +# Usage: ./resnet_demo +./resnet_demo res2net50_int8_A311D2.adla imgs/ labels.txt +``` + +**Note:** Replace `res2net50_int8_A311D2.adla` with your actual model file path. + +### Python + +**Prerequisites:** +- Python 3.10 +- Required packages: `numpy`, `opencv-python`, `amlnnlite` + +**Install dependencies:** +```bash +pip install numpy opencv-python amlnnlite-1.0.0-cp310-cp310-linux_aarch64.whl +``` + +**Run on device:** +```bash +python resnet.py \ + --model-path ./res2net50_int8_A311D2.adla \ + --image-dir ./imgs \ + --labels labels.txt \ + --run-cycles 1 \ + --loglevel INFO +``` +Argument Descriptions: +| Argument | Description | +| ----------------- | ------------------------------------------------------------ | +| --board-work-path | Work path on board, default is /data/local/tmp | +| --model-path | path to .adla model | +| --image-dir | Directory containing test images | +| --labels | Path to synset_words.txt or labels.txt | +| --run-cycles | Number of inference cycles, default is 1 | +| --loglevel | Logging level: DEBUG / INFO / WARNING / ERROR, default is WARNING | + +The script will automatically process all image files (`.jpg`, `.jpeg`, `.png`, `.bmp`) in the current directory and save results to a `{model_name}_result` folder. + +## 5.Results +**Performance Feedback** + +By setting the loglevel to INFO, the program provides real-time performance metrics upon completion. The console log will display essential hardware and execution details, including: +- Hardware Information: System and ADLA library versions. +- Model Overview: Basic input/output configurations. +- NPU Metrics: Total inference time (latency) and total DRAM bandwidth consumption. + +**Classification Output** + +For each image, the program prints the Top-5 classification results with their respective scores: +```bash +============================================================ +Processing image 1/1: dog.jpg +============================================================ Top-5 Results: +1: Pekinese score=9.851644 +2: West Highland white terrier score=5.055449 +3: Maltese dog score=4.796195 +4: basenji score=3.111045 +5: Scotch terrier score=2.786978 ============================================================ +``` +**Profiling Visualization** + +After a successful run of the Python demo, a folder named after the model (e.g., `{model_name}`) will be generated in the script directory. This folder contains 5 HTML files that provide a visual and detailed breakdown of per-layer performance: +- `hard_op_chart.html` & `soft_op_chart.html`: Hardware/Software op execution details. +- `dram_rd_chart.html` & `dram_wr_chart.html`: Bandwidth read/write distribution. +- `pie_charts_distribution.html`: Overall resource allocation. + +You can pull the result folder back to view it: +```bash +adb pull /data/local/tmp/res2net50_int8_A311D2 +``` + +Taking hard_op_chart.html as an example (shown below), each layer's ADLA operator name includes parentheses containing the index of the corresponding quantized .tflite layer(s); by default, these indices are suppressed, and operators are labeled generically as "hardware" or "software" without numerical suffixes. + +![alt text](Visualization.png) \ No newline at end of file diff --git a/examples/resnet/Visualization.png b/examples/resnet/Visualization.png new file mode 100755 index 0000000..17bec1b Binary files /dev/null and b/examples/resnet/Visualization.png differ diff --git a/examples/resnet/py/resnet.py b/examples/resnet/py/resnet.py index 7591281..cdf44d9 100755 --- a/examples/resnet/py/resnet.py +++ b/examples/resnet/py/resnet.py @@ -52,8 +52,8 @@ def postprocess_topk(logits, labels, k=5): def main(): parser = argparse.ArgumentParser(description="Classification AMLNNLite Demo") - parser.add_argument('--board-work-path', default='/data/nn', help='Work path on board') - parser.add_argument('--model-path', required=True, help='Path to .adla or .tflite model') + parser.add_argument('--board-work-path', default='/data/local/tmp', help='Work path on board') + parser.add_argument('--model-path', required=True, help='Path to .adla model') parser.add_argument('--image-dir', required=True, help='Directory containing test images') parser.add_argument('--labels', required=True, help='Path to synset_words.txt or labels.txt') parser.add_argument('--run-cycles', type=int, default=1, help='Number of inference cycles') diff --git a/examples/retinaface/README.md b/examples/retinaface/README.md index e69de29..70f0ddc 100755 --- a/examples/retinaface/README.md +++ b/examples/retinaface/README.md @@ -0,0 +1,160 @@ +# retinaface + +## 1.Overview + + +## 2.Model Download + +- **Open Source model** + + - **Open Source projects:** + + - **Export Model Step:** + + - **Install ultralytics** + + pip install torch==2.4.1 + + pip install torchvision==0.19.1 + + pip install ultralytics==8.3.0 + + - **Download weights** + + + + - **Export Model** + + + + +- **Exported Model** + + ​ link to amlogic server( **onnx model or quantized tflite**) + + + +## 3. Model Conversion + +``` +cd model +Usage: ./adla_covnert.sh model_path adla_tookkit_path target_platform + +example + +``` + +| Parameter | Discription | +| ----------------- | ------------------------------------------------------------ | +| model_path | onnx model path | +| adla_tookkit_path | path to adla_toolkit | +| target_platform | Specify target platform. for A311D2 : PRODUCT_PID0XA003. for S905X5: PRODUCT_PID0XA005 | + + + +## 4. Demo Run + +### CPP + +#### 1. Compile + +**Prerequisites:** +- Android NDK (r25e recommended) +- `ANDROID_NDK_PATH` environment variable set + +**Build:** +```bash +# Build for arm64-v8a +cd examples/retinaface/cpp +./build-android.sh -a arm64-v8a +``` + +The executable will be generated at `build/android/retinaface_demo` (Note: executable name may vary, verify in build folder). + +#### 2. Run + +```bash +# Push executable to device +adb push build/android/retinaface_demo /data/local/tmp/ +adb push model/RetinaFace_int8_A311D2.adla /data/local/tmp/ +adb push imgs /data/local/tmp/ + +# Run on device +adb shell +cd /data/local/tmp +chmod +x retinaface_demo +export LD_LIBRARY_PATH=/vendor/lib64 or (/vendor/lib) + +# Usage: ./retinaface_demo +./retinaface_demo RetinaFace_int8_A311D2.adla ./imgs +``` + +**Note:** Replace `RetinaFace_int8_A311D2.adla` with your actual model file path. + +### Python + +**Prerequisites:** +- Python 3.10 +- Required packages: `numpy`, `opencv-python`, `amlnnlite` + +**Install dependencies:** +```bash +pip install numpy opencv-python amlnnlite-1.0.0-cp310-cp310-linux_aarch64.whl +``` + +**Run on device:** +```bash +python RetinaFace.py \ + --model-path ./RetinaFace_int8_A311D2.adla \ + --image-dir ./imgs \ + --run-cycles 1 \ + --loglevel INFO +``` + +Argument Descriptions: +| Argument | Description | +| ----------------- | ------------------------------------------------------------ | +| --board-work-path | Work path on board, default is /data/local/tmp | +| --model-path | path to .adla model | +| --image-dir | Directory containing test images | +| --run-cycles | Number of inference cycles, default is 1 | +| --loglevel | Logging level: DEBUG / INFO / WARNING / ERROR, default is WARNING | + +The script will automatically process all image files (`.jpg`, `.jpeg`, `.png`, `.bmp`) in the current directory and save results to a `{model_name}_result` folder. + +## 5.Results + +**Performance Feedback** + +By setting the loglevel to INFO, the program provides real-time performance metrics upon completion. The console log will display essential hardware and execution details, including: +- Hardware Information: System and ADLA library versions. +- Model Overview: Basic input/output configurations. +- NPU Metrics: Total inference time (latency) and total DRAM bandwidth consumption. + +**Detection Output** + +The program will print the detection count. The output images, featuring bounding boxes and five facial landmarks (eyes, nose, and mouth corners), will be saved to the `{model_name}_result` folder. + + +You can pull the result folder back to view it: +```bash +adb pull /data/local/tmp/RetinaFace_int8_A311D2_result +``` +![alt text](result.jpg) + + +**Profiling Visualization** + +After a successful run of the Python demo, a folder named after the model (e.g., `{model_name}`) will be generated in the script directory. This folder contains 5 HTML files that provide a visual and detailed breakdown of per-layer performance: +- `hard_op_chart.html` & `soft_op_chart.html`: Hardware/Software op execution details. +- `dram_rd_chart.html` & `dram_wr_chart.html`: Bandwidth read/write distribution. +- `pie_charts_distribution.html`: Overall resource allocation. + +You can pull the result folder back to view it: +```bash +adb pull /data/local/tmp/RetinaFace_int8_A311D2 +``` + +Taking hard_op_chart.html as an example (shown below), each layer's ADLA operator name includes parentheses containing the index of the corresponding quantized .tflite layer(s); by default, these indices are suppressed, and operators are labeled generically as "hardware" or "software" without numerical suffixes. + +![alt text](Visualization.png) diff --git a/examples/retinaface/Visualization.png b/examples/retinaface/Visualization.png new file mode 100755 index 0000000..67277d2 Binary files /dev/null and b/examples/retinaface/Visualization.png differ diff --git a/examples/retinaface/cpp/src/main.cpp b/examples/retinaface/cpp/src/main.cpp index 6591726..36bfeca 100755 --- a/examples/retinaface/cpp/src/main.cpp +++ b/examples/retinaface/cpp/src/main.cpp @@ -55,7 +55,8 @@ int main(int argc, char** argv) { size_t num_priors = priors.size(); std::vector chw_buffer(kInputW * kInputH * 3); - const std::string out_dir = "retinaface_result"; + std::string model_stem = fs::path(argv[1]).stem().string(); + const std::string out_dir = model_stem + "_result"; fs::create_directory(out_dir); std::vector image_paths; diff --git a/examples/retinaface/py/RetinaFace.py b/examples/retinaface/py/RetinaFace.py index 904654f..91f5441 100755 --- a/examples/retinaface/py/RetinaFace.py +++ b/examples/retinaface/py/RetinaFace.py @@ -107,7 +107,7 @@ def preprocess(img_path, input_size=(320, 320)): def main(): parser = argparse.ArgumentParser(description="RetinaFace AMLNNLite Demo") - parser.add_argument('--board-work-path', type=str, default='/data/nn') + parser.add_argument('--board-work-path', type=str, default='/data/local/tmp') parser.add_argument('--model-path', required=True, help='Path to .adla model') parser.add_argument('--image-dir', required=True, help='Directory of test images') parser.add_argument('--run-cycles', type=int, default=1, help='Inference cycles') @@ -122,13 +122,18 @@ def main(): amlnn.init() priors = PriorBox((320, 320)).forward() - image_files = sorted(glob.glob(os.path.join(args.image_dir, "*.[jp][pn][g]"))) + image_files = [] + for ext in ["*.jpg", "*.jpeg", "*.png", "*.bmp"]: + image_files.extend(glob.glob(os.path.join(args.image_dir, ext))) + image_files.extend(glob.glob(os.path.join(args.image_dir, ext.upper()))) + image_files.sort() if not image_files: print(f"No images found in {args.image_dir}") amlnn.uninit(); return - res_dir = "retinaface_result" + model_stem = Path(args.model_path).stem + res_dir = f"{model_stem}_result" os.makedirs(res_dir, exist_ok=True) for idx, img_path in enumerate(image_files, start=1): diff --git a/examples/retinaface/result.jpg b/examples/retinaface/result.jpg new file mode 100755 index 0000000..0939279 Binary files /dev/null and b/examples/retinaface/result.jpg differ diff --git a/examples/yolov11/README.md b/examples/yolov11/README.md index e69de29..6f34ee9 100755 --- a/examples/yolov11/README.md +++ b/examples/yolov11/README.md @@ -0,0 +1,170 @@ +# yolov11 + +## 1.Overview + +​ YOLOv11 was released by Ultralytics on October 2, 2024. It introduces significant architectural refinements and efficiency optimizations, delivering superior accuracy-speed trade-offs compared to previous generations. With enhanced feature extraction capabilities, YOLOv11 is designed for high-performance real-time applications—including object detection, instance segmentation, and pose estimation—to handle demanding tasks in a wide range of applications. + +## 2.Model Download + +- **Open Source model** + + - **Open Source projects:** https://github.com/ultralytics/ultralytics/tree/v8.3.0 + + - **Export Model Step:** + + - **Install ultralytics** + + pip install torch==2.4.1 + + pip install torchvision==0.19.1 + + pip install ultralytics==8.3.0 + + - **Download weights** + + wget https://github.com/ultralytics/assets/releases/download/v8.3.0/yolo11m.pt + + wget https://github.com/ultralytics/assets/releases/download/v8.3.0/yolo11s.pt + + wget https://github.com/ultralytics/assets/releases/download/v8.3.0/yolo11n.pt + + - **Export Model** + + ``` + from ultralytics import YOLO + + model = YOLO("yolo11n.pt") + model.export(format="onnx", opset=12, simplify=True, dynamic=False, imgsz=640) + ``` + + +- **Exported Model** + + ​ link to amlogic server( **onnx model or quantized tflite**) + + + +## 3. Model Conversion + +``` +cd model +Usage: ./adla_covnert.sh model_path adla_tookkit_path target_platform + +example + ./adla_covnert.sh yolov11m.onnx /xxxx/adla-toolkit-binary-3.2.9.3 PRODUCT_PID0XA005 + ./adla_covnert.sh yolov11s.onnx /xxxx/adla-toolkit-binary-3.2.9.3 PRODUCT_PID0XA005 + ./adla_covnert.sh yolov11n.onnx /xxxx/adla-toolkit-binary-3.2.9.3 PRODUCT_PID0XA005 +``` + +| Parameter | Discription | +| ----------------- | ------------------------------------------------------------ | +| model_path | onnx model path | +| adla_tookkit_path | path to adla_toolkit | +| target_platform | Specify target platform. for A311D2 : PRODUCT_PID0XA003. for S905X5: PRODUCT_PID0XA005 | + + + +## 4. Demo Run + +### CPP + +#### 1. Compile + +**Prerequisites:** +- Android NDK (r25e recommended) +- `ANDROID_NDK_PATH` environment variable set + +**Build:** +```bash +# Build for arm64-v8a +cd examples/yolov11/cpp +./build-android.sh -a arm64-v8a +``` + +The executable will be generated at `build/android/yolo11_demo` (Note: executable name may vary, verify in build folder). + +#### 2. Run + +```bash +# Push executable to device +adb push build/android/yolo11_demo /data/local/tmp/ +adb push model/yolov11n_int8_A311D2.adla /data/local/tmp/ +adb push imgs /data/local/tmp/ + +# Run on device +adb shell +cd /data/local/tmp +chmod +x yolo11_demo +export LD_LIBRARY_PATH=/vendor/lib64 or (/vendor/lib) + +# Usage: ./yolo11_demo +./yolo11_demo yolov11n_int8_A311D2.adla ./imgs +``` + +**Note:** Replace `yolov11n_int8_A311D2.adla` with your actual model file path. + +### Python + +**Prerequisites:** +- Python 3.10 +- Required packages: `numpy`, `opencv-python`, `amlnnlite` + +**Install dependencies:** +```bash +pip install numpy opencv-python amlnnlite-1.0.0-cp310-cp310-linux_aarch64.whl +``` + +**Run on device:** +```bash +python yolov11.py \ + --model-path ./yolov11n_int8_A311D2.adla \ + --image-dir ./imgs \ + --run-cycles 1 \ + --loglevel INFO +``` + +Argument Descriptions: +| Argument | Description | +| ----------------- | ------------------------------------------------------------ | +| --board-work-path | Work path on board, default is /data/local/tmp | +| --model-path | path to .adla model | +| --image-dir | Directory containing test images | +| --run-cycles | Number of inference cycles, default is 1 | +| --loglevel | Logging level: DEBUG / INFO / WARNING / ERROR, default is WARNING | + +The script will automatically process all image files (`.jpg`, `.jpeg`, `.png`, `.bmp`) in the current directory and save results to a `{model_name}_result` folder. + +## 5.Results + +**Performance Feedback** + +By setting the loglevel to INFO, the program provides real-time performance metrics upon completion. The console log will display essential hardware and execution details, including: +- Hardware Information: System and ADLA library versions. +- Model Overview: Basic input/output configurations. +- NPU Metrics: Total inference time (latency) and total DRAM bandwidth consumption. + +**Detection Output** + +The program will print the detection count. The result image with bounding boxes will be saved to the specified output path (`{model_name}_result`). + +You can pull the result folder back to view it: +```bash +adb pull /data/local/tmp/yolov11n_int8_A311D2_result +``` +![alt text](result.jpg) + +**Profiling Visualization** + +After a successful run of the Python demo, a folder named after the model (e.g., `{model_name}`) will be generated in the script directory. This folder contains 5 HTML files that provide a visual and detailed breakdown of per-layer performance: +- `hard_op_chart.html` & `soft_op_chart.html`: Hardware/Software op execution details. +- `dram_rd_chart.html` & `dram_wr_chart.html`: Bandwidth read/write distribution. +- `pie_charts_distribution.html`: Overall resource allocation. + +You can pull the result folder back to view it: +```bash +adb pull /data/local/tmp/yolov11n_int8_A311D2 +``` + +Taking hard_op_chart.html as an example (shown below), each layer's ADLA operator name includes parentheses containing the index of the corresponding quantized .tflite layer(s); by default, these indices are suppressed, and operators are labeled generically as "hardware" or "software" without numerical suffixes. + +![alt text](Visualization.png) \ No newline at end of file diff --git a/examples/yolov11/Visualization.png b/examples/yolov11/Visualization.png new file mode 100755 index 0000000..53aa25a Binary files /dev/null and b/examples/yolov11/Visualization.png differ diff --git a/examples/yolov11/py/yolov11.py b/examples/yolov11/py/yolov11.py index 2bd5d55..1b5e8d0 100755 --- a/examples/yolov11/py/yolov11.py +++ b/examples/yolov11/py/yolov11.py @@ -93,8 +93,8 @@ def postprocess(outputs, scale, pad, strides=[32,16,8], conf_threshold=0.25, iou def main(): parser = argparse.ArgumentParser(description="YOLOV11 AMLNNLite Demo") - parser.add_argument('--board-work-path', default='/data/nn', help='Work path on board') - parser.add_argument('-m', '--model-path', required=True, help='Path to .adla or .tflite model') + parser.add_argument('--board-work-path', default='/data/local/tmp', help='Work path on board') + parser.add_argument('-m', '--model-path', required=True, help='Path to .adla model') parser.add_argument('--image-dir', required=True, help='Directory containing test images') parser.add_argument('--run-cycles', type=int, default=1, help='Inference cycles for profiling') parser.add_argument('--loglevel', default='WARNING', choices=['DEBUG', 'INFO', 'WARNING', 'ERROR'], help='Log level') @@ -110,7 +110,7 @@ def main(): amlnn.init() image_files = [] - for ext in ["*.jpg", "*.jpeg", "*.png"]: + for ext in ["*.jpg", "*.jpeg", "*.png", "*.bmp"]: image_files.extend(glob.glob(os.path.join(args.image_dir, ext))) image_files.extend(glob.glob(os.path.join(args.image_dir, ext.upper()))) image_files.sort() diff --git a/examples/yolov11/result.jpg b/examples/yolov11/result.jpg new file mode 100755 index 0000000..242de48 Binary files /dev/null and b/examples/yolov11/result.jpg differ diff --git a/examples/yolov8/model/test.png b/examples/yolov8/model/test.png new file mode 100755 index 0000000..0a7c36b Binary files /dev/null and b/examples/yolov8/model/test.png differ diff --git a/examples/yoloworld/py/yoloworld.py b/examples/yoloworld/py/yoloworld.py index 0ae5680..8c182c4 100755 --- a/examples/yoloworld/py/yoloworld.py +++ b/examples/yoloworld/py/yoloworld.py @@ -390,7 +390,6 @@ Examples: traceback.print_exc() return 1 - # Use try-finally to ensure resources are released try: # Find all image files in the specified directory image_dir = args.image_dir @@ -493,7 +492,6 @@ Examples: amlnn.visualize() print("Visualization charts saved.") finally: - # Always release resources if amlnn is not None: print("\nReleasing resources...") amlnn.uninit() diff --git a/resource/coco_subset/dataset.txt b/resource/coco_subset/dataset.txt new file mode 100755 index 0000000..e69de29