Skip to content

Commit cc6484c

Browse files
committed
Add docs and fix some typechecks
1 parent 9eb6061 commit cc6484c

8 files changed

Lines changed: 154 additions & 43 deletions

File tree

apps/computer-vision/app/instance_segmentation/index.tsx

Lines changed: 52 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,14 @@
11
import Spinner from '../../components/Spinner';
22
import { BottomBar } from '../../components/BottomBar';
33
import { getImage } from '../../utils';
4-
import { useInstanceSegmentation } from 'react-native-executorch';
4+
import {
5+
useInstanceSegmentation,
6+
YOLO26N_SEG,
7+
YOLO26L_SEG,
8+
YOLO26M_SEG,
9+
YOLO26S_SEG,
10+
YOLO26X_SEG,
11+
} from 'react-native-executorch';
512
import {
613
Canvas,
714
Image as SkiaImage,
@@ -41,15 +48,54 @@ const instanceColors = [
4148
// Available input sizes for YOLO models
4249
const AVAILABLE_INPUT_SIZES = [384, 416, 512, 640, 1024];
4350

51+
/**
52+
* EXAMPLE: Using built-in YOLO models with COCO labels (80 classes)
53+
*
54+
* const { forward } = useInstanceSegmentation({
55+
* model: YOLO26N_SEG, // or YOLO26S_SEG, YOLO26M_SEG, etc.
56+
* });
57+
*
58+
* // Filter by specific COCO classes:
59+
* const results = await forward(imageUri, {
60+
* classesOfInterest: ['PERSON', 'CAR', 'DOG'],
61+
* confidenceThreshold: 0.5,
62+
* inputSize: 640,
63+
* });
64+
*
65+
*
66+
* EXAMPLE: Using a custom model with custom labels
67+
*
68+
* // 1. Define your custom label enum
69+
* const MyLabels = { APPLE: 0, ORANGE: 1, BANANA: 2 } as const;
70+
*
71+
* // 2. Load using InstanceSegmentationModule directly (not the hook)
72+
* const customModel = await InstanceSegmentationModule.fromCustomConfig(
73+
* 'https://example.com/my-model.pte',
74+
* {
75+
* labelMap: MyLabels,
76+
* availableInputSizes: [640],
77+
* defaultInputSize: 640,
78+
* postprocessorConfig: {
79+
* type: 'yolo',
80+
* defaultConfidenceThreshold: 0.5,
81+
* defaultIouThreshold: 0.45,
82+
* applyNMS: true,
83+
* },
84+
* }
85+
* );
86+
*
87+
* // 3. Run inference
88+
* const results = await customModel.forward(imageUri, {
89+
* classesOfInterest: ['APPLE', 'BANANA'],
90+
* });
91+
*/
92+
4493
export default function InstanceSegmentationScreen() {
4594
const { setGlobalGenerating } = useContext(GeneratingContext);
4695

4796
const { isReady, isGenerating, downloadProgress, forward, error } =
4897
useInstanceSegmentation({
49-
model: {
50-
modelName: 'yolo26n-seg',
51-
modelSource: 'http://192.168.83.59:3000/yolo26n-seg.pte',
52-
},
98+
model: YOLO26X_SEG,
5399
});
54100

55101
const [imageUri, setImageUri] = useState('');
@@ -81,7 +127,7 @@ export default function InstanceSegmentationScreen() {
81127
try {
82128
const output = await forward(imageUri, {
83129
confidenceThreshold: 0.5,
84-
iouThreshold: 0.45,
130+
iouThreshold: 0.55,
85131
maxInstances: 20,
86132
returnMaskAtOriginalResolution: true,
87133
inputSize: selectedInputSize,

docs/docs/02-benchmarks/inference-time.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,23 @@ Times presented in the tables are measured as consecutive runs of the model. Ini
127127
| ----------------- | ---------------------------- | -------------------------------- | --------------------------------- |
128128
| DEELABV3_RESNET50 | 1000 | 670 | 700 |
129129

130+
## Instance Segmentation
131+
132+
:::warning
133+
Times presented in the tables are measured as consecutive runs of the model. Initial run times may be up to 2x longer due to model loading and initialization.
134+
:::
135+
:::warning
136+
Times presented in the tables are measured for forward method with input size equal to 512. Other input sizes may yeild slower or faster inference times.
137+
:::
138+
139+
| Model | Samsung Galaxy S24 (XNNPACK) [ms] | Iphone 17 pro (XNNPACK) [ms] |
140+
| ----------- | --------------------------------- | ---------------------------- |
141+
| YOLO26n_SEG | 92 | 90 |
142+
| YOLO26s_SEG | 220 | 188 |
143+
| YOLO26m_SEG | 570 | 550 |
144+
| YOLO26l_SEG | 680 | 608 |
145+
| YOLO26x_SEG | 1410 | 1338 |
146+
130147
## Text to image
131148

132149
| Model | iPhone 17 Pro (XNNPACK) [ms] | iPhone 16 Pro (XNNPACK) [ms] | iPhone SE 3 (XNNPACK) [ms] | Samsung Galaxy S24 (XNNPACK) [ms] | OnePlus 12 (XNNPACK) [ms] |

docs/docs/02-benchmarks/memory-usage.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,20 @@ Data presented in the following sections is based on inference with non-resized
9393
| ----------------- | ---------------------- | ------------------ |
9494
| DEELABV3_RESNET50 | 930 | 660 |
9595

96+
## Instance Segmentation
97+
98+
:::warning
99+
Data presented in the following sections is based on inference with forward_1024 method.
100+
:::
101+
102+
| Model | Android (XNNPACK) [MB] | iOS (XNNPACK) [MB] |
103+
| ----------- | ---------------------- | ------------------ |
104+
| YOLO26n_SEG | 92 | 668 |
105+
| YOLO26s_SEG | 220 | 712 |
106+
| YOLO26m_SEG | 570 | 815 |
107+
| YOLO26l_SEG | 680 | 1024 |
108+
| YOLO26x_SEG | 1410 | 1450 |
109+
96110
## Text to image
97111

98112
| Model | Android (XNNPACK) [MB] | iOS (XNNPACK) [MB] |

packages/react-native-executorch/src/constants/modelUrls.ts

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -657,6 +657,55 @@ export const SELFIE_SEGMENTATION = {
657657
modelSource: SELFIE_SEGMENTATION_MODEL,
658658
} as const;
659659

660+
/**
661+
* @category Models - Instance Segmentation
662+
*/
663+
const YOLO26N_SEG_MODEL = `${URL_PREFIX}-yolo26-seg/${NEXT_VERSION_TAG}/yolo26n-seg/xnnpack/yolo26n-seg.pte`;
664+
const YOLO26S_SEG_MODEL = `${URL_PREFIX}-yolo26-seg/${NEXT_VERSION_TAG}/yolo26s-seg/xnnpack/yolo26s-seg.pte`;
665+
const YOLO26M_SEG_MODEL = `${URL_PREFIX}-yolo26-seg/${NEXT_VERSION_TAG}/yolo26m-seg/xnnpack/yolo26m-seg.pte`;
666+
const YOLO26L_SEG_MODEL = `${URL_PREFIX}-yolo26-seg/${NEXT_VERSION_TAG}/yolo26l-seg/xnnpack/yolo26l-seg.pte`;
667+
const YOLO26X_SEG_MODEL = `${URL_PREFIX}-yolo26-seg/${NEXT_VERSION_TAG}/yolo26x-seg/xnnpack/yolo26x-seg.pte`;
668+
669+
/**
670+
* @category Models - Instance Segmentation
671+
*/
672+
export const YOLO26N_SEG = {
673+
modelName: 'yolo26n-seg',
674+
modelSource: YOLO26N_SEG_MODEL,
675+
} as const;
676+
677+
/**
678+
* @category Models - Instance Segmentation
679+
*/
680+
export const YOLO26S_SEG = {
681+
modelName: 'yolo26s-seg',
682+
modelSource: YOLO26S_SEG_MODEL,
683+
} as const;
684+
685+
/**
686+
* @category Models - Instance Segmentation
687+
*/
688+
export const YOLO26M_SEG = {
689+
modelName: 'yolo26m-seg',
690+
modelSource: YOLO26M_SEG_MODEL,
691+
} as const;
692+
693+
/**
694+
* @category Models - Instance Segmentation
695+
*/
696+
export const YOLO26L_SEG = {
697+
modelName: 'yolo26l-seg',
698+
modelSource: YOLO26L_SEG_MODEL,
699+
} as const;
700+
701+
/**
702+
* @category Models - Instance Segmentation
703+
*/
704+
export const YOLO26X_SEG = {
705+
modelName: 'yolo26x-seg',
706+
modelSource: YOLO26X_SEG_MODEL,
707+
} as const;
708+
660709
// Image Embeddings
661710
const CLIP_VIT_BASE_PATCH32_IMAGE_MODEL = `${URL_PREFIX}-clip-vit-base-patch32/${VERSION_TAG}/clip-vit-base-patch32-vision_xnnpack.pte`;
662711

packages/react-native-executorch/src/hooks/computer_vision/useInstanceSegmentation.ts

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -47,9 +47,7 @@ export const useInstanceSegmentation = <
4747
>({
4848
model,
4949
preventLoad = false,
50-
}: InstanceSegmentationProps<C>): InstanceSegmentationType<
51-
InstanceSegmentationLabels<InstanceModelNameOf<C>>
52-
> => {
50+
}: InstanceSegmentationProps<C>): InstanceSegmentationType<LabelEnum> => {
5351
const [error, setError] = useState<RnExecutorchError | null>(null);
5452
const [isReady, setIsReady] = useState(false);
5553
const [isGenerating, setIsGenerating] = useState(false);
@@ -96,9 +94,7 @@ export const useInstanceSegmentation = <
9694

9795
const forward = async (
9896
imageSource: string,
99-
options?: InstanceSegmentationOptions<
100-
InstanceSegmentationLabels<InstanceModelNameOf<C>>
101-
>
97+
options?: InstanceSegmentationOptions<LabelEnum>
10298
) => {
10399
if (!isReady || !instance) {
104100
throw new RnExecutorchError(

packages/react-native-executorch/src/modules/computer_vision/InstanceSegmentationModule.ts

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,7 @@ const ModelConfigs = {
3131
'yolo26m-seg': YOLO_SEG_CONFIG,
3232
'yolo26l-seg': YOLO_SEG_CONFIG,
3333
'yolo26x-seg': YOLO_SEG_CONFIG,
34-
} as const satisfies Record<
35-
InstanceSegmentationModelName,
36-
InstanceSegmentationConfig<LabelEnum>
37-
>;
34+
} as const;
3835

3936
/** @internal */
4037
type ModelConfigsType = typeof ModelConfigs;
@@ -90,11 +87,11 @@ export class InstanceSegmentationModule<
9087
T extends InstanceSegmentationModelName | LabelEnum,
9188
> extends BaseModule {
9289
private labelMap: ResolveLabels<T>;
93-
private modelConfig: InstanceSegmentationConfig<ResolveLabels<T>>;
90+
private modelConfig: InstanceSegmentationConfig<LabelEnum>;
9491

9592
private constructor(
9693
labelMap: ResolveLabels<T>,
97-
modelConfig: InstanceSegmentationConfig<ResolveLabels<T>>,
94+
modelConfig: InstanceSegmentationConfig<LabelEnum>,
9895
nativeModule: unknown
9996
) {
10097
super();
@@ -127,7 +124,7 @@ export class InstanceSegmentationModule<
127124
onDownloadProgress: (progress: number) => void = () => {}
128125
): Promise<InstanceSegmentationModule<InstanceModelNameOf<C>>> {
129126
const { modelName, modelSource } = config;
130-
const modelConfig = ModelConfigs[modelName];
127+
const modelConfig = ModelConfigs[modelName as keyof typeof ModelConfigs];
131128

132129
const paths = await ResourceFetcher.fetch(onDownloadProgress, modelSource);
133130
if (!paths?.[0]) {
@@ -155,9 +152,7 @@ export class InstanceSegmentationModule<
155152

156153
return new InstanceSegmentationModule<InstanceModelNameOf<C>>(
157154
modelConfig.labelMap as ResolveLabels<InstanceModelNameOf<C>>,
158-
modelConfig as InstanceSegmentationConfig<
159-
ResolveLabels<InstanceModelNameOf<C>>
160-
>,
155+
modelConfig,
161156
nativeModule
162157
);
163158
}
@@ -221,7 +216,7 @@ export class InstanceSegmentationModule<
221216

222217
return new InstanceSegmentationModule<L>(
223218
config.labelMap as ResolveLabels<L>,
224-
config as InstanceSegmentationConfig<ResolveLabels<L>>,
219+
config,
225220
nativeModule
226221
);
227222
}
@@ -298,6 +293,8 @@ export class InstanceSegmentationModule<
298293
})
299294
: [];
300295

296+
// Measure inference time
297+
const startTime = performance.now();
301298
const nativeResult = await this.nativeModule.generate(
302299
imageSource,
303300
confidenceThreshold,
@@ -307,10 +304,18 @@ export class InstanceSegmentationModule<
307304
returnMaskAtOriginalResolution,
308305
inputSize // Pass inputSize as number instead of methodName as string
309306
);
307+
const endTime = performance.now();
308+
const inferenceTime = endTime - startTime;
309+
310+
console.log(
311+
`[Instance Segmentation] Inference completed in ${inferenceTime.toFixed(2)}ms | Input size: ${inputSize}x${inputSize} | Detected: ${nativeResult.length} instances`
312+
);
310313

311314
// Convert label indices back to label names
312315
// YOLO outputs 0-indexed class IDs, but COCO labels are 1-indexed, so add 1
313-
const reverseLabelMap = Object.entries(this.labelMap).reduce(
316+
const reverseLabelMap = Object.entries(
317+
this.labelMap as Record<string, number>
318+
).reduce(
314319
(acc, [key, value]) => {
315320
acc[value as number] = key;
316321
return acc;

packages/react-native-executorch/src/modules/computer_vision/SemanticSegmentationModule.ts

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -185,13 +185,6 @@ export class SemanticSegmentationModule<
185185
);
186186
}
187187

188-
InstanceSegConfig = {
189-
'yolo26n-seg': {
190-
labelMap: LabelEnum,
191-
prepocessorConfig: undefined,
192-
availableInputSizes: [Number],
193-
},
194-
};
195188
/**
196189
* Executes the model's forward pass to perform semantic segmentation on the provided image.
197190
*

packages/react-native-executorch/src/types/instanceSegmentation.ts

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { RnExecutorchError } from '../errors/errorUtils';
22
import { LabelEnum, ResourceSource } from './common';
3-
import { Bbox, CocoLabel } from './objectDetection';
3+
import { Bbox } from './objectDetection';
44

55
/**
66
* Represents a single detected instance in instance segmentation output.
@@ -133,7 +133,6 @@ export type InstanceSegmentationModelSources =
133133
| { modelName: 'yolo26s-seg'; modelSource: ResourceSource }
134134
| { modelName: 'yolo26m-seg'; modelSource: ResourceSource }
135135
| { modelName: 'yolo26l-seg'; modelSource: ResourceSource }
136-
| { modelName: 'rfdetr_seg'; modelSource: ResourceSource }
137136
| { modelName: 'yolo26x-seg'; modelSource: ResourceSource };
138137

139138
/**
@@ -145,20 +144,12 @@ export type InstanceSegmentationModelName =
145144
InstanceSegmentationModelSources['modelName'];
146145

147146
/**
148-
* Extracts the model name from a {@link InstanceSegmentationModelSources} config object.
149-
*
150-
* @category Types
151-
*/
152-
export type ModelNameOf<C extends InstanceSegmentationModelSources> =
153-
C['modelName'];
154-
155-
/**
156-
* Alias for {@link ModelNameOf}. Extracts the instance segmentation model name from a config object.
147+
* Extracts the instance segmentation model name from a {@link InstanceSegmentationModelSources} config object.
157148
*
158149
* @category Types
159150
*/
160151
export type InstanceModelNameOf<C extends InstanceSegmentationModelSources> =
161-
ModelNameOf<C>;
152+
C['modelName'];
162153

163154
/**
164155
* Props for the `useInstanceSegmentation` hook.

0 commit comments

Comments
 (0)