From b5c48794f9e731c4b7167e6467ed3a394924a515 Mon Sep 17 00:00:00 2001 From: Norbert Klockiewicz Date: Thu, 19 Mar 2026 17:07:54 +0100 Subject: [PATCH 1/3] feat: make classification module a vision labeled module --- .cspell-wordlist.txt | 39 + .../02-computer-vision/useClassification.md | 16 +- .../ClassificationModule.md | 43 +- .../models/classification/Classification.cpp | 28 +- .../models/classification/Classification.h | 13 +- .../tests/integration/ClassificationTest.cpp | 57 +- .../src/constants/classification.ts | 1008 +++++++++++++++++ .../computer_vision/useClassification.ts | 19 +- packages/react-native-executorch/src/index.ts | 10 +- .../computer_vision/ClassificationModule.ts | 181 ++- .../src/types/classification.ts | 58 +- 11 files changed, 1359 insertions(+), 113 deletions(-) create mode 100644 packages/react-native-executorch/src/constants/classification.ts diff --git a/.cspell-wordlist.txt b/.cspell-wordlist.txt index 7746a87919..07f647238c 100644 --- a/.cspell-wordlist.txt +++ b/.cspell-wordlist.txt @@ -129,6 +129,45 @@ metaprogramming ktlint lefthook espeak +KOMODO +DUNGENESS +SHIH +RIDGEBACK +BLUETICK +REDBONE +IBIZAN +OTTERHOUND +BULLTERRIER +BEDLINGTON +SEALYHAM +DANDIE +DINMONT +VIZSLA +CLUMBER +MALINOIS +KOMONDOR +BOUVIER +FLANDRES +APPENZELLER +ENTLEBUCHER +LEONBERG +BRABANCON +LYCAENID +PATAS +INDRI +BARRACOUTA +ABAYA +BOTTLECAP +CHAINLINK +GASMASK +GOLFCART +HOOPSKIRT +LUMBERMILL +PADDLEWHEEL +PICKELHAUBE +CARBONARA +GYROMITRA +BOLETE NCHW həlˈO wˈɜɹld diff --git a/docs/docs/03-hooks/02-computer-vision/useClassification.md b/docs/docs/03-hooks/02-computer-vision/useClassification.md index e88cce1aff..2c286b642b 100644 --- a/docs/docs/03-hooks/02-computer-vision/useClassification.md +++ b/docs/docs/03-hooks/02-computer-vision/useClassification.md @@ -37,9 +37,13 @@ try { `useClassification` takes [`ClassificationProps`](../../06-api-reference/interfaces/ClassificationProps.md) that consists of: -- `model` containing [`modelSource`](../../06-api-reference/interfaces/ClassificationProps.md#modelsource). +- `model` - An object containing: + - `modelName` - The name of a built-in model. See [`ClassificationModelSources`](../../06-api-reference/interfaces/ClassificationProps.md) for the list of supported models. + - `modelSource` - The location of the model binary (a URL or a bundled resource). - An optional flag [`preventLoad`](../../06-api-reference/interfaces/ClassificationProps.md#preventload) which prevents auto-loading of the model. +The hook is generic over the model config — TypeScript automatically infers the correct label type based on the `modelName` you provide. No explicit generic parameter is needed. + You need more details? Check the following resources: - For detailed information about `useClassification` arguments check this section: [`useClassification` arguments](../../06-api-reference/functions/useClassification.md#parameters). @@ -48,11 +52,17 @@ You need more details? Check the following resources: ### Returns -`useClassification` returns an object called `ClassificationType` containing bunch of functions to interact with Classification models. To get more details please read: [`ClassificationType` API Reference](../../06-api-reference/interfaces/ClassificationType.md). +`useClassification` returns a [`ClassificationType`](../../06-api-reference/interfaces/ClassificationType.md) object containing: + +- `isReady` - Whether the model is loaded and ready to process images. +- `isGenerating` - Whether the model is currently processing an image. +- `error` - An error object if the model failed to load or encountered a runtime error. +- `downloadProgress` - A value between 0 and 1 representing the download progress of the model binary. +- `forward` - A function to run inference on an image. ## Running the model -To run the model, use the [`forward`](../../06-api-reference/interfaces/ClassificationType.md#forward) method. It accepts one argument — the image to classify. The image can be a remote URL, a local file URI, a base64-encoded image (whole URI or only raw base64), or a [`PixelData`](../../06-api-reference/interfaces/PixelData.md) object (raw RGB pixel buffer). The function returns a promise resolving to an object containing categories with their probabilities. +To run the model, use the [`forward`](../../06-api-reference/interfaces/ClassificationType.md#forward) method. It accepts one argument — the image to classify. The image can be a remote URL, a local file URI, a base64-encoded image (whole URI or only raw base64), or a [`PixelData`](../../06-api-reference/interfaces/PixelData.md) object (raw RGB pixel buffer). The function returns a promise resolving to an object mapping label keys to their probabilities. :::info Images from external sources are stored in your application's temporary directory. diff --git a/docs/docs/04-typescript-api/02-computer-vision/ClassificationModule.md b/docs/docs/04-typescript-api/02-computer-vision/ClassificationModule.md index a9bf6ed77d..256e918123 100644 --- a/docs/docs/04-typescript-api/02-computer-vision/ClassificationModule.md +++ b/docs/docs/04-typescript-api/02-computer-vision/ClassificationModule.md @@ -33,24 +33,45 @@ All methods of `ClassificationModule` are explained in details here: [`Classific ## Loading the model -To create a ready-to-use instance, call the static [`fromModelName`](../../06-api-reference/classes/ClassificationModule.md#frommodelname) factory with the following parameters: - -- `namedSources` - Object containing: - - `modelName` - Model name identifier. - - `modelSource` - Location of the model binary. - -- `onDownloadProgress` - Optional callback to track download progress (value between 0 and 1). - -The factory returns a promise that resolves to a loaded `ClassificationModule` instance. +Use the static [`fromModelName`](../../06-api-reference/classes/ClassificationModule.md#frommodelname) factory method. It accepts a model config object (e.g. `EFFICIENTNET_V2_S`) and an optional `onDownloadProgress` callback. It returns a promise resolving to a `ClassificationModule` instance. For more information on loading resources, take a look at [loading models](../../01-fundamentals/02-loading-models.md) page. ## Running the model -To run the model, use the [`forward`](../../06-api-reference/classes/ClassificationModule.md#forward) method. It accepts one argument — the image to classify. The image can be a remote URL, a local file URI, a base64-encoded image (whole URI or only raw base64), or a [`PixelData`](../../06-api-reference/interfaces/PixelData.md) object (raw RGB pixel buffer). The method returns a promise resolving to an object containing categories with their probabilities. +To run the model, use the [`forward`](../../06-api-reference/classes/ClassificationModule.md#forward) method. It accepts one argument — the image to classify. The image can be a remote URL, a local file URI, a base64-encoded image (whole URI or only raw base64), or a [`PixelData`](../../06-api-reference/interfaces/PixelData.md) object (raw RGB pixel buffer). The method returns a promise resolving to an object mapping label keys to their probabilities. For real-time frame processing, use [`runOnFrame`](../../03-hooks/02-computer-vision/visioncamera-integration.md) instead. +## Using a custom model + +Use [`fromCustomModel`](../../06-api-reference/classes/ClassificationModule.md#fromcustommodel) to load your own exported model binary instead of a built-in preset. + +```typescript +import { ClassificationModule } from 'react-native-executorch'; + +const MyLabels = { CAT: 0, DOG: 1, BIRD: 2 } as const; + +const classifier = await ClassificationModule.fromCustomModel( + 'https://example.com/custom_classifier.pte', + { labelMap: MyLabels }, + (progress) => console.log(progress) +); + +const result = await classifier.forward(imageUri); +// result is typed as Record<'CAT' | 'DOG' | 'BIRD', number> +``` + +### Required model contract + +The `.pte` binary must expose a single `forward` method with the following interface: + +**Input:** one `float32` tensor of shape `[1, 3, H, W]` — a single RGB image, values in `[0, 1]` after optional per-channel normalization `(pixel − mean) / std`. H and W are read from the model's declared input shape at load time. + +**Output:** one `float32` tensor of shape `[1, C]` containing raw logits — one value per class, in the same order as the entries in your `labelMap`. Softmax is applied by the native runtime. + +Preprocessing (resize → normalize) is handled by the native runtime — your model only needs to produce the raw logits. + ## Managing memory -The module is a regular JavaScript object, and as such its lifespan will be managed by the garbage collector. In most cases this should be enough, and you should not worry about freeing the memory of the module yourself, but in some cases you may want to release the memory occupied by the module before the garbage collector steps in. In this case use the method [`delete`](../../06-api-reference/classes/ClassificationModule.md#forward) on the module object you will no longer use, and want to remove from the memory. Note that you cannot use [`forward`](../../06-api-reference/classes/ClassificationModule.md#forward) after [`delete`](../../06-api-reference/classes/ClassificationModule.md#forward) unless you load the module again. +The module is a regular JavaScript object, and as such its lifespan will be managed by the garbage collector. In most cases this should be enough, and you should not worry about freeing the memory of the module yourself, but in some cases you may want to release the memory occupied by the module before the garbage collector steps in. In this case use the method [`delete`](../../06-api-reference/classes/ClassificationModule.md#delete) on the module object you will no longer use, and want to remove from the memory. Note that you cannot use [`forward`](../../06-api-reference/classes/ClassificationModule.md#forward) after [`delete`](../../06-api-reference/classes/ClassificationModule.md#delete) unless you load the module again. diff --git a/packages/react-native-executorch/common/rnexecutorch/models/classification/Classification.cpp b/packages/react-native-executorch/common/rnexecutorch/models/classification/Classification.cpp index f713b59605..4baa92e88e 100644 --- a/packages/react-native-executorch/common/rnexecutorch/models/classification/Classification.cpp +++ b/packages/react-native-executorch/common/rnexecutorch/models/classification/Classification.cpp @@ -1,18 +1,26 @@ #include "Classification.h" -#include - #include #include #include #include -#include namespace rnexecutorch::models::classification { Classification::Classification(const std::string &modelSource, + std::vector normMean, + std::vector normStd, + std::vector labelNames, std::shared_ptr callInvoker) - : VisionModel(modelSource, callInvoker) { + : VisionModel(modelSource, callInvoker), + labelNames_(std::move(labelNames)) { + if (normMean.size() == 3) { + normMean_ = cv::Scalar(normMean[0], normMean[1], normMean[2]); + } + if (normStd.size() == 3) { + normStd_ = cv::Scalar(normStd[0], normStd[1], normStd[2]); + } + auto inputShapes = getAllInputShapes(); if (inputShapes.size() == 0) { throw RnExecutorchError(RnExecutorchErrorCode::UnexpectedNumInputs, @@ -37,7 +45,11 @@ Classification::runInference(cv::Mat image) { cv::Mat preprocessed = preprocess(image); auto inputTensor = - image_processing::getTensorFromMatrix(modelInputShape_, preprocessed); + (normMean_ && normStd_) + ? image_processing::getTensorFromMatrix( + modelInputShape_, preprocessed, *normMean_, *normStd_) + : image_processing::getTensorFromMatrix(modelInputShape_, + preprocessed); auto forwardResult = BaseModel::forward(inputTensor); if (!forwardResult.ok()) { @@ -78,13 +90,13 @@ Classification::postprocess(const Tensor &tensor) { static_cast(tensor.const_data_ptr()), tensor.numel()); std::vector resultVec(resultData.begin(), resultData.end()); - if (resultVec.size() != constants::kImagenet1kV1Labels.size()) { + if (resultVec.size() != labelNames_.size()) { char errorMessage[100]; std::snprintf( errorMessage, sizeof(errorMessage), "Unexpected classification output size, was expecting: %zu classes " "but got: %zu classes", - constants::kImagenet1kV1Labels.size(), resultVec.size()); + labelNames_.size(), resultVec.size()); throw RnExecutorchError(RnExecutorchErrorCode::InvalidModelOutput, errorMessage); } @@ -93,7 +105,7 @@ Classification::postprocess(const Tensor &tensor) { std::unordered_map probs; for (std::size_t cl = 0; cl < resultVec.size(); ++cl) { - probs[constants::kImagenet1kV1Labels[cl]] = resultVec[cl]; + probs[labelNames_[cl]] = resultVec[cl]; } return probs; diff --git a/packages/react-native-executorch/common/rnexecutorch/models/classification/Classification.h b/packages/react-native-executorch/common/rnexecutorch/models/classification/Classification.h index 9f62864b9e..2ea0e17bbb 100644 --- a/packages/react-native-executorch/common/rnexecutorch/models/classification/Classification.h +++ b/packages/react-native-executorch/common/rnexecutorch/models/classification/Classification.h @@ -1,5 +1,6 @@ #pragma once +#include #include #include @@ -16,7 +17,9 @@ using executorch::extension::TensorPtr; class Classification : public VisionModel { public: - Classification(const std::string &modelSource, + Classification(const std::string &modelSource, std::vector normMean, + std::vector normStd, + std::vector labelNames, std::shared_ptr callInvoker); [[nodiscard("Registered non-void function")]] std::unordered_map< @@ -35,9 +38,15 @@ class Classification : public VisionModel { std::unordered_map runInference(cv::Mat image); std::unordered_map postprocess(const Tensor &tensor); + + std::vector labelNames_; + std::optional normMean_; + std::optional normStd_; }; } // namespace models::classification REGISTER_CONSTRUCTOR(models::classification::Classification, std::string, + std::vector, std::vector, + std::vector, std::shared_ptr); -} // namespace rnexecutorch \ No newline at end of file +} // namespace rnexecutorch diff --git a/packages/react-native-executorch/common/rnexecutorch/tests/integration/ClassificationTest.cpp b/packages/react-native-executorch/common/rnexecutorch/tests/integration/ClassificationTest.cpp index d164fcacb0..642f63ecc3 100644 --- a/packages/react-native-executorch/common/rnexecutorch/tests/integration/ClassificationTest.cpp +++ b/packages/react-native-executorch/common/rnexecutorch/tests/integration/ClassificationTest.cpp @@ -15,6 +15,18 @@ constexpr auto kValidClassificationModelPath = "efficientnet_v2_s_xnnpack.pte"; constexpr auto kValidTestImagePath = "file:///data/local/tmp/rnexecutorch_tests/test_image.jpg"; +static std::vector kImagenetNormMean = {0.485f, 0.456f, 0.406f}; +static std::vector kImagenetNormStd = {0.229f, 0.224f, 0.225f}; + +static std::vector getImagenetLabelNames() { + std::vector names; + names.reserve(constants::kImagenet1kV1Labels.size()); + for (const auto &label : constants::kImagenet1kV1Labels) { + names.emplace_back(label); + } + return names; +} + // ============================================================================ // Common tests via typed test suite // ============================================================================ @@ -23,11 +35,12 @@ template <> struct ModelTraits { using ModelType = Classification; static ModelType createValid() { - return ModelType(kValidClassificationModelPath, nullptr); + return ModelType(kValidClassificationModelPath, kImagenetNormMean, + kImagenetNormStd, getImagenetLabelNames(), nullptr); } static ModelType createInvalid() { - return ModelType("nonexistent.pte", nullptr); + return ModelType("nonexistent.pte", {}, {}, {}, nullptr); } static void callGenerate(ModelType &model) { @@ -46,37 +59,43 @@ INSTANTIATE_TYPED_TEST_SUITE_P(Classification, VisionModelTest, // Model-specific tests // ============================================================================ TEST(ClassificationGenerateTests, InvalidImagePathThrows) { - Classification model(kValidClassificationModelPath, nullptr); + Classification model(kValidClassificationModelPath, kImagenetNormMean, + kImagenetNormStd, getImagenetLabelNames(), nullptr); EXPECT_THROW((void)model.generateFromString("nonexistent_image.jpg"), RnExecutorchError); } TEST(ClassificationGenerateTests, EmptyImagePathThrows) { - Classification model(kValidClassificationModelPath, nullptr); + Classification model(kValidClassificationModelPath, kImagenetNormMean, + kImagenetNormStd, getImagenetLabelNames(), nullptr); EXPECT_THROW((void)model.generateFromString(""), RnExecutorchError); } TEST(ClassificationGenerateTests, MalformedURIThrows) { - Classification model(kValidClassificationModelPath, nullptr); + Classification model(kValidClassificationModelPath, kImagenetNormMean, + kImagenetNormStd, getImagenetLabelNames(), nullptr); EXPECT_THROW((void)model.generateFromString("not_a_valid_uri://bad"), RnExecutorchError); } TEST(ClassificationGenerateTests, ValidImageReturnsResults) { - Classification model(kValidClassificationModelPath, nullptr); + Classification model(kValidClassificationModelPath, kImagenetNormMean, + kImagenetNormStd, getImagenetLabelNames(), nullptr); auto results = model.generateFromString(kValidTestImagePath); EXPECT_FALSE(results.empty()); } TEST(ClassificationGenerateTests, ResultsHaveCorrectSize) { - Classification model(kValidClassificationModelPath, nullptr); + Classification model(kValidClassificationModelPath, kImagenetNormMean, + kImagenetNormStd, getImagenetLabelNames(), nullptr); auto results = model.generateFromString(kValidTestImagePath); auto expectedNumClasses = constants::kImagenet1kV1Labels.size(); EXPECT_EQ(results.size(), expectedNumClasses); } TEST(ClassificationGenerateTests, ResultsContainValidProbabilities) { - Classification model(kValidClassificationModelPath, nullptr); + Classification model(kValidClassificationModelPath, kImagenetNormMean, + kImagenetNormStd, getImagenetLabelNames(), nullptr); auto results = model.generateFromString(kValidTestImagePath); float sum = 0.0f; @@ -89,7 +108,8 @@ TEST(ClassificationGenerateTests, ResultsContainValidProbabilities) { } TEST(ClassificationGenerateTests, TopPredictionHasReasonableConfidence) { - Classification model(kValidClassificationModelPath, nullptr); + Classification model(kValidClassificationModelPath, kImagenetNormMean, + kImagenetNormStd, getImagenetLabelNames(), nullptr); auto results = model.generateFromString(kValidTestImagePath); float maxProb = 0.0f; @@ -101,8 +121,16 @@ TEST(ClassificationGenerateTests, TopPredictionHasReasonableConfidence) { EXPECT_GT(maxProb, 0.0f); } +TEST(ClassificationGenerateTests, WrongLabelCountThrows) { + Classification model(kValidClassificationModelPath, kImagenetNormMean, + kImagenetNormStd, {"A", "B", "C"}, nullptr); + EXPECT_THROW((void)model.generateFromString(kValidTestImagePath), + RnExecutorchError); +} + TEST(ClassificationInheritedTests, GetInputShapeWorks) { - Classification model(kValidClassificationModelPath, nullptr); + Classification model(kValidClassificationModelPath, kImagenetNormMean, + kImagenetNormStd, getImagenetLabelNames(), nullptr); auto shape = model.getInputShape("forward", 0); EXPECT_EQ(shape.size(), 4); EXPECT_EQ(shape[0], 1); @@ -110,13 +138,15 @@ TEST(ClassificationInheritedTests, GetInputShapeWorks) { } TEST(ClassificationInheritedTests, GetAllInputShapesWorks) { - Classification model(kValidClassificationModelPath, nullptr); + Classification model(kValidClassificationModelPath, kImagenetNormMean, + kImagenetNormStd, getImagenetLabelNames(), nullptr); auto shapes = model.getAllInputShapes("forward"); EXPECT_FALSE(shapes.empty()); } TEST(ClassificationInheritedTests, GetMethodMetaWorks) { - Classification model(kValidClassificationModelPath, nullptr); + Classification model(kValidClassificationModelPath, kImagenetNormMean, + kImagenetNormStd, getImagenetLabelNames(), nullptr); auto result = model.getMethodMeta("forward"); EXPECT_TRUE(result.ok()); } @@ -125,7 +155,8 @@ TEST(ClassificationInheritedTests, GetMethodMetaWorks) { // generateFromPixels smoke test // ============================================================================ TEST(ClassificationPixelTests, ValidPixelsReturnsResults) { - Classification model(kValidClassificationModelPath, nullptr); + Classification model(kValidClassificationModelPath, kImagenetNormMean, + kImagenetNormStd, getImagenetLabelNames(), nullptr); std::vector buf(64 * 64 * 3, 128); JSTensorViewIn view{ buf.data(), {64, 64, 3}, executorch::aten::ScalarType::Byte}; diff --git a/packages/react-native-executorch/src/constants/classification.ts b/packages/react-native-executorch/src/constants/classification.ts new file mode 100644 index 0000000000..f43c93c26a --- /dev/null +++ b/packages/react-native-executorch/src/constants/classification.ts @@ -0,0 +1,1008 @@ +/** + * ImageNet-1K class labels used for image classification. + * Contains 1000 classes from the ImageNet Large Scale Visual Recognition Challenge. + * + * @category Types + */ +export enum Imagenet1kLabel { + TENCH = 0, + GOLDFISH = 1, + GREAT_WHITE_SHARK = 2, + TIGER_SHARK = 3, + HAMMERHEAD = 4, + ELECTRIC_RAY = 5, + STINGRAY = 6, + COCK = 7, + HEN = 8, + OSTRICH = 9, + BRAMBLING = 10, + GOLDFINCH = 11, + HOUSE_FINCH = 12, + JUNCO = 13, + INDIGO_BUNTING = 14, + ROBIN = 15, + BULBUL = 16, + JAY = 17, + MAGPIE = 18, + CHICKADEE = 19, + WATER_OUZEL = 20, + KITE = 21, + BALD_EAGLE = 22, + VULTURE = 23, + GREAT_GREY_OWL = 24, + EUROPEAN_FIRE_SALAMANDER = 25, + COMMON_NEWT = 26, + EFT = 27, + SPOTTED_SALAMANDER = 28, + AXOLOTL = 29, + BULLFROG = 30, + TREE_FROG = 31, + TAILED_FROG = 32, + LOGGERHEAD = 33, + LEATHERBACK_TURTLE = 34, + MUD_TURTLE = 35, + TERRAPIN = 36, + BOX_TURTLE = 37, + BANDED_GECKO = 38, + COMMON_IGUANA = 39, + AMERICAN_CHAMELEON = 40, + WHIPTAIL = 41, + AGAMA = 42, + FRILLED_LIZARD = 43, + ALLIGATOR_LIZARD = 44, + GILA_MONSTER = 45, + GREEN_LIZARD = 46, + AFRICAN_CHAMELEON = 47, + KOMODO_DRAGON = 48, + AFRICAN_CROCODILE = 49, + AMERICAN_ALLIGATOR = 50, + TRICERATOPS = 51, + THUNDER_SNAKE = 52, + RINGNECK_SNAKE = 53, + HOGNOSE_SNAKE = 54, + GREEN_SNAKE = 55, + KING_SNAKE = 56, + GARTER_SNAKE = 57, + WATER_SNAKE = 58, + VINE_SNAKE = 59, + NIGHT_SNAKE = 60, + BOA_CONSTRICTOR = 61, + ROCK_PYTHON = 62, + INDIAN_COBRA = 63, + GREEN_MAMBA = 64, + SEA_SNAKE = 65, + HORNED_VIPER = 66, + DIAMONDBACK = 67, + SIDEWINDER = 68, + TRILOBITE = 69, + HARVESTMAN = 70, + SCORPION = 71, + BLACK_AND_GOLD_GARDEN_SPIDER = 72, + BARN_SPIDER = 73, + GARDEN_SPIDER = 74, + BLACK_WIDOW = 75, + TARANTULA = 76, + WOLF_SPIDER = 77, + TICK = 78, + CENTIPEDE = 79, + BLACK_GROUSE = 80, + PTARMIGAN = 81, + RUFFED_GROUSE = 82, + PRAIRIE_CHICKEN = 83, + PEACOCK = 84, + QUAIL = 85, + PARTRIDGE = 86, + AFRICAN_GREY = 87, + MACAW = 88, + SULPHUR_CRESTED_COCKATOO = 89, + LORIKEET = 90, + COUCAL = 91, + BEE_EATER = 92, + HORNBILL = 93, + HUMMINGBIRD = 94, + JACAMAR = 95, + TOUCAN = 96, + DRAKE = 97, + RED_BREASTED_MERGANSER = 98, + GOOSE = 99, + BLACK_SWAN = 100, + TUSKER = 101, + ECHIDNA = 102, + PLATYPUS = 103, + WALLABY = 104, + KOALA = 105, + WOMBAT = 106, + JELLYFISH = 107, + SEA_ANEMONE = 108, + BRAIN_CORAL = 109, + FLATWORM = 110, + NEMATODE = 111, + CONCH = 112, + SNAIL = 113, + SLUG = 114, + SEA_SLUG = 115, + CHITON = 116, + CHAMBERED_NAUTILUS = 117, + DUNGENESS_CRAB = 118, + ROCK_CRAB = 119, + FIDDLER_CRAB = 120, + KING_CRAB = 121, + AMERICAN_LOBSTER = 122, + SPINY_LOBSTER = 123, + CRAYFISH = 124, + HERMIT_CRAB = 125, + ISOPOD = 126, + WHITE_STORK = 127, + BLACK_STORK = 128, + SPOONBILL = 129, + FLAMINGO = 130, + LITTLE_BLUE_HERON = 131, + AMERICAN_EGRET = 132, + BITTERN = 133, + CRANE_BIRD = 134, + LIMPKIN = 135, + EUROPEAN_GALLINULE = 136, + AMERICAN_COOT = 137, + BUSTARD = 138, + RUDDY_TURNSTONE = 139, + RED_BACKED_SANDPIPER = 140, + REDSHANK = 141, + DOWITCHER = 142, + OYSTERCATCHER = 143, + PELICAN = 144, + KING_PENGUIN = 145, + ALBATROSS = 146, + GREY_WHALE = 147, + KILLER_WHALE = 148, + DUGONG = 149, + SEA_LION = 150, + CHIHUAHUA = 151, + JAPANESE_SPANIEL = 152, + MALTESE_DOG = 153, + PEKINESE = 154, + SHIH_TZU = 155, + BLENHEIM_SPANIEL = 156, + PAPILLON = 157, + TOY_TERRIER = 158, + RHODESIAN_RIDGEBACK = 159, + AFGHAN_HOUND = 160, + BASSET = 161, + BEAGLE = 162, + BLOODHOUND = 163, + BLUETICK = 164, + BLACK_AND_TAN_COONHOUND = 165, + WALKER_HOUND = 166, + ENGLISH_FOXHOUND = 167, + REDBONE = 168, + BORZOI = 169, + IRISH_WOLFHOUND = 170, + ITALIAN_GREYHOUND = 171, + WHIPPET = 172, + IBIZAN_HOUND = 173, + NORWEGIAN_ELKHOUND = 174, + OTTERHOUND = 175, + SALUKI = 176, + SCOTTISH_DEERHOUND = 177, + WEIMARANER = 178, + STAFFORDSHIRE_BULLTERRIER = 179, + AMERICAN_STAFFORDSHIRE_TERRIER = 180, + BEDLINGTON_TERRIER = 181, + BORDER_TERRIER = 182, + KERRY_BLUE_TERRIER = 183, + IRISH_TERRIER = 184, + NORFOLK_TERRIER = 185, + NORWICH_TERRIER = 186, + YORKSHIRE_TERRIER = 187, + WIRE_HAIRED_FOX_TERRIER = 188, + LAKELAND_TERRIER = 189, + SEALYHAM_TERRIER = 190, + AIREDALE = 191, + CAIRN = 192, + AUSTRALIAN_TERRIER = 193, + DANDIE_DINMONT = 194, + BOSTON_BULL = 195, + MINIATURE_SCHNAUZER = 196, + GIANT_SCHNAUZER = 197, + STANDARD_SCHNAUZER = 198, + SCOTCH_TERRIER = 199, + TIBETAN_TERRIER = 200, + SILKY_TERRIER = 201, + SOFT_COATED_WHEATEN_TERRIER = 202, + WEST_HIGHLAND_WHITE_TERRIER = 203, + LHASA = 204, + FLAT_COATED_RETRIEVER = 205, + CURLY_COATED_RETRIEVER = 206, + GOLDEN_RETRIEVER = 207, + LABRADOR_RETRIEVER = 208, + CHESAPEAKE_BAY_RETRIEVER = 209, + GERMAN_SHORT_HAIRED_POINTER = 210, + VIZSLA = 211, + ENGLISH_SETTER = 212, + IRISH_SETTER = 213, + GORDON_SETTER = 214, + BRITTANY_SPANIEL = 215, + CLUMBER = 216, + ENGLISH_SPRINGER = 217, + WELSH_SPRINGER_SPANIEL = 218, + COCKER_SPANIEL = 219, + SUSSEX_SPANIEL = 220, + IRISH_WATER_SPANIEL = 221, + KUVASZ = 222, + SCHIPPERKE = 223, + GROENENDAEL = 224, + MALINOIS = 225, + BRIARD = 226, + KELPIE = 227, + KOMONDOR = 228, + OLD_ENGLISH_SHEEPDOG = 229, + SHETLAND_SHEEPDOG = 230, + COLLIE = 231, + BORDER_COLLIE = 232, + BOUVIER_DES_FLANDRES = 233, + ROTTWEILER = 234, + GERMAN_SHEPHERD = 235, + DOBERMAN = 236, + MINIATURE_PINSCHER = 237, + GREATER_SWISS_MOUNTAIN_DOG = 238, + BERNESE_MOUNTAIN_DOG = 239, + APPENZELLER = 240, + ENTLEBUCHER = 241, + BOXER = 242, + BULL_MASTIFF = 243, + TIBETAN_MASTIFF = 244, + FRENCH_BULLDOG = 245, + GREAT_DANE = 246, + SAINT_BERNARD = 247, + ESKIMO_DOG = 248, + MALAMUTE = 249, + SIBERIAN_HUSKY = 250, + DALMATIAN = 251, + AFFENPINSCHER = 252, + BASENJI = 253, + PUG = 254, + LEONBERG = 255, + NEWFOUNDLAND = 256, + GREAT_PYRENEES = 257, + SAMOYED = 258, + POMERANIAN = 259, + CHOW = 260, + KEESHOND = 261, + BRABANCON_GRIFFON = 262, + PEMBROKE = 263, + CARDIGAN = 264, + TOY_POODLE = 265, + MINIATURE_POODLE = 266, + STANDARD_POODLE = 267, + MEXICAN_HAIRLESS = 268, + TIMBER_WOLF = 269, + WHITE_WOLF = 270, + RED_WOLF = 271, + COYOTE = 272, + DINGO = 273, + DHOLE = 274, + AFRICAN_HUNTING_DOG = 275, + HYENA = 276, + RED_FOX = 277, + KIT_FOX = 278, + ARCTIC_FOX = 279, + GREY_FOX = 280, + TABBY = 281, + TIGER_CAT = 282, + PERSIAN_CAT = 283, + SIAMESE_CAT = 284, + EGYPTIAN_CAT = 285, + COUGAR = 286, + LYNX = 287, + LEOPARD = 288, + SNOW_LEOPARD = 289, + JAGUAR = 290, + LION = 291, + TIGER = 292, + CHEETAH = 293, + BROWN_BEAR = 294, + AMERICAN_BLACK_BEAR = 295, + ICE_BEAR = 296, + SLOTH_BEAR = 297, + MONGOOSE = 298, + MEERKAT = 299, + TIGER_BEETLE = 300, + LADYBUG = 301, + GROUND_BEETLE = 302, + LONG_HORNED_BEETLE = 303, + LEAF_BEETLE = 304, + DUNG_BEETLE = 305, + RHINOCEROS_BEETLE = 306, + WEEVIL = 307, + FLY = 308, + BEE = 309, + ANT = 310, + GRASSHOPPER = 311, + CRICKET = 312, + WALKING_STICK = 313, + COCKROACH = 314, + MANTIS = 315, + CICADA = 316, + LEAFHOPPER = 317, + LACEWING = 318, + DRAGONFLY = 319, + DAMSELFLY = 320, + ADMIRAL = 321, + RINGLET = 322, + MONARCH = 323, + CABBAGE_BUTTERFLY = 324, + SULPHUR_BUTTERFLY = 325, + LYCAENID = 326, + STARFISH = 327, + SEA_URCHIN = 328, + SEA_CUCUMBER = 329, + WOOD_RABBIT = 330, + HARE = 331, + ANGORA = 332, + HAMSTER = 333, + PORCUPINE = 334, + FOX_SQUIRREL = 335, + MARMOT = 336, + BEAVER = 337, + GUINEA_PIG = 338, + SORREL = 339, + ZEBRA = 340, + HOG = 341, + WILD_BOAR = 342, + WARTHOG = 343, + HIPPOPOTAMUS = 344, + OX = 345, + WATER_BUFFALO = 346, + BISON = 347, + RAM = 348, + BIGHORN = 349, + IBEX = 350, + HARTEBEEST = 351, + IMPALA = 352, + GAZELLE = 353, + ARABIAN_CAMEL = 354, + LLAMA = 355, + WEASEL = 356, + MINK = 357, + POLECAT = 358, + BLACK_FOOTED_FERRET = 359, + OTTER = 360, + SKUNK = 361, + BADGER = 362, + ARMADILLO = 363, + THREE_TOED_SLOTH = 364, + ORANGUTAN = 365, + GORILLA = 366, + CHIMPANZEE = 367, + GIBBON = 368, + SIAMANG = 369, + GUENON = 370, + PATAS = 371, + BABOON = 372, + MACAQUE = 373, + LANGUR = 374, + COLOBUS = 375, + PROBOSCIS_MONKEY = 376, + MARMOSET = 377, + CAPUCHIN = 378, + HOWLER_MONKEY = 379, + TITI = 380, + SPIDER_MONKEY = 381, + SQUIRREL_MONKEY = 382, + MADAGASCAR_CAT = 383, + INDRI = 384, + INDIAN_ELEPHANT = 385, + AFRICAN_ELEPHANT = 386, + LESSER_PANDA = 387, + GIANT_PANDA = 388, + BARRACOUTA = 389, + EEL = 390, + COHO = 391, + ROCK_BEAUTY = 392, + ANEMONE_FISH = 393, + STURGEON = 394, + GAR = 395, + LIONFISH = 396, + PUFFER = 397, + ABACUS = 398, + ABAYA = 399, + ACADEMIC_GOWN = 400, + ACCORDION = 401, + ACOUSTIC_GUITAR = 402, + AIRCRAFT_CARRIER = 403, + AIRLINER = 404, + AIRSHIP = 405, + ALTAR = 406, + AMBULANCE = 407, + AMPHIBIAN = 408, + ANALOG_CLOCK = 409, + APIARY = 410, + APRON = 411, + ASHCAN = 412, + ASSAULT_RIFLE = 413, + BACKPACK = 414, + BAKERY = 415, + BALANCE_BEAM = 416, + BALLOON = 417, + BALLPOINT = 418, + BAND_AID = 419, + BANJO = 420, + BANNISTER = 421, + BARBELL = 422, + BARBER_CHAIR = 423, + BARBERSHOP = 424, + BARN = 425, + BAROMETER = 426, + BARREL = 427, + BARROW = 428, + BASEBALL = 429, + BASKETBALL = 430, + BASSINET = 431, + BASSOON = 432, + BATHING_CAP = 433, + BATH_TOWEL = 434, + BATHTUB = 435, + BEACH_WAGON = 436, + BEACON = 437, + BEAKER = 438, + BEARSKIN = 439, + BEER_BOTTLE = 440, + BEER_GLASS = 441, + BELL_COTE = 442, + BIB = 443, + BICYCLE_BUILT_FOR_TWO = 444, + BIKINI = 445, + BINDER = 446, + BINOCULARS = 447, + BIRDHOUSE = 448, + BOATHOUSE = 449, + BOBSLED = 450, + BOLO_TIE = 451, + BONNET = 452, + BOOKCASE = 453, + BOOKSHOP = 454, + BOTTLECAP = 455, + BOW = 456, + BOW_TIE = 457, + BRASS = 458, + BRASSIERE = 459, + BREAKWATER = 460, + BREASTPLATE = 461, + BROOM = 462, + BUCKET = 463, + BUCKLE = 464, + BULLETPROOF_VEST = 465, + BULLET_TRAIN = 466, + BUTCHER_SHOP = 467, + CAB = 468, + CALDRON = 469, + CANDLE = 470, + CANNON = 471, + CANOE = 472, + CAN_OPENER = 473, + CARDIGAN_474 = 474, + CAR_MIRROR = 475, + CAROUSEL = 476, + CARPENTERS_KIT = 477, + CARTON = 478, + CAR_WHEEL = 479, + CASH_MACHINE = 480, + CASSETTE = 481, + CASSETTE_PLAYER = 482, + CASTLE = 483, + CATAMARAN = 484, + CD_PLAYER = 485, + CELLO = 486, + CELLULAR_TELEPHONE = 487, + CHAIN = 488, + CHAINLINK_FENCE = 489, + CHAIN_MAIL = 490, + CHAIN_SAW = 491, + CHEST = 492, + CHIFFONIER = 493, + CHIME = 494, + CHINA_CABINET = 495, + CHRISTMAS_STOCKING = 496, + CHURCH = 497, + CINEMA = 498, + CLEAVER = 499, + CLIFF_DWELLING = 500, + CLOAK = 501, + CLOG = 502, + COCKTAIL_SHAKER = 503, + COFFEE_MUG = 504, + COFFEEPOT = 505, + COIL = 506, + COMBINATION_LOCK = 507, + COMPUTER_KEYBOARD = 508, + CONFECTIONERY = 509, + CONTAINER_SHIP = 510, + CONVERTIBLE = 511, + CORKSCREW = 512, + CORNET = 513, + COWBOY_BOOT = 514, + COWBOY_HAT = 515, + CRADLE = 516, + CRANE_MACHINE = 517, + CRASH_HELMET = 518, + CRATE = 519, + CRIB = 520, + CROCK_POT = 521, + CROQUET_BALL = 522, + CRUTCH = 523, + CUIRASS = 524, + DAM = 525, + DESK = 526, + DESKTOP_COMPUTER = 527, + DIAL_TELEPHONE = 528, + DIAPER = 529, + DIGITAL_CLOCK = 530, + DIGITAL_WATCH = 531, + DINING_TABLE = 532, + DISHRAG = 533, + DISHWASHER = 534, + DISK_BRAKE = 535, + DOCK = 536, + DOGSLED = 537, + DOME = 538, + DOORMAT = 539, + DRILLING_PLATFORM = 540, + DRUM = 541, + DRUMSTICK = 542, + DUMBBELL = 543, + DUTCH_OVEN = 544, + ELECTRIC_FAN = 545, + ELECTRIC_GUITAR = 546, + ELECTRIC_LOCOMOTIVE = 547, + ENTERTAINMENT_CENTER = 548, + ENVELOPE = 549, + ESPRESSO_MAKER = 550, + FACE_POWDER = 551, + FEATHER_BOA = 552, + FILE = 553, + FIREBOAT = 554, + FIRE_ENGINE = 555, + FIRE_SCREEN = 556, + FLAGPOLE = 557, + FLUTE = 558, + FOLDING_CHAIR = 559, + FOOTBALL_HELMET = 560, + FORKLIFT = 561, + FOUNTAIN = 562, + FOUNTAIN_PEN = 563, + FOUR_POSTER = 564, + FREIGHT_CAR = 565, + FRENCH_HORN = 566, + FRYING_PAN = 567, + FUR_COAT = 568, + GARBAGE_TRUCK = 569, + GASMASK = 570, + GAS_PUMP = 571, + GOBLET = 572, + GO_KART = 573, + GOLF_BALL = 574, + GOLFCART = 575, + GONDOLA = 576, + GONG = 577, + GOWN = 578, + GRAND_PIANO = 579, + GREENHOUSE = 580, + GRILLE = 581, + GROCERY_STORE = 582, + GUILLOTINE = 583, + HAIR_SLIDE = 584, + HAIR_SPRAY = 585, + HALF_TRACK = 586, + HAMMER = 587, + HAMPER = 588, + HAND_BLOWER = 589, + HAND_HELD_COMPUTER = 590, + HANDKERCHIEF = 591, + HARD_DISC = 592, + HARMONICA = 593, + HARP = 594, + HARVESTER = 595, + HATCHET = 596, + HOLSTER = 597, + HOME_THEATER = 598, + HONEYCOMB = 599, + HOOK = 600, + HOOPSKIRT = 601, + HORIZONTAL_BAR = 602, + HORSE_CART = 603, + HOURGLASS = 604, + IPOD = 605, + IRON = 606, + JACK_O_LANTERN = 607, + JEAN = 608, + JEEP = 609, + JERSEY = 610, + JIGSAW_PUZZLE = 611, + JINRIKISHA = 612, + JOYSTICK = 613, + KIMONO = 614, + KNEE_PAD = 615, + KNOT = 616, + LAB_COAT = 617, + LADLE = 618, + LAMPSHADE = 619, + LAPTOP = 620, + LAWN_MOWER = 621, + LENS_CAP = 622, + LETTER_OPENER = 623, + LIBRARY = 624, + LIFEBOAT = 625, + LIGHTER = 626, + LIMOUSINE = 627, + LINER = 628, + LIPSTICK = 629, + LOAFER = 630, + LOTION = 631, + LOUDSPEAKER = 632, + LOUPE = 633, + LUMBERMILL = 634, + MAGNETIC_COMPASS = 635, + MAILBAG = 636, + MAILBOX = 637, + MAILLOT = 638, + MAILLOT_639 = 639, + MANHOLE_COVER = 640, + MARACA = 641, + MARIMBA = 642, + MASK = 643, + MATCHSTICK = 644, + MAYPOLE = 645, + MAZE = 646, + MEASURING_CUP = 647, + MEDICINE_CHEST = 648, + MEGALITH = 649, + MICROPHONE = 650, + MICROWAVE = 651, + MILITARY_UNIFORM = 652, + MILK_CAN = 653, + MINIBUS = 654, + MINISKIRT = 655, + MINIVAN = 656, + MISSILE = 657, + MITTEN = 658, + MIXING_BOWL = 659, + MOBILE_HOME = 660, + MODEL_T = 661, + MODEM = 662, + MONASTERY = 663, + MONITOR = 664, + MOPED = 665, + MORTAR = 666, + MORTARBOARD = 667, + MOSQUE = 668, + MOSQUITO_NET = 669, + MOTOR_SCOOTER = 670, + MOUNTAIN_BIKE = 671, + MOUNTAIN_TENT = 672, + MOUSE = 673, + MOUSETRAP = 674, + MOVING_VAN = 675, + MUZZLE = 676, + NAIL = 677, + NECK_BRACE = 678, + NECKLACE = 679, + NIPPLE = 680, + NOTEBOOK = 681, + OBELISK = 682, + OBOE = 683, + OCARINA = 684, + ODOMETER = 685, + OIL_FILTER = 686, + ORGAN = 687, + OSCILLOSCOPE = 688, + OVERSKIRT = 689, + OXCART = 690, + OXYGEN_MASK = 691, + PACKET = 692, + PADDLE = 693, + PADDLEWHEEL = 694, + PADLOCK = 695, + PAINTBRUSH = 696, + PAJAMA = 697, + PALACE = 698, + PANPIPE = 699, + PAPER_TOWEL = 700, + PARACHUTE = 701, + PARALLEL_BARS = 702, + PARK_BENCH = 703, + PARKING_METER = 704, + PASSENGER_CAR = 705, + PATIO = 706, + PAY_PHONE = 707, + PEDESTAL = 708, + PENCIL_BOX = 709, + PENCIL_SHARPENER = 710, + PERFUME = 711, + PETRI_DISH = 712, + PHOTOCOPIER = 713, + PICK = 714, + PICKELHAUBE = 715, + PICKET_FENCE = 716, + PICKUP = 717, + PIER = 718, + PIGGY_BANK = 719, + PILL_BOTTLE = 720, + PILLOW = 721, + PING_PONG_BALL = 722, + PINWHEEL = 723, + PIRATE = 724, + PITCHER = 725, + PLANE = 726, + PLANETARIUM = 727, + PLASTIC_BAG = 728, + PLATE_RACK = 729, + PLOW = 730, + PLUNGER = 731, + POLAROID_CAMERA = 732, + POLE = 733, + POLICE_VAN = 734, + PONCHO = 735, + POOL_TABLE = 736, + POP_BOTTLE = 737, + POT = 738, + POTTERS_WHEEL = 739, + POWER_DRILL = 740, + PRAYER_RUG = 741, + PRINTER = 742, + PRISON = 743, + PROJECTILE = 744, + PROJECTOR = 745, + PUCK = 746, + PUNCHING_BAG = 747, + PURSE = 748, + QUILL = 749, + QUILT = 750, + RACER = 751, + RACKET = 752, + RADIATOR = 753, + RADIO = 754, + RADIO_TELESCOPE = 755, + RAIN_BARREL = 756, + RECREATIONAL_VEHICLE = 757, + REEL = 758, + REFLEX_CAMERA = 759, + REFRIGERATOR = 760, + REMOTE_CONTROL = 761, + RESTAURANT = 762, + REVOLVER = 763, + RIFLE = 764, + ROCKING_CHAIR = 765, + ROTISSERIE = 766, + RUBBER_ERASER = 767, + RUGBY_BALL = 768, + RULE = 769, + RUNNING_SHOE = 770, + SAFE = 771, + SAFETY_PIN = 772, + SALTSHAKER = 773, + SANDAL = 774, + SARONG = 775, + SAX = 776, + SCABBARD = 777, + SCALE = 778, + SCHOOL_BUS = 779, + SCHOONER = 780, + SCOREBOARD = 781, + SCREEN = 782, + SCREW = 783, + SCREWDRIVER = 784, + SEAT_BELT = 785, + SEWING_MACHINE = 786, + SHIELD = 787, + SHOE_SHOP = 788, + SHOJI = 789, + SHOPPING_BASKET = 790, + SHOPPING_CART = 791, + SHOVEL = 792, + SHOWER_CAP = 793, + SHOWER_CURTAIN = 794, + SKI = 795, + SKI_MASK = 796, + SLEEPING_BAG = 797, + SLIDE_RULE = 798, + SLIDING_DOOR = 799, + SLOT = 800, + SNORKEL = 801, + SNOWMOBILE = 802, + SNOWPLOW = 803, + SOAP_DISPENSER = 804, + SOCCER_BALL = 805, + SOCK = 806, + SOLAR_DISH = 807, + SOMBRERO = 808, + SOUP_BOWL = 809, + SPACE_BAR = 810, + SPACE_HEATER = 811, + SPACE_SHUTTLE = 812, + SPATULA = 813, + SPEEDBOAT = 814, + SPIDER_WEB = 815, + SPINDLE = 816, + SPORTS_CAR = 817, + SPOTLIGHT = 818, + STAGE = 819, + STEAM_LOCOMOTIVE = 820, + STEEL_ARCH_BRIDGE = 821, + STEEL_DRUM = 822, + STETHOSCOPE = 823, + STOLE = 824, + STONE_WALL = 825, + STOPWATCH = 826, + STOVE = 827, + STRAINER = 828, + STREETCAR = 829, + STRETCHER = 830, + STUDIO_COUCH = 831, + STUPA = 832, + SUBMARINE = 833, + SUIT = 834, + SUNDIAL = 835, + SUNGLASS = 836, + SUNGLASSES = 837, + SUNSCREEN = 838, + SUSPENSION_BRIDGE = 839, + SWAB = 840, + SWEATSHIRT = 841, + SWIMMING_TRUNKS = 842, + SWING = 843, + SWITCH = 844, + SYRINGE = 845, + TABLE_LAMP = 846, + TANK = 847, + TAPE_PLAYER = 848, + TEAPOT = 849, + TEDDY = 850, + TELEVISION = 851, + TENNIS_BALL = 852, + THATCH = 853, + THEATER_CURTAIN = 854, + THIMBLE = 855, + THRESHER = 856, + THRONE = 857, + TILE_ROOF = 858, + TOASTER = 859, + TOBACCO_SHOP = 860, + TOILET_SEAT = 861, + TORCH = 862, + TOTEM_POLE = 863, + TOW_TRUCK = 864, + TOYSHOP = 865, + TRACTOR = 866, + TRAILER_TRUCK = 867, + TRAY = 868, + TRENCH_COAT = 869, + TRICYCLE = 870, + TRIMARAN = 871, + TRIPOD = 872, + TRIUMPHAL_ARCH = 873, + TROLLEYBUS = 874, + TROMBONE = 875, + TUB = 876, + TURNSTILE = 877, + TYPEWRITER_KEYBOARD = 878, + UMBRELLA = 879, + UNICYCLE = 880, + UPRIGHT = 881, + VACUUM = 882, + VASE = 883, + VAULT = 884, + VELVET = 885, + VENDING_MACHINE = 886, + VESTMENT = 887, + VIADUCT = 888, + VIOLIN = 889, + VOLLEYBALL = 890, + WAFFLE_IRON = 891, + WALL_CLOCK = 892, + WALLET = 893, + WARDROBE = 894, + WARPLANE = 895, + WASHBASIN = 896, + WASHER = 897, + WATER_BOTTLE = 898, + WATER_JUG = 899, + WATER_TOWER = 900, + WHISKEY_JUG = 901, + WHISTLE = 902, + WIG = 903, + WINDOW_SCREEN = 904, + WINDOW_SHADE = 905, + WINDSOR_TIE = 906, + WINE_BOTTLE = 907, + WING = 908, + WOK = 909, + WOODEN_SPOON = 910, + WOOL = 911, + WORM_FENCE = 912, + WRECK = 913, + YAWL = 914, + YURT = 915, + WEB_SITE = 916, + COMIC_BOOK = 917, + CROSSWORD_PUZZLE = 918, + STREET_SIGN = 919, + TRAFFIC_LIGHT = 920, + BOOK_JACKET = 921, + MENU = 922, + PLATE = 923, + GUACAMOLE = 924, + CONSOMME = 925, + HOT_POT = 926, + TRIFLE = 927, + ICE_CREAM = 928, + ICE_LOLLY = 929, + FRENCH_LOAF = 930, + BAGEL = 931, + PRETZEL = 932, + CHEESEBURGER = 933, + HOTDOG = 934, + MASHED_POTATO = 935, + HEAD_CABBAGE = 936, + BROCCOLI = 937, + CAULIFLOWER = 938, + ZUCCHINI = 939, + SPAGHETTI_SQUASH = 940, + ACORN_SQUASH = 941, + BUTTERNUT_SQUASH = 942, + CUCUMBER = 943, + ARTICHOKE = 944, + BELL_PEPPER = 945, + CARDOON = 946, + MUSHROOM = 947, + GRANNY_SMITH = 948, + STRAWBERRY = 949, + ORANGE = 950, + LEMON = 951, + FIG = 952, + PINEAPPLE = 953, + BANANA = 954, + JACKFRUIT = 955, + CUSTARD_APPLE = 956, + POMEGRANATE = 957, + HAY = 958, + CARBONARA = 959, + CHOCOLATE_SAUCE = 960, + DOUGH = 961, + MEAT_LOAF = 962, + PIZZA = 963, + POTPIE = 964, + BURRITO = 965, + RED_WINE = 966, + ESPRESSO = 967, + CUP = 968, + EGGNOG = 969, + ALP = 970, + BUBBLE = 971, + CLIFF = 972, + CORAL_REEF = 973, + GEYSER = 974, + LAKESIDE = 975, + PROMONTORY = 976, + SANDBAR = 977, + SEASHORE = 978, + VALLEY = 979, + VOLCANO = 980, + BALLPLAYER = 981, + GROOM = 982, + SCUBA_DIVER = 983, + RAPESEED = 984, + DAISY = 985, + YELLOW_LADYS_SLIPPER = 986, + CORN = 987, + ACORN = 988, + HIP = 989, + BUCKEYE = 990, + CORAL_FUNGUS = 991, + AGARIC = 992, + GYROMITRA = 993, + STINKHORN = 994, + EARTHSTAR = 995, + HEN_OF_THE_WOODS = 996, + BOLETE = 997, + EAR = 998, + TOILET_TISSUE = 999, +} diff --git a/packages/react-native-executorch/src/hooks/computer_vision/useClassification.ts b/packages/react-native-executorch/src/hooks/computer_vision/useClassification.ts index 2e3b4e22a0..b000511723 100644 --- a/packages/react-native-executorch/src/hooks/computer_vision/useClassification.ts +++ b/packages/react-native-executorch/src/hooks/computer_vision/useClassification.ts @@ -1,5 +1,9 @@ -import { ClassificationModule } from '../../modules/computer_vision/ClassificationModule'; import { + ClassificationModule, + ClassificationLabels, +} from '../../modules/computer_vision/ClassificationModule'; +import { + ClassificationModelSources, ClassificationProps, ClassificationType, } from '../../types/classification'; @@ -9,14 +13,17 @@ import { useModuleFactory } from '../useModuleFactory'; /** * React hook for managing a Classification model instance. * + * @typeParam C - A {@link ClassificationModelSources} config specifying which built-in model to load. * @category Hooks - * @param ClassificationProps - Configuration object containing `model` source and optional `preventLoad` flag. + * @param props - Configuration object containing `model` source and optional `preventLoad` flag. * @returns Ready to use Classification model. */ -export const useClassification = ({ +export const useClassification = ({ model, preventLoad = false, -}: ClassificationProps): ClassificationType => { +}: ClassificationProps): ClassificationType< + ClassificationLabels +> => { const { error, isReady, @@ -32,8 +39,8 @@ export const useClassification = ({ preventLoad, }); - const forward = (imageSource: string | PixelData) => - runForward((inst) => inst.forward(imageSource)); + const forward = (input: string | PixelData) => + runForward((inst) => inst.forward(input)); return { error, diff --git a/packages/react-native-executorch/src/index.ts b/packages/react-native-executorch/src/index.ts index fd91af5376..4c96a8957f 100644 --- a/packages/react-native-executorch/src/index.ts +++ b/packages/react-native-executorch/src/index.ts @@ -43,13 +43,18 @@ declare global { normStd: Triple | [], allClasses: string[] ) => Promise; - var loadClassification: (source: string) => Promise; var loadInstanceSegmentation: ( source: string, normMean: Triple | [], normStd: Triple | [], applyNMS: boolean - ) => any; + ) => Promise; + var loadClassification: ( + source: string, + normMean: Triple | [], + normStd: Triple | [], + labelNames: string[] + ) => Promise; var loadObjectDetection: ( source: string, normMean: Triple | [], @@ -199,6 +204,7 @@ export * from './types/tti'; // constants export * from './constants/commonVision'; +export * from './constants/classification'; export * from './constants/modelUrls'; export * from './constants/ocr/models'; export * from './constants/tts/models'; diff --git a/packages/react-native-executorch/src/modules/computer_vision/ClassificationModule.ts b/packages/react-native-executorch/src/modules/computer_vision/ClassificationModule.ts index d9ef0d7f73..8c0b23c8a4 100644 --- a/packages/react-native-executorch/src/modules/computer_vision/ClassificationModule.ts +++ b/packages/react-native-executorch/src/modules/computer_vision/ClassificationModule.ts @@ -1,83 +1,160 @@ -import { ResourceFetcher } from '../../utils/ResourceFetcher'; -import { PixelData, ResourceSource } from '../../types/common'; -import { ClassificationModelName } from '../../types/classification'; -import { RnExecutorchErrorCode } from '../../errors/ErrorCodes'; -import { parseUnknownError, RnExecutorchError } from '../../errors/errorUtils'; -import { Logger } from '../../common/Logger'; -import { VisionModule } from './VisionModule'; +import { LabelEnum, PixelData, ResourceSource } from '../../types/common'; +import { + ClassificationConfig, + ClassificationModelName, + ClassificationModelSources, +} from '../../types/classification'; +import { Imagenet1kLabel } from '../../constants/classification'; +import { IMAGENET1K_MEAN, IMAGENET1K_STD } from '../../constants/commonVision'; +import { + fetchModelPath, + ResolveLabels as ResolveLabelsFor, + VisionLabeledModule, +} from './VisionLabeledModule'; + +const ModelConfigs = { + 'efficientnet-v2-s': { + labelMap: Imagenet1kLabel, + preprocessorConfig: { normMean: IMAGENET1K_MEAN, normStd: IMAGENET1K_STD }, + }, + 'efficientnet-v2-s-quantized': { + labelMap: Imagenet1kLabel, + preprocessorConfig: { normMean: IMAGENET1K_MEAN, normStd: IMAGENET1K_STD }, + }, +} as const satisfies Record< + ClassificationModelName, + ClassificationConfig +>; + +type ModelConfigsType = typeof ModelConfigs; /** - * Module for image classification tasks. + * Resolves the {@link LabelEnum} for a given built-in classification model name. + * + * @typeParam M - A built-in model name from {@link ClassificationModelName}. + * + * @category Types + */ +export type ClassificationLabels = + ResolveLabelsFor; + +type ModelNameOf = C['modelName']; + +/** @internal */ +type ResolveLabels = + ResolveLabelsFor; + +/** + * Generic classification module with type-safe label maps. + * + * @typeParam T - Either a built-in model name (e.g. `'efficientnet-v2-s'`) + * or a custom {@link LabelEnum} label map. * * @category Typescript API */ -export class ClassificationModule extends VisionModule<{ - [category: string]: number; -}> { - private constructor(nativeModule: unknown) { - super(); - this.nativeModule = nativeModule; +export class ClassificationModule< + T extends ClassificationModelName | LabelEnum, +> extends VisionLabeledModule< + Record, number>, + ResolveLabels +> { + private constructor(labelMap: ResolveLabels, nativeModule: unknown) { + super(labelMap, nativeModule); } + /** * Creates a classification instance for a built-in model. * - * @param namedSources - An object specifying which built-in model to load and where to fetch it from. + * @param namedSources - A {@link ClassificationModelSources} object specifying which model to load and where to fetch it from. * @param onDownloadProgress - Optional callback to monitor download progress, receiving a value between 0 and 1. - * @returns A Promise resolving to a `ClassificationModule` instance. + * @returns A Promise resolving to a `ClassificationModule` instance typed to the chosen model's label map. */ - static async fromModelName( - namedSources: { - modelName: ClassificationModelName; - modelSource: ResourceSource; - }, + static async fromModelName( + namedSources: C, onDownloadProgress: (progress: number) => void = () => {} - ): Promise { - try { - const paths = await ResourceFetcher.fetch( - onDownloadProgress, - namedSources.modelSource - ); - - if (!paths?.[0]) { - throw new RnExecutorchError( - RnExecutorchErrorCode.DownloadInterrupted, - 'The download has been interrupted. As a result, not every file was downloaded. Please retry the download.' - ); - } - - return new ClassificationModule( - await global.loadClassification(paths[0]) - ); - } catch (error) { - Logger.error('Load failed:', error); - throw parseUnknownError(error); + ): Promise>> { + const { modelSource } = namedSources; + const { labelMap, preprocessorConfig } = ModelConfigs[ + namedSources.modelName + ] as ClassificationConfig; + const normMean = preprocessorConfig?.normMean ?? []; + const normStd = preprocessorConfig?.normStd ?? []; + const allLabelNames: string[] = []; + for (const [name, value] of Object.entries(labelMap)) { + if (typeof value === 'number') allLabelNames[value] = name; } + for (let i = 0; i < allLabelNames.length; i++) { + if (allLabelNames[i] == null) allLabelNames[i] = ''; + } + const modelPath = await fetchModelPath(modelSource, onDownloadProgress); + const nativeModule = await global.loadClassification( + modelPath, + normMean, + normStd, + allLabelNames + ); + return new ClassificationModule>( + labelMap as ResolveLabels>, + nativeModule + ); } /** - * Creates a classification instance with a user-provided model binary. + * Creates a classification instance with a user-provided model binary and label map. * Use this when working with a custom-exported model that is not one of the built-in presets. * - * @remarks The native model contract for this method is not formally defined and may change - * between releases. Refer to the native source code for the current expected tensor interface. + * ## Required model contract + * + * The `.pte` model binary must expose a single `forward` method with the following interface: + * + * **Input:** one `float32` tensor of shape `[1, 3, H, W]` — a single RGB image, values in + * `[0, 1]` after optional per-channel normalization `(pixel − mean) / std`. + * H and W are read from the model's declared input shape at load time. + * + * **Output:** one `float32` tensor of shape `[1, C]` containing raw logits — one value per class, + * in the same order as the entries in your `labelMap`. Softmax is applied by the native runtime. * * @param modelSource - A fetchable resource pointing to the model binary. + * @param config - A {@link ClassificationConfig} object with the label map and optional preprocessing parameters. * @param onDownloadProgress - Optional callback to monitor download progress, receiving a value between 0 and 1. - * @returns A Promise resolving to a `ClassificationModule` instance. + * @returns A Promise resolving to a `ClassificationModule` instance typed to the provided label map. */ - static fromCustomModel( + static async fromCustomModel( modelSource: ResourceSource, + config: ClassificationConfig, onDownloadProgress: (progress: number) => void = () => {} - ): Promise { - return ClassificationModule.fromModelName( - { modelName: 'custom' as ClassificationModelName, modelSource }, - onDownloadProgress + ): Promise> { + const normMean = config.preprocessorConfig?.normMean ?? []; + const normStd = config.preprocessorConfig?.normStd ?? []; + const allLabelNames: string[] = []; + for (const [name, value] of Object.entries(config.labelMap)) { + if (typeof value === 'number') allLabelNames[value] = name; + } + for (let i = 0; i < allLabelNames.length; i++) { + if (allLabelNames[i] == null) allLabelNames[i] = ''; + } + const modelPath = await fetchModelPath(modelSource, onDownloadProgress); + const nativeModule = await global.loadClassification( + modelPath, + normMean, + normStd, + allLabelNames + ); + return new ClassificationModule( + config.labelMap as ResolveLabels, + nativeModule ); } - async forward( + /** + * Executes the model's forward pass to classify the provided image. + * + * @param input - A string image source (file path, URI, or Base64) or a {@link PixelData} object. + * @returns A Promise resolving to an object mapping label keys to confidence scores. + */ + override async forward( input: string | PixelData - ): Promise<{ [category: string]: number }> { + ): Promise, number>> { return super.forward(input); } } diff --git a/packages/react-native-executorch/src/types/classification.ts b/packages/react-native-executorch/src/types/classification.ts index 994d72a05c..3c9ba6a0f2 100644 --- a/packages/react-native-executorch/src/types/classification.ts +++ b/packages/react-native-executorch/src/types/classification.ts @@ -1,26 +1,52 @@ import { RnExecutorchError } from '../errors/errorUtils'; -import { ResourceSource, PixelData, Frame } from './common'; +import { LabelEnum, Triple, ResourceSource, PixelData, Frame } from './common'; +import { Imagenet1kLabel } from '../constants/classification'; +export { Imagenet1kLabel }; + +/** + * Configuration for a custom classification model. + * + * @typeParam T - The {@link LabelEnum} type for the model. + * @property labelMap - The enum-like object mapping class names to indices. + * @property preprocessorConfig - Optional preprocessing parameters. + * @property preprocessorConfig.normMean - Per-channel mean values for input normalization. + * @property preprocessorConfig.normStd - Per-channel standard deviation values for input normalization. + * + * @category Types + */ +export type ClassificationConfig = { + labelMap: T; + preprocessorConfig?: { normMean?: Triple; normStd?: Triple }; +}; + +/** + * Per-model config for {@link ClassificationModule.fromModelName}. + * Each model name maps to its required fields. + * + * @category Types + */ +export type ClassificationModelSources = + | { modelName: 'efficientnet-v2-s'; modelSource: ResourceSource } + | { modelName: 'efficientnet-v2-s-quantized'; modelSource: ResourceSource }; /** * Union of all built-in classification model names. * * @category Types */ -export type ClassificationModelName = - | 'efficientnet-v2-s' - | 'efficientnet-v2-s-quantized'; +export type ClassificationModelName = ClassificationModelSources['modelName']; /** * Props for the `useClassification` hook. * - * @category Types - * @property {Object} model - An object containing the model configuration. - * @property {ClassificationModelName} model.modelName - Unique name identifying the model. - * @property {ResourceSource} model.modelSource - The source of the classification model binary. + * @typeParam C - A {@link ClassificationModelSources} config specifying which built-in model to load. + * @property model - The model config containing `modelName` and `modelSource`. * @property {boolean} [preventLoad] - Boolean that can prevent automatic model loading (and downloading the data if you load it for the first time) after running the hook. + * + * @category Types */ -export interface ClassificationProps { - model: { modelName: ClassificationModelName; modelSource: ResourceSource }; +export interface ClassificationProps { + model: C; preventLoad?: boolean; } @@ -28,9 +54,11 @@ export interface ClassificationProps { * Return type for the `useClassification` hook. * Manages the state and operations for Computer Vision image classification. * + * @typeParam L - The {@link LabelEnum} representing the model's class labels. + * * @category Types */ -export interface ClassificationType { +export interface ClassificationType { /** * Contains the error object if the model failed to load, download, or encountered a runtime error during classification. */ @@ -61,12 +89,10 @@ export interface ClassificationType { * **Note**: For VisionCamera frame processing, use `runOnFrame` instead. * * @param input - Image source (string or PixelData object) - * @returns A Promise that resolves to the classification result (labels and confidence scores). + * @returns A Promise that resolves to the classification result mapping label keys to confidence scores. * @throws {RnExecutorchError} If the model is not loaded or is currently processing another image. */ - forward: ( - input: string | PixelData - ) => Promise<{ [category: string]: number }>; + forward: (input: string | PixelData) => Promise>; /** * Synchronous worklet function for real-time VisionCamera frame processing. @@ -80,5 +106,5 @@ export interface ClassificationType { * @param frame - VisionCamera Frame object * @returns Object mapping class labels to confidence scores. */ - runOnFrame: ((frame: Frame) => { [category: string]: number }) | null; + runOnFrame: ((frame: Frame) => Record) | null; } From 30ecd90cf19fa6c0ec0f3397fa2620655f8e719c Mon Sep 17 00:00:00 2001 From: Norbert Klockiewicz Date: Fri, 20 Mar 2026 11:35:46 +0100 Subject: [PATCH 2/3] fix: don't use normalization for efficient net model --- .../02-computer-vision/useClassification.md | 6 +- .../models/classification/Constants.h | 1022 ----------------- .../tests/integration/ClassificationTest.cpp | 11 +- .../computer_vision/ClassificationModule.ts | 3 - 4 files changed, 8 insertions(+), 1034 deletions(-) delete mode 100644 packages/react-native-executorch/common/rnexecutorch/models/classification/Constants.h diff --git a/docs/docs/03-hooks/02-computer-vision/useClassification.md b/docs/docs/03-hooks/02-computer-vision/useClassification.md index 2c286b642b..4fe456c073 100644 --- a/docs/docs/03-hooks/02-computer-vision/useClassification.md +++ b/docs/docs/03-hooks/02-computer-vision/useClassification.md @@ -100,6 +100,6 @@ function App() { ## Supported models -| Model | Number of classes | Class list | Quantized | -| ------------------------------------------------------------------------------------------------------ | ----------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :-------: | -| [efficientnet_v2_s](https://huggingface.co/software-mansion/react-native-executorch-efficientnet-v2-s) | 1000 | [ImageNet1k_v1](https://github.com/software-mansion/react-native-executorch/blob/main/packages/react-native-executorch/common/rnexecutorch/models/classification/Constants.h) | Yes | +| Model | Number of classes | Class list | Quantized | +| ------------------------------------------------------------------------------------------------------ | ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- | :-------: | +| [efficientnet_v2_s](https://huggingface.co/software-mansion/react-native-executorch-efficientnet-v2-s) | 1000 | [ImageNet1k_v1](https://github.com/software-mansion/react-native-executorch/blob/main/packages/react-native-executorch/src/constants/classification.ts) | Yes | diff --git a/packages/react-native-executorch/common/rnexecutorch/models/classification/Constants.h b/packages/react-native-executorch/common/rnexecutorch/models/classification/Constants.h deleted file mode 100644 index b35538e302..0000000000 --- a/packages/react-native-executorch/common/rnexecutorch/models/classification/Constants.h +++ /dev/null @@ -1,1022 +0,0 @@ -#pragma once - -#include -#include - -namespace rnexecutorch::models::classification::constants { -inline constexpr std::array kImagenet1kV1Labels = { - "tench, Tinca tinca", - "goldfish, Carassius auratus", - "great white shark, white shark, man-eater, man-eating shark, Carcharodon " - "carcharias", - "tiger shark, Galeocerdo cuvieri", - "hammerhead, hammerhead shark", - "electric ray, crampfish, numbfish, torpedo", - "stingray", - "cock", - "hen", - "ostrich, Struthio camelus", - "brambling, Fringilla montifringilla", - "goldfinch, Carduelis carduelis", - "house finch, linnet, Carpodacus mexicanus", - "junco, snowbird", - "indigo bunting, indigo finch, indigo bird, Passerina cyanea", - "robin, American robin, Turdus migratorius", - "bulbul", - "jay", - "magpie", - "chickadee", - "water ouzel, dipper", - "kite", - "bald eagle, American eagle, Haliaeetus leucocephalus", - "vulture", - "great grey owl, great gray owl, Strix nebulosa", - "European fire salamander, Salamandra salamandra", - "common newt, Triturus vulgaris", - "eft", - "spotted salamander, Ambystoma maculatum", - "axolotl, mud puppy, Ambystoma mexicanum", - "bullfrog, Rana catesbeiana", - "tree frog, tree-frog", - "tailed frog, bell toad, ribbed toad, tailed toad, Ascaphus trui", - "loggerhead, loggerhead turtle, Caretta caretta", - "leatherback turtle, leatherback, leathery turtle, Dermochelys coriacea", - "mud turtle", - "terrapin", - "box turtle, box tortoise", - "banded gecko", - "common iguana, iguana, Iguana iguana", - "American chameleon, anole, Anolis carolinensis", - "whiptail, whiptail lizard", - "agama", - "frilled lizard, Chlamydosaurus kingi", - "alligator lizard", - "Gila monster, Heloderma suspectum", - "green lizard, Lacerta viridis", - "African chameleon, Chamaeleo chamaeleon", - "Komodo dragon, Komodo lizard, dragon lizard, giant lizard, Varanus " - "komodoensis", - "African crocodile, Nile crocodile, Crocodylus niloticus", - "American alligator, Alligator mississipiensis", - "triceratops", - "thunder snake, worm snake, Carphophis amoenus", - "ringneck snake, ring-necked snake, ring snake", - "hognose snake, puff adder, sand viper", - "green snake, grass snake", - "king snake, kingsnake", - "garter snake, grass snake", - "water snake", - "vine snake", - "night snake, Hypsiglena torquata", - "boa constrictor, Constrictor constrictor", - "rock python, rock snake, Python sebae", - "Indian cobra, Naja naja", - "green mamba", - "sea snake", - "horned viper, cerastes, sand viper, horned asp, Cerastes cornutus", - "diamondback, diamondback rattlesnake, Crotalus adamanteus", - "sidewinder, horned rattlesnake, Crotalus cerastes", - "trilobite", - "harvestman, daddy longlegs, Phalangium opilio", - "scorpion", - "black and gold garden spider, Argiope aurantia", - "barn spider, Araneus cavaticus", - "garden spider, Aranea diademata", - "black widow, Latrodectus mactans", - "tarantula", - "wolf spider, hunting spider", - "tick", - "centipede", - "black grouse", - "ptarmigan", - "ruffed grouse, partridge, Bonasa umbellus", - "prairie chicken, prairie grouse, prairie fowl", - "peacock", - "quail", - "partridge", - "African grey, African gray, Psittacus erithacus", - "macaw", - "sulphur-crested cockatoo, Kakatoe galerita, Cacatua galerita", - "lorikeet", - "coucal", - "bee eater", - "hornbill", - "hummingbird", - "jacamar", - "toucan", - "drake", - "red-breasted merganser, Mergus serrator", - "goose", - "black swan, Cygnus atratus", - "tusker", - "echidna, spiny anteater, anteater", - "platypus, duckbill, duckbilled platypus, duck-billed platypus, " - "Ornithorhynchus anatinus", - "wallaby, brush kangaroo", - "koala, koala bear, kangaroo bear, native bear, Phascolarctos cinereus", - "wombat", - "jellyfish", - "sea anemone, anemone", - "brain coral", - "flatworm, platyhelminth", - "nematode, nematode worm, roundworm", - "conch", - "snail", - "slug", - "sea slug, nudibranch", - "chiton, coat-of-mail shell, sea cradle, polyplacophore", - "chambered nautilus, pearly nautilus, nautilus", - "Dungeness crab, Cancer magister", - "rock crab, Cancer irroratus", - "fiddler crab", - "king crab, Alaska crab, Alaskan king crab, Alaska king crab, Paralithodes " - "camtschatica", - "American lobster, Northern lobster, Maine lobster, Homarus americanus", - "spiny lobster, langouste, rock lobster, crawfish, crayfish, sea crawfish", - "crayfish, crawfish, crawdad, crawdaddy", - "hermit crab", - "isopod", - "white stork, Ciconia ciconia", - "black stork, Ciconia nigra", - "spoonbill", - "flamingo", - "little blue heron, Egretta caerulea", - "American egret, great white heron, Egretta albus", - "bittern", - "crane(bird)", - "limpkin, Aramus pictus", - "European gallinule, Porphyrio porphyrio", - "American coot, marsh hen, mud hen, water hen, Fulica americana", - "bustard", - "ruddy turnstone, Arenaria interpres", - "red-backed sandpiper, dunlin, Erolia alpina", - "redshank, Tringa totanus", - "dowitcher", - "oystercatcher, oyster catcher", - "pelican", - "king penguin, Aptenodytes patagonica", - "albatross, mollymawk", - "grey whale, gray whale, devilfish, Eschrichtius gibbosus, Eschrichtius " - "robustus", - "killer whale, killer, orca, grampus, sea wolf, Orcinus orca", - "dugong, Dugong dugon", - "sea lion", - "Chihuahua", - "Japanese spaniel", - "Maltese dog, Maltese terrier, Maltese", - "Pekinese, Pekingese, Peke", - "Shih-Tzu", - "Blenheim spaniel", - "papillon", - "toy terrier", - "Rhodesian ridgeback", - "Afghan hound, Afghan", - "basset, basset hound", - "beagle", - "bloodhound, sleuthhound", - "bluetick", - "black-and-tan coonhound", - "Walker hound, Walker foxhound", - "English foxhound", - "redbone", - "borzoi, Russian wolfhound", - "Irish wolfhound", - "Italian greyhound", - "whippet", - "Ibizan hound, Ibizan Podenco", - "Norwegian elkhound, elkhound", - "otterhound, otter hound", - "Saluki, gazelle hound", - "Scottish deerhound, deerhound", - "Weimaraner", - "Staffordshire bullterrier, Staffordshire bull terrier", - "American Staffordshire terrier, Staffordshire terrier, American pit bull " - "terrier, pit bull terrier", - "Bedlington terrier", - "Border terrier", - "Kerry blue terrier", - "Irish terrier", - "Norfolk terrier", - "Norwich terrier", - "Yorkshire terrier", - "wire-haired fox terrier", - "Lakeland terrier", - "Sealyham terrier, Sealyham", - "Airedale, Airedale terrier", - "cairn, cairn terrier", - "Australian terrier", - "Dandie Dinmont, Dandie Dinmont terrier", - "Boston bull, Boston terrier", - "miniature schnauzer", - "giant schnauzer", - "standard schnauzer", - "Scotch terrier, Scottish terrier, Scottie", - "Tibetan terrier, chrysanthemum dog", - "silky terrier, Sydney silky", - "soft-coated wheaten terrier", - "West Highland white terrier", - "Lhasa, Lhasa apso", - "flat-coated retriever", - "curly-coated retriever", - "golden retriever", - "Labrador retriever", - "Chesapeake Bay retriever", - "German short-haired pointer", - "vizsla, Hungarian pointer", - "English setter", - "Irish setter, red setter", - "Gordon setter", - "Brittany spaniel", - "clumber, clumber spaniel", - "English springer, English springer spaniel", - "Welsh springer spaniel", - "cocker spaniel, English cocker spaniel, cocker", - "Sussex spaniel", - "Irish water spaniel", - "kuvasz", - "schipperke", - "groenendael", - "malinois", - "briard", - "kelpie", - "komondor", - "Old English sheepdog, bobtail", - "Shetland sheepdog, Shetland sheep dog, Shetland", - "collie", - "Border collie", - "Bouvier des Flandres, Bouviers des Flandres", - "Rottweiler", - "German shepherd, German shepherd dog, German police dog, alsatian", - "Doberman, Doberman pinscher", - "miniature pinscher", - "Greater Swiss Mountain dog", - "Bernese mountain dog", - "Appenzeller", - "EntleBucher", - "boxer", - "bull mastiff", - "Tibetan mastiff", - "French bulldog", - "Great Dane", - "Saint Bernard, St Bernard", - "Eskimo dog, husky", - "malamute, malemute, Alaskan malamute", - "Siberian husky", - "dalmatian, coach dog, carriage dog", - "affenpinscher, monkey pinscher, monkey dog", - "basenji", - "pug, pug-dog", - "Leonberg", - "Newfoundland, Newfoundland dog", - "Great Pyrenees", - "Samoyed, Samoyede", - "Pomeranian", - "chow, chow chow", - "keeshond", - "Brabancon griffon", - "Pembroke, Pembroke Welsh corgi", - "Cardigan, Cardigan Welsh corgi", - "toy poodle", - "miniature poodle", - "standard poodle", - "Mexican hairless", - "timber wolf, grey wolf, gray wolf, Canis lupus", - "white wolf, Arctic wolf, Canis lupus tundrarum", - "red wolf, maned wolf, Canis rufus, Canis niger", - "coyote, prairie wolf, brush wolf, Canis latrans", - "dingo, warrigal, warragal, Canis dingo", - "dhole, Cuon alpinus", - "African hunting dog, hyena dog, Cape hunting dog, Lycaon pictus", - "hyena, hyaena", - "red fox, Vulpes vulpes", - "kit fox, Vulpes macrotis", - "Arctic fox, white fox, Alopex lagopus", - "grey fox, gray fox, Urocyon cinereoargenteus", - "tabby, tabby cat", - "tiger cat", - "Persian cat", - "Siamese cat, Siamese", - "Egyptian cat", - "cougar, puma, catamount, mountain lion, painter, panther, Felis concolor", - "lynx, catamount", - "leopard, Panthera pardus", - "snow leopard, ounce, Panthera uncia", - "jaguar, panther, Panthera onca, Felis onca", - "lion, king of beasts, Panthera leo", - "tiger, Panthera tigris", - "cheetah, chetah, Acinonyx jubatus", - "brown bear, bruin, Ursus arctos", - "American black bear, black bear, Ursus americanus, Euarctos americanus", - "ice bear, polar bear, Ursus Maritimus, Thalarctos maritimus", - "sloth bear, Melursus ursinus, Ursus ursinus", - "mongoose", - "meerkat, mierkat", - "tiger beetle", - "ladybug, ladybeetle, lady beetle, ladybird, ladybird beetle", - "ground beetle, carabid beetle", - "long-horned beetle, longicorn, longicorn beetle", - "leaf beetle, chrysomelid", - "dung beetle", - "rhinoceros beetle", - "weevil", - "fly", - "bee", - "ant, emmet, pismire", - "grasshopper, hopper", - "cricket", - "walking stick, walkingstick, stick insect", - "cockroach, roach", - "mantis, mantid", - "cicada, cicala", - "leafhopper", - "lacewing, lacewing fly", - "dragonfly, darning needle, devil's darning needle, sewing needle, snake " - "feeder, snake doctor, mosquito hawk, skeeter hawk", - "damselfly", - "admiral", - "ringlet, ringlet butterfly", - "monarch, monarch butterfly, milkweed butterfly, Danaus plexippus", - "cabbage butterfly", - "sulphur butterfly, sulfur butterfly", - "lycaenid, lycaenid butterfly", - "starfish, sea star", - "sea urchin", - "sea cucumber, holothurian", - "wood rabbit, cottontail, cottontail rabbit", - "hare", - "Angora, Angora rabbit", - "hamster", - "porcupine, hedgehog", - "fox squirrel, eastern fox squirrel, Sciurus niger", - "marmot", - "beaver", - "guinea pig, Cavia cobaya", - "sorrel", - "zebra", - "hog, pig, grunter, squealer, Sus scrofa", - "wild boar, boar, Sus scrofa", - "warthog", - "hippopotamus, hippo, river horse, Hippopotamus amphibius", - "ox", - "water buffalo, water ox, Asiatic buffalo, Bubalus bubalis", - "bison", - "ram, tup", - "bighorn, bighorn sheep, cimarron, Rocky Mountain bighorn, Rocky Mountain " - "sheep, Ovis canadensis", - "ibex, Capra ibex", - "hartebeest", - "impala, Aepyceros melampus", - "gazelle", - "Arabian camel, dromedary, Camelus dromedarius", - "llama", - "weasel", - "mink", - "polecat, fitch, foulmart, foumart, Mustela putorius", - "black-footed ferret, ferret, Mustela nigripes", - "otter", - "skunk, polecat, wood pussy", - "badger", - "armadillo", - "three-toed sloth, ai, Bradypus tridactylus", - "orangutan, orang, orangutang, Pongo pygmaeus", - "gorilla, Gorilla gorilla", - "chimpanzee, chimp, Pan troglodytes", - "gibbon, Hylobates lar", - "siamang, Hylobates syndactylus, Symphalangus syndactylus", - "guenon, guenon monkey", - "patas, hussar monkey, Erythrocebus patas", - "baboon", - "macaque", - "langur", - "colobus, colobus monkey", - "proboscis monkey, Nasalis larvatus", - "marmoset", - "capuchin, ringtail, Cebus capucinus", - "howler monkey, howler", - "titi, titi monkey", - "spider monkey, Ateles geoffroyi", - "squirrel monkey, Saimiri sciureus", - "Madagascar cat, ring-tailed lemur, Lemur catta", - "indri, indris, Indri indri, Indri brevicaudatus", - "Indian elephant, Elephas maximus", - "African elephant, Loxodonta africana", - "lesser panda, red panda, panda, bear cat, cat bear, Ailurus fulgens", - "giant panda, panda, panda bear, coon bear, Ailuropoda melanoleuca", - "barracouta, snoek", - "eel", - "coho, cohoe, coho salmon, blue jack, silver salmon, Oncorhynchus kisutch", - "rock beauty, Holocanthus tricolor", - "anemone fish", - "sturgeon", - "gar, garfish, garpike, billfish, Lepisosteus osseus", - "lionfish", - "puffer, pufferfish, blowfish, globefish", - "abacus", - "abaya", - "academic gown, academic robe, judge's robe", - "accordion, piano accordion, squeeze box", - "acoustic guitar", - "aircraft carrier, carrier, flattop, attack aircraft carrier", - "airliner", - "airship, dirigible", - "altar", - "ambulance", - "amphibian, amphibious vehicle", - "analog clock", - "apiary, bee house", - "apron", - "ashcan, trash can, garbage can, wastebin, ash bin, ash-bin, ashbin, " - "dustbin, trash barrel, trash bin", - "assault rifle, assault gun", - "backpack, back pack, knapsack, packsack, rucksack, haversack", - "bakery, bakeshop, bakehouse", - "balance beam, beam", - "balloon", - "ballpoint, ballpoint pen, ballpen, Biro", - "Band Aid", - "banjo", - "bannister, banister, balustrade, balusters, handrail", - "barbell", - "barber chair", - "barbershop", - "barn", - "barometer", - "barrel, cask", - "barrow, garden cart, lawn cart, wheelbarrow", - "baseball", - "basketball", - "bassinet", - "bassoon", - "bathing cap, swimming cap", - "bath towel", - "bathtub, bathing tub, bath, tub", - "beach wagon, station wagon, wagon, estate car, beach waggon, station " - "waggon, waggon", - "beacon, lighthouse, beacon light, pharos", - "beaker", - "bearskin, busby, shako", - "beer bottle", - "beer glass", - "bell cote, bell cot", - "bib", - "bicycle-built-for-two, tandem bicycle, tandem", - "bikini, two-piece", - "binder, ring-binder", - "binoculars, field glasses, opera glasses", - "birdhouse", - "boathouse", - "bobsled, bobsleigh, bob", - "bolo tie, bolo, bola tie, bola", - "bonnet, poke bonnet", - "bookcase", - "bookshop, bookstore, bookstall", - "bottlecap", - "bow", - "bow tie, bow-tie, bowtie", - "brass, memorial tablet, plaque", - "brassiere, bra, bandeau", - "breakwater, groin, groyne, mole, bulwark, seawall, jetty", - "breastplate, aegis, egis", - "broom", - "bucket, pail", - "buckle", - "bulletproof vest", - "bullet train, bullet", - "butcher shop, meat market", - "cab, hack, taxi, taxicab", - "caldron, cauldron", - "candle, taper, wax light", - "cannon", - "canoe", - "can opener, tin opener", - "cardigan", - "car mirror", - "carousel, carrousel, merry-go-round, roundabout, whirligig", - "carpenter's kit, tool kit", - "carton", - "car wheel", - "cash machine, cash dispenser, automated teller machine, automatic teller " - "machine, automated teller, automatic teller, ATM", - "cassette", - "cassette player", - "castle", - "catamaran", - "CD player", - "cello, violoncello", - "cellular telephone, cellular phone, cellphone, cell, mobile phone", - "chain", - "chainlink fence", - "chain mail, ring mail, mail, chain armor, chain armour, ring armor, ring " - "armour", - "chain saw, chainsaw", - "chest", - "chiffonier, commode", - "chime, bell, gong", - "china cabinet, china closet", - "Christmas stocking", - "church, church building", - "cinema, movie theater, movie theatre, movie house, picture palace", - "cleaver, meat cleaver, chopper", - "cliff dwelling", - "cloak", - "clog, geta, patten, sabot", - "cocktail shaker", - "coffee mug", - "coffeepot", - "coil, spiral, volute, whorl, helix", - "combination lock", - "computer keyboard, keypad", - "confectionery, confectionary, candy store", - "container ship, containership, container vessel", - "convertible", - "corkscrew, bottle screw", - "cornet, horn, trumpet, trump", - "cowboy boot", - "cowboy hat, ten-gallon hat", - "cradle", - "crane(machine)", - "crash helmet", - "crate", - "crib, cot", - "Crock Pot", - "croquet ball", - "crutch", - "cuirass", - "dam, dike, dyke", - "desk", - "desktop computer", - "dial telephone, dial phone", - "diaper, nappy, napkin", - "digital clock", - "digital watch", - "dining table, board", - "dishrag, dishcloth", - "dishwasher, dish washer, dishwashing machine", - "disk brake, disc brake", - "dock, dockage, docking facility", - "dogsled, dog sled, dog sleigh", - "dome", - "doormat, welcome mat", - "drilling platform, offshore rig", - "drum, membranophone, tympan", - "drumstick", - "dumbbell", - "Dutch oven", - "electric fan, blower", - "electric guitar", - "electric locomotive", - "entertainment center", - "envelope", - "espresso maker", - "face powder", - "feather boa, boa", - "file, file cabinet, filing cabinet", - "fireboat", - "fire engine, fire truck", - "fire screen, fireguard", - "flagpole, flagstaff", - "flute, transverse flute", - "folding chair", - "football helmet", - "forklift", - "fountain", - "fountain pen", - "four-poster", - "freight car", - "French horn, horn", - "frying pan, frypan, skillet", - "fur coat", - "garbage truck, dustcart", - "gasmask, respirator, gas helmet", - "gas pump, gasoline pump, petrol pump, island dispenser", - "goblet", - "go-kart", - "golf ball", - "golfcart, golf cart", - "gondola", - "gong, tam-tam", - "gown", - "grand piano, grand", - "greenhouse, nursery, glasshouse", - "grille, radiator grille", - "grocery store, grocery, food market, market", - "guillotine", - "hair slide", - "hair spray", - "half track", - "hammer", - "hamper", - "hand blower, blow dryer, blow drier, hair dryer, hair drier", - "hand-held computer, hand-held microcomputer", - "handkerchief, hankie, hanky, hankey", - "hard disc, hard disk, fixed disk", - "harmonica, mouth organ, harp, mouth harp", - "harp", - "harvester, reaper", - "hatchet", - "holster", - "home theater, home theatre", - "honeycomb", - "hook, claw", - "hoopskirt, crinoline", - "horizontal bar, high bar", - "horse cart, horse-cart", - "hourglass", - "iPod", - "iron, smoothing iron", - "jack-o'-lantern", - "jean, blue jean, denim", - "jeep, landrover", - "jersey, T-shirt, tee shirt", - "jigsaw puzzle", - "jinrikisha, ricksha, rickshaw", - "joystick", - "kimono", - "knee pad", - "knot", - "lab coat, laboratory coat", - "ladle", - "lampshade, lamp shade", - "laptop, laptop computer", - "lawn mower, mower", - "lens cap, lens cover", - "letter opener, paper knife, paperknife", - "library", - "lifeboat", - "lighter, light, igniter, ignitor", - "limousine, limo", - "liner, ocean liner", - "lipstick, lip rouge", - "Loafer", - "lotion", - "loudspeaker, speaker, speaker unit, loudspeaker system, speaker system", - "loupe, jeweler's loupe", - "lumbermill, sawmill", - "magnetic compass", - "mailbag, postbag", - "mailbox, letter box", - "maillot", - "maillot, tank suit", - "manhole cover", - "maraca", - "marimba, xylophone", - "mask", - "matchstick", - "maypole", - "maze, labyrinth", - "measuring cup", - "medicine chest, medicine cabinet", - "megalith, megalithic structure", - "microphone, mike", - "microwave, microwave oven", - "military uniform", - "milk can", - "minibus", - "miniskirt, mini", - "minivan", - "missile", - "mitten", - "mixing bowl", - "mobile home, manufactured home", - "Model T", - "modem", - "monastery", - "monitor", - "moped", - "mortar", - "mortarboard", - "mosque", - "mosquito net", - "motor scooter, scooter", - "mountain bike, all-terrain bike, off-roader", - "mountain tent", - "mouse, computer mouse", - "mousetrap", - "moving van", - "muzzle", - "nail", - "neck brace", - "necklace", - "nipple", - "notebook, notebook computer", - "obelisk", - "oboe, hautboy, hautbois", - "ocarina, sweet potato", - "odometer, hodometer, mileometer, milometer", - "oil filter", - "organ, pipe organ", - "oscilloscope, scope, cathode-ray oscilloscope, CRO", - "overskirt", - "oxcart", - "oxygen mask", - "packet", - "paddle, boat paddle", - "paddlewheel, paddle wheel", - "padlock", - "paintbrush", - "pajama, pyjama, pj's, jammies", - "palace", - "panpipe, pandean pipe, syrinx", - "paper towel", - "parachute, chute", - "parallel bars, bars", - "park bench", - "parking meter", - "passenger car, coach, carriage", - "patio, terrace", - "pay-phone, pay-station", - "pedestal, plinth, footstall", - "pencil box, pencil case", - "pencil sharpener", - "perfume, essence", - "Petri dish", - "photocopier", - "pick, plectrum, plectron", - "pickelhaube", - "picket fence, paling", - "pickup, pickup truck", - "pier", - "piggy bank, penny bank", - "pill bottle", - "pillow", - "ping-pong ball", - "pinwheel", - "pirate, pirate ship", - "pitcher, ewer", - "plane, carpenter's plane, woodworking plane", - "planetarium", - "plastic bag", - "plate rack", - "plow, plough", - "plunger, plumber's helper", - "Polaroid camera, Polaroid Land camera", - "pole", - "police van, police wagon, paddy wagon, patrol wagon, wagon, black Maria", - "poncho", - "pool table, billiard table, snooker table", - "pop bottle, soda bottle", - "pot, flowerpot", - "potter's wheel", - "power drill", - "prayer rug, prayer mat", - "printer", - "prison, prison house", - "projectile, missile", - "projector", - "puck, hockey puck", - "punching bag, punch bag, punching ball, punchball", - "purse", - "quill, quill pen", - "quilt, comforter, comfort, puff", - "racer, race car, racing car", - "racket, racquet", - "radiator", - "radio, wireless", - "radio telescope, radio reflector", - "rain barrel", - "recreational vehicle, RV, R.V.", - "reel", - "reflex camera", - "refrigerator, icebox", - "remote control, remote", - "restaurant, eating house, eating place, eatery", - "revolver, six-gun, six-shooter", - "rifle", - "rocking chair, rocker", - "rotisserie", - "rubber eraser, rubber, pencil eraser", - "rugby ball", - "rule, ruler", - "running shoe", - "safe", - "safety pin", - "saltshaker, salt shaker", - "sandal", - "sarong", - "sax, saxophone", - "scabbard", - "scale, weighing machine", - "school bus", - "schooner", - "scoreboard", - "screen, CRT screen", - "screw", - "screwdriver", - "seat belt, seatbelt", - "sewing machine", - "shield, buckler", - "shoe shop, shoe-shop, shoe store", - "shoji", - "shopping basket", - "shopping cart", - "shovel", - "shower cap", - "shower curtain", - "ski", - "ski mask", - "sleeping bag", - "slide rule, slipstick", - "sliding door", - "slot, one-armed bandit", - "snorkel", - "snowmobile", - "snowplow, snowplough", - "soap dispenser", - "soccer ball", - "sock", - "solar dish, solar collector, solar furnace", - "sombrero", - "soup bowl", - "space bar", - "space heater", - "space shuttle", - "spatula", - "speedboat", - "spider web, spider's web", - "spindle", - "sports car, sport car", - "spotlight, spot", - "stage", - "steam locomotive", - "steel arch bridge", - "steel drum", - "stethoscope", - "stole", - "stone wall", - "stopwatch, stop watch", - "stove", - "strainer", - "streetcar, tram, tramcar, trolley, trolley car", - "stretcher", - "studio couch, day bed", - "stupa, tope", - "submarine, pigboat, sub, U-boat", - "suit, suit of clothes", - "sundial", - "sunglass", - "sunglasses, dark glasses, shades", - "sunscreen, sunblock, sun blocker", - "suspension bridge", - "swab, swob, mop", - "sweatshirt", - "swimming trunks, bathing trunks", - "swing", - "switch, electric switch, electrical switch", - "syringe", - "table lamp", - "tank, army tank, armored combat vehicle, armoured combat vehicle", - "tape player", - "teapot", - "teddy, teddy bear", - "television, television system", - "tennis ball", - "thatch, thatched roof", - "theater curtain, theatre curtain", - "thimble", - "thresher, thrasher, threshing machine", - "throne", - "tile roof", - "toaster", - "tobacco shop, tobacconist shop, tobacconist", - "toilet seat", - "torch", - "totem pole", - "tow truck, tow car, wrecker", - "toyshop", - "tractor", - "trailer truck, tractor trailer, trucking rig, rig, articulated lorry, " - "semi", - "tray", - "trench coat", - "tricycle, trike, velocipede", - "trimaran", - "tripod", - "triumphal arch", - "trolleybus, trolley coach, trackless trolley", - "trombone", - "tub, vat", - "turnstile", - "typewriter keyboard", - "umbrella", - "unicycle, monocycle", - "upright, upright piano", - "vacuum, vacuum cleaner", - "vase", - "vault", - "velvet", - "vending machine", - "vestment", - "viaduct", - "violin, fiddle", - "volleyball", - "waffle iron", - "wall clock", - "wallet, billfold, notecase, pocketbook", - "wardrobe, closet, press", - "warplane, military plane", - "washbasin, handbasin, washbowl, lavabo, wash-hand basin", - "washer, automatic washer, 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, woolen, woollen", - "worm fence, snake fence, snake-rail fence, Virginia fence", - "wreck", - "yawl", - "yurt", - "web site, website, internet site, site", - "comic book", - "crossword puzzle, crossword", - "street sign", - "traffic light, traffic signal, stoplight", - "book jacket, dust cover, dust jacket, dust wrapper", - "menu", - "plate", - "guacamole", - "consomme", - "hot pot, hotpot", - "trifle", - "ice cream, icecream", - "ice lolly, lolly, lollipop, popsicle", - "French loaf", - "bagel, beigel", - "pretzel", - "cheeseburger", - "hotdog, hot dog, red hot", - "mashed potato", - "head cabbage", - "broccoli", - "cauliflower", - "zucchini, courgette", - "spaghetti squash", - "acorn squash", - "butternut squash", - "cucumber, cuke", - "artichoke, globe artichoke", - "bell pepper", - "cardoon", - "mushroom", - "Granny Smith", - "strawberry", - "orange", - "lemon", - "fig", - "pineapple, ananas", - "banana", - "jackfruit, jak, jack", - "custard apple", - "pomegranate", - "hay", - "carbonara", - "chocolate sauce, chocolate syrup", - "dough", - "meat loaf, meatloaf", - "pizza, pizza pie", - "potpie", - "burrito", - "red wine", - "espresso", - "cup", - "eggnog", - "alp", - "bubble", - "cliff, drop, drop-off", - "coral reef", - "geyser", - "lakeside, lakeshore", - "promontory, headland, head, foreland", - "sandbar, sand bar", - "seashore, coast, seacoast, sea-coast", - "valley, vale", - "volcano", - "ballplayer, baseball player", - "groom, bridegroom", - "scuba diver", - "rapeseed", - "daisy", - "yellow lady's slipper, yellow lady-slipper, Cypripedium calceolus, " - "Cypripedium parviflorum", - "corn", - "acorn", - "hip, rose hip, rosehip", - "buckeye, horse chestnut, conker", - "coral fungus", - "agaric", - "gyromitra", - "stinkhorn, carrion fungus", - "earthstar", - "hen-of-the-woods, hen of the woods, Polyporus frondosus, Grifola frondosa", - "bolete", - "ear, spike, capitulum", - "toilet tissue, toilet paper, bathroom tissue"}; -} // namespace rnexecutorch::models::classification::constants diff --git a/packages/react-native-executorch/common/rnexecutorch/tests/integration/ClassificationTest.cpp b/packages/react-native-executorch/common/rnexecutorch/tests/integration/ClassificationTest.cpp index 642f63ecc3..6991c2fe06 100644 --- a/packages/react-native-executorch/common/rnexecutorch/tests/integration/ClassificationTest.cpp +++ b/packages/react-native-executorch/common/rnexecutorch/tests/integration/ClassificationTest.cpp @@ -5,8 +5,6 @@ #include #include #include -#include - using namespace rnexecutorch; using namespace rnexecutorch::models::classification; using namespace model_tests; @@ -14,15 +12,16 @@ using namespace model_tests; constexpr auto kValidClassificationModelPath = "efficientnet_v2_s_xnnpack.pte"; constexpr auto kValidTestImagePath = "file:///data/local/tmp/rnexecutorch_tests/test_image.jpg"; +constexpr size_t kImagenet1kNumClasses = 1000; static std::vector kImagenetNormMean = {0.485f, 0.456f, 0.406f}; static std::vector kImagenetNormStd = {0.229f, 0.224f, 0.225f}; static std::vector getImagenetLabelNames() { std::vector names; - names.reserve(constants::kImagenet1kV1Labels.size()); - for (const auto &label : constants::kImagenet1kV1Labels) { - names.emplace_back(label); + names.reserve(kImagenet1kNumClasses); + for (size_t i = 0; i < kImagenet1kNumClasses; ++i) { + names.emplace_back("class_" + std::to_string(i)); } return names; } @@ -89,7 +88,7 @@ TEST(ClassificationGenerateTests, ResultsHaveCorrectSize) { Classification model(kValidClassificationModelPath, kImagenetNormMean, kImagenetNormStd, getImagenetLabelNames(), nullptr); auto results = model.generateFromString(kValidTestImagePath); - auto expectedNumClasses = constants::kImagenet1kV1Labels.size(); + auto expectedNumClasses = kImagenet1kNumClasses; EXPECT_EQ(results.size(), expectedNumClasses); } diff --git a/packages/react-native-executorch/src/modules/computer_vision/ClassificationModule.ts b/packages/react-native-executorch/src/modules/computer_vision/ClassificationModule.ts index 8c0b23c8a4..78c7916820 100644 --- a/packages/react-native-executorch/src/modules/computer_vision/ClassificationModule.ts +++ b/packages/react-native-executorch/src/modules/computer_vision/ClassificationModule.ts @@ -5,7 +5,6 @@ import { ClassificationModelSources, } from '../../types/classification'; import { Imagenet1kLabel } from '../../constants/classification'; -import { IMAGENET1K_MEAN, IMAGENET1K_STD } from '../../constants/commonVision'; import { fetchModelPath, ResolveLabels as ResolveLabelsFor, @@ -15,11 +14,9 @@ import { const ModelConfigs = { 'efficientnet-v2-s': { labelMap: Imagenet1kLabel, - preprocessorConfig: { normMean: IMAGENET1K_MEAN, normStd: IMAGENET1K_STD }, }, 'efficientnet-v2-s-quantized': { labelMap: Imagenet1kLabel, - preprocessorConfig: { normMean: IMAGENET1K_MEAN, normStd: IMAGENET1K_STD }, }, } as const satisfies Record< ClassificationModelName, From ddf9d0f86cc5c8e81ec6a8f75414ad6de82a6cb2 Mon Sep 17 00:00:00 2001 From: Norbert Klockiewicz Date: Fri, 20 Mar 2026 11:41:03 +0100 Subject: [PATCH 3/3] chore: warning on wrong shape of normMean/normStd --- .../rnexecutorch/models/classification/Classification.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/packages/react-native-executorch/common/rnexecutorch/models/classification/Classification.cpp b/packages/react-native-executorch/common/rnexecutorch/models/classification/Classification.cpp index 4baa92e88e..e34f68fe64 100644 --- a/packages/react-native-executorch/common/rnexecutorch/models/classification/Classification.cpp +++ b/packages/react-native-executorch/common/rnexecutorch/models/classification/Classification.cpp @@ -2,6 +2,8 @@ #include #include +#include + #include #include @@ -16,9 +18,15 @@ Classification::Classification(const std::string &modelSource, labelNames_(std::move(labelNames)) { if (normMean.size() == 3) { normMean_ = cv::Scalar(normMean[0], normMean[1], normMean[2]); + } else if (!normMean.empty()) { + log(LOG_LEVEL::Warn, + "normMean must have 3 elements — ignoring provided value."); } if (normStd.size() == 3) { normStd_ = cv::Scalar(normStd[0], normStd[1], normStd[2]); + } else if (!normStd.empty()) { + log(LOG_LEVEL::Warn, + "normStd must have 3 elements — ignoring provided value."); } auto inputShapes = getAllInputShapes();