Mobile OCR: Real-Time Text Recognition via Camera

A user points a camera at a faded receipt in dim light. Without image preprocessing, standard OCR libraries produce up to 50% errors. The solution is to apply contrast stretching (`vImageContrastStretch` on iOS, `OpenCV` on Android) and binarization at the capture stage. Only then feed the frame to

Development and support of all types of mobile applications:

Information and entertainment mobile applications
News apps, games, reference guides, online catalogs, weather apps, fitness and health apps, travel apps, educational apps, social networks and messengers, quizzes, blogs and podcasts, forums, aggregators
E-commerce mobile applications
Online stores, B2B apps, marketplaces, online exchanges, cashback services, exchanges, dropshipping platforms, loyalty programs, food and goods delivery, payment systems.
Business process management mobile applications
CRM systems, ERP systems, project management, sales team tools, financial management, production management, logistics and delivery management, HR management, data monitoring systems
Electronic services mobile applications
Classified ads platforms, online schools, online cinemas, electronic service platforms, cashback platforms, video hosting, thematic portals, online booking and scheduling platforms, online trading platforms

These are just some of the types of mobile applications we work with, and each of them may have its own specific features and functionality, tailored to the specific needs and goals of the client.

Showing 1 of 1All 1734 services
Mobile OCR: Real-Time Text Recognition via Camera
Medium
~2-3 days

Our competencies:

Frequently Asked Questions

Latest works

  • image_mobile-applications_feedme_467_0.webp
    Development of a mobile application for FEEDME
    895
  • image_mobile-applications_xoomer_471_0.webp
    Development of a mobile application for XOOMER
    782
  • image_mobile-applications_rhl_428_0.webp
    Development of a mobile application for RHL
    1216
  • image_mobile-applications_zippy_411_0.webp
    Development of a mobile application for ZIPPY
    1079
  • image_mobile-applications_affhome_429_0.webp
    Development of a mobile application for Affhome
    1003
  • image_mobile-applications_flavors_409_0.webp
    Development of a mobile application for the FLAVORS company
    597

A user points a camera at a faded receipt in dim light. Without image preprocessing, standard OCR libraries produce up to 50% errors. The solution is to apply contrast stretching (vImageContrastStretch on iOS, OpenCV on Android) and binarization at the capture stage. Only then feed the frame to VNRecognizeTextRequest or ML Kit Text Recognition. In our practice, this chain raises accuracy from 70% to 98-99% on printed text.

Over five years, we have delivered more than 20 OCR projects for retail (price tags and receipts), logistics (waybill tracking), and fintech (passport data verification). Every project had its own set of filters and post-processing steps. A common mistake is expecting the OCR library to produce perfect results out of the box. Without image preprocessing and result post-processing, accuracy drops to 50–70%. Therefore, the first stage of any project is collecting real document samples and testing on them.

Why Preprocessing Is Critical for Accurate OCR

Preprocessing is a key stage that determines final accuracy. In poor lighting or blur, we use:

  • Contrast enhancement via vImageContrastStretch (iOS) or OpenCV (Android).
  • Grayscale conversion followed by AdaptiveThreshold.
  • Sharpen CIFilter before feeding into OCR.

For handwritten text, standard frameworks show 40–60% accuracy. In such cases, custom models based on TensorFlow Lite help — this is a separate task requiring labeled data and training.

How Native OCR Frameworks Work

iOS: Vision + VNRecognizeTextRequest

Since iOS 13, the Vision framework can recognize text offline. VNRecognizeTextRequest supports two modes: .fast (approximate, instant) and .accurate (slower but 15% more accurate for complex fonts). For complex fonts, the .accurate mode gives a 15% accuracy boost.

func recognizeText(in image: UIImage) { guard let cgImage = image.cgImage else { return } let request = VNRecognizeTextRequest { [weak self] request, error in guard let observations = request.results as? [VNRecognizedTextObservation] else { return } let text = observations.compactMap { $0.topCandidates(1).first?.string }.joined(separator: "\n") DispatchQueue.main.async { self?.handleRecognized(text: text) } } request.recognitionLevel = .accurate request.usesLanguageCorrection = true request.recognitionLanguages = ["ru-RU", "en-US"] // order = priority let handler = VNImageRequestHandler(cgImage: cgImage, options: [: ]) try? handler.perform([request]) } 

usesLanguageCorrection helps with typos, but sometimes "corrects" abbreviations and article numbers — for technical documents it is better to disable it.

Android: ML Kit Text Recognition v2

com.google.mlkit:text-recognition supports Latin, Cyrillic, Chinese, Japanese, Korean via separate modules. It downloads on first use (~5 MB for Latin).

val recognizer = TextRecognition.getClient( TextRecognizerOptions.DEFAULT_OPTIONS // or RussianTextRecognizerOptions ) val image = InputImage.fromBitmap(bitmap, 0) recognizer.process(image) .addOnSuccessListener { visionText -> val fullText = visionText.textBlocks .joinToString("\n") { block -> block.text } handleRecognized(fullText) } .addOnFailureListener { e -> handleError(e) } 

ML Kit also returns bounding boxes for each text block — useful for highlighting recognized areas in the UI.

Live Mode: Real-Time Text from Video Stream

For live-overlay (text highlighted directly in the video stream) on iOS we use AVCaptureSession + CMSampleBuffer:

// Delegate method AVCaptureVideoDataOutput func captureOutput(_ output: AVCaptureOutput, didOutput sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection) { guard let pixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer) else { return } // Do not start a new request if previous is still running guard !isProcessing else { return } isProcessing = true let request = VNRecognizeTextRequest { [weak self] request, _ in defer { self?.isProcessing = false } // handle results... } request.recognitionLevel = .fast // speed matters for live try? VNImageRequestHandler(cvPixelBuffer: pixelBuffer, options: [: ]).perform([request]) } 

The isProcessing flag is mandatory — without it at 30 FPS, the request queue piles up and memory grows until crash.

On Android — CameraX + ImageAnalysis.Analyzer. ML Kit is optimized to work directly with ImageProxy without converting to Bitmap.

Parameter Static Recognition Live Recognition
Processing speed 100-200 ms up to 30 ms per frame
Accuracy up to 99% up to 95% (due to speed compromise)
Battery consumption low medium (continuous processing)
Application document scanning, receipts pointing at business cards, license plates

Improving Recognition Quality in Difficult Conditions

Contrast enhancement and binarization are standard techniques. For specific documents (e.g., faded receipts), we add custom filters.

Common integration mistakes:

  • Forgetting the isProcessing flag in live mode → memory leak.
  • Leaving usesLanguageCorrection enabled for technical texts → corrupts abbreviations.
  • Not checking bounding boxes for overlap with UI → text overlays on interface.

Post-Processing: From Raw Text to Structured Data

Raw OCR output is a stream of strings. Most tasks require structuring:

  • Receipts: extract lines with prices via regex, parse final amount.
  • Business cards: NSDataDetector (iOS) or Patterns (Android) for phones, emails, addresses.
  • Passports/documents: MRZ zone read by ICAO 9303 standard, parsers available.
  • License plates: separate task — better to use specialized models (OpenALPR, PlateRecognizer API).

For poor-quality Cyrillic text, preprocessing helps: increase contrast via vImageContrastStretch, grayscale, Sharpen CIFilter before OCR.

Comparison of Native Frameworks

Parameter Vision (iOS) ML Kit (Android)
Modes .fast, .accurate base model
Languages up to 15 in one request modules: Lat, Cyr, Chi, Jap, Kor
Offline yes yes (model ~5 MB)
Accuracy on printed ~98% ~97%
Bounding boxes yes yes
Speed (full HD) 100-200 ms 80-150 ms
Click for more details on preprocessing techniques

For extreme conditions, we use adaptive thresholding (e.g., cv2.adaptiveThreshold with block size 11) and morphological operations to remove noise. These steps can improve accuracy by an additional 10-15%.

Deliverables Included in Development

When ordering this service, you receive:

  • Integration of Vision or ML Kit into your app.
  • Tuning recognition parameters for your document type.
  • Live mode with text highlighting on camera (optional).
  • Data post-processing: parsing receipts, business cards, numbers.
  • Integration and testing documentation.
  • Support during App Store / Google Play review.

Work Process

  1. Define use cases: document types, languages, need for live mode or only static photo.
  2. Implement image capture (camera + gallery), preprocessing.
  3. Integrate OCR: native Vision/ML Kit or cloud (Google Vision API, AWS Textract) if higher accuracy is needed for complex documents.
  4. Post-processing for the specific task: data structuring, regex, NER.
  5. Test on real samples in different lighting conditions.

Timeline Estimates

Basic static text recognition via native framework — 2-3 days (starting from $2,000). Live mode with overlay + data structuring for a specific document type — 1-2 weeks (approx $5,000–$8,000). Complex scenarios with custom models — from one month (budget $15,000+). Contact us for an exact estimate for your project.

Our guaranteed accuracy on printed text is 98% with preprocessing; we provide a certified integration with documented results. Over 5 years of experience ensures reliable project delivery.

Get a consultation for your project — we will select the optimal solution. Contact us to discuss your task and estimate the cost of OCR development for your app. Our solution supports multilingual OCR offline including Russian, English, Chinese, and Japanese.