native_opencv
A Flutter FFI plugin that wraps OpenCV for Android and iOS.
It exposes real-time blur detection and ID-card perspective-crop via dart:ffi — no platform channels required, zero JNI overhead.
Features
| Feature | Android | iOS |
|---|---|---|
getOpenCVVersion() |
✅ | ✅ |
isImageBlurred() |
✅ | ✅ |
cropIdCard() |
✅ | ✅ |
Installation
Add to your pubspec.yaml:
dependencies:
native_opencv_kit: ^1.0.0
Then run:
flutter pub get
Note: This plugin wraps the OpenCV native libraries.
You must supply the OpenCV SDK separately for each platform (see setup below).
The pre-built binaries are not bundled with the pub package due to their size (~2 GB).
Android Setup
1. Download the OpenCV Android SDK
Download the OpenCV Android SDK from opencv.org/releases/ (e.g. opencv-4.10.0-android-sdk.zip) and unzip it.
2. Copy SDK files into the plugin cache
After flutter pub get, the plugin will be downloaded to your Flutter pub cache.
Navigate to it:
~/.pub-cache/hosted/pub.flutter-io.cn/native_opencv-<version>/android/
Copy these two folders from the unzipped OpenCV SDK into that android/ directory:
android/
sdk/
native/
jni/ ← CMake find-package configs and headers
libs/ ← Pre-built .so files (arm64-v8a, armeabi-v7a, x86_64)
3. Verify build.gradle
The plugin's android/build.gradle is already configured to:
- Point CMake to
sdk/native/jnifor the OpenCV find-package path - Bundle
sdk/native/libs/*.sointo your APK automatically
No additional Gradle changes are needed in your app.
Minimum Android SDK
minSdk = 31 (Android 12)
iOS Setup
1. Download the OpenCV iOS Framework
Download opencv2.framework (or opencv2.xcframework for newer SDKs) from opencv.org/releases/.
2. Copy the framework into the plugin cache
After flutter pub get, navigate to:
~/.pub-cache/hosted/pub.flutter-io.cn/native_opencv-<version>/ios/
Place the framework there:
ios/
opencv2.framework/ ← copied from the OpenCV iOS SDK
3. CocoaPods
The plugin's native_opencv.podspec already declares the framework as a vendored dependency. Running pod install inside your app's ios/ folder will pick it up automatically.
Usage
import 'package:native_opencv_kit/native_opencv.dart';
// 1. Get the linked OpenCV version
final version = NativeOpencv.getOpenCVVersion();
print('OpenCV $version');
// 2. Blur detection
// rgbaBytes — Uint8List from your camera frame (RGBA, width * height * 4 bytes)
final bool blurry = NativeOpencv.isImageBlurred(rgbaBytes, width, height);
if (blurry) {
print('Image is too blurry, ask user to hold steady.');
}
// 3. ID-card cropping
// Returns a new Uint8List (RGBA) of fixed size, or null when no card is found.
final int outW = NativeOpencv.idCardOutputWidth;
final int outH = NativeOpencv.idCardOutputHeight;
final Uint8List? cropped = NativeOpencv.cropIdCard(rgbaBytes, width, height);
if (cropped != null) {
// Use cropped RGBA buffer (outW × outH × 4 bytes)
}
See the example/ folder for a full camera-based demo using package:camera.
API Reference
NativeOpencv.getOpenCVVersion() → String
Returns the OpenCV version string compiled into the native library (e.g. "4.10.0").
NativeOpencv.isImageBlurred(Uint8List rgbaBytes, int width, int height) → bool
Returns true when the Laplacian variance of the image falls below the blur threshold.
Input must be a tightly-packed RGBA buffer (width × height × 4 bytes).
NativeOpencv.idCardOutputWidth → int
NativeOpencv.idCardOutputHeight → int
Fixed output dimensions of the cropped ID-card image returned by cropIdCard.
NativeOpencv.cropIdCard(Uint8List rgbaBytes, int width, int height) → Uint8List?
Detects a rectangular card in the frame, applies a perspective transform, and returns a normalised RGBA image of size idCardOutputWidth × idCardOutputHeight × 4 bytes.
Returns null when no card is detected.
Native source
All C++ source lives in src/:
| File | Purpose |
|---|---|
native_opencv.cpp |
C FFI entry-points exported to Dart |
BlurDetector.cpp/.hpp |
Laplacian-variance blur metric |
IdCardCropper.cpp/.hpp |
Contour detection + perspective warp |
CMakeLists.txt |
CMake build (links OpenCV + c++_shared) |
Contributing
Pull requests are welcome! Please open an issue first to discuss what you would like to change.
License
MIT — see LICENSE.