440 lines
13 KiB
Dart
440 lines
13 KiB
Dart
import 'dart:convert';
|
|
import 'dart:io';
|
|
import 'dart:ui';
|
|
|
|
import 'package:flutter/cupertino.dart';
|
|
import 'package:flutter/material.dart';
|
|
import 'package:flutter_tesseract_ocr/android_ios.dart';
|
|
import 'package:get/get.dart';
|
|
import 'package:google_mlkit_text_recognition/google_mlkit_text_recognition.dart';
|
|
import 'package:image_picker/image_picker.dart';
|
|
|
|
class OCRController extends GetxController {
|
|
final text = RxString('');
|
|
|
|
void setText(value) {
|
|
text.value = value;
|
|
}
|
|
}
|
|
|
|
class TextExtractionController extends GetxController {
|
|
String extractedText = '';
|
|
bool isloading = false;
|
|
File? _scannedImage;
|
|
// Convert the extracted text to JSON
|
|
// Convert the extracted text to JSON
|
|
String getTextAsJSON(String text) {
|
|
final lines = text.split('\n');
|
|
final jsonList = lines.map((line) {
|
|
return {
|
|
'line_text': line,
|
|
'num_words': line.trim().split(' ').length,
|
|
};
|
|
}).toList();
|
|
|
|
final json = {
|
|
'lines': jsonList,
|
|
'num_lines': lines.length,
|
|
};
|
|
|
|
return jsonEncode(json);
|
|
}
|
|
|
|
// Convert the extracted text to blocks by line
|
|
List<String> getTextBlocks(String text) {
|
|
return text.split('\n');
|
|
}
|
|
|
|
Future<void> pickAndExtractText() async {
|
|
final pickedImage = await ImagePicker().pickImage(
|
|
source: ImageSource.camera,
|
|
preferredCameraDevice: CameraDevice.rear,
|
|
maxHeight: Get.height * .3,
|
|
maxWidth: Get.width * .8,
|
|
imageQuality: 99,
|
|
);
|
|
if (pickedImage != null) {
|
|
isloading = true;
|
|
update();
|
|
final imagePath = pickedImage.path;
|
|
final languages = [
|
|
'eng',
|
|
'ara'
|
|
]; // Specify the languages you want to use for text extraction
|
|
|
|
try {
|
|
final text = await FlutterTesseractOcr.extractText(imagePath,
|
|
language:
|
|
languages.join('+'), // Combine multiple languages with '+'
|
|
args: {
|
|
"psm": "4",
|
|
"preserve_interword_spaces": "1",
|
|
// "rectangle": const Rect.fromLTWH(100, 100, 200, 200),
|
|
} // Additional options if needed
|
|
);
|
|
isloading = false;
|
|
final jsonText = getTextAsJSON(text);
|
|
final textBlocks = getTextBlocks(text);
|
|
update();
|
|
extractedText =
|
|
textBlocks.toString(); // Convert the extracted text to JSON.
|
|
|
|
// Print the JSON to the console.
|
|
print(jsonText);
|
|
update();
|
|
// print(text);
|
|
} catch (e) {
|
|
print('Error during text extraction: $e');
|
|
extractedText = '';
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
class TextMLGoogleRecognizerController extends GetxController {
|
|
@override
|
|
void onInit() {
|
|
scanText();
|
|
super.onInit();
|
|
}
|
|
|
|
// The ImagePicker instance
|
|
final ImagePicker _imagePicker = ImagePicker();
|
|
|
|
// The GoogleMlKit TextRecognizer instance
|
|
final TextRecognizer _textRecognizer = TextRecognizer();
|
|
|
|
// The scanned text
|
|
String? scannedText;
|
|
String? jsonOutput;
|
|
final List<Map<String, dynamic>> lines = [];
|
|
|
|
Map decode = {};
|
|
|
|
Future<void> scanText() async {
|
|
// Pick an image from the camera or gallery
|
|
final XFile? image =
|
|
await _imagePicker.pickImage(source: ImageSource.gallery);
|
|
|
|
// If no image was picked, return
|
|
if (image == null) {
|
|
return;
|
|
}
|
|
|
|
// Convert the XFile object to an InputImage object
|
|
final InputImage inputImage = InputImage.fromFile(File(image.path));
|
|
|
|
// Recognize the text in the image
|
|
final RecognizedText recognizedText =
|
|
await _textRecognizer.processImage(inputImage);
|
|
scannedText = recognizedText.text;
|
|
Map extractedData = {};
|
|
// Extract the scanned text line by line
|
|
for (var i = 0; i < recognizedText.blocks.length; i++) {
|
|
final block = recognizedText.blocks[i];
|
|
for (final line in block.lines) {
|
|
final lineText = line.text;
|
|
|
|
if (lineText.contains('DL')) {
|
|
final dlNumber = lineText.split('DL')[1].trim();
|
|
extractedData['dl_number'] = dlNumber;
|
|
}
|
|
if (lineText.contains('USA')) {
|
|
final usa = lineText.split('USA')[1].trim();
|
|
extractedData['USA'] = usa;
|
|
}
|
|
if (lineText.contains('DRIVER LICENSE')) {
|
|
final driverl = lineText;
|
|
extractedData['DRIVER_LICENSE'] = driverl;
|
|
}
|
|
|
|
if (lineText.contains('EXP')) {
|
|
final expiryDate = lineText.split('EXP')[1].trim();
|
|
extractedData['expiry_date'] = expiryDate;
|
|
}
|
|
|
|
if (lineText.contains('DOB')) {
|
|
final dob = lineText.split('DOB')[1].trim();
|
|
extractedData['dob'] = dob;
|
|
}
|
|
|
|
if (lineText.contains("LN")) {
|
|
if ((lineText.indexOf("LN") == 0)) {
|
|
final lastName = lineText.split('LN')[1].trim();
|
|
extractedData['lastName'] = lastName;
|
|
}
|
|
}
|
|
if (lineText.contains("FN")) {
|
|
final firstName = lineText.split('FN')[1].trim();
|
|
extractedData['firstName'] = firstName;
|
|
}
|
|
if (lineText.contains("RSTR")) {
|
|
final rstr = lineText.split('RSTR')[1].trim();
|
|
extractedData['rstr'] = rstr;
|
|
}
|
|
if (lineText.contains("CLASS")) {
|
|
final class1 = lineText.split('CLASS')[1].trim();
|
|
extractedData['class'] = class1;
|
|
}
|
|
if (lineText.contains("END")) {
|
|
final end = lineText.split('END')[1].trim();
|
|
extractedData['end'] = end;
|
|
}
|
|
if (lineText.contains("DD")) {
|
|
final dd = lineText.split('DD')[1].trim();
|
|
extractedData['dd'] = dd;
|
|
}
|
|
if (lineText.contains("EYES")) {
|
|
final eyes = lineText.split('EYES')[1].trim();
|
|
extractedData['eyes'] = eyes;
|
|
}
|
|
if (lineText.contains("SEX")) {
|
|
final parts = lineText.split("SEX ")[1];
|
|
extractedData['sex'] = parts[0];
|
|
}
|
|
if (lineText.contains("HAIR")) {
|
|
final hair = lineText.split('HAIR')[1].trim();
|
|
extractedData['hair'] = hair;
|
|
}
|
|
|
|
if (lineText.contains('STREET') || lineText.contains(',')) {
|
|
final address = lineText;
|
|
extractedData['address'] = address;
|
|
}
|
|
|
|
// Repeat this process for other relevant data fields
|
|
}
|
|
}
|
|
|
|
// Convert the list of lines to a JSON string
|
|
jsonOutput = jsonEncode(extractedData);
|
|
decode = jsonDecode(jsonOutput!);
|
|
|
|
update();
|
|
print('jsonOutput------------------------------');
|
|
print(scannedText);
|
|
}
|
|
}
|
|
|
|
class PassportRecognizerController extends GetxController {
|
|
@override
|
|
void onInit() {
|
|
scanText();
|
|
super.onInit();
|
|
}
|
|
|
|
// The ImagePicker instance
|
|
final ImagePicker _imagePicker = ImagePicker();
|
|
Map extractedData = {};
|
|
|
|
// The GoogleMlKit TextRecognizer instance
|
|
final TextRecognizer _textRecognizer = TextRecognizer();
|
|
|
|
// The scanned text
|
|
String? scannedText;
|
|
String? jsonOutput;
|
|
final List<Map<String, dynamic>> lines = [];
|
|
|
|
Map decode = {};
|
|
// Picks an image from the camera or gallery and extracts the text
|
|
|
|
Future<void> scanText() async {
|
|
// Pick an image from the camera or gallery
|
|
final XFile? image =
|
|
await _imagePicker.pickImage(source: ImageSource.gallery);
|
|
|
|
// If no image was picked, return
|
|
if (image == null) {
|
|
return;
|
|
}
|
|
|
|
// Convert the XFile object to an InputImage object
|
|
final InputImage inputImage = InputImage.fromFile(File(image.path));
|
|
|
|
// Recognize the text in the image
|
|
final RecognizedText recognizedText =
|
|
await _textRecognizer.processImage(inputImage);
|
|
scannedText = recognizedText.text;
|
|
// Extract the scanned text line by line
|
|
final List<Map<String, dynamic>> lines = [];
|
|
for (var i = 0; i < recognizedText.blocks.length; i++) {
|
|
lines.add({
|
|
i.toString() +
|
|
'_' +
|
|
recognizedText.blocks[i].text.toString().split('\n')[0]:
|
|
recognizedText.blocks[i].text,
|
|
});
|
|
}
|
|
// for (var i = 0; i < recognizedText.blocks.length; i++) {
|
|
// final block = recognizedText.blocks[i];
|
|
for (final line in lines) {
|
|
final key = line.keys.first;
|
|
final value = line.values.first;
|
|
if (line.values.contains('UNITED STATES OF')) {
|
|
final title = line;
|
|
extractedData['title'] = title;
|
|
}
|
|
if (line.values.contains('PASSPORT CARD')) {
|
|
final passport = line;
|
|
extractedData['passport'] = passport;
|
|
}
|
|
if (key == "7_Surname") {
|
|
final nextItem = lines[lines.indexOf(line) + 1];
|
|
extractedData['surname'] = nextItem.values.first;
|
|
}
|
|
if (key == "6_Nationality") {
|
|
var nationality = value.split('\n')[1];
|
|
extractedData['nationality'] = nationality;
|
|
}
|
|
if (key.contains('CARD')) {
|
|
var passportCard = value;
|
|
extractedData['passportCard'] = passportCard;
|
|
}
|
|
if (key.contains("9_Given")) {
|
|
var givenNames = value.split('\n')[1];
|
|
extractedData['givenNames'] = givenNames;
|
|
}
|
|
if (key.contains("13_Date of Birth")) {
|
|
final parts = value.split('\n');
|
|
if (parts.length > 1) {
|
|
var dateOfBirth = parts[1];
|
|
extractedData['dateOfBirth'] = dateOfBirth;
|
|
|
|
var sex = parts[0].split(' ')[1];
|
|
extractedData['sex'] = sex;
|
|
}
|
|
}
|
|
|
|
// }
|
|
}
|
|
|
|
// Convert the list of lines to a JSON string
|
|
jsonOutput = jsonEncode(extractedData);
|
|
decode = jsonDecode(jsonOutput!);
|
|
|
|
update();
|
|
print('jsonOutput------------------------------');
|
|
print(decode);
|
|
// print(jsonEncode(lines));
|
|
}
|
|
}
|
|
|
|
class PassportDataExtractor extends GetxController {
|
|
@override
|
|
void onInit() {
|
|
extractPassportData();
|
|
super.onInit();
|
|
}
|
|
|
|
final ImagePicker _imagePicker = ImagePicker();
|
|
late final XFile? image;
|
|
final TextRecognizer _textRecognizer = TextRecognizer();
|
|
|
|
Future<Map<String, dynamic>> extractPassportData() async {
|
|
image = await _imagePicker.pickImage(source: ImageSource.gallery);
|
|
update();
|
|
if (image == null) {
|
|
throw Exception('No image picked');
|
|
}
|
|
|
|
final InputImage inputImage = InputImage.fromFile(File(image!.path));
|
|
final RecognizedText recognisedText =
|
|
await _textRecognizer.processImage(inputImage);
|
|
|
|
final Map<String, dynamic> extractedData = {};
|
|
final List<Map<String, dynamic>> extractedTextWithCoordinates = [];
|
|
|
|
for (TextBlock block in recognisedText.blocks) {
|
|
for (TextLine line in block.lines) {
|
|
final String lineText = line.text;
|
|
final Rect lineBoundingBox = line.boundingBox!;
|
|
|
|
extractedTextWithCoordinates.add({
|
|
'text': lineText,
|
|
'boundingBox': {
|
|
'left': lineBoundingBox.left,
|
|
'top': lineBoundingBox.top,
|
|
'width': lineBoundingBox.width,
|
|
'height': lineBoundingBox.height,
|
|
},
|
|
});
|
|
|
|
// if (lineText.contains('Passport Number')) {
|
|
// final String passportNumber =
|
|
// lineText.split('Passport Number')[1].trim();
|
|
// extractedData['passportNumber'] = passportNumber;
|
|
// }
|
|
// if (lineText.contains('Given Names')) {
|
|
// final String givenNames = lineText.split('Given Names')[1].trim();
|
|
// extractedData['givenNames'] = givenNames;
|
|
// }
|
|
// if (lineText.contains('Surname')) {
|
|
// final String surname = lineText.split('Surname')[1].trim();
|
|
// extractedData['surname'] = surname;
|
|
// }
|
|
// if (lineText.contains('Nationality')) {
|
|
// final String nationality = lineText.split('Nationality')[1].trim();
|
|
// extractedData['nationality'] = nationality;
|
|
// }
|
|
// if (lineText.contains('Date of Birth')) {
|
|
// final String dob = lineText.split('Date of Birth')[1].trim();
|
|
// extractedData['dateOfBirth'] = dob;
|
|
// }
|
|
// Add more field extraction conditions as needed
|
|
}
|
|
}
|
|
|
|
extractedData['extractedTextWithCoordinates'] =
|
|
extractedTextWithCoordinates;
|
|
print(jsonEncode(extractedData));
|
|
return extractedData;
|
|
}
|
|
}
|
|
|
|
class PassportDataController extends GetxController {
|
|
PassportDataExtractor passportDataExtractor = PassportDataExtractor();
|
|
List<Map<String, dynamic>> extractedTextWithCoordinates = [];
|
|
|
|
Future<void> extractDataAndDrawBoundingBoxes() async {
|
|
try {
|
|
Map<String, dynamic> extractedData =
|
|
await passportDataExtractor.extractPassportData();
|
|
extractedTextWithCoordinates =
|
|
extractedData['extractedTextWithCoordinates'];
|
|
update(); // Notify GetX that the state has changed
|
|
print(extractedTextWithCoordinates);
|
|
} catch (e) {
|
|
print('Passport data extraction failed: $e');
|
|
}
|
|
}
|
|
}
|
|
|
|
class BoundingBoxPainter extends CustomPainter {
|
|
final List<Map<String, dynamic>> boundingBoxes;
|
|
|
|
BoundingBoxPainter(this.boundingBoxes);
|
|
|
|
@override
|
|
void paint(Canvas canvas, Size size) {
|
|
final Paint paint = Paint()
|
|
..color = Colors.red
|
|
..style = PaintingStyle.stroke
|
|
..strokeWidth = 2.0;
|
|
|
|
for (Map<String, dynamic> boundingBox in boundingBoxes) {
|
|
double left = boundingBox['left'];
|
|
double top = boundingBox['top'];
|
|
double width = boundingBox['width'];
|
|
double height = boundingBox['height'];
|
|
|
|
Rect rect = Rect.fromLTWH(left, top, width, height);
|
|
canvas.drawRect(rect, paint);
|
|
}
|
|
}
|
|
|
|
@override
|
|
bool shouldRepaint(covariant CustomPainter oldDelegate) {
|
|
return false;
|
|
}
|
|
}
|