Skip to content

Commit 3863425

Browse files
msluszniakbarhancIgorSwat
authored
chore: Add model selections and small fixes (#977)
## Description <!-- Provide a concise and descriptive summary of the changes implemented in this PR. --> ### Introduces a breaking change? - [ ] Yes - [x] No ### Type of change - [x] Bug fix (change which fixes an issue) - [ ] New feature (change which adds functionality) - [ ] Documentation update (improves or adds clarity to existing documentation) - [x] Other (chores, tests, code style improvements etc.) ### Tested on - [x] iOS - [ ] Android ### Testing instructions Run models from demo apps and check if you can select different models and they works: - [x] Computer Vision - [x] LLM - [x] Speech Additionally: - [x] Check that without registering streamInsert demo app with text to speech fails - [x] Check that without changes in OCR and Vertical OCR demo app fails - [x] Check that text to image example looks now simpler and better - [x] Check that image embeddings example works ### Screenshots <!-- Add screenshots here, if applicable --> ### Related issues Closes #958 ### 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 (Not applicable) - [x] My changes generate no new warnings ### Additional notes ~Additionally, I found out that links for VLMs are incorrect since they point out to `main` on hugging face. @NorbertKlockiewicz could you create 0.8.0 tag on huggingface as for lfm instruct and change links here: https://github.com/software-mansion/react-native-executorch/blob/main/packages/react-native-executorch/src/constants/modelUrls.ts#L408-L411?~ Thanks --------- Co-authored-by: Bartosz Hanc <bartosz.hanc02@gmail.com> Co-authored-by: IgorSwat <114943112+IgorSwat@users.noreply.github.com>
1 parent 654f401 commit 3863425

File tree

20 files changed

+971
-195
lines changed

20 files changed

+971
-195
lines changed

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

Lines changed: 26 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,40 @@
11
import Spinner from '../../components/Spinner';
22
import { BottomBar } from '../../components/BottomBar';
3+
import { ModelPicker, ModelOption } from '../../components/ModelPicker';
34
import { getImage } from '../../utils';
45
import {
56
Detection,
67
useObjectDetection,
78
RF_DETR_NANO,
9+
SSDLITE_320_MOBILENET_V3_LARGE,
10+
ObjectDetectionModelSources,
811
} from 'react-native-executorch';
912
import { View, StyleSheet, Image } from 'react-native';
1013
import ImageWithBboxes from '../../components/ImageWithBboxes';
1114
import React, { useContext, useEffect, useState } from 'react';
1215
import { GeneratingContext } from '../../context';
1316
import ScreenWrapper from '../../ScreenWrapper';
1417

18+
const MODELS: ModelOption<ObjectDetectionModelSources>[] = [
19+
{ label: 'RF-DeTR Nano', value: RF_DETR_NANO },
20+
{ label: 'SSDLite MobileNet', value: SSDLITE_320_MOBILENET_V3_LARGE },
21+
];
22+
1523
export default function ObjectDetectionScreen() {
1624
const [imageUri, setImageUri] = useState('');
1725
const [results, setResults] = useState<Detection[]>([]);
1826
const [imageDimensions, setImageDimensions] = useState<{
1927
width: number;
2028
height: number;
2129
}>();
30+
const [selectedModel, setSelectedModel] =
31+
useState<ObjectDetectionModelSources>(RF_DETR_NANO);
2232

23-
const rfDetr = useObjectDetection({ model: RF_DETR_NANO });
33+
const model = useObjectDetection({ model: selectedModel });
2434
const { setGlobalGenerating } = useContext(GeneratingContext);
2535
useEffect(() => {
26-
setGlobalGenerating(rfDetr.isGenerating);
27-
}, [rfDetr.isGenerating, setGlobalGenerating]);
36+
setGlobalGenerating(model.isGenerating);
37+
}, [model.isGenerating, setGlobalGenerating]);
2838

