Commit e51547e
feat!: make image segmentation generic, general refactor (software-mansion#814)
## Description
Refactors image segmentation into a generic, multi-model architecture.
Previously the module was hardcoded to DeepLab V3 — now it supports
multiple built-in models (DeepLab V3, selfie segmentation, RF-DETR) and
custom user-provided models with type-safe label maps.
**Key changes:**
- **C++ base class**: Extracted `BaseImageSegmentation` with virtual
`preprocess()`/`postprocess()` methods. `ImageSegmentation` is now a
thin subclass. This allows future models to override preprocessing (e.g.
different normalization) or postprocessing without duplicating the
pipeline.
- **Optional normalization in C++**: `readImageToTensor` now accepts
optional `normMean`/`normStd` params, eliminating duplicated
normalization logic. **also, imo it would be a good idea to do such
factories for the entire API**
- **Generic TypeScript module**: `ImageSegmentationModule<T>` is generic
over model name or custom `LabelEnum`. Two static factories:
`fromModelName()` (built-in models with auto label resolution) and
`fromCustomConfig()` (custom models with user-provided labels).
- **Generic hook**: `useImageSegmentation` infers the model's label
types from the config — no explicit generic parameter needed.
`forward()` return type narrows based on `classesOfInterest` passed in.
- **Correct return types**: `forward()` now returns `Record<'ARGMAX',
Int32Array> & Record<K, Float32Array>` matching what the native side
actually produces (was incorrectly typed as `number[]`).
- **ARGMAX always returned**: Removed `'ARGMAX'` from
`classesOfInterest` — it's always in the output regardless, and the
return type reflects this.
### Introduces a breaking change?
- [x] Yes
- [ ] No
### Type of change
- [ ] Bug fix (change which fixes an issue)
- [x] New feature (change which adds functionality)
- [ ] Documentation update (improves or adds clarity to existing
documentation)
- [ ] Other (chores, tests, code style improvements etc.)
### Tested on
- [ ] iOS
- [x] Android
### Testing instructions
1. Build and run the `computer-vision` demo app
2. Navigate to Image Segmentation screen
3. Pick an image and run segmentation — verify the ARGMAX overlay
renders correctly
4. Verify the hook API works as expected:
```ts
const { isReady, forward } = useImageSegmentation({
model: { modelName: 'deeplab-v3', modelSource: DEEPLAB_V3_RESNET50 },
});
// Returns Record<'ARGMAX', Int32Array> — no generic needed
const result = await forward(imageUri);
// Narrows return type to include 'PERSON' key as Float32Array
const result2 = await forward(imageUri, ['PERSON']);
```
5. Verify TypeScript autocompletion: `classesOfInterest` should only
suggest valid label keys for the chosen model (e.g. `'PERSON'`, `'CAR'`
for DeepLab, `'SELFIE'`/`'BACKGROUND'` for selfie segmentation)
6. You can also try changing the parameters, to say selfie segmentation
and see how the return types react. Please contact me for weights for
selfie segmentation as I'm not pushing them to HF yet
### Screenshots
<!-- Add screenshots here, if applicable -->
### Related issues
<!-- Link related issues here using #issue-number -->
### Checklist
- [x] I have performed a self-review of my code
- [x] I have commented my code, particularly in hard-to-understand areas
- [ ] I have updated the documentation accordingly
- [x] My changes generate no new warnings
### Additional notes
The `ImageSegmentationModule.fromCustomConfig()` API allows users to
bring their own segmentation model with a custom label map:
```ts
const MyLabels = { BACKGROUND: 0, FOREGROUND: 1 } as const;
const seg = await ImageSegmentationModule.fromCustomConfig(
'https://example.com/model.pte',
{ labelMap: MyLabels },
);
```
---------
Co-authored-by: Mateusz Kopcinski <120639731+mkopcins@users.noreply.github.com>1 parent 2d58410 commit e51547e
31 files changed
Lines changed: 954 additions & 341 deletions
File tree
- apps/computer-vision/app/image_segmentation
- docs/docs
- 03-hooks/02-computer-vision
- 04-typescript-api/02-computer-vision
- 06-api-reference
- enumerations
- type-aliases
- variables
- packages/react-native-executorch
- common/rnexecutorch
- data_processing
- models
- image_segmentation
- src
- constants
- hooks
- computer_vision
- modules/computer_vision
- types
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
111 | 111 | | |
112 | 112 | | |
113 | 113 | | |
114 | | - | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
2 | 2 | | |
3 | 3 | | |
4 | 4 | | |
5 | | - | |
6 | 5 | | |
7 | | - | |
| 6 | + | |
8 | 7 | | |
9 | 8 | | |
10 | 9 | | |
| |||
44 | 43 | | |
45 | 44 | | |
46 | 45 | | |
47 | | - | |
48 | 46 | | |
49 | | - | |
50 | | - | |
51 | | - | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
52 | 51 | | |
53 | 52 | | |
54 | 53 | | |
55 | 54 | | |
56 | 55 | | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
57 | 60 | | |
58 | 61 | | |
59 | 62 | | |
| |||
69 | 72 | | |
70 | 73 | | |
71 | 74 | | |
72 | | - | |
73 | | - | |
74 | | - | |
75 | | - | |
76 | | - | |
77 | | - | |
| 75 | + | |
| 76 | + | |
78 | 77 | | |
79 | 78 | | |
80 | 79 | | |
| |||
105 | 104 | | |
106 | 105 | | |
107 | 106 | | |
108 | | - | |
| 107 | + | |
109 | 108 | | |
110 | 109 | | |
111 | | - | |
112 | | - | |
| 110 | + | |
| 111 | + | |
113 | 112 | | |
114 | 113 | | |
115 | 114 | | |
| |||
Lines changed: 54 additions & 22 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
21 | 21 | | |
22 | 22 | | |
23 | 23 | | |
24 | | - | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
25 | 27 | | |
26 | 28 | | |
27 | 29 | | |
28 | 30 | | |
29 | | - | |
| 31 | + | |
| 32 | + | |
30 | 33 | | |
31 | 34 | | |
32 | 35 | | |
| |||
36 | 39 | | |
37 | 40 | | |
38 | 41 | | |
39 | | - | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
40 | 45 | | |
41 | 46 | | |
| 47 | + | |
| 48 | + | |
42 | 49 | | |
43 | 50 | | |
44 | 51 | | |
| |||
47 | 54 | | |
48 | 55 | | |
49 | 56 | | |
50 | | - | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
51 | 64 | | |
52 | 65 | | |
53 | 66 | | |
54 | | - | |
| 67 | + | |
55 | 68 | | |
56 | | - | |
57 | | - | |
58 | | - | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
59 | 72 | | |
60 | 73 | | |
61 | 74 | | |
62 | 75 | | |
63 | 76 | | |
64 | | - | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
65 | 81 | | |
66 | | - | |
67 | | - | |
| 82 | + | |
68 | 83 | | |
69 | 84 | | |
70 | 85 | | |
71 | 86 | | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
72 | 93 | | |
73 | | - | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
74 | 97 | | |
75 | | - | |
76 | | - | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
77 | 113 | | |
78 | | - | |
79 | | - | |
80 | | - | |
81 | | - | |
82 | | - | |
83 | 114 | | |
84 | 115 | | |
85 | 116 | | |
86 | 117 | | |
87 | 118 | | |
88 | 119 | | |
89 | | - | |
90 | | - | |
91 | | - | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
Lines changed: 62 additions & 20 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
19 | 19 | | |
20 | 20 | | |
21 | 21 | | |
22 | | - | |
23 | | - | |
24 | | - | |
25 | | - | |
26 | | - | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
27 | 27 | | |
28 | 28 | | |
29 | | - | |
| 29 | + | |
| 30 | + | |
30 | 31 | | |
31 | 32 | | |
32 | 33 | | |
| |||
35 | 36 | | |
36 | 37 | | |
37 | 38 | | |
38 | | - | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
39 | 51 | | |
40 | | - | |
41 | | - | |
| 52 | + | |
42 | 53 | | |
43 | | - | |
| 54 | + | |
44 | 55 | | |
45 | | - | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
46 | 74 | | |
47 | 75 | | |
48 | 76 | | |
49 | 77 | | |
50 | 78 | | |
51 | | - | |
| 79 | + | |
52 | 80 | | |
53 | | - | |
54 | | - | |
55 | | - | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
56 | 84 | | |
57 | 85 | | |
58 | | - | |
| 86 | + | |
59 | 87 | | |
60 | 88 | | |
61 | | - | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
62 | 93 | | |
63 | | - | |
64 | | - | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
65 | 107 | | |
66 | 108 | | |
67 | 109 | | |
68 | | - | |
| 110 | + | |
0 commit comments