zp_cccd_scanner 1.10.0
zp_cccd_scanner: ^1.10.0 copied to clipboard
Flutter plugin quét và nhận diện thẻ CCCD / Căn cước Việt Nam (đủ 3 mẫu thẻ, 2 mặt) bằng camera native trên iOS (AVFoundation + Vision) và Android (CameraX + ML Kit).
1.10.0 #
- iOS: nới ràng buộc version
onnxruntime-objctừ~> 1.30.0xuống>= 1.23.0— sửa xung đột khi app host đã có sẵn 1 lib khác (vdflutter_onnxruntime) ghim đúng 1 bảnonnxruntime-objccụ thể khác 1.30.x: trước đây CocoaPods sẽ báo lỗi "không tìm được bản thoả mãn cả 2 ràng buộc" và app không build được. Đã xác nhận trực tiếp (so header, không chỉ đọc tài liệu) 4 API ObjC plugin này dùng (ORTEnv/ORTSession/ORTValueinit,run(withInputs:outputNames:runOptions:),tensorData()) có chữ ký giống hệt ở bản1.23.0, và đã build thật thành công khi ép CocoaPods resolve về đúng bản đó (giả lập đúng tình huống có lib khác ghim 1.23.0). Không đổi code Swift, không đổi hành vi — chỉ nới ràng buộc version để CocoaPods có thể gộp chung 1 bản ONNX Runtime cho cả app thay vì xung đột. App host không có dependency ONNX Runtime nào khác không bị ảnh hưởng (vẫn resolve về bản mới nhất như trước, đã kiểm chứng 1.30.0).
1.9.0 #
- BREAKING: gỡ
ZpCccdAiModel.int8— chỉ cònZpCccdAiModel.fp32. App nào đang dùngZpCccdAiModel.int8sẽ lỗi build khi lên phiên bản này, chuyển sangZpCccdAiModel.fp32. Filecccd_seg_int8.onnx(~3.2MB) không còn đóng gói trong asset Android/iOS. Lý do: đo thực tế cho thấy phần nặng nhất của plugin là thư viện native ONNX Runtime (~34-41MB tuỳ ABI), không phải file model (~10-14MB) — bỏint8chỉ tiết kiệm ~3.2MB trong khi đổi lại độ chính xác kém hơn rõ rệt (mAP50-95 box 0.945 so với 0.990 của fp32), không đáng đánh đổi. Model đã lượng tử hoá vẫn còn trongmodel_handover/(tài liệu tham khảo, không đóng gói vào package) nếu cần. - Android: bỏ hẳn nhận diện khuôn mặt (
com.google.mlkit:face-detection) — đo thực tế bằng cách build 2 app Flutter tối giản (có/không có plugin) rồi so sánh (xem.build/measure-size-impact.sh): tích hợp plugin vào app host giờ chỉ còn tăng +68.00MB trên arm64-v8a (trước đây +79.91MB sau khi gỡint8, +81.69MB trước đó) — tiết kiệm thêm ~11.9MB. Tín hiệu này chỉ phục vụ chấm che avatar của luồng Hough cổ điển; khi bật AI, code đã chủ động không dùng tới (model AI tự có lớp "bị che" riêng). Hành vi đổi: luồng Hough cổ điển (không bật AI) giờ chỉ còn chấm che avatar bằng tín hiệu "độ phẳng" (quay lại đúng hành vi trước bản 1.6.0) — vật che có vân/texture riêng (vd ngón tay) có thể khó bị phát hiện hơn so với khi có thêm tín hiệu khuôn mặt. Không ảnh hưởng gì khi bật AI (ZpCccdScanner.aiModel != null) — AI chưa từng dùng tín hiệu này. iOS không đổi gì: nhận diện khuôn mặt trên iOS dùngVision(framework hệ thống của Apple, không tốn thêm dung lượng IPA), nên giữ nguyên để không mất độ chính xác miễn phí.CccdObservation.faces/CccdStill.facesvẫn còn trên Dart (Android giờ luôn gửinull, được xử lý y hệt case "bộ dò lỗi/không chạy" đã có sẵn — không cần đổi gì ở tầng Dart).
1.8.0 #
- Bỏ fallback về Hough khi đã chọn AI (thay đổi hành vi so với 1.7.0): trước đây nếu model AI
nạp lỗi hoặc suy luận lỗi liên tục nhiều khung hình, thư viện tự động rơi về
CardQuadDetector(Hough) cho phần còn lại của phiên. Từ bản này, đã setZpCccdScanner.aiModelthì cả phiên chỉ dùng AI để dò 4 góc + bị che — không gọi Hough, không chấm che theo độ phẳng/khuôn mặt/màu của luồng cũ, và không tự chuyển sang Hough dù model nạp lỗi hay suy luận lỗi liên tục. Model không nạp được (ZpCccdScanner.aiActive == false) thì phiên đó không dò được thẻ — app host nên tự kiểm traaiActivesau khi gọistart()để quyết định xử lý (báo lỗi người dùng, hoặc khởi tạo lại phiên vớiaiModel = nullđể dùng Hough). - Android: tách luồng nhận diện khỏi luồng vẽ camera: ML Kit (OCR/mã vạch) và suy luận AI nay
chạy trên một
ExecutorServiceriêng (detectExecutor), không còn dùng chung luồng với việc vẽ texture preview — một lượt nhận diện/suy luận chậm không còn làm giật hình xem trước. ThêmSessionOptionscho ONNX Runtime (intraOpNumThreads = 2,interOpNumThreads = 1, tắt spin) để nhường lõi CPU cho luồng vẽ.AiCardDetector.analyze()chuyển từ read lock sang write lock (livestream và ảnh tĩnh không còn suy luận chồng nhau). - Bỏ dò khuôn mặt + tín hiệu màu (chroma) khi đã chọn AI (Android lẫn iOS): 2 tín hiệu này chỉ phục vụ chấm che avatar/vân tay/QR/PDF417 của luồng Hough cũ — không cần khi AI đã đảm nhiệm dò che, bớt việc cho ML Kit Face Detection/Vision mỗi khung hình.
- Sửa số liệu dung lượng tải về của mục "Dung lượng (thư viện native ONNX Runtime)" ở bản 1.7.0:
bản
libonnxruntime.sođo ở bản 1.7.0 là dung lượng cài đặt (không nén); đo thêm bằnggzip -9trên cùng file cho dung lượng tải về thực tế qua Play Store: ~12.9MB (arm64-v8a), ~11.6MB (armeabi-v7a) — thấp hơn đáng kể so với ~24-41MB cài đặt đã công bố ở 1.7.0. - Màu 4 góc khung đổi khi khoá thẻ (thay đổi hành vi mặc định, áp dụng cho MỌI app, không
cần bật cờ nào): từ lúc
CccdScanState.verifyingtrở đi (gồm cả lúcrejectedđang hold vàdone), màu 4 góc đổi thànhCccdScannerView.lockedColor(mặc địnhColor(0xFF22C55E), xanh lá) thay vì tiếp tục dùngdetectedColornhư trước.detectedColortừ bản này không còn hiệu lực nhìn thấy được ở bất kỳ đâu (đã đánh dấu@Deprecated, giữ lại tham số chỉ để không phá API cũ) — app đã tuỳ biếndetectedColorđể chờ đổi màu lúc khoá thẻ cần chuyển sang tuỳ biếnlockedColorthay thế. trackCardCorners+freezeOnVerify(mặc địnhtrue): 4 góc khoá vào đúng thẻ thật lúc verifying: trong lúc đang tìm thẻ, 4 góc overlay LUÔN ở khung hướng dẫn tĩnh (kể cả khi bậttrackCardCorners) — tránh cảm giác giật do quad dò được dao động nhẹ mỗi khung hình. Chỉ khi cả 2 cờ cùng bật VÀ thẻ đã khoá (verifying), 4 góc mới trượt mượt — đúng MỘT LẦN, bo tròn giống hệt 4 góc tĩnh — từ khung tĩnh tới đúng 4 góc thẻ thật đã dò được, và tia quét chạy dọc theo đúng hình thẻ đó (nghiêng theo thẻ nếu thẻ nghiêng) thay vì kẻ ngang cố định. Giữ nguyên vị trí này xuyên suốtrejected/done, không giật.trackCardCorners: false(mặc định) hoặcfreezeOnVerify: false(chế độ lưới) không đổi gì so với trước.- Ẩn lớp phủ tối ngoài khung lúc đã khoá thẻ: từ lúc
CccdScanState.verifyingtớidone, lớp phủ tối (maskColor) không còn vẽ nữa — ảnh đã đóng băng rõ ràng nên lớp phủ chỉ còn che bớt hình, không còn tác dụng hướng dẫn tìm thẻ. Hiện lại ngay khi bị từ chối (rejected) hoặc khi thực sự quét lại. Áp dụng cho MỌI app, không cần bật cờ nào; 4 góc/tia quét/lưới vẫn vẽ bình thường, chỉ lớp phủ tối bị ẩn.
1.7.0 #
- Bộ dò thẻ bằng AI (tuỳ chọn, mặc định tắt): thêm
ZpCccdAiModel(fp32/int8) vàZpCccdScanner.aiModel— set trước khi gọiZpCccdScanner.start()để chọn dùng model AI (ONNX Runtime) dò 4 góc thẻ + phát hiện che khuất, thay cho bộ dò Hough transform cổ điển (CardQuadDetector) đã có từ 1.0.0. Mỗi phiên quét chỉ chạy đúng một trong hai kỹ thuật — không bao giờ cả hai cùng chạy trên một frame: bật AI thì Hough hoàn toàn không chạy trong phiên đó (kể cả ở bước xác thực ảnh tĩnh); không bật (hoặc native load model thất bại, xemaiActivebên dưới) thì dùng Hough như trước giờ.- AI chỉ dò hình học (4 góc thẻ + bị che hay không) — không đọc chữ, không phân loại thẻ,
không thay thế
CccdValidator(validator OCR/MRZ/QR không đổi gì, vẫn chạy như cũ dù bật AI hay không). ZpCccdScanner.aiActive(read-only):truekhi model yêu cầu đã load thành công trên máy hiện tại trong phiên này. Nếu native load model thất bại (thiếu asset, ABI thiết bị không hỗ trợ...), thư viện tự động rơi về bộ dò cổ điển cho cả phiên quét đó — không crash, không treo app.- Mặc định
aiModel = null(AI tắt) — không đổi API, không đổi hành vi so với trước khi có tính năng này; app host hiện tại không cần sửa gì. - App demo: thêm 2 switch loại trừ lẫn nhau "Dùng AI dò thẻ (fp32)" / "Dùng AI dò thẻ (int8, nhẹ hơn)" để thử nhanh.
- int8 nhẹ hơn, KHÔNG nhanh hơn:
int8nhỏ hơn fp32 (~3.2MB so với ~10.6MB) nhưng chạy chậm hơn ~36% trên CPU (đo trongmodel_handover/README.mdmục 5: fp32 ~55ms/khung hình, int8 ~76ms, cùng một máy), và độ chính xác dò che khuất kém hơn một chút. Chọnint8vì dung lượng, không phải vì tốc độ. - Giới hạn phạm vi dò che khuất của AI: model chỉ có lớp "bị che" riêng cho CCCD nhựa kiểu
mới (
cccd_moi_truoc_che/cccd_moi_sau_che, xemmodel_handover/README.mdmục 2) — với CCCD nhựa kiểu cũ và CMT giấy, đường AI không có tín hiệu che khuất hình học nào (không giống bộ dò Hough cổ điển, vốn có kiểm tra che góc chung cho mọi hình dạng thẻ). Bật AI cho các loại thẻ này chỉ còn lại việc dò 4 góc, không dò được che khuất qua hình học.
- AI chỉ dò hình học (4 góc thẻ + bị che hay không) — không đọc chữ, không phân loại thẻ,
không thay thế
- Android
minSdknâng từ 21 lên 24 — bắt buộc bởi dependency mớicom.microsoft.onnxruntime:onnxruntime-android:1.31.1. Ảnh hưởng mọi app host cập nhật lên bản này, kể cả app không bật AI (tương tự cách 1.6.0 đã thêmcom.google.mlkit:face-detection— dependency đó không đổi gì ở bản này, chỉ nhắc lại để không nhầm với dependency ONNX Runtime mới này). - Dung lượng (file model): cả 2 file model AI (
cccd_seg_fp32.onnx~10.6MB,cccd_seg_int8.onnx~3.2MB — tổng ~13.8MB) được đóng gói vô điều kiện vào asset của cả Android lẫn iOS, tăng dung lượng APK/IPA của mọi app host dù có bật AI hay không. Chưa hỗ trợ tách theo flavor/dynamic delivery ở bản này (known tradeoff, dự kiến cải thiện sau). - Dung lượng (thư viện native ONNX Runtime) — KHÁC, LỚN HƠN dung lượng file model ở trên: bản
thân thư viện native
onnxruntime-android/onnxruntime-c(không phải file.onnx) cũng tăng dung lượng đáng kể, đo trực tiếp trên bản dựng thật của release này:- Android:
libonnxruntime.sonặng ~34.2MB (arm64-v8a, ABI phổ biến nhất trên máy thật), ~24.2MB (armeabi-v7a), ~40.7-40.8MB (x86/x86_64) — cộng thêmlibonnxruntime4j_jni.sonhỏ (~60-120KB mỗi ABI). Một APK "fat" (không tách theo ABI) gộp cả 4 ABI; AAB/split APK (khuyến nghị) chỉ gửi đúng 1 ABI cho mỗi máy, nên thực tế người dùng cuối chỉ tải thêm ~24-41MB tuỳ ABI thiết bị, không phải tổng cả 4. - iOS: pod
onnxruntime-cnặng ~243MB trên đĩa (du -shthư mục pod — gồm nhiều lát kiến trúc: thiết bị thật + simulator arm64/x86_64 + macOS); riêng látios-arm64(thiết bị thật) nặng ~46MB. Dung lượng thực tế cộng vào app sau khi linker loại bỏ phần không dùng (dead-code stripping/thinning) nhỏ hơn con số này nhưng KHÔNG được đo chính xác trong môi trường kiểm thử này (không có thiết bị thật + App Store Connect size report để đo).
- Android:
- Telemetry ONNX Runtime:
- Android: đã xác nhận bị tắt từ bản này.
ai.onnxruntime.TelemetryInitializer— mộtContentProviderchạy ở mọi process khởi động app host (bất kể có bật AI hay không) nạp thư viện native ONNX Runtime và dựng hẳn một client telemetry Microsoft 1DS (endpointhttps://mobile.events.data.microsoft.com/OneCollector/1.0cứng trong code) — plugin gỡ provider này khỏi manifest (tools:node="remove") và tự gọiOrtEnvironment.setTelemetry(false)khi nạp model (phòng vệ kép). Đã kiểm chứng bằng build release thật: manifest merger log ghi rõ provider này bịREJECTED, và log runtime của chính ONNX Runtime xác nhậnHttpClienttelemetry "was not initialized". Tài liệu C API chính thức của ONNX Runtime ghi "Telemetry events are on by default since they are lightweight" — tức mặc định BẬT trên MỌI nền tảng, không phải chỉ Windows như bản mô tả trước đây của plugin này (đã sửa, xem bản phát hành trước). - Quyền
INTERNET/ACCESS_NETWORK_STATEvẫn merge vào manifest app host dù provider đã bị gỡ (dependency vẫn tự khai 2 quyền này độc lập với provider). App host không muốn 2 quyền này có thể tự gỡ bằngtools:node="remove"trong chính manifest của mình — nhưng cân nhắc kỹ trước khi làm vậy nếu app còn dùng mạng cho việc khác (upload ảnh lên backend eKYC chẳng hạn). - iOS: đã triển khai tắt qua C API thô (
OrtApi::DisableTelemetryEvents, vìonnxruntime-objc'sORTEnvkhông expose API này) — đã kiểm chứng chuỗi gọiCreateEnv→DisableTelemetryEventschạy thành công, không crash, trên iOS Simulator. KHÔNG bắt được gói tin mạng thực tế để xác nhận 0% traffic (không có công cụ network-capture trong môi trường kiểm thử) — chỉ xác nhận lệnh gọi API công khai, tài liệu hoá của chính ONNX Runtime báo cáo thành công.
- Android: đã xác nhận bị tắt từ bản này.
- iOS: thêm dependency
onnxruntime-objc(~> 1.30.0) qua CocoaPods; deployment target giữ nguyên 15.5 (đã cao hơn yêu cầu 15.1 của dependency nên không cần nâng). Podspec của plugin bậtstatic_framework = true(bắt buộc vìonnxruntime-objc/onnxruntime-cmang theo thư viện tĩnh — chỉ áp dụng cho riêng pod của plugin, không ép linkage mode cho Podfile của app host). - Giấy phép AGPL-3.0: trọng số model AI bundle kèm (
cccd_seg_fp32.onnx/cccd_seg_int8.onnx) được train bắt đầu từ Ultralytics YOLO26 (giấy phép AGPL-3.0) nên phải xem là AGPL-3.0 (xemmodel_handover/README.mdmục 7). Sản phẩm cần đóng source hoặc dùng thương mại theo cách không tương thích AGPL-3.0 thì cần tự kiểm tra điều khoản đúng phiên bản Ultralytics đã dùng (8.4.175) tại thời điểm phát hành, mua giấy phép Ultralytics Enterprise, hoặc train lại từ một model nền khác mà mình có giấy phép.- Dữ liệu huấn luyện ảnh che khuất: đây là ràng buộc khác, độc lập với AGPL-3.0 ở trên —
ảnh che khuất tổng hợp dùng để train lấy ảnh thẻ gốc từ các bộ dữ liệu công khai (Roboflow) có
điều khoản riêng (thường giới hạn phi thương mại), ảnh tổng hợp kế thừa điều khoản của ảnh gốc.
Phải tự kiểm tra giấy phép của từng nguồn ảnh trước khi phát hành thương mại (xem
model_handover/README.mdmục 7).
- Dữ liệu huấn luyện ảnh che khuất: đây là ràng buộc khác, độc lập với AGPL-3.0 ở trên —
ảnh che khuất tổng hợp dùng để train lấy ảnh thẻ gốc từ các bộ dữ liệu công khai (Roboflow) có
điều khoản riêng (thường giới hạn phi thương mại), ảnh tổng hợp kế thừa điều khoản của ảnh gốc.
Phải tự kiểm tra giấy phép của từng nguồn ảnh trước khi phát hành thương mại (xem
- Model AI nâng từ 8 lên 12 lớp: phân biệt riêng CCCD 2021 và thẻ Căn cước 2024 (trước đó gộp
chung thành 1 lớp "CCCD nhựa kiểu mới") — xem
model_handover/README.mdmục 2. Id lớp 0-7 giữ nguyên ý nghĩa, chỉ đổi tên (cu→2016,cmt→cmnd,moi→2021); thêm lớp 8-11 cho CCCD 2024 (sạch/bị che, mặt trước/sau). Không đổi API, không đổi logic hình học (minAreaRectCorners).- Cảnh báo từ
model_handover/README.mdmục 5: bản 12 lớp kém hơn bản 8 lớp cũ ở phát hiện che nhỏ (1-8% diện tích ở góc — ví dụ che 1%: 84.0% so với 96.3% trước đó) và chặn nhầm thẻ sạch nhiều hơn (3.3% so với 1.5%). Bản int8 yếu hơn rõ rệt riêng cho thẻ 2024 (mAP50cccd_2024_sau0.962, recallcccd_2024_sau_che0.933). Dữ liệu CCCD 2024 trong tập train rất ít (124 ảnh thật, phần lớn gần giống nhau; chỉ 5 ảnh che thật) — chưa có đánh giá trên thẻ 2024 chụp bằng camera thật.
- Cảnh báo từ
CccdScannerView.trackCardCorners(mặc địnhfalse): khi bật, 4 góc overlay bám theo vị trí/góc nghiêng thật của thẻ đã dò được (Hough hoặc AI, dùng chungCardQuad.corners) thay vì đứng yên ở khung hướng dẫn — hiệu ứng "focus/khoá vào thẻ". Tắt theo mặc định nên không đổi hành vi app host hiện tại.
1.6.0 #
- Dò che nội dung chính xác hơn (avatar, vân tay, QR, PDF417): bổ sung 2 tín hiệu mới chạy
song song (OR) với kỹ thuật đo "độ phẳng" đã có từ trước, không thay thế:
- Nhận diện khuôn mặt cho vùng avatar (Vision trên iOS, ML Kit Face Detection trên Android) — sửa đúng ca thực tế đã gặp: vật che có texture riêng (VD ngón tay) vẫn có thể "qua mặt" kỹ thuật đo độ phẳng một khi camera đã lấy nét tốt, trong khi dò khuôn mặt xác nhận trực tiếp có đúng khuôn mặt hay không nên không bị đánh lừa kiểu đó.
- Dò màu cho vân tay/QR/PDF417 (các vùng in mực đen trắng) — vật che có màu (da tay, vải...) đọc khác hẳn mực in nên bắt được cả trường hợp texture đánh lừa độ phẳng.
- Áp dụng cho cả frame preview lẫn ảnh tĩnh lúc chụp (backstop cuối cùng trước khi chấp nhận kết quả), cả 3 loại thẻ (CCCD mã vạch, CCCD gắn chip, Căn cước).
- Không đổi API public — hành vi mặc định tương thích ngược hoàn toàn, app host không cần sửa gì để nhận lợi ích này.
- Android: thêm dependency mới
com.google.mlkit:face-detection— có thể tăng nhẹ dung lượng APK của app host (model nhận diện khuôn mặt đóng gói kèm). - Các ngưỡng mới (
kMinFaceOverlapFraction,kMinColorValue,kMaxColoredFraction) là ước lượng ban đầu, sẽ tiếp tục hiệu chỉnh bằng log thiết bị thật ở các bản sau.
1.5.0 #
CccdScannerView.freezeOnVerify(mặc địnhtrue, giữ nguyên hành vi cũ): đặtfalseđể không đóng băng khung hình khi xác thực lần 2 — camera tiếp tục chạy live (gọiretain()native thay vìfreeze()), phủ hiệu ứng lưới (mesh) có dải sáng quét lặp lại (giống máy scan tài liệu) lên vùng thẻ trong lúc xác thực vẫn chạy ngầm trên frame đã giữ lại. Hint mặc định ở trạng tháiverifyingcũng đổi theo: "Giữ vững, đang chụp..." thay vì "Giữ yên điện thoại, đang chụp ảnh thẻ..." như khifreezeOnVerify: true.CccdScannerView.tipWarningColor(mặc địnhnull= không đổi màu): màu 4 góc khung khi đang tìm thẻ (CccdScanState.searching) mà có bất kỳ gợi ýCccdScanTipnào đang active (mất nét, đưa ra xa, thiếu sáng, sai loại giấy tờ, bị che — cả 5 tip) hoặc khi frame hiện tại chưa thấy giấy tờ nào.CccdScannerView.onNoCandidateChanged: callbackValueChanged<bool>báo khi tín hiệu "frame hiện tại có/không thấy giấy tờ nào" đổi (chỉ có ý nghĩa lúcCccdScanState.searching). Dùng khi app host tự vẽ hint ở vị trí khác quaoverlaythay vìhintBuildermặc định.- Cả 3 đều tuỳ chọn, giữ giá trị mặc định như hành vi cũ — app host hiện tại không cần đổi gì.
- Export mới
cccdHintText/cccdTipText(src/hint_text.dart): 2 hàm thuần tuý sinh câu hint mặc định của thư viện, nay public để app host tự vẽ hint UI hoàn toàn riêng (VD đặt text ở vị trí khác ngoài vị trí mặc định) mà vẫn tái dùng đúng nguyên văn câu chữ của thư viện thay vì tự chép lại. - Cập nhật câu chữ hướng dẫn mặc định (chỉ ảnh hưởng app đang dùng hint mặc định; app có
hintBuilderriêng không dùng text này nên không bị ảnh hưởng):CccdScanTip.holdStill: "Giữ yên điện thoại để ảnh rõ nét" → "Giấy tờ tùy thân mất nét. Hãy giữ yên."CccdScanTip.cardObscured: "Thẻ đang bị che khuất, vui lòng bỏ vật che (ngón tay...) ra khỏi thẻ" → "Giấy tờ tùy thân bị che một phần. Hãy tránh che bằng ngón tay hoặc các đồ vật khác."CccdScanTip.otherDocument: "Đây không phải CCCD / Căn cước, vui lòng đưa đúng loại giấy tờ" → "Không khớp với loại giấy tờ tùy thân đã chọn. Hãy sử dụng đúng giấy tờ tùy thân hoặc chọn lại loại giấy tờ tùy thân của bạn."- Mới: khi đang tìm thẻ (
searching) mà frame hiện tại không thấy giấy tờ nào (chưa có tip cụ thể), hiện "Không phát hiện thấy giấy tờ tùy thân. Hãy đặt giấy tờ tùy thân trong khung hình."
1.4.0 #
- Chặn chụp khi góc thẻ bị che: khi ít nhất một góc thẻ có dấu hiệu bị che (ngón
tay, vật cản...) — đặc biệt là che QR — thư viện không còn tự chụp/nhận diện thẻ đó
nữa, kể cả khi phần chữ/QR còn lại vẫn đủ để đọc được. Báo qua
onTipChangedvớiCccdScanTip.cardObscuredmới để app hiển thị "Thẻ đang bị che khuất, vui lòng bỏ vật che ra khỏi thẻ". Nếu app cóswitchđầy đủ theoCccdScanTipthì cần thêm casecardObscured. - Chặn chụp khi vùng nội dung ở giữa thẻ bị che: mở rộng phát hiện che khuất ra
ngoài 4 góc — chặn cả khi avatar, mã vạch (PDF417), QR, dòng MRZ, nhãn thông tin
khác, hoặc vân tay bị che. Áp dụng cho cả 3 loại thẻ (CCCD mã vạch, CCCD gắn chip,
Căn cước). Vẫn báo qua
CccdScanTip.cardObscuredđã có, không thêm tip/API mới. - Sửa lỗi: sau khi bỏ vật che ra, thư viện có thể vẫn báo "bị che" và chặn chụp rất lâu nếu vật che lướt qua rìa vùng theo dõi vài lần lúc rút ra (mỗi lần lại tính lại thời gian chờ 1.5s từ đầu). Giờ chỉ bằng chứng che kéo dài (đã làm mượt) mới giữ cooldown dài; 1 lần chạm thoáng qua chỉ giữ cooldown ngắn (0.5s), không cộng dồn.
1.3.0 #
- Sửa lỗi: không nhận diện được mặt sau CCCD mã vạch cấp từ 2019 (VD thẻ cấp năm 2020). Từ 2019 cơ quan cấp đổi thành "Cục Cảnh sát quản lý hành chính về trật tự xã hội" — cùng tên với mặt sau thẻ chip — nên mặt sau bị nhận nhầm là thẻ chip và đòi MRZ. Giờ chỉ dùng dòng tiếng Anh làm dấu hiệu thẻ chip; mẫu mã vạch từ 2019 được nhận qua PDF417 hoặc đủ cụm chữ cơ quan cấp khi không có dòng MRZ.
onDiagnostic: sự kiệnframekèm chữ OCR và mã đọc được (có vị trí) để chạy lại nhận diện offline (test/replay/replay_log_test.dart).CccdScanTip.otherDocument: báo quaonTipChangedkhi khung hình rõ ràng là một loại giấy tờ khác (GPLX, hộ chiếu...), không phải CCCD/Căn cước. Nếu app cóswitchđầy đủ theoCccdScanTipthì cần thêm caseotherDocument.CccdScannerController,CccdManualCaptureResult: cho phép app host chụp ảnh thủ công vùng khung hướng dẫn khi auto-detect không nhận diện được sau một khoảng thời gian do app tự quyết định (ảnh gửi lên BE xử lý tiếp, không qua validator).CccdScannerView.controller(tuỳ chọn).
1.2.0 #
- Lấy nét ổn định, không giật (đặc biệt iPhone Pro có macro):
- iOS không còn ép AF quét lại mỗi khi khung hình thay đổi; chỉ dời điểm lấy nét khi lệch đủ xa hoặc khi chạm.
- Android chỉ gửi lại tham số Camera2 khi vùng lấy nét / fps thực sự đổi.
- Giữ macro (iOS tự chuyển ống ultra-wide khi thẻ quá gần), đồng thời zoom bù để khoảng cầm máy tự nhiên nằm ngoài vùng chuyển ống.
- Không chụp ảnh mờ: native gửi kèm độ nét (phương sai Laplacian) và trạng thái đang lấy nét / vừa đổi ống kính; chỉ xác nhận frame đủ nét và đóng băng frame nét nhất.
- Ảnh độ phân giải cao: chụp ảnh tĩnh (iOS
AVCapturePhotoOutput~12MP, AndroidImageCaptuređộ phân giải cao nhất) ngay khi đóng băng, dò lại 4 góc thẻ trên ảnh đó rồi cắt; tự quay về frame video nếu không chụp được.CccdScanResult.highResolutioncho biết nguồn ảnh. - Thiếu sáng: tự tăng bù sáng và cho phơi sáng lâu hơn (không tự bật đèn); gợi ý người dùng bật đèn.
- Gợi ý phụ
CccdScanTip(giữ yên máy, đưa ra xa, thiếu sáng) qua dòng hướng dẫn mặc định vàonTipChanged. - API mới:
ZpCccdScanner.torch,ZpCccdScanner.lowLight,CccdScannerView.highResolutionImage. showDebugOverlayhiển thị thêm độ nét, ống kính đang dùng, zoom, khoảng cách ước lượng, độ sáng, ISO.CccdScannerView.onDiagnostic: sự kiện chẩn đoán (thông số camera, từng frame, đóng băng, ảnh tĩnh, kết quả) để ghi log khi test; app example có mục xuất file log.- Sửa lỗi (có từ 1.0.0): mở liền 2 màn quét (VD mặt trước -> mặt sau) thì camera màn sau bị đen. Màn cũ dispose sau khi màn mới đã mở camera nên tắt nhầm camera mới và ngắt kênh event. Giờ
ZpCccdScanner.stop(textureId)chỉ tắt đúng camera của mình, các listener dùng chung một luồng event, màn không còn ở trên cùng thì bỏ qua frame. overlaycủaCccdScannerViewnhận ràng buộc phủ kín view (ghi rõ trong tài liệu); app example đặt hàng nút lên trên cùng.
1.0.0 #
- Phát hành đầu tiên trên pub.dev.
- Nhận diện 3 mẫu thẻ còn hiệu lực, cả 2 mặt: CCCD mã vạch (2016), CCCD gắn chip (2021), thẻ Căn cước (2024).
- Chống nhận nhầm: MRZ
IDVNMđủ 5 check digit ICAO 9303, PDF417 + cụm chữ đặc trưng, tiêu đề + số định danh khớp chéo ngày sinh / giới tính; xác nhận lần 2 trên frame đã đóng băng. - Chỉ chụp khi thẻ nằm trọn trong khung (dò 4 cạnh thẻ); ảnh trả về chứa trọn thẻ kèm 4 góc.
- Hiệu ứng giống Zalo: đóng băng frame và tia quét từ trên xuống khi phát hiện thẻ.
CccdScannerViewquét từng mặt, báo khi đưa nhầm mặt / thẻ chưa nằm trọn trong khung;CccdPairingkiểm tra 2 mặt cùng một thẻ.- Camera native: iOS AVFoundation + Vision, Android CameraX + ML Kit (bundled); zoom, đèn flash, chạm để lấy nét.