2939
const handleCameraPress = async (isCamera: boolean) => {
3040
const image = await getImage(isCamera);
@@ -42,19 +52,19 @@ export default function ObjectDetectionScreen() {
4252
const runForward = async () => {
4353
if (imageUri) {
4454
try {
45-
const output = await rfDetr.forward(imageUri);
55+
const output = await model.forward(imageUri);
4656
setResults(output);
4757
} catch (e) {
4858
console.error(e);
4959
}
5060
}
5161
};
5262

53-
if (!rfDetr.isReady) {
63+
if (!model.isReady) {
5464
return (
5565
<Spinner
56-
visible={!rfDetr.isReady}
57-
textContent={`Loading the model ${(rfDetr.downloadProgress * 100).toFixed(0)} %`}
66+
visible={!model.isReady}
67+
textContent={`Loading the model ${(model.downloadProgress * 100).toFixed(0)} %`}
5868
/>
5969
);
6070
}
@@ -81,6 +91,15 @@ export default function ObjectDetectionScreen() {
8191
)}
8292
</View>
8393
</View>
94+
<ModelPicker
95+
models={MODELS}
96+
selectedModel={selectedModel}
97+
disabled={model.isGenerating}
98+
onSelect={(m) => {
99+
setSelectedModel(m);
100+
setResults([]);
101+
}}
102+
/>
84103
<BottomBar
85104
handleCameraPress={handleCameraPress}
86105
runForward={runForward}
@@ -100,31 +119,6 @@ const styles = StyleSheet.create({
100119
borderRadius: 8,
101120
width: '100%',
102121
},
103-
results: {
104-
flex: 1,
105-
alignItems: 'center',
106-
justifyContent: 'center',
107-
gap: 4,
108-
padding: 4,
109-
},
110-
resultHeader: {
111-
fontSize: 18,
112-
color: 'navy',
113-
},
114-
resultsList: {
115-
flex: 1,
116-
},
117-
resultRecord: {
118-
flexDirection: 'row',
119-
width: '100%',
120-
justifyContent: 'space-between',
121-
padding: 8,
122-
borderBottomWidth: 1,
123-
},
124-
resultLabel: {
125-
flex: 1,
126-
marginRight: 4,
127-
},
128122
fullSizeImage: {
129123
width: '100%',
130124
height: '100%',

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

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,48 @@
11
import Spinner from '../../components/Spinner';
22
import { BottomBar } from '../../components/BottomBar';
3+
import { ModelPicker, ModelOption } from '../../components/ModelPicker';
34
import { getImage } from '../../utils';
4-
import { useOCR, OCR_ENGLISH } from 'react-native-executorch';
5+
import {
6+
useOCR,
7+
OCR_ENGLISH,
8+
OCR_GERMAN,
9+
OCR_FRENCH,
10+
OCR_SPANISH,
11+
OCR_ITALIAN,
12+
OCR_JAPANESE,
13+
OCR_KOREAN,
14+
OCRProps,
15+
} from 'react-native-executorch';
516
import { View, StyleSheet, Image, Text, ScrollView } from 'react-native';
617
import ImageWithBboxes2 from '../../components/ImageWithOCRBboxes';
718
import React, { useContext, useEffect, useState } from 'react';
819
import { GeneratingContext } from '../../context';
920
import ScreenWrapper from '../../ScreenWrapper';
1021

22+
type OCRModelSources = OCRProps['model'];
23+
24+
const MODELS: ModelOption<OCRModelSources>[] = [
25+
{ label: 'English', value: OCR_ENGLISH },
26+
{ label: 'German', value: OCR_GERMAN },
27+
{ label: 'French', value: OCR_FRENCH },
28+
{ label: 'Spanish', value: OCR_SPANISH },
29+
{ label: 'Italian', value: OCR_ITALIAN },
30+
{ label: 'Japanese', value: OCR_JAPANESE },
31+
{ label: 'Korean', value: OCR_KOREAN },
32+
];
33+
1134
export default function OCRScreen() {
1235
const [imageUri, setImageUri] = useState('');
1336
const [results, setResults] = useState<any[]>([]);
1437
const [imageDimensions, setImageDimensions] = useState<{
1538
width: number;
1639
height: number;
1740
}>();
41+
const [selectedModel, setSelectedModel] =
42+
useState<OCRModelSources>(OCR_ENGLISH);
1843

1944
const model = useOCR({
20-
model: OCR_ENGLISH,
45+
model: selectedModel,
2146
});
2247
const { setGlobalGenerating } = useContext(GeneratingContext);
2348
useEffect(() => {
@@ -89,6 +114,15 @@ export default function OCRScreen() {
89114
</View>
90115
)}
91116
</View>
117+
<ModelPicker
118+
models={MODELS}
119+
selectedModel={selectedModel}
120+
disabled={model.isGenerating}
121+
onSelect={(m) => {
122+
setSelectedModel(m);
123+
setResults([]);
124+
}}
125+
/>
92126
<BottomBar
93127
handleCameraPress={handleCameraPress}
94128
runForward={runForward}

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

Lines changed: 40 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,16 @@
11
import Spinner from '../../components/Spinner';
22
import { BottomBar } from '../../components/BottomBar';
3+
import { ModelPicker, ModelOption } from '../../components/ModelPicker';
34
import { getImage } from '../../utils';
45
import {
56
DEEPLAB_V3_MOBILENET_V3_LARGE_QUANTIZED,
7+
DEEPLAB_V3_RESNET50_QUANTIZED,
8+
DEEPLAB_V3_RESNET101_QUANTIZED,
9+
LRASPP_MOBILENET_V3_LARGE_QUANTIZED,
10+
FCN_RESNET50_QUANTIZED,
11+
FCN_RESNET101_QUANTIZED,
612
useSemanticSegmentation,
13+
SemanticSegmentationModelSources,
714
} from 'react-native-executorch';
815
import {
916
Canvas,
@@ -42,12 +49,28 @@ const numberToColor: number[][] = [
4249
[162, 51, 255], // 20 Amethyst
4350
];
4451

52+
const MODELS: ModelOption<SemanticSegmentationModelSources>[] = [
53+
{
54+
label: 'DeepLab MobileNet',
55+
value: DEEPLAB_V3_MOBILENET_V3_LARGE_QUANTIZED,
56+
},
57+
{ label: 'DeepLab ResNet50', value: DEEPLAB_V3_RESNET50_QUANTIZED },
58+
{ label: 'DeepLab ResNet101', value: DEEPLAB_V3_RESNET101_QUANTIZED },
59+
{ label: 'LRASPP MobileNet', value: LRASPP_MOBILENET_V3_LARGE_QUANTIZED },
60+
{ label: 'FCN ResNet50', value: FCN_RESNET50_QUANTIZED },
61+
{ label: 'FCN ResNet101', value: FCN_RESNET101_QUANTIZED },
62+
];
63+
4564
export default function SemanticSegmentationScreen() {
4665
const { setGlobalGenerating } = useContext(GeneratingContext);
66+
const [selectedModel, setSelectedModel] =
67+
useState<SemanticSegmentationModelSources>(
68+
DEEPLAB_V3_MOBILENET_V3_LARGE_QUANTIZED
69+
);
70+
4771
const { isReady, isGenerating, downloadProgress, forward } =
48-
useSemanticSegmentation({
49-
model: DEEPLAB_V3_MOBILENET_V3_LARGE_QUANTIZED,
50-
});
72+
useSemanticSegmentation({ model: selectedModel });
73+
5174
const [imageUri, setImageUri] = useState('');
5275
const [imageSize, setImageSize] = useState({ width: 0, height: 0 });
5376
const [segImage, setSegImage] = useState<SkImage | null>(null);
@@ -61,10 +84,7 @@ export default function SemanticSegmentationScreen() {
6184
const image = await getImage(isCamera);
6285
if (!image?.uri) return;
6386
setImageUri(image.uri);
64-
setImageSize({
65-
width: image.width ?? 0,
66-
height: image.height ?? 0,
67-
});
87+
setImageSize({ width: image.width ?? 0, height: image.height ?? 0 });
6888
setSegImage(null);
6989
};
7090

@@ -150,6 +170,15 @@ export default function SemanticSegmentationScreen() {
150170
</View>
151171
)}
152172
</View>
173+
<ModelPicker
174+
models={MODELS}
175+
selectedModel={selectedModel}
176+
disabled={isGenerating}
177+
onSelect={(m) => {
178+
setSelectedModel(m);
179+
setSegImage(null);
180+
}}
181+
/>
153182
<BottomBar
154183
handleCameraPress={handleCameraPress}
155184
runForward={runForward}
@@ -159,29 +188,15 @@ export default function SemanticSegmentationScreen() {
159188
}
160189

161190
const styles = StyleSheet.create({
162-
imageCanvasContainer: {
163-
flex: 6,
164-
width: '100%',
165-
padding: 16,
166-
},
167-
imageContainer: {
168-
flex: 1,
169-
width: '100%',
170-
},
171-
image: {
172-
flex: 1,
173-
borderRadius: 8,
174-
width: '100%',
175-
},
191+
imageCanvasContainer: { flex: 6, width: '100%', padding: 16 },
192+
imageContainer: { flex: 1, width: '100%' },
193+
image: { flex: 1, borderRadius: 8, width: '100%' },
176194
canvasContainer: {
177195
flex: 1,
178196
justifyContent: 'center',
179197
alignItems: 'center',
180198
gap: 4,
181199
padding: 4,
182200
},
183-
canvas: {
184-
width: '100%',
185-
height: '100%',
186-
},
201+
canvas: { width: '100%', height: '100%' },
187202
});

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

Lines changed: 35 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,40 @@
11
import Spinner from '../../components/Spinner';
22
import { BottomBar } from '../../components/BottomBar';
3+
import { ModelPicker, ModelOption } from '../../components/ModelPicker';
34
import { getImage } from '../../utils';
45
import {
56
useStyleTransfer,
67
STYLE_TRANSFER_CANDY_QUANTIZED,
8+
STYLE_TRANSFER_MOSAIC_QUANTIZED,
9+
STYLE_TRANSFER_RAIN_PRINCESS_QUANTIZED,
10+
STYLE_TRANSFER_UDNIE_QUANTIZED,
11+
StyleTransferModelName,
12+
ResourceSource,
713
} from 'react-native-executorch';
14+
815
import { View, StyleSheet, Image } from 'react-native';
916
import React, { useContext, useEffect, useState } from 'react';
1017
import { GeneratingContext } from '../../context';
1118
import ScreenWrapper from '../../ScreenWrapper';
1219

20+
type StyleTransferModelSources = {
21+
modelName: StyleTransferModelName;
22+
modelSource: ResourceSource;
23+
};
24+
25+
const MODELS: ModelOption<StyleTransferModelSources>[] = [
26+
{ label: 'Candy', value: STYLE_TRANSFER_CANDY_QUANTIZED },
27+
{ label: 'Mosaic', value: STYLE_TRANSFER_MOSAIC_QUANTIZED },
28+
{ label: 'Rain Princess', value: STYLE_TRANSFER_RAIN_PRINCESS_QUANTIZED },
29+
{ label: 'Udnie', value: STYLE_TRANSFER_UDNIE_QUANTIZED },
30+
];
31+
1332
export default function StyleTransferScreen() {
14-
const model = useStyleTransfer({ model: STYLE_TRANSFER_CANDY_QUANTIZED });
33+
const [selectedModel, setSelectedModel] = useState<StyleTransferModelSources>(
34+
STYLE_TRANSFER_CANDY_QUANTIZED
35+
);
36+
37+
const model = useStyleTransfer({ model: selectedModel });
1538
const { setGlobalGenerating } = useContext(GeneratingContext);
1639
useEffect(() => {
1740
setGlobalGenerating(model.isGenerating);
@@ -64,6 +87,15 @@ export default function StyleTransferScreen() {
6487
}
6588
/>
6689
</View>
90+
<ModelPicker
91+
models={MODELS}
92+
selectedModel={selectedModel}
93+
disabled={model.isGenerating}
94+
onSelect={(m) => {
95+
setSelectedModel(m);
96+
setStyledUri('');
97+
}}
98+
/>
6799
<BottomBar
68100
handleCameraPress={handleCameraPress}
69101
runForward={runForward}
@@ -73,14 +105,6 @@ export default function StyleTransferScreen() {
73105
}
74106

75107
const styles = StyleSheet.create({
76-
imageContainer: {
77-
flex: 6,
78-
width: '100%',
79-
padding: 16,
80-
},
81-
image: {
82-
flex: 1,
83-
borderRadius: 8,
84-
width: '100%',
85-
},
108+
imageContainer: { flex: 6, width: '100%', padding: 16 },
109+
image: { flex: 1, borderRadius: 8, width: '100%' },
86110
});

0 commit comments

Comments
 (0)