--- language: - en license: apache-2.0 tags: - vision - image-classification - edge-ai - mobile - plant-identification - nature - tflite - torchscript pipeline_tag: image-classification --- # Kindwise Router Classifier (tiny) [![Kindwise](https://img.shields.io/badge/Kindwise-Homepage-blue)](https://www.kindwise.com) [![Docs](https://img.shields.io/badge/API-Documentation-green)](https://admin.kindwise.com/public/docs) [![Python SDK](https://img.shields.io/pypi/v/kindwise-api-client?label=kindwise-api-client)](https://pypi.org/project/kindwise-api-client/) [![License: Apache 2.0](https://img.shields.io/badge/License-Apache_2.0-yellow.svg)](https://opensource.org/licenses/Apache-2.0) This model classifies images based on their content, acting as an on-device router to direct requests to the appropriate [Kindwise API](https://www.kindwise.com) before uploading data to the cloud. It detects whether an image contains a **plant, unhealthy plant, crop, mushroom, insect, or human**. Using the router as the first step in your pipeline minimizes cloud latency, optimizes bandwidth, and protects privacy by keeping non-target photos (such as people) on the device. ## Available Variants | Variant | TFLite | Optimized | RAM Est. | Primary Focus | | :--- | :---: | :---: | :---: | :--- | | **`router.tiny`** (this model) | 53 MB | **14 MB** | ~40 MB | Ultra-low footprint & edge devices | | [`router.small`](https://huggingface.co/kindwise/router.small) | 146 MB | 38 MB | ~80 MB | Balanced accuracy & latency | | [`router.base`](https://huggingface.co/kindwise/router.base) | 375 MB | 96 MB | ~220 MB | Highest precision | ## Downstream Routing Route predicted categories to specialized Kindwise APIs (100 free credits available at [admin.kindwise.com](https://admin.kindwise.com)): - `plant` → **[Plant.id API](https://www.kindwise.com/plant-id)** (35,000+ taxa, cultivars, care data · [Live Demo](https://plant.id)) - `unhealthy_plant` → **[plant.health API](https://www.kindwise.com/plant-health)** (548 diseases, pests, abiotic disorders) - `crop` + `unhealthy_plant` → **[crop.health API](https://www.kindwise.com/crop-health)** (288 conditions across 23 staple crops + EPPO codes) - `mushroom` → **[mushroom.id API](https://www.kindwise.com/mushroom-id)** (5,000 fungi, toxicity & edibility) - `insect` → **[insect.id API](https://www.kindwise.com/insect-id)** (14,000+ terrestrial invertebrates) - `human` → *Handle locally (privacy filter)* ## Technical Details and Formats Available in two deployment formats: - **TorchScript** (`model.traced.pt`): For server-side inference and high-throughput production services. - **TensorFlow Lite** (`model.tflite`, `model.optimized.tflite`): For mobile and embedded devices. You can also use this model directly via Python SDK: `pip install kindwise-api-client[router]`. ## Usage Here is how to use this model to classify an image into one of the basic classes: ### PyTorch ```python from huggingface_hub import hf_hub_download import cv2 import numpy as np import PIL.Image import torch import torchvision DEVICE_NAME = 'cuda:0' MODEL_PATH = hf_hub_download('kindwise/router.tiny', 'model.traced.pt') CLASSES_PATH = hf_hub_download('kindwise/router.tiny', 'classes.txt') IMAGE_PATH = '/tmp/photo.jpg' with open(CLASSES_PATH) as f: CLASSES = [line.strip() for line in f] MODEL = torch.jit.load(MODEL_PATH).eval().to(DEVICE_NAME) def resize_crop(image_data: np.ndarray, target_size: int = 480) -> np.ndarray | None: height, width, _ = image_data.shape # Determine the size of the square crop crop_size = min(height, width) # Calculate coordinates for center crop start_x = (width - crop_size) // 2 start_y = (height - crop_size) // 2 # Perform center crop cropped_img = image_data[ start_y : start_y + crop_size, start_x : start_x + crop_size ] # Resize cropped image to target size return cv2.resize( cropped_img, (target_size, target_size), interpolation=cv2.INTER_AREA, ) with torch.no_grad(): image_array = np.array(PIL.Image.open(IMAGE_PATH)) image_array_resized = resize_crop(image_array) image_tensor = torchvision.transforms.functional.to_tensor(image_array_resized).to(DEVICE_NAME) prediction = MODEL(image_tensor.unsqueeze(0)).squeeze(0).cpu().numpy() for i in (-prediction).argsort(): print(f'{CLASSES[i]:>10}: {100 * prediction[i]:.1f}%') ``` Output: ```text plant: 91.3% unhealthy_plant: 53.3% crop: 16.2% insect: 0.4% human: 0.1% mushroom: 0.0% ``` ### TensorFlow Lite ```python from huggingface_hub import hf_hub_download import numpy as np import tensorflow as tf MODEL_PATH = hf_hub_download('kindwise/router.tiny', 'model.tflite') # or model.optimized.tflite CLASSES_PATH = hf_hub_download('kindwise/router.tiny', 'classes.txt') with open(CLASSES_PATH) as f: CLASSES = [line.strip() for line in f] INTERPRETER = tf.lite.Interpreter(model_path=MODEL_PATH) INTERPRETER.allocate_tensors() image_array_resized = ... # see the previous example tf_input = np.expand_dims( # add batch dimension (image_array_resized / 255).astype(np.float32), # image values in [0..1] 0, ) input_details = INTERPRETER.get_input_details() output_details = INTERPRETER.get_output_details() INTERPRETER.set_tensor( input_details[0]['index'], tf_input, ) INTERPRETER.invoke() logits = INTERPRETER.get_tensor(output_details[0]['index'])[0] prediction = tf.nn.sigmoid(logits).numpy() for i in (-prediction).argsort(): print(f'{CLASSES[i]:>10}: {100 * prediction[i]:.1f}%') ``` Output: ```text plant: 91.3% unhealthy_plant: 53.3% crop: 16.2% insect: 0.4% human: 0.1% mushroom: 0.0% ```