Overview
The useOCR hook manages an OCR (Optical Character Recognition) instance for detecting and recognizing text in images. It combines text detection and recognition in a single pipeline.
Import
import { useOCR } from 'react-native-executorch' ;
Hook Signature
const ocr = useOCR ({ model , preventLoad }: OCRProps ): OCRType
Parameters
Object containing model sources and configuration Source location of the text detector model binary (.pte)
Source location of the text recognizer model binary (.pte)
Language configuration for OCR (e.g., ‘en’, ‘ch’, ‘pl’, etc.)
If true, prevents automatic model loading and downloading when the hook mounts
Return Value
Returns an object with the following properties and methods:
State Properties
Indicates whether both detector and recognizer models are loaded and ready to process images.
Indicates whether the OCR pipeline is currently processing an image.
Combined download progress as a value between 0 and 1.
Contains error details if the models fail to load or encounter an error during OCR.
Methods
Executes the complete OCR pipeline (detection + recognition) on the provided image. forward ( imageSource : string ): Promise < OCRDetection [] >
Image source as a file path, URI, or base64 string
Returns a promise that resolves to an array of OCRDetection objects, each containing detected text, bounding box, and confidence score.
Types
OCRDetection
interface OCRDetection {
bbox : Point []; // Bounding box vertices (4 points)
text : string ; // Recognized text
score : number ; // Confidence score (0-1)
}
Point
interface Point {
x : number ;
y : number ;
}
OCRLanguage
Supported languages include: 'en', 'ch', 'pl', and others based on available symbol sets.
Usage Examples
Basic Text Recognition
import { useOCR } from 'react-native-executorch' ;
import { useState } from 'react' ;
import { launchImageLibrary } from 'react-native-image-picker' ;
function TextRecognizer () {
const [ imageUri , setImageUri ] = useState < string | null >( null );
const [ detections , setDetections ] = useState < OCRDetection []>([]);
const ocr = useOCR ({
model: {
detectorSource: 'https://huggingface.co/.../detector.pte' ,
recognizerSource: 'https://huggingface.co/.../recognizer.pte' ,
language: 'en' ,
},
});
const recognizeText = async ( uri : string ) => {
if ( ! ocr . isReady ) return ;
try {
const results = await ocr . forward ( uri );
setDetections ( results );
console . log ( 'Detected text blocks:' , results . length );
results . forEach (( det , idx ) => {
console . log ( `[ ${ idx } ] " ${ det . text } " ( ${ ( det . score * 100 ). toFixed ( 1 ) } %)` );
});
} catch ( error ) {
console . error ( 'OCR failed:' , error );
}
};
const pickAndRecognize = async () => {
const result = await launchImageLibrary ({ mediaType: 'photo' });
if ( result . assets ?.[ 0 ]?. uri ) {
const uri = result . assets [ 0 ]. uri ;
setImageUri ( uri );
await recognizeText ( uri );
}
};
return (
< View >
< Text > Status : { ocr . isReady ? 'Ready' : 'Loading...' }</ Text >
< Text > Progress : {(ocr.downloadProgress * 100). toFixed (0)}%</ Text >
< Button
title = "Pick Image & Recognize"
onPress = { pickAndRecognize }
disabled = {!ocr. isReady }
/>
{ imageUri && (
< Image source = {{ uri : imageUri }} style = {{ width : 400 , height : 400 }} />
)}
{ ocr . isGenerating && < ActivityIndicator />}
< ScrollView >
{ detections . map (( det , idx ) => (
< View key = { idx } style = {{ padding : 10 , borderBottomWidth : 1 }} >
< Text style = {{ fontWeight : 'bold' }} > {det. text } </ Text >
< Text style = {{ color : 'gray' }} >
Confidence : {(det.score * 100). toFixed (1)}%
</ Text >
</ View >
))}
</ ScrollView >
</ View >
);
}
Drawing Bounding Boxes
import { useOCR } from 'react-native-executorch' ;
import { useState } from 'react' ;
import Svg , { Polygon , Text as SvgText } from 'react-native-svg' ;
function OCRVisualizer () {
const [ imageUri , setImageUri ] = useState < string | null >( null );
const [ imageDimensions , setImageDimensions ] = useState ({ width: 0 , height: 0 });
const [ detections , setDetections ] = useState < any []>([]);
const ocr = useOCR ({
model: {
detectorSource: require ( './models/detector.pte' ),
recognizerSource: require ( './models/recognizer.pte' ),
language: 'en' ,
},
});
const processImage = async ( uri : string ) => {
// Get image dimensions
Image . getSize ( uri , ( width , height ) => {
setImageDimensions ({ width , height });
});
if ( ! ocr . isReady ) return ;
try {
const results = await ocr . forward ( uri );
setDetections ( results );
} catch ( error ) {
console . error ( 'OCR failed:' , error );
}
};
return (
< View >
{ imageUri && (
< View >
< Image
source = {{ uri : imageUri }}
style = {{ width : 400 , height : 400 }}
/>
< Svg
style = {{ position : 'absolute' , top : 0 , left : 0 }}
width = { 400 }
height = { 400 }
>
{ detections . map (( det , idx ) => {
const scaleX = 400 / imageDimensions . width ;
const scaleY = 400 / imageDimensions . height ;
const points = det . bbox
.map( p => ` ${ p . x * scaleX } , ${ p . y * scaleY } ` )
.join( ' ' );
return (
<React.Fragment key={idx}>
<Polygon
points={points}
stroke= "red"
strokeWidth= "2"
fill= "none"
/>
<SvgText
x={det.bbox[0].x * scaleX}
y={det.bbox[0].y * scaleY - 5}
fill= "red"
fontSize= "12"
fontWeight= "bold"
>
{det.text}
</SvgText>
</React.Fragment>
);
})}
</Svg>
</View>
)}
</View>
);
}
import { useOCR } from 'react-native-executorch' ;
import { useState } from 'react' ;
import Clipboard from '@react-native-clipboard/clipboard' ;
function TextExtractor () {
const [ extractedText , setExtractedText ] = useState ( '' );
const ocr = useOCR ({
model: {
detectorSource: 'https://example.com/detector.pte' ,
recognizerSource: 'https://example.com/recognizer.pte' ,
language: 'en' ,
},
});
const extractText = async ( imageUri : string ) => {
if ( ! ocr . isReady ) return ;
try {
const detections = await ocr . forward ( imageUri );
// Sort by vertical position (top to bottom)
const sorted = detections . sort (( a , b ) => {
const avgYA = a . bbox . reduce (( sum , p ) => sum + p . y , 0 ) / a . bbox . length ;
const avgYB = b . bbox . reduce (( sum , p ) => sum + p . y , 0 ) / b . bbox . length ;
return avgYA - avgYB ;
});
// Concatenate all text
const fullText = sorted . map ( det => det . text ). join ( ' \n ' );
setExtractedText ( fullText );
} catch ( error ) {
console . error ( 'Text extraction failed:' , error );
}
};
const copyToClipboard = () => {
Clipboard . setString ( extractedText );
};
return (
< View >
< Text style = {{ fontWeight : 'bold' }} > Extracted Text : </ Text >
< Text >{ extractedText } </ Text >
< Button title = "Copy to Clipboard" onPress = { copyToClipboard } />
</ View >
);
}
Multi-language Support
import { useOCR , OCRLanguage } from 'react-native-executorch' ;
import { useState } from 'react' ;
function MultiLanguageOCR () {
const [ language , setLanguage ] = useState < OCRLanguage >( 'en' );
const [ detections , setDetections ] = useState < any []>([]);
const ocr = useOCR ({
model: {
detectorSource: require ( './models/detector.pte' ),
recognizerSource: require ( './models/recognizer.pte' ),
language: language ,
},
});
const languages : OCRLanguage [] = [ 'en' , 'ch' , 'pl' ];
return (
< View >
< Text > Select Language : </ Text >
< View style = {{ flexDirection : 'row' }} >
{ languages . map (( lang ) => (
< Button
key = { lang }
title = {lang.toUpperCase()}
onPress = {() => setLanguage ( lang )}
/>
))}
</ View >
< Text > Current : { language }</ Text >
< Text > Status : { ocr . isReady ? 'Ready' : 'Loading...' }</ Text >
</ View >
);
}
Filtering by Confidence
import { useOCR } from 'react-native-executorch' ;
import { useState } from 'react' ;
function ConfidenceFilteredOCR () {
const [ minConfidence , setMinConfidence ] = useState ( 0.7 );
const [ allDetections , setAllDetections ] = useState < any []>([]);
const [ filteredDetections , setFilteredDetections ] = useState < any []>([]);
const ocr = useOCR ({
model: {
detectorSource: 'https://example.com/detector.pte' ,
recognizerSource: 'https://example.com/recognizer.pte' ,
language: 'en' ,
},
});
const processImage = async ( imageUri : string ) => {
if ( ! ocr . isReady ) return ;
try {
const results = await ocr . forward ( imageUri );
setAllDetections ( results );
// Filter by confidence threshold
const filtered = results . filter ( det => det . score >= minConfidence );
setFilteredDetections ( filtered );
} catch ( error ) {
console . error ( 'OCR failed:' , error );
}
};
return (
< View >
< Text > Minimum Confidence : {( minConfidence * 100). toFixed (0)}%</ Text >
< Slider
value = { minConfidence }
onValueChange = { setMinConfidence }
minimumValue = { 0 }
maximumValue = { 1 }
/>
< Text > Total detections : { allDetections . length }</ Text >
< Text > Filtered detections : { filteredDetections . length }</ Text >
{ filteredDetections . map (( det , idx ) => (
< View key = { idx } >
< Text >{det. text } - {( det . score * 100). toFixed (1)} %</ Text >
</ View >
))}
</ View >
);
}
Document Scanner
import { useOCR } from 'react-native-executorch' ;
import { useState } from 'react' ;
import { Camera } from 'react-native-vision-camera' ;
import { useRef } from 'react' ;
function DocumentScanner () {
const cameraRef = useRef < Camera >( null );
const [ scannedText , setScannedText ] = useState < string []>([]);
const ocr = useOCR ({
model: {
detectorSource: require ( './models/detector.pte' ),
recognizerSource: require ( './models/recognizer.pte' ),
language: 'en' ,
},
});
const captureAndScan = async () => {
if ( ! cameraRef . current || ! ocr . isReady ) return ;
try {
const photo = await cameraRef . current . takePhoto ();
const results = await ocr . forward ( photo . path );
const lines = results
. filter ( det => det . score > 0.6 )
. map ( det => det . text );
setScannedText ( lines );
} catch ( error ) {
console . error ( 'Scan failed:' , error );
}
};
return (
< View style = {{ flex : 1 }} >
< Camera
ref = { cameraRef }
style = {{ flex : 1 }}
device = { /* camera device */ }
isActive = { true }
/>
< Button
title = "Scan Document"
onPress = { captureAndScan }
disabled = {!ocr.isReady || ocr. isGenerating }
/>
< ScrollView style = {{ maxHeight : 200 }} >
{ scannedText . map (( line , idx ) => (
< Text key = { idx } > { line } </ Text >
))}
</ ScrollView >
</ View >
);
}
Notes
Both detector and recognizer models automatically load when the hook mounts unless preventLoad is set to true.
OCR processing can be computationally intensive. Consider showing a loading indicator during processing.
For best results, use images with good lighting and clear, unobstructed text. Consider preprocessing images to improve contrast if needed.
Image Quality : Higher quality images generally produce better results
Text Size : Ensure text is large enough and not too small
Lighting : Good, even lighting improves detection accuracy
Contrast : High contrast between text and background works best
Orientation : Text should be horizontal for best results
See Also