diff --git a/csharp/sample/Microsoft.ML.OnnxRuntime.ResNet50v2Sample/LabelMap.cs b/csharp/sample/Microsoft.ML.OnnxRuntime.ResNet50v2Sample/LabelMap.cs new file mode 100644 index 0000000000..90cb514c6f --- /dev/null +++ b/csharp/sample/Microsoft.ML.OnnxRuntime.ResNet50v2Sample/LabelMap.cs @@ -0,0 +1,1006 @@ +namespace Microsoft.ML.OnnxRuntime.ResNet50v2Sample +{ + public class LabelMap + { + public static readonly string[] Labels = new[] {"tench", + "goldfish", + "great white shark", + "tiger shark", + "hammerhead shark", + "electric ray", + "stingray", + "cock", + "hen", + "ostrich", + "brambling", + "goldfinch", + "house finch", + "junco", + "indigo bunting", + "American robin", + "bulbul", + "jay", + "magpie", + "chickadee", + "American dipper", + "kite", + "bald eagle", + "vulture", + "great grey owl", + "fire salamander", + "smooth newt", + "newt", + "spotted salamander", + "axolotl", + "American bullfrog", + "tree frog", + "tailed frog", + "loggerhead sea turtle", + "leatherback sea turtle", + "mud turtle", + "terrapin", + "box turtle", + "banded gecko", + "green iguana", + "Carolina anole", + "desert grassland whiptail lizard", + "agama", + "frilled-necked lizard", + "alligator lizard", + "Gila monster", + "European green lizard", + "chameleon", + "Komodo dragon", + "Nile crocodile", + "American alligator", + "triceratops", + "worm snake", + "ring-necked snake", + "eastern hog-nosed snake", + "smooth green snake", + "kingsnake", + "garter snake", + "water snake", + "vine snake", + "night snake", + "boa constrictor", + "African rock python", + "Indian cobra", + "green mamba", + "sea snake", + "Saharan horned viper", + "eastern diamondback rattlesnake", + "sidewinder", + "trilobite", + "harvestman", + "scorpion", + "yellow garden spider", + "barn spider", + "European garden spider", + "southern black widow", + "tarantula", + "wolf spider", + "tick", + "centipede", + "black grouse", + "ptarmigan", + "ruffed grouse", + "prairie grouse", + "peacock", + "quail", + "partridge", + "grey parrot", + "macaw", + "sulphur-crested cockatoo", + "lorikeet", + "coucal", + "bee eater", + "hornbill", + "hummingbird", + "jacamar", + "toucan", + "duck", + "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", + "red king crab", + "American lobster", + "spiny lobster", + "crayfish", + "hermit crab", + "isopod", + "white stork", + "black stork", + "spoonbill", + "flamingo", + "little blue heron", + "great egret", + "bittern", + "crane (bird)", + "limpkin", + "common gallinule", + "American coot", + "bustard", + "ruddy turnstone", + "dunlin", + "common redshank", + "dowitcher", + "oystercatcher", + "pelican", + "king penguin", + "albatross", + "grey whale", + "killer whale", + "dugong", + "sea lion", + "Chihuahua", + "Japanese Chin", + "Maltese", + "Pekingese", + "Shih Tzu", + "King Charles Spaniel", + "Papillon", + "toy terrier", + "Rhodesian Ridgeback", + "Afghan Hound", + "Basset Hound", + "Beagle", + "Bloodhound", + "Bluetick Coonhound", + "Black and Tan Coonhound", + "Treeing Walker Coonhound", + "English foxhound", + "Redbone Coonhound", + "borzoi", + "Irish Wolfhound", + "Italian Greyhound", + "Whippet", + "Ibizan Hound", + "Norwegian Elkhound", + "Otterhound", + "Saluki", + "Scottish Deerhound", + "Weimaraner", + "Staffordshire Bull Terrier", + "American Staffordshire Terrier", + "Bedlington Terrier", + "Border Terrier", + "Kerry Blue Terrier", + "Irish Terrier", + "Norfolk Terrier", + "Norwich Terrier", + "Yorkshire Terrier", + "Wire Fox Terrier", + "Lakeland Terrier", + "Sealyham Terrier", + "Airedale Terrier", + "Cairn Terrier", + "Australian Terrier", + "Dandie Dinmont Terrier", + "Boston Terrier", + "Miniature Schnauzer", + "Giant Schnauzer", + "Standard Schnauzer", + "Scottish Terrier", + "Tibetan Terrier", + "Australian Silky Terrier", + "Soft-coated Wheaten Terrier", + "West Highland White Terrier", + "Lhasa Apso", + "Flat-Coated Retriever", + "Curly-coated Retriever", + "Golden Retriever", + "Labrador Retriever", + "Chesapeake Bay Retriever", + "German Shorthaired Pointer", + "Vizsla", + "English Setter", + "Irish Setter", + "Gordon Setter", + "Brittany", + "Clumber Spaniel", + "English Springer Spaniel", + "Welsh Springer Spaniel", + "Cocker Spaniels", + "Sussex Spaniel", + "Irish Water Spaniel", + "Kuvasz", + "Schipperke", + "Groenendael", + "Malinois", + "Briard", + "Australian Kelpie", + "Komondor", + "Old English Sheepdog", + "Shetland Sheepdog", + "collie", + "Border Collie", + "Bouvier des Flandres", + "Rottweiler", + "German Shepherd Dog", + "Dobermann", + "Miniature Pinscher", + "Greater Swiss Mountain Dog", + "Bernese Mountain Dog", + "Appenzeller Sennenhund", + "Entlebucher Sennenhund", + "Boxer", + "Bullmastiff", + "Tibetan Mastiff", + "French Bulldog", + "Great Dane", + "St. Bernard", + "husky", + "Alaskan Malamute", + "Siberian Husky", + "Dalmatian", + "Affenpinscher", + "Basenji", + "pug", + "Leonberger", + "Newfoundland", + "Pyrenean Mountain Dog", + "Samoyed", + "Pomeranian", + "Chow Chow", + "Keeshond", + "Griffon Bruxellois", + "Pembroke Welsh Corgi", + "Cardigan Welsh Corgi", + "Toy Poodle", + "Miniature Poodle", + "Standard Poodle", + "Mexican hairless dog", + "grey wolf", + "Alaskan tundra wolf", + "red wolf", + "coyote", + "dingo", + "dhole", + "African wild dog", + "hyena", + "red fox", + "kit fox", + "Arctic fox", + "grey fox", + "tabby cat", + "tiger cat", + "Persian cat", + "Siamese cat", + "Egyptian Mau", + "cougar", + "lynx", + "leopard", + "snow leopard", + "jaguar", + "lion", + "tiger", + "cheetah", + "brown bear", + "American black bear", + "polar bear", + "sloth bear", + "mongoose", + "meerkat", + "tiger beetle", + "ladybug", + "ground beetle", + "longhorn beetle", + "leaf beetle", + "dung beetle", + "rhinoceros beetle", + "weevil", + "fly", + "bee", + "ant", + "grasshopper", + "cricket", + "stick insect", + "cockroach", + "mantis", + "cicada", + "leafhopper", + "lacewing", + "dragonfly", + "damselfly", + "red admiral", + "ringlet", + "monarch butterfly", + "small white", + "sulphur butterfly", + "gossamer-winged butterfly", + "starfish", + "sea urchin", + "sea cucumber", + "cottontail rabbit", + "hare", + "Angora rabbit", + "hamster", + "porcupine", + "fox squirrel", + "marmot", + "beaver", + "guinea pig", + "common sorrel", + "zebra", + "pig", + "wild boar", + "warthog", + "hippopotamus", + "ox", + "water buffalo", + "bison", + "ram", + "bighorn sheep", + "Alpine ibex", + "hartebeest", + "impala", + "gazelle", + "dromedary", + "llama", + "weasel", + "mink", + "European polecat", + "black-footed ferret", + "otter", + "skunk", + "badger", + "armadillo", + "three-toed sloth", + "orangutan", + "gorilla", + "chimpanzee", + "gibbon", + "siamang", + "guenon", + "patas monkey", + "baboon", + "macaque", + "langur", + "black-and-white colobus", + "proboscis monkey", + "marmoset", + "white-headed capuchin", + "howler monkey", + "titi", + "Geoffroy's spider monkey", + "common squirrel monkey", + "ring-tailed lemur", + "indri", + "Asian elephant", + "African bush elephant", + "red panda", + "giant panda", + "snoek", + "eel", + "coho salmon", + "rock beauty", + "clownfish", + "sturgeon", + "garfish", + "lionfish", + "pufferfish", + "abacus", + "abaya", + "academic gown", + "accordion", + "acoustic guitar", + "aircraft carrier", + "airliner", + "airship", + "altar", + "ambulance", + "amphibious vehicle", + "analog clock", + "apiary", + "apron", + "waste container", + "assault rifle", + "backpack", + "bakery", + "balance beam", + "balloon", + "ballpoint pen", + "Band-Aid", + "banjo", + "baluster", + "barbell", + "barber chair", + "barbershop", + "barn", + "barometer", + "barrel", + "wheelbarrow", + "baseball", + "basketball", + "bassinet", + "bassoon", + "swimming cap", + "bath towel", + "bathtub", + "station wagon", + "lighthouse", + "beaker", + "military cap", + "beer bottle", + "beer glass", + "bell-cot", + "bib", + "tandem bicycle", + "bikini", + "ring binder", + "binoculars", + "birdhouse", + "boathouse", + "bobsleigh", + "bolo tie", + "poke bonnet", + "bookcase", + "bookstore", + "bottle cap", + "bow", + "bow tie", + "brass", + "bra", + "breakwater", + "breastplate", + "broom", + "bucket", + "buckle", + "bulletproof vest", + "high-speed train", + "butcher shop", + "taxicab", + "cauldron", + "candle", + "cannon", + "canoe", + "can opener", + "cardigan", + "car mirror", + "carousel", + "tool kit", + "carton", + "car wheel", + "automated teller machine", + "cassette", + "cassette player", + "castle", + "catamaran", + "CD player", + "cello", + "mobile phone", + "chain", + "chain-link fence", + "chain mail", + "chainsaw", + "chest", + "chiffonier", + "chime", + "china cabinet", + "Christmas stocking", + "church", + "movie theater", + "cleaver", + "cliff dwelling", + "cloak", + "clogs", + "cocktail shaker", + "coffee mug", + "coffeemaker", + "coil", + "combination lock", + "computer keyboard", + "confectionery store", + "container ship", + "convertible", + "corkscrew", + "cornet", + "cowboy boot", + "cowboy hat", + "cradle", + "crane (machine)", + "crash helmet", + "crate", + "infant bed", + "Crock Pot", + "croquet ball", + "crutch", + "cuirass", + "dam", + "desk", + "desktop computer", + "rotary dial telephone", + "diaper", + "digital clock", + "digital watch", + "dining table", + "dishcloth", + "dishwasher", + "disc brake", + "dock", + "dog sled", + "dome", + "doormat", + "drilling rig", + "drum", + "drumstick", + "dumbbell", + "Dutch oven", + "electric fan", + "electric guitar", + "electric locomotive", + "entertainment center", + "envelope", + "espresso machine", + "face powder", + "feather boa", + "filing cabinet", + "fireboat", + "fire engine", + "fire screen sheet", + "flagpole", + "flute", + "folding chair", + "football helmet", + "forklift", + "fountain", + "fountain pen", + "four-poster bed", + "freight car", + "French horn", + "frying pan", + "fur coat", + "garbage truck", + "gas mask", + "gas pump", + "goblet", + "go-kart", + "golf ball", + "golf cart", + "gondola", + "gong", + "gown", + "grand piano", + "greenhouse", + "grille", + "grocery store", + "guillotine", + "barrette", + "hair spray", + "half-track", + "hammer", + "hamper", + "hair dryer", + "hand-held computer", + "handkerchief", + "hard disk drive", + "harmonica", + "harp", + "harvester", + "hatchet", + "holster", + "home theater", + "honeycomb", + "hook", + "hoop skirt", + "horizontal bar", + "horse-drawn vehicle", + "hourglass", + "iPod", + "clothes iron", + "jack-o'-lantern", + "jeans", + "jeep", + "T-shirt", + "jigsaw puzzle", + "pulled rickshaw", + "joystick", + "kimono", + "knee pad", + "knot", + "lab coat", + "ladle", + "lampshade", + "laptop computer", + "lawn mower", + "lens cap", + "paper knife", + "library", + "lifeboat", + "lighter", + "limousine", + "ocean liner", + "lipstick", + "slip-on shoe", + "lotion", + "speaker", + "loupe", + "sawmill", + "magnetic compass", + "mail bag", + "mailbox", + "tights", + "tank suit", + "manhole cover", + "maraca", + "marimba", + "mask", + "match", + "maypole", + "maze", + "measuring cup", + "medicine chest", + "megalith", + "microphone", + "microwave oven", + "military uniform", + "milk can", + "minibus", + "miniskirt", + "minivan", + "missile", + "mitten", + "mixing bowl", + "mobile home", + "Model T", + "modem", + "monastery", + "monitor", + "moped", + "mortar", + "square academic cap", + "mosque", + "mosquito net", + "scooter", + "mountain bike", + "tent", + "computer mouse", + "mousetrap", + "moving van", + "muzzle", + "nail", + "neck brace", + "necklace", + "nipple", + "notebook computer", + "obelisk", + "oboe", + "ocarina", + "odometer", + "oil filter", + "organ", + "oscilloscope", + "overskirt", + "bullock cart", + "oxygen mask", + "packet", + "paddle", + "paddle wheel", + "padlock", + "paintbrush", + "pajamas", + "palace", + "pan flute", + "paper towel", + "parachute", + "parallel bars", + "park bench", + "parking meter", + "passenger car", + "patio", + "payphone", + "pedestal", + "pencil case", + "pencil sharpener", + "perfume", + "Petri dish", + "photocopier", + "plectrum", + "Pickelhaube", + "picket fence", + "pickup truck", + "pier", + "piggy bank", + "pill bottle", + "pillow", + "ping-pong ball", + "pinwheel", + "pirate ship", + "pitcher", + "hand plane", + "planetarium", + "plastic bag", + "plate rack", + "plow", + "plunger", + "Polaroid camera", + "pole", + "police van", + "poncho", + "billiard table", + "soda bottle", + "pot", + "potter's wheel", + "power drill", + "prayer rug", + "printer", + "prison", + "projectile", + "projector", + "hockey puck", + "punching bag", + "purse", + "quill", + "quilt", + "race car", + "racket", + "radiator", + "radio", + "radio telescope", + "rain barrel", + "recreational vehicle", + "reel", + "reflex camera", + "refrigerator", + "remote control", + "restaurant", + "revolver", + "rifle", + "rocking chair", + "rotisserie", + "eraser", + "rugby ball", + "ruler", + "running shoe", + "safe", + "safety pin", + "salt shaker", + "sandal", + "sarong", + "saxophone", + "scabbard", + "weighing scale", + "school bus", + "schooner", + "scoreboard", + "CRT screen", + "screw", + "screwdriver", + "seat belt", + "sewing machine", + "shield", + "shoe store", + "shoji", + "shopping basket", + "shopping cart", + "shovel", + "shower cap", + "shower curtain", + "ski", + "ski mask", + "sleeping bag", + "slide rule", + "sliding door", + "slot machine", + "snorkel", + "snowmobile", + "snowplow", + "soap dispenser", + "soccer ball", + "sock", + "solar thermal collector", + "sombrero", + "soup bowl", + "space bar", + "space heater", + "space shuttle", + "spatula", + "motorboat", + "spider web", + "spindle", + "sports car", + "spotlight", + "stage", + "steam locomotive", + "through arch bridge", + "steel drum", + "stethoscope", + "scarf", + "stone wall", + "stopwatch", + "stove", + "strainer", + "tram", + "stretcher", + "couch", + "stupa", + "submarine", + "suit", + "sundial", + "sunglass", + "sunglasses", + "sunscreen", + "suspension bridge", + "mop", + "sweatshirt", + "swimsuit", + "swing", + "switch", + "syringe", + "table lamp", + "tank", + "tape player", + "teapot", + "teddy bear", + "television", + "tennis ball", + "thatched roof", + "front curtain", + "thimble", + "threshing machine", + "throne", + "tile roof", + "toaster", + "tobacco shop", + "toilet seat", + "torch", + "totem pole", + "tow truck", + "toy store", + "tractor", + "semi-trailer truck", + "tray", + "trench coat", + "tricycle", + "trimaran", + "tripod", + "triumphal arch", + "trolleybus", + "trombone", + "tub", + "turnstile", + "typewriter keyboard", + "umbrella", + "unicycle", + "upright piano", + "vacuum cleaner", + "vase", + "vault", + "velvet", + "vending machine", + "vestment", + "viaduct", + "violin", + "volleyball", + "waffle iron", + "wall clock", + "wallet", + "wardrobe", + "military aircraft", + "sink", + "washing machine", + "water bottle", + "water jug", + "water tower", + "whiskey jug", + "whistle", + "wig", + "window screen", + "window shade", + "Windsor tie", + "wine bottle", + "wing", + "wok", + "wooden spoon", + "wool", + "split-rail fence", + "shipwreck", + "yawl", + "yurt", + "website", + "comic book", + "crossword", + "traffic sign", + "traffic light", + "dust jacket", + "menu", + "plate", + "guacamole", + "consomme", + "hot pot", + "trifle", + "ice cream", + "ice pop", + "baguette", + "bagel", + "pretzel", + "cheeseburger", + "hot dog", + "mashed potato", + "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 syrup", + "dough", + "meatloaf", + "pizza", + "pot pie", + "burrito", + "red wine", + "espresso", + "cup", + "eggnog", + "alp", + "bubble", + "cliff", + "coral reef", + "geyser", + "lakeshore", + "promontory", + "shoal", + "seashore", + "valley", + "volcano", + "baseball player", + "bridegroom", + "scuba diver", + "rapeseed", + "daisy", + "yellow lady's slipper", + "corn", + "acorn", + "rose hip", + "horse chestnut seed", + "coral fungus", + "agaric", + "gyromitra", + "stinkhorn mushroom", + "earth star", + "hen-of-the-woods", + "bolete", + "ear", + "toilet paper"}; + } +} \ No newline at end of file diff --git a/csharp/sample/Microsoft.ML.OnnxRuntime.ResNet50v2Sample/Microsoft.ML.OnnxRuntime.ResNet50v2Sample.csproj b/csharp/sample/Microsoft.ML.OnnxRuntime.ResNet50v2Sample/Microsoft.ML.OnnxRuntime.ResNet50v2Sample.csproj new file mode 100644 index 0000000000..504c667860 --- /dev/null +++ b/csharp/sample/Microsoft.ML.OnnxRuntime.ResNet50v2Sample/Microsoft.ML.OnnxRuntime.ResNet50v2Sample.csproj @@ -0,0 +1,14 @@ + + + + Exe + netcoreapp3.1 + 8.0 + + + + + + + + diff --git a/csharp/sample/Microsoft.ML.OnnxRuntime.ResNet50v2Sample/Prediction.cs b/csharp/sample/Microsoft.ML.OnnxRuntime.ResNet50v2Sample/Prediction.cs new file mode 100644 index 0000000000..1a08f67fcd --- /dev/null +++ b/csharp/sample/Microsoft.ML.OnnxRuntime.ResNet50v2Sample/Prediction.cs @@ -0,0 +1,8 @@ +namespace Microsoft.ML.OnnxRuntime.ResNet50v2Sample +{ + internal class Prediction + { + public string Label { get; set; } + public float Confidence { get; set; } + } +} \ No newline at end of file diff --git a/csharp/sample/Microsoft.ML.OnnxRuntime.ResNet50v2Sample/Program.cs b/csharp/sample/Microsoft.ML.OnnxRuntime.ResNet50v2Sample/Program.cs new file mode 100644 index 0000000000..65afa6186c --- /dev/null +++ b/csharp/sample/Microsoft.ML.OnnxRuntime.ResNet50v2Sample/Program.cs @@ -0,0 +1,80 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using Microsoft.ML.OnnxRuntime.Tensors; +using SixLabors.ImageSharp; +using SixLabors.ImageSharp.Formats; +using SixLabors.ImageSharp.PixelFormats; +using SixLabors.ImageSharp.Processing; + +namespace Microsoft.ML.OnnxRuntime.ResNet50v2Sample +{ + class Program + { + public static void Main(string[] args) + { + // Read paths + string modelFilePath = args[0]; + string imageFilePath = args[1]; + + // Read image + using Image image = Image.Load(imageFilePath, out IImageFormat format); + + // Resize image + using Stream imageStream = new MemoryStream(); + image.Mutate(x => + { + x.Resize(new ResizeOptions + { + Size = new Size(224, 224), + Mode = ResizeMode.Crop + }); + }); + image.Save(imageStream, format); + + // Preprocess image + Tensor input = new DenseTensor(new[] { 1, 3, 224, 224 }); + var mean = new[] { 0.485f, 0.456f, 0.406f }; + var stddev = new[] { 0.229f, 0.224f, 0.225f }; + for (int y = 0; y < image.Height; y++) + { + Span pixelSpan = image.GetPixelRowSpan(y); + for (int x = 0; x < image.Width; x++) + { + input[0, 0, y, x] = ((pixelSpan[x].R / 255f) - mean[0]) / stddev[0]; + input[0, 1, y, x] = ((pixelSpan[x].G / 255f) - mean[1]) / stddev[1]; + input[0, 2, y, x] = ((pixelSpan[x].B / 255f) - mean[2]) / stddev[2]; + } + } + + // Setup inputs + var inputs = new List + { + NamedOnnxValue.CreateFromTensor("data", input) + }; + + // Run inference + using var session = new InferenceSession(modelFilePath); + using IDisposableReadOnlyCollection results = session.Run(inputs); + + // Postprocess to get softmax vector + IEnumerable output = results.First().AsEnumerable(); + float sum = output.Sum(x => (float)Math.Exp(x)); + IEnumerable softmax = output.Select(x => (float)Math.Exp(x) / sum); + + // Extract top 10 predicted classes + IEnumerable top10 = softmax.Select((x, i) => new Prediction { Label = LabelMap.Labels[i], Confidence = x }) + .OrderByDescending(x => x.Confidence) + .Take(10); + + // Print results to console + Console.WriteLine("Top 10 predictions for ResNet50 v2..."); + Console.WriteLine("--------------------------------------------------------------"); + foreach (var t in top10) + { + Console.WriteLine($"Label: {t.Label}, Confidence: {t.Confidence}"); + } + } + } +} diff --git a/csharp/sample/Microsoft.ML.OnnxRuntime.ResNet50v2Sample/README.md b/csharp/sample/Microsoft.ML.OnnxRuntime.ResNet50v2Sample/README.md new file mode 100644 index 0000000000..7e72547624 --- /dev/null +++ b/csharp/sample/Microsoft.ML.OnnxRuntime.ResNet50v2Sample/README.md @@ -0,0 +1,169 @@ +# C# Sample: ResNet50 v2 + +The sample walks through how to run a pretrained ResNet50 v2 ONNX model using the Onnx Runtime C# API. + +The source code for this sample is available [here](Program.cs). + +## Prerequisites + +To run this sample, you'll need the following things: + +1. Install [.NET Core 3.1](https://dotnet.microsoft.com/download/dotnet-core/3.1) or higher for you OS (Mac, Windows or Linux). +2. Download the [ResNet50 v2](https://github.com/onnx/models/blob/master/vision/classification/resnet/model/resnet50-v2-7.onnx) ONNX model to your local system. +3. Download [this picture of a dog](dog.jpeg) to test the model. You can also use any image you like. + +## Getting Started + +Now we have everything set up, we can start adding code to run the model on the image. We'll do this in the main method of the program for simplicity. + +### Read paths + +Firstly, let's read the path to the model and path to the image we want to test in through program arguments: + +```cs +string modelFilePath = args[0]; +string imageFilePath = args[1]; +``` + +### Read image + +Next, we will read the image in using the cross-platform image library [ImageSharp](https://www.nuget.org/packages/SixLabors.ImageSharp): + +```cs +using Image image = Image.Load(imageFilePath, out IImageFormat format); +``` + +Note, we're specifically reading the `Rgb24` type so we can efficiently preprocess the image in a later step. + +### Resize image + +Next, we will resize the image to the appropriate size that the model is expecting; 224 pixels by 224 pixels: + +```cs +using Stream imageStream = new MemoryStream(); +image.Mutate(x => +{ + x.Resize(new ResizeOptions + { + Size = new Size(224, 224), + Mode = ResizeMode.Crop + }); +}); +image.Save(imageStream, format); +``` + +Note, we're doing a centered crop resize to preserve aspect ratio. + +### Preprocess image + +Next, we will preprocess the image according to the [requirements of the model](https://github.com/onnx/models/tree/master/vision/classification/resnet#preprocessing): + +```cs +Tensor input = new DenseTensor(new[] { 1, 3, 224, 224 }); +var mean = new[] { 0.485f, 0.456f, 0.406f }; +var stddev = new[] { 0.229f, 0.224f, 0.225f }; +for (int y = 0; y < image.Height; y++) +{ + Span pixelSpan = image.GetPixelRowSpan(y); + for (int x = 0; x < image.Width; x++) + { + input[0, 0, y, x] = ((pixelSpan[x].R / 255f) - mean[0]) / stddev[0]; + input[0, 1, y, x] = ((pixelSpan[x].G / 255f) - mean[1]) / stddev[1]; + input[0, 2, y, x] = ((pixelSpan[x].B / 255f) - mean[2]) / stddev[2]; + } +} +``` + +Here, we're creating a Tensor of the required size `(batch-size, channels, height, width)`, accessing the pixel values, preprocessing them and finally assigning them to the tensor at the appropriate indicies. + +### Setup inputs + +Next, we will create the inputs to the model: + +```cs +var inputs = new List +{ + NamedOnnxValue.CreateFromTensor("data", input) +}; +``` + +To check the input node names for an ONNX model, you can use [Netron](https://github.com/lutzroeder/netron) to visualise the model and see input/output names. In this case, this model has `data` as the input node name. + +### Run inference + +Next, we will create an inference session and run the input through it: + +```cs +using var session = new InferenceSession(modelFilePath); +using IDisposableReadOnlyCollection results = session.Run(inputs); +``` + +### Postprocess output + +Next, we will need to postprocess the output to get the softmax vector, as this is not handled by the model itself: + +```cs +IEnumerable output = results.First().AsEnumerable(); +float sum = output.Sum(x => (float)Math.Exp(x)); +IEnumerable softmax = output.Select(x => (float)Math.Exp(x) / sum); +``` + +Other models may apply a Softmax node before the output, in which case you won't need this step. Again, you can use Netron to see the model outputs. + +### Extract top 10 + +Next, we will extract the top 10 class predictions: + +```cs +IEnumerable top10 = softmax.Select((x, i) => new Prediction { Label = LabelMap.Labels[i], Confidence = x }) + .OrderByDescending(x => x.Confidence) + .Take(10); +``` + +### Print results + +Next, we will print the top 10 results to the console: + +```cs +Console.WriteLine("Top 10 predictions for ResNet50 v2..."); +Console.WriteLine("--------------------------------------------------------------"); +foreach (var t in top10) +{ + Console.WriteLine($"Label: {t.Label}, Confidence: {t.Confidence}"); +} +``` + +## Running the program + +Now the program is created, we can run it will the following command: + +``` +dotnet run [path-to-model] [path-to-image] +``` + +e.g. + +``` +dotnet run ~/Downloads/resnet50-v2-7.onnx ~/Downloads/dog.jpeg +``` + +Running this on the following image: + +![](dog.jpeg) + +We get the following output: + +``` +Top 10 predictions for ResNet50 v2... +-------------------------------------------------------------- +Label: Golden Retriever, Confidence: 0.9212826 +Label: Kuvasz, Confidence: 0.026514154 +Label: Clumber Spaniel, Confidence: 0.012455719 +Label: Labrador Retriever, Confidence: 0.004103844 +Label: Saluki, Confidence: 0.0033182495 +Label: Flat-Coated Retriever, Confidence: 0.0032045357 +Label: English Setter, Confidence: 0.002513516 +Label: Brittany, Confidence: 0.0023459378 +Label: Cocker Spaniels, Confidence: 0.0019343802 +Label: Sussex Spaniel, Confidence: 0.0019247672 +``` diff --git a/csharp/sample/Microsoft.ML.OnnxRuntime.ResNet50v2Sample/dog.jpeg b/csharp/sample/Microsoft.ML.OnnxRuntime.ResNet50v2Sample/dog.jpeg new file mode 100644 index 0000000000..8c4f1ce11a Binary files /dev/null and b/csharp/sample/Microsoft.ML.OnnxRuntime.ResNet50v2Sample/dog.jpeg differ diff --git a/samples/README.md b/samples/README.md index 4e7f1c5e6b..101c70a369 100644 --- a/samples/README.md +++ b/samples/README.md @@ -38,6 +38,7 @@ For a list of available dockerfiles and published images to help with getting st ## C# * [Inference Tutorial](../docs/CSharp_API.md#getting-started) +* [ResNet50 v2 Tutorial](../csharp/sample/Microsoft.ML.OnnxRuntime.ResNet50v2Sample) ## C/C++ * [C: SqueezeNet](../csharp/test/Microsoft.ML.OnnxRuntime.EndToEndTests.Capi/C_Api_Sample.cpp)