cccd_card_detector
Flutter package chuyên biệt cho việc nhận diện thẻ CCCD (detect-only):
- Tự động quản lý camera preview.
- Nhận diện realtime mặt trước / mặt sau thẻ CCCD.
- Tự vẽ Overlay với 4 góc bo tròn và viền bám theo thẻ trên màn hình.
- Emit sự kiện (
DetectionFrame,DetectorStatus) về ứng dụng qua callback. - Ranh giới cứng: Thư viện KHÔNG tự động chụp và KHÔNG hiển thị UI lỗi. Mọi quyết định chụp và xử lý lỗi thuộc về ứng dụng host.
- Expose hàm
controller.captureStill()để app chủ động chụp khi thỏa mãn điều kiện.
Cài đặt
dependencies:
cccd_card_detector: ^0.1.3
# OpenCV chỉ giữ imgproc + imgcodecs. Thiếu block này thì APK nặng hơn.
hooks:
user_defines:
dartcv4:
exclude_modules:
- calib3d
- contrib
- dnn
- features2d
- flann
- highgui
- objdetect
- photo
- stitching
- video
- videoio
App tích hợp có thể giữ sdk: ">=2.18.0 <4.0.0". Package cần máy đang cài Dart từ 3.3 và Flutter từ 3.19, vì OpenCV dùng Dart 3. camera nhận cả 0.10.6 và 0.11.x. iOS tối thiểu là 15.5 (Google ML Kit). App host phải đặt platform :ios, '15.5' trong ios/Podfile và IPHONEOS_DEPLOYMENT_TARGET = 15.5.
Block hooks phải nằm trong pubspec.yaml của app, không phải của package. OCR và QR trên Android dùng Google Play Services. Máy không có Play Services thì app tự chụp, không nhận diện và không crop.
Sử dụng
import 'package:flutter/material.dart';
import 'package:cccd_card_detector/cccd_card_detector.dart';
class MyScannerScreen extends StatefulWidget {
@override
State<MyScannerScreen> createState() => _MyScannerScreenState();
}
class _MyScannerScreenState extends State<MyScannerScreen> {
final _controller = CccdDetectorController();
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: CccdDetectorView(
controller: _controller,
config: const CccdDetectorConfig(
minConfidence: 0.8,
detectionFps: 12,
showOverlay: true,
cropPadding: 0.05,
overlayStyle: CccdOverlayStyle.defaults,
),
onDetection: (DetectionFrame frame) {
// Xử lý policy của App (kiểm tra độ nét, độ nghiêng, đếm frame ổn định,...)
if (frame.side == CardSide.front && frame.confidence >= 0.85) {
// App có thể tự gọi: final file = await _controller.captureStill();
}
},
onStatusChanged: (DetectorStatus status) {
debugPrint('Trạng thái: $status');
},
onError: (DetectorError error) {
// App tự quyết định hiển thị thông báo lỗi hay bỏ qua
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Lỗi: ${error.message}')),
);
},
),
);
}
}