File size: 5,811 Bytes
5c0ccbd
a927e75
 
53b0237
a927e75
5c0ccbd
 
a927e75
 
 
 
 
 
 
5c0ccbd
 
a927e75
5c0ccbd
a927e75
 
 
 
75c8f1b
a927e75
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
75c8f1b
 
 
a927e75
 
 
 
 
75c8f1b
a927e75
5c0ccbd
 
 
a927e75
1232ce7
5c0ccbd
 
 
 
 
 
 
 
 
75c8f1b
 
5c0ccbd
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2fd1892
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
---
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%
```