diff --git a/tf-mobilenet-image/PurpleGallinule.jpg b/tf-mobilenet-image/PurpleGallinule.jpg new file mode 100644 index 0000000..491b618 Binary files /dev/null and b/tf-mobilenet-image/PurpleGallinule.jpg differ diff --git a/tf-mobilenet-image/README.md b/tf-mobilenet-image/README.md new file mode 100644 index 0000000..4151d1e --- /dev/null +++ b/tf-mobilenet-image/README.md @@ -0,0 +1,68 @@ +# Mobilenet Example For WASI-NN with Tensorflow Backend + +This package is a high-level Rust bindings for [wasi-nn] example of Mobilenet with Tensorflow backend. + +[wasi-nn]: https://github.com/second-state/wasmedge-wasi-nn + +## Dependencies + +This crate depends on the `wasi-nn` in the `Cargo.toml`: + +```toml +[dependencies] +wasmedge-wasi-nn = "0.2.1" +``` + +## Build + +Compile the application to WebAssembly: + +```bash +cd rust/tf-mobilenet && cargo build --target=wasm32-wasi --release +``` + +The output WASM file will be at [`rust/tf-mobilenet/target/wasm32-wasi/release/wasmedge-wasinn-example-tf-mobilenet-image.wasm`](wasmedge-wasinn-example-tf-mobilenet-image.wasm). +To speed up the image processing, we can enable the AOT mode in WasmEdge with: + +```bash +wasmedgec rust/tf-mobilenet/target/wasm32-wasi/release/wasmedge-wasinn-example-tf-mobilenet-image.wasm run.wasm +``` + +## Run + +### Download fixture + +The testing image is located at `./PurpleGallinule.jpg` downloaded from [link](https://raw.githubusercontent.com/second-state/wasm-learning/master/rust/mobilenet_birds_tfhub/PurpleGallinule.jpg). + +The `tf` model is located at `./saved_model.pb` downloaded from [link](https://tfhub.dev/google/aiy/vision/classifier/birds_V1/1). Please note that, the model should be saved by tensorflow [SavedModel](https://www.tensorflow.org/guide/saved_model) format with no extra assets and variables. + +### Generate Image Tensor + +If you want to generate the [raw](birdx224x224x3.rgb) tensor, you can run: + +```shell +cd rust/image-converter/ && cargo run ../../PurpleGallinule.jpg ../../birdX224X224X3.rgb && cd ../.. +``` + +### Execute + +Execute the WASM with the `wasmedge` with Tensorflow supporting: + +```bash +wasmedge --dir .:. wasmedge-wasinn-example-tf-mobilenet-image.wasm saved_model.pb PurpleGallinule.jpg +``` + +You will get the output: + +```console +Read graph weights, size in bytes: 3561598 +Loaded graph into wasi-nn with ID: 0 +Created wasi-nn execution context with ID: 0 +Read input tensor, size in bytes: 150528 +Executed graph inference + 1.) [576](0.8951)Porphyrio martinicus + 2.) [427](0.0123)Cynanthus latirostris + 3.) [331](0.0064)Porphyrio poliocephalus + 4.) [798](0.0039)Porphyrio hochstetteri + 5.) [743](0.0033)Hemiphaga novaeseelandiae +``` diff --git a/tf-mobilenet-image/birdX224X224X3.rgb b/tf-mobilenet-image/birdX224X224X3.rgb new file mode 100644 index 0000000..10f1894 Binary files /dev/null and b/tf-mobilenet-image/birdX224X224X3.rgb differ diff --git a/tf-mobilenet-image/rust/image-converter/Cargo.toml b/tf-mobilenet-image/rust/image-converter/Cargo.toml new file mode 100644 index 0000000..393b494 --- /dev/null +++ b/tf-mobilenet-image/rust/image-converter/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "image-converter" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +image = { version = "0.23.14", default-features = false, features = ["gif", "jpeg", "ico", "png", "pnm", "tga", "tiff", "webp", "bmp", "hdr", "dxt", "dds", "farbfeld"] } diff --git a/tf-mobilenet-image/rust/image-converter/src/main.rs b/tf-mobilenet-image/rust/image-converter/src/main.rs new file mode 100644 index 0000000..0be8e35 --- /dev/null +++ b/tf-mobilenet-image/rust/image-converter/src/main.rs @@ -0,0 +1,48 @@ +use std::env; +use std::fs; +use std::fs::File; +use std::io::Read; + +fn main() { + let args: Vec = env::args().collect(); + let image_name: &str = &args[1]; + let output_name: &str = &args[2]; + + let tensor_data = image_to_tensor(image_name.to_string(), 224, 224); + println!( + "Read image with {} bytes to write {}", + tensor_data.len(), + output_name + ); + fs::write(output_name.to_string(), tensor_data).expect("Failed to write tensor") +} + +fn image_to_tensor(path: String, height: u32, width: u32) -> Vec { + let mut file_img = File::open(path).unwrap(); + let mut img_buf = Vec::new(); + file_img.read_to_end(&mut img_buf).unwrap(); + let img = image::load_from_memory(&img_buf).unwrap().to_rgb8(); + let resized = + image::imageops::resize(&img, height, width, ::image::imageops::FilterType::Triangle); + let mut flat_img: Vec = Vec::new(); + for rgb in resized.pixels() { + flat_img.push(rgb[0] as f32 / 255.0); + flat_img.push(rgb[1] as f32 / 255.0); + flat_img.push(rgb[2] as f32 / 255.0); + } + let bytes_required = flat_img.len() * 4; + let mut u8_f32_arr: Vec = vec![0; bytes_required]; + + for c in 0..3 { + for i in 0..(flat_img.len() / 3) { + // Read the number as a f32 and break it into u8 bytes + let u8_f32: f32 = flat_img[i * 3 + c] as f32; + let u8_bytes = u8_f32.to_ne_bytes(); + + for j in 0..4 { + u8_f32_arr[((i * 3 + c) * 4) + j] = u8_bytes[j]; + } + } + } + return u8_f32_arr; +} diff --git a/tf-mobilenet-image/rust/tf-mobilenet/Cargo.toml b/tf-mobilenet-image/rust/tf-mobilenet/Cargo.toml new file mode 100644 index 0000000..f7cda3e --- /dev/null +++ b/tf-mobilenet-image/rust/tf-mobilenet/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "wasmedge-wasinn-example-tf-mobilenet-image" +version = "0.19.0" +authors = ["Second-State"] +readme = "README.md" +edition = "2018" +publish = false + +[dependencies] +image = { version = "0.23.14", default-features = false, features = ["gif", "jpeg", "ico", "png", "pnm", "tga", "tiff", "webp", "bmp", "hdr", "dxt", "dds", "farbfeld"] } +wasi-nn = { version = "0.2.1"} + +# This crate is built with the wasm32-wasi target, so it's separate +# from the main Wasmtime build, so use this directive to exclude it +# from the parent directory's workspace. +[workspace] diff --git a/tf-mobilenet-image/rust/tf-mobilenet/src/imagenet_classes.rs b/tf-mobilenet-image/rust/tf-mobilenet/src/imagenet_classes.rs new file mode 100644 index 0000000..7ab228b --- /dev/null +++ b/tf-mobilenet-image/rust/tf-mobilenet/src/imagenet_classes.rs @@ -0,0 +1,986 @@ +/** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + +/* The code in this file is adapted from https://github.com/tensorflow/tfjs-models/blob/master/mobilenet/src/imagenet_classes.ts */ + +pub const AIY_BIRDS_V1: [&str; 965] = [ + "Haemorhous cassinii", + "Aramus guarauna", + "Rupornis magnirostris", + "Cyanocitta cristata", + "Cyanocitta stelleri", + "Balearica regulorum", + "Pyrocephalus rubinus", + "Recurvirostra americana", + "Ardeotis kori", + "Pica nuttalli", + "Perisoreus canadensis", + "Antigone canadensis", + "Parkesia noveboracensis", + "Ardea herodias occidentalis", + "Porzana carolina", + "Anas platyrhynchos diazi", + "Motacilla cinerea", + "Empidonax difficilis", + "Empidonax minimus", + "Empidonax fulvifrons", + "Empidonax traillii", + "Empidonax hammondii", + "Empidonax occidentalis", + "Rallus limicola", + "Grus grus", + "Quiscalus major", + "Branta leucopsis", + "Cyanocorax yucatanicus", + "Cyanocorax yncas", + "Oceanites oceanicus", + "Quiscalus niger", + "Psilorhinus morio", + "Megarynchus pitangua", + "Gallinula tenebrosa", + "Gallus gallus domesticus", + "Numida meleagris", + "Junco hyemalis caniceps", + "Tyrannus vociferans", + "Tyrannus tyrannus", + "Tyrannus forficatus", + "Tyrannus crassirostris", + "Tyrannus verticalis", + "Tyrannus savana", + "Gallirallus australis", + "Calocitta formosa", + "Calocitta colliei", + "Fulica americana", + "Pachyramphus aglaiae", + "Buteo lagopus", + "Cygnus atratus", + "Philesturnus rufusater", + "Larus marinus", + "Pitangus sulphuratus", + "Anas rubripes", + "Anthus novaeseelandiae novaeseelandiae", + "Sayornis phoebe", + "Sayornis nigricans", + "Tityra semifasciata", + "Dryocopus lineatus", + "Porphyrio melanotus", + "Anas bahamensis", + "Egretta novaehollandiae", + "Anas crecca carolinensis", + "Alectoris chukar", + "Tachybaptus dominicus", + "Artemisiospiza belli", + "Gallus gallus", + "Cardinalis sinuatus", + "Cardinalis cardinalis", + "Melospiza lincolnii", + "Podilymbus podiceps", + "Melospiza georgiana", + "Meleagris gallopavo", + "Meleagris ocellata", + "Lagopus lagopus", + "Spizella atrogularis", + "Pyrrhocorax graculus", + "Spizella breweri", + "Sialia currucoides", + "Spizella pusilla", + "Anas superciliosa", + "Passerella iliaca", + "Phoenicopterus ruber", + "Sylvia atricapilla", + "Vireo bellii", + "Vireo plumbeus", + "Vireo philadelphicus", + "Vireo flavifrons", + "Vireo olivaceus", + "Zonotrichia querula", + "Vireo huttoni", + "Zonotrichia albicollis", + "Zonotrichia atricapilla", + "Emberiza citrinella", + "Bucephala islandica", + "Emberiza schoeniclus", + "Vireo gilvus", + "Serinus serinus", + "Serinus mozambicus", + "Lophura leucomelanos", + "Euphonia elegantissima", + "Euphonia hirundinacea", + "Euphonia affinis", + "Agelaius tricolor", + "Momotus lessonii", + "Zosterops japonicus", + "Phalacrocorax pelagicus", + "Icterus cucullatus", + "Icterus graduacauda", + "Motacilla aguimp", + "Anas superciliosa × platyrhynchos", + "Icterus pustulatus", + "Icterus gularis", + "Carduelis cannabina", + "Catharus minimus", + "Amaurornis phoenicurus", + "Pavo cristatus", + "Rallus crepitans", + "Nestor meridionalis septentrionalis", + "Pipilo chlorurus", + "Pipilo maculatus", + "Pipilo erythrophthalmus", + "Cairina moschata domestica", + "Phalacrocorax varius", + "Picoides dorsalis", + "Picoides nuttallii", + "Picoides scalaris", + "Callipepla gambelii", + "Pyrrhula pyrrhula", + "Phalacrocorax brasilianus", + "Picoides pubescens", + "Colinus virginianus", + "Sporophila torqueola", + "Picoides villosus", + "Calidris pusilla", + "Picoides arcticus", + "Aythya marila", + "Phaethon aethereus", + "Sturnella magna", + "Melopsittacus undulatus", + "Aythya affinis", + "Aythya novaeseelandiae", + "Cyrtonyx montezumae", + "Pelecanus occidentalis", + "Cinclus cinclus", + "Chen rossii", + "Callipepla californica", + "Quiscalus quiscula", + "Quiscalus mexicanus", + "Callipepla squamata", + "Dryocopus pileatus", + "Passerina caerulea", + "Amazilia beryllina", + "Geothlypis trichas", + "Trogon melanocephalus", + "Sylvia communis", + "Pinicola enucleator", + "Coccothraustes vespertinus", + "Coccothraustes coccothraustes", + "Vermivora chrysoptera", + "Opisthocomus hoazin", + "Setophaga coronata coronata", + "Diglossa baritula", + "Saltator coerulescens", + "Saltator atriceps", + "Sicalis flaveola", + "Aix galericulata", + "Junco hyemalis hyemalis", + "Eupsittula canicularis", + "Microcarbo melanoleucos", + "Piranga rubra", + "Piranga olivacea", + "Piranga flava", + "Amphispiza bilineata", + "Larus dominicanus", + "Piaya cayana", + "Aimophila ruficeps", + "Melanerpes lewis", + "Melanerpes uropygialis", + "Passerculus sandwichensis", + "Melanerpes pucherani", + "Salpinctes obsoletus", + "Melanerpes carolinus", + "Melanerpes chrysogenys", + "Melanerpes formicivorus", + "Colaptes auratus", + "Basileuterus rufifrons", + "Larus michahellis", + "Ramphocelus passerinii", + "Athene cunicularia", + "Branta hutchinsii", + "Fringilla montifringilla", + "Fringilla coelebs", + "Junco hyemalis", + "Cuculus canorus", + "Junco phaeonotus", + "Ammodramus nelsoni", + "Ammodramus savannarum", + "Ammodramus maritimus", + "Coccyzus erythropthalmus", + "Coccyzus minor", + "Coccyzus americanus", + "Nucifraga columbiana", + "Crotophaga sulcirostris", + "Pooecetes gramineus", + "Arremonops rufivirgatus", + "Geococcyx californianus", + "Geococcyx velox", + "Coereba flaveola", + "Passerina ciris", + "Alectura lathami", + "Passerina leclancherii", + "Passerina amoena", + "Icteria virens", + "Crax rubra", + "Penelope purpurascens", + "Copsychus malabaricus", + "Paroaria capitata", + "Cyanerpes cyaneus", + "Microcarbo melanoleucos brevirostris", + "Sphyrapicus thyroideus", + "Pheucticus ludovicianus", + "Sphyrapicus ruber", + "Pheucticus melanocephalus", + "Sphyrapicus nuchalis", + "Ortalis poliocephala", + "Ortalis vetula", + "Corvus albus", + "Mniotilta varia", + "Volatinia jacarina", + "Thraupis palmarum", + "Momotus mexicanus", + "Euphagus cyanocephalus", + "Cacatua galerita", + "Junco hyemalis oreganus", + "Pluvialis fulva", + "Molothrus aeneus", + "Molothrus ater", + "Merops pusillus", + "Merops apiaster", + "Pteroglossus torquatus", + "Loxia curvirostra", + "Merops orientalis", + "Loxia leucoptera", + "Coracias garrulus", + "Coracias caudatus", + "Coracias benghalensis", + "Xanthocephalus xanthocephalus", + "Chondestes grammacus", + "Dolichonyx oryzivorus", + "Pandion haliaetus", + "Phainopepla nitens", + "Tyrannus couchii", + "Phylloscopus collybita", + "Circus cyaneus hudsonius", + "Grallina cyanoleuca", + "Plectrophenax nivalis", + "Calamospiza melanocorys", + "Regulus calendula", + "Regulus ignicapilla", + "Regulus regulus", + "Regulus satrapa", + "Tyrannus melancholicus", + "Pelecanus conspicillatus", + "Aulacorhynchus prasinus", + "Todiramphus sanctus", + "Icterus bullockii", + "Spiza americana", + "Tyrannus dominicensis", + "Chlidonias niger", + "Oriturus superciliosus", + "Psarocolius montezuma", + "Turdus pilaris", + "Notiomystis cincta", + "Sagittarius serpentarius", + "Psittacula krameri", + "Platycercus eximius", + "Protonotaria citrea", + "Megaceryle torquata", + "Nestor meridionalis", + "Amazona viridigenalis", + "Amazona albifrons", + "Amazona oratrix", + "Saxicola rubetra", + "Ara militaris", + "Spizelloides arborea", + "Ceryle rudis", + "Chloroceryle aenea", + "Chloroceryle amazona", + "Myiozetetes similis", + "Toxostoma curvirostre", + "Megaceryle alcyon", + "Eremophila alpestris", + "Alisterus scapularis", + "Cinnyris jugularis", + "Xiphorhynchus flavigaster", + "Jacana jacana", + "Phalaropus fulicarius", + "Streptopelia turtur", + "Pica hudsonia", + "Corvus cornix", + "Myiopsitta monachus", + "Streptopelia decaocto", + "Piranga ludoviciana", + "Ixobrychus exilis", + "Auriparus flaviceps", + "Geothlypis tolmiei", + "Columba livia", + "Setophaga citrina", + "Setophaga cerulea", + "Columba palumbus", + "Piranga bidentata", + "Patagioenas leucocephala", + "Patagioenas fasciata", + "Patagioenas flavirostris", + "Setophaga discolor", + "Chordeiles minor", + "Chordeiles acutipennis", + "Platalea leucorodia", + "Phalaenoptilus nuttallii", + "Haemorhous mexicanus", + "Haemorhous purpureus", + "Nyctidromus albicollis", + "Campephilus guatemalensis", + "Toxostoma rufum", + "Leptotila verreauxi", + "Nyctibius jamaicensis", + "Anas penelope", + "Buteo plagiatus", + "Selasphorus calliope", + "Megascops kennicottii", + "Porphyrio poliocephalus", + "Megascops asio", + "Zenaida auriculata", + "Hymenolaimus malacorhynchos", + "Setophaga caerulescens", + "Camptostoma imberbe", + "Caracara plancus", + "Columbina passerina", + "Eupsittula nana", + "Nestor notabilis", + "Columbina talpacoti", + "Geopelia striata", + "Athene noctua", + "Crotophaga ani", + "Sialia sialis", + "Platalea alba", + "Bubo virginianus", + "Petrochelidon fulva", + "Progne subis", + "Setophaga coronata auduboni", + "Hirundo neoxena", + "Hirundo rustica", + "Calidris virgata", + "Calidris pugnax", + "Platalea regia", + "Tachycineta thalassina", + "Bostrychia hagedash", + "Riparia riparia", + "Eudocimus albus", + "Plegadis falcinellus", + "Plegadis chihi", + "Corvus corax", + "Stelgidopteryx serripennis", + "Sula dactylatra", + "Sula sula", + "Sula leucogaster", + "Morus serrator", + "Eudyptula minor", + "Megadyptes antipodes", + "Scopus umbretta", + "Troglodytes troglodytes", + "Calidris canutus", + "Lanius collurio", + "Calidris bairdii", + "Meleagris gallopavo intermedia", + "Calidris mauri", + "Calidris maritima", + "Calidris alpina", + "Calidris ferruginea", + "Calidris melanotos", + "Limnodromus griseus", + "Malurus cyaneus", + "Tringa nebularia", + "Todiramphus sanctus vagans", + "Tringa ochropus", + "Tringa glareola", + "Tringa melanoleuca", + "Tringa flavipes", + "Numenius arquata", + "Numenius phaeopus", + "Phalacrocorax carbo novaehollandiae", + "Petroica macrocephala macrocephala", + "Petroica australis longipes", + "Prosthemadera novaeseelandiae novaeseelandiae", + "Asio flammeus", + "Rhipidura fuliginosa fuliginosa", + "Scolopax minor", + "Arenaria interpres", + "Arenaria melanocephala", + "Rhipidura fuliginosa placabilis", + "Limosa limosa", + "Limosa haemastica", + "Limosa fedoa", + "Phalaropus lobatus", + "Bartramia longicauda", + "Limosa lapponica", + "Aegolius acadicus", + "Actitis hypoleucos", + "Trichoglossus haematodus", + "Surnia ulula", + "Polioptila caerulea", + "Spizella passerina", + "Pycnonotus jocosus", + "Passerina cyanea", + "Passerina versicolor", + "Manorina melanocephala", + "Ocyphaps lophotes", + "Jabiru mycteria", + "Pycnonotus cafer", + "Anser cygnoides domesticus", + "Picus viridis", + "Phoebastria nigripes", + "Struthio camelus", + "Phoebastria immutabilis", + "Fulmarus glacialis", + "Francolinus pondicerianus", + "Cynanthus latirostris", + "Podiceps nigricollis", + "Podiceps cristatus", + "Podiceps auritus", + "Dendrocopos major", + "Podiceps grisegena", + "Tachybaptus ruficollis", + "Charadrius montanus", + "Phalacrocorax auritus", + "Phalacrocorax carbo", + "Phalacrocorax penicillatus", + "Aechmophorus clarkii", + "Pelecanus onocrotalus", + "Pelecanus erythrorhynchos", + "Zenaida macroura", + "Vanellus miles", + "Larus occidentalis", + "Trogon massena", + "Larus thayeri", + "Larus heermanni", + "Larus livens", + "Larus canus", + "Larus glaucoides", + "Larus delawarensis", + "Trogon collaris", + "Zenaida asiatica", + "Larus fuscus", + "Larus californicus", + "Prosthemadera novaeseelandiae", + "Trogon elegans", + "Larus glaucescens", + "Trogon citreolus", + "Cepphus columba", + "Himantopus leucocephalus", + "Cepphus grylle", + "Anthornis melanura", + "Leptoptilos crumenifer", + "Threskiornis moluccus", + "Thraupis episcopus", + "Geranoaetus albicaudatus", + "Sterna paradisaea", + "Sterna hirundo", + "Sterna forsteri", + "Lanius excubitor", + "Pharomachrus mocinno", + "Sterna striata", + "Stercorarius parasiticus", + "Stercorarius pomarinus", + "Anas gracilis", + "Rissa tridactyla", + "Rynchops niger", + "Alca torda", + "Fratercula arctica", + "Fratercula cirrhata", + "Turdus merula", + "Turdus plumbeus", + "Turdus grayi", + "Turdus migratorius", + "Turdus viscivorus", + "Cerorhinca monocerata", + "Turdus philomelos", + "Galbula ruficauda", + "Jacana spinosa", + "Saxicola rubicola", + "Upupa epops", + "Euphagus carolinus", + "Gavia pacifica", + "Mimus gilvus", + "Passer italiae", + "Gavia immer", + "Gavia stellata", + "Oenanthe oenanthe", + "Fregata magnificens", + "Fregata minor", + "Falco subbuteo", + "Falco mexicanus", + "Falco femoralis", + "Falco peregrinus", + "Falco rufigularis", + "Falco sparverius", + "Strix varia", + "Falco columbarius", + "Gallinula chloropus", + "Cardellina pusilla", + "Catharus ustulatus", + "Falco novaeseelandiae", + "Catharus guttatus", + "Catharus fuscescens", + "Caracara cheriway", + "Herpetotheres cachinnans", + "Calcarius lapponicus", + "Milvago chimachima", + "Ciconia ciconia", + "Mycteria americana", + "Mycteria ibis", + "Sialia mexicana", + "Ephippiorhynchus senegalensis", + "Cathartes aura", + "Myadestes townsendi", + "Cathartes burrovianus", + "Sarcoramphus papa", + "Coragyps atratus", + "Strix nebulosa", + "Anastomus lamelligerus", + "Pluvialis squatarola", + "Gymnogyps californianus", + "Muscicapa striata", + "Charadrius vociferus", + "Charadrius wilsonia", + "Charadrius melodus", + "Phoenicurus phoenicurus", + "Phoenicurus ochruros", + "Charadrius dubius", + "Eumomota superciliosa", + "Anas querquedula", + "Himantopus mexicanus", + "Haematopus bachmani", + "Pica pica", + "Haematopus ostralegus", + "Haematopus unicolor", + "Vanellus vanellus", + "Vanellus spinosus", + "Vanellus armatus", + "Luscinia svecica", + "Columbina inca", + "Recurvirostra avosetta", + "Phasianus colchicus", + "Pluvialis dominica", + "Cinclus mexicanus", + "Erithacus rubecula", + "Melanerpes aurifrons", + "Charadrius hiaticula", + "Egretta gularis", + "Egretta caerulea", + "Egretta tricolor", + "Egretta thula", + "Egretta garzetta", + "Egretta sacra", + "Monticola solitarius", + "Ardea cocoi", + "Ardea cinerea", + "Ardea herodias", + "Nycticorax nycticorax", + "Turdus rufopalliatus", + "Ardeola ralloides", + "Nyctanassa violacea", + "Aramides cajaneus", + "Bubulcus ibis", + "Butorides virescens", + "Porphyrio martinicus", + "Botaurus lentiginosus", + "Cochlearius cochlearius", + "Anhinga novaehollandiae", + "Anhinga rufa", + "Melozone fusca", + "Aquila chrysaetos", + "Hylocichla mustelina", + "Aphelocoma wollweberi", + "Accipiter striatus", + "Accipiter nisus", + "Accipiter gentilis", + "Egretta rufescens", + "Bucephala clangula", + "Anous stolidus", + "Actitis macularius", + "Ardea purpurea", + "Todiramphus chloris", + "Grus americana", + "Himantopus himantopus", + "Glaucidium gnoma", + "Circus approximans", + "Circus aeruginosus", + "Phalacrocorax sulcirostris", + "Buteo albonotatus", + "Butorides striata", + "Platalea ajaja", + "Buteo brachyurus", + "Ardea alba", + "Buteo swainsoni", + "Alectoris rufa", + "Buteo lineatus", + "Buteo jamaicensis", + "Charadrius nivosus", + "Tringa incana", + "Tringa semipalmata", + "Terathopius ecaudatus", + "Gallinago delicata", + "Buteogallus anthracinus", + "Chroicocephalus philadelphia", + "Circaetus gallicus", + "Chroicocephalus novaehollandiae", + "Chroicocephalus ridibundus", + "Leucophaeus atricilla", + "Leucophaeus pipixcan", + "Onychoprion fuscatus", + "Sternula antillarum", + "Hydroprogne caspia", + "Thalasseus maximus", + "Thalasseus bergii", + "Elanus leucurus", + "Alopochen aegyptiaca", + "Streptopelia senegalensis", + "Gerygone igata", + "Haliaeetus leucocephalus", + "Cistothorus platensis", + "Haliaeetus vocifer", + "Bubo scandiacus", + "Ciccaba virgata", + "Bonasa umbellus", + "Busarellus nigricollis", + "Rostrhamus sociabilis", + "Milvus milvus", + "Gyps fulvus", + "Ficedula hypoleuca", + "Momotus coeruliceps", + "Charadrius semipalmatus", + "Haliastur indus", + "Gyps africanus", + "Ictinia mississippiensis", + "Dives dives", + "Baeolophus atricristatus", + "Baeolophus bicolor", + "Baeolophus inornatus", + "Melospiza melodia", + "Spinus spinus", + "Motacilla alba", + "Certhia americana", + "Bucorvus leadbeateri", + "Anthus pratensis", + "Anthus rubescens", + "Tachycineta albilinea", + "Poecile carolinensis", + "Poecile atricapillus", + "Poecile gambeli", + "Poecile rufescens", + "Periparus ater", + "Chlorophanes spiza", + "Estrilda astrild", + "Cyanistes caeruleus", + "Sphyrapicus varius", + "Petrochelidon pyrrhonota", + "Troglodytes pacificus", + "Troglodytes hiemalis", + "Passer montanus", + "Passer domesticus", + "Aphelocoma californica", + "Amazilia yucatanensis", + "Amazilia tzacatl", + "Dicrurus adsimilis", + "Amazilia violiceps", + "Lonchura punctulata", + "Tigrisoma mexicanum", + "Porphyrio melanotus melanotus", + "Melanitta americana", + "Spizella pallida", + "Amazilia rutila", + "Zenaida aurita", + "Prunella modularis", + "Falco tinnunculus", + "Ixoreus naevius", + "Archilochus colubris", + "Lampornis clemenciae", + "Myiarchus tuberculifer", + "Setophaga ruticilla", + "Myiarchus tyrannulus", + "Zosterops lateralis", + "Zonotrichia leucophrys", + "Agelaius phoeniceus", + "Parus major", + "Zonotrichia capensis", + "Oreothlypis peregrina", + "Oreothlypis celata", + "Oreothlypis ruficapilla", + "Geothlypis philadelphia", + "Geothlypis formosa", + "Setophaga tigrina", + "Setophaga americana", + "Setophaga magnolia", + "Setophaga castanea", + "Setophaga fusca", + "Setophaga petechia", + "Setophaga striata", + "Setophaga palmarum", + "Setophaga pinus", + "Setophaga coronata", + "Setophaga dominica", + "Campylopterus hemileucurus", + "Vireo cassinii", + "Setophaga nigrescens", + "Setophaga townsendi", + "Setophaga occidentalis", + "Setophaga chrysoparia", + "Setophaga virens", + "Cardellina canadensis", + "Cardellina rubra", + "Aphelocoma coerulescens", + "Melanerpes erythrocephalus", + "Emberiza calandra", + "Acanthis flammea", + "Spinus pinus", + "Thraupis abbas", + "Spinus psaltria", + "Spinus lawrencei", + "Spinus tristis", + "Threskiornis aethiopicus", + "Gygis alba", + "Tachycineta bicolor", + "Larus dominicanus dominicanus", + "Lonchura oryzivora", + "Haematopus palliatus", + "Chloris chloris", + "Accipiter cooperii", + "Vireo solitarius", + "Selasphorus platycercus", + "Chroicocephalus scopulinus", + "Aechmophorus occidentalis", + "Hemiphaga novaeseelandiae", + "Xema sabini", + "Ramphastos sulfuratus", + "Dacelo novaeguineae", + "Fulica atra", + "Hirundo rustica erythrogaster", + "Calypte costae", + "Calypte anna", + "Colaptes auratus cafer", + "Sula nebouxii", + "Copsychus saularis", + "Selasphorus sasin", + "Selasphorus rufus", + "Calothorax lucifer", + "Pycnonotus barbatus", + "Larus glaucescens × occidentalis", + "Aphelocoma woodhouseii", + "Florisuga mellivora", + "Haematopus finschi", + "Falcipennis canadensis", + "Archilochus alexandri", + "Circus cyaneus", + "Ardea alba modesta", + "Myiarchus crinitus", + "Buteo regalis", + "Aeronautes saxatalis", + "Chaetura vauxi", + "Chaetura pelagica", + "Setophaga pensylvanica", + "Lanius ludovicianus", + "Anhinga anhinga", + "Acridotheres tristis", + "Sitta pygmaea", + "Actophilornis africanus", + "Sitta canadensis", + "Sitta europaea", + "Sitta pusilla", + "Apus apus", + "Sturnus vulgaris", + "Seiurus aurocapilla", + "Motacilla flava", + "Vireo griseus", + "Toxostoma longirostre", + "Calidris alba", + "Toxostoma redivivum", + "Gallinula galeata", + "Calidris himantopus", + "Eugenes fulgens", + "Icterus wagleri", + "Icterus parisorum", + "Buteo platypterus", + "Gallinago gallinago", + "Icterus spurius", + "Calidris minutilla", + "Dumetella carolinensis", + "Porphyrio hochstetteri", + "Calidris fuscicollis", + "Phalaropus tricolor", + "Colaptes auratus auratus", + "Melanotis caerulescens", + "Tiaris olivaceus", + "Oreoscoptes montanus", + "Limnodromus scolopaceus", + "Tringa solitaria", + "Sitta carolinensis", + "Tringa totanus", + "Dendrocygna autumnalis", + "Dendrocygna viduata", + "Dendrocygna bicolor", + "Icterus abeillei", + "Vanellus chilensis", + "Cygnus buccinator", + "Cygnus cygnus", + "Cygnus columbianus", + "Cygnus olor", + "Icterus galbula", + "Anas platyrhynchos", + "Anas acuta", + "Anas crecca", + "Anas cyanoptera", + "Anas fulvigula", + "Anas discors", + "Anas strepera", + "Anas clypeata", + "Anas chlorotis", + "Rhipidura leucophrys", + "Anas americana", + "Bucephala albeola", + "Mergus serrator", + "Mergus merganser", + "Anser anser", + "Anser albifrons", + "Somateria mollissima", + "Rallus obsoletus", + "Platycercus elegans", + "Melanitta fusca", + "Milvus migrans", + "Gelochelidon nilotica", + "Ninox novaeseelandiae novaeseelandiae", + "Melanitta perspicillata", + "Aythya collaris", + "Aythya ferina", + "Aythya fuligula", + "Numenius americanus", + "Chen caerulescens", + "Chamaea fasciata", + "Branta canadensis", + "Thalasseus elegans", + "Branta sandvicensis", + "Aythya americana", + "Aix sponsa", + "Lophodytes cucullatus", + "Histrionicus histrionicus", + "Aratinga nenday", + "Psittacara holochlorus", + "Cairina moschata", + "Netta rufina", + "Psittacara erythrogenys", + "Sayornis saya", + "Aythya valisineria", + "Picoides albolarvatus", + "Vermivora cyanoptera", + "Corvus caurinus", + "Asio otus", + "Corvus brachyrhynchos", + "Clangula hyemalis", + "Chenonetta jubata", + "Thalasseus sandvicensis", + "Eolophus roseicapilla", + "Colaptes rubiginosus", + "Meleagris gallopavo silvestris", + "Ptiliogonys cinereus", + "Elanoides forficatus", + "Carduelis carduelis", + "Cassiculus melanicterus", + "Dendragapus fuliginosus", + "Psaltriparus minimus", + "Aegithalos caudatus", + "Zosterops lateralis lateralis", + "Haliaeetus leucogaster", + "Uria aalge", + "Tringa semipalmata inornatus", + "Alauda arvensis", + "Galerida cristata", + "Delichon urbicum", + "Helmitheros vermivorum", + "Hylocharis leucotis", + "Mimus polyglottos", + "Gymnorhina tibicen", + "Alcedo atthis", + "Streptopelia chinensis", + "Bombycilla cedrorum", + "Bombycilla garrulus", + "Tadorna tadorna", + "Petroica australis australis", + "Amazona autumnalis", + "Dendragapus obscurus", + "Catherpes mexicanus", + "Tadorna ferruginea", + "Campylorhynchus brunneicapillus", + "Campylorhynchus rufinucha", + "Rhipidura fuliginosa", + "Polioptila melanura", + "Pelecanus occidentalis carolinensis", + "Melozone aberti", + "Melozone crissalis", + "Thryothorus ludovicianus", + "Parabuteo unicinctus", + "Anas platyrhynchos domesticus", + "Troglodytes aedon", + "Buteo lineatus elegans", + "Thamnophilus doliatus", + "Thryomanes bewickii", + "Tadorna variegata", + "Myioborus miniatus", + "Phalacrocorax varius varius", + "Myioborus pictus", + "Larus argentatus smithsonianus", + "Parkesia motacilla", + "Sula granti", + "Ara macao", + "Peucaea ruficauda", + "Calidris subruficollis", + "Phoenicopterus roseus", + "Morus bassanus", + "Pelecanus occidentalis californicus", + "Glaucidium brasilianum", + "Oxyura jamaicensis", + "Myiarchus cinerascens", + "Chloroceryle americana", + "Sturnella neglecta", + "Ramphastos ambiguus", + "Paroaria coronata", + "Buteo buteo", + "Myiodynastes luteiventris", + "Contopus sordidulus", + "Corvus corone", + "Cyanoramphus novaezelandiae", + "Contopus virens", + "Contopus pertinax", + "Contopus cooperi", + "Larus argentatus", + "Halcyon smyrnensis", + "Onychognathus morio", + "Cyanocompsa parellina", + "Cistothorus palustris", + "Tyto alba", + "Trogon caligatus", + "Corvus monedula", + "Corvus ossifragus", + "Spheniscus demersus", + "Corvus frugilegus", + "Corvus splendens", + "Branta bernicla", + "Larus hyperboreus", + "Columba livia domestica", + "Garrulus glandarius", + "Anser anser domesticus", + "Mitrephanes phaeocercus", + "Ardenna creatopus", + "Ardenna gravis", + "background", +]; diff --git a/tf-mobilenet-image/rust/tf-mobilenet/src/main.rs b/tf-mobilenet-image/rust/tf-mobilenet/src/main.rs new file mode 100644 index 0000000..0edda61 --- /dev/null +++ b/tf-mobilenet-image/rust/tf-mobilenet/src/main.rs @@ -0,0 +1,129 @@ +use std::convert::TryInto; +use std::env; +use std::fs; +use std::fs::File; +use std::io::Read; +use wasi_nn; +mod imagenet_classes; + +pub fn main() { + main_entry(); +} + +#[no_mangle] +fn main_entry() { + infer_image(); +} + +fn infer_image() { + let args: Vec = env::args().collect(); + let model_bin_name: &str = &args[1]; + let image_name: &str = &args[2]; + + let weights = fs::read(model_bin_name).unwrap(); + let tagset = ""; + let signature = "image_classifier"; + println!("Read graph weights, size in bytes: {}", weights.len()); + + let graph = unsafe { + wasi_nn::load( + &[&weights, &tagset.as_bytes(), &signature.as_bytes()], + wasi_nn::GRAPH_ENCODING_TENSORFLOW, // encoding for tflite + wasi_nn::EXECUTION_TARGET_CPU, + ) + .unwrap() + }; + println!("Loaded graph into wasi-nn with ID: {}", graph); + + let context = unsafe { wasi_nn::init_execution_context(graph).unwrap() }; + println!("Created wasi-nn execution context with ID: {}", context); + + // Load a tensor that precisely matches the graph input tensor (see + let tensor_data = image_to_tensor(image_name.to_string(), 224, 224); + println!("Read input tensor, size in bytes: {}", tensor_data.len()); + let tensor = wasi_nn::Tensor { + dimensions: &[1, 224, 224, 3], + type_: wasi_nn::TENSOR_TYPE_F32, + data: &tensor_data, + }; + unsafe { + wasi_nn::set_input(context, 0, tensor).unwrap(); + } + println!("Set input done"); + // Execute the inference. + unsafe { + wasi_nn::compute(context).unwrap(); + } + println!("Executed graph inference"); + // Retrieve the output. + let mut output_buffer = vec![0f32; 965]; + unsafe { + wasi_nn::get_output( + context, + 0, + &mut output_buffer[..] as *mut [f32] as *mut u8, + (output_buffer.len() * 4).try_into().unwrap(), + ) + .unwrap(); + } + + let results = sort_results(&output_buffer); + for i in 0..5 { + println!( + " {}.) [{}]({:.4}){}", + i + 1, + results[i].0, + results[i].1, + imagenet_classes::AIY_BIRDS_V1[results[i].0] + ); + } +} + +// Sort the buffer of probabilities. The graph places the match probability for each class at the +// index for that class (e.g. the probability of class 42 is placed at buffer[42]). Here we convert +// to a wrapping InferenceResult and sort the results. +fn sort_results(buffer: &[f32]) -> Vec { + let mut results: Vec = buffer + .iter() + .enumerate() + .map(|(c, p)| InferenceResult(c, *p)) + .collect(); + results.sort_by(|a, b| b.1.partial_cmp(&a.1).unwrap()); + results +} + +// Take the image located at 'path', open it, resize it to height x width, and then converts +// the pixel precision to FP32. The resulting BGR pixel vector is then returned. +fn image_to_tensor(path: String, height: u32, width: u32) -> Vec { + let mut file_img = File::open(path).unwrap(); + let mut img_buf = Vec::new(); + file_img.read_to_end(&mut img_buf).unwrap(); + let img = image::load_from_memory(&img_buf).unwrap().to_rgb8(); + let resized = + image::imageops::resize(&img, height, width, ::image::imageops::FilterType::Triangle); + let mut flat_img: Vec = Vec::new(); + for rgb in resized.pixels() { + flat_img.push(rgb[0] as f32 / 255.); + flat_img.push(rgb[1] as f32 / 255.); + flat_img.push(rgb[2] as f32 / 255.); + } + let bytes_required = flat_img.len() * 4; + let mut u8_f32_arr: Vec = vec![0; bytes_required]; + + for c in 0..3 { + for i in 0..(flat_img.len() / 3) { + // Read the number as a f32 and break it into u8 bytes + let u8_f32: f32 = flat_img[i * 3 + c] as f32; + let u8_bytes = u8_f32.to_ne_bytes(); + + for j in 0..4 { + u8_f32_arr[((i * 3 + c) * 4) + j] = u8_bytes[j]; + } + } + } + return u8_f32_arr; +} + +// A wrapper for class ID and match probabilities. +#[derive(Debug, PartialEq)] +struct InferenceResult(usize, f32); diff --git a/tf-mobilenet-image/saved_model.pb b/tf-mobilenet-image/saved_model.pb new file mode 100644 index 0000000..f10b5a3 Binary files /dev/null and b/tf-mobilenet-image/saved_model.pb differ diff --git a/tf-mobilenet-image/wasmedge-wasinn-example-tf-mobilenet-image.wasm b/tf-mobilenet-image/wasmedge-wasinn-example-tf-mobilenet-image.wasm new file mode 100755 index 0000000..1e12f72 Binary files /dev/null and b/tf-mobilenet-image/wasmedge-wasinn-example-tf-mobilenet-image.wasm differ