-
Notifications
You must be signed in to change notification settings - Fork 11
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #18 from LeBzul/feature/refacto
Gestion de l'ocr sans widget
- Loading branch information
Showing
10 changed files
with
293 additions
and
162 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,231 @@ | ||
import 'dart:io'; | ||
import 'dart:ui' as ui show Image; | ||
|
||
import 'package:file_picker/file_picker.dart'; | ||
import 'package:flutter/material.dart'; | ||
import 'package:google_mlkit_text_recognition/google_mlkit_text_recognition.dart'; | ||
import 'package:image/image.dart' as img; | ||
import 'package:path/path.dart' as path; | ||
import 'package:pdf_render/pdf_render.dart'; | ||
|
||
import '../../ocr_scan_text.dart'; | ||
import '../helper/pdf_helper.dart'; | ||
import '../render/scan_renderer.dart'; | ||
|
||
enum Mode { | ||
camera, | ||
static, | ||
} | ||
|
||
class OcrScanService { | ||
static Mode _actualMode = Mode.camera; | ||
static Mode get actualMode => _actualMode; | ||
List<ScanModule> scanModules; | ||
|
||
/// MLKit text detection object | ||
final TextRecognizer textRecognizer = TextRecognizer(); | ||
|
||
OcrScanService( | ||
this.scanModules, | ||
); | ||
|
||
Future<OcrTextRecognizerResult?> startScanWithPhoto() async { | ||
return _startStaticScanProcess( | ||
await FilePicker.platform.pickFiles( | ||
type: FileType.image, | ||
allowCompression: false, | ||
allowMultiple: false, | ||
), | ||
); | ||
} | ||
|
||
Future<OcrTextRecognizerResult?> startScanWithOpenFile() async { | ||
return _startStaticScanProcess( | ||
await FilePicker.platform.pickFiles( | ||
type: FileType.custom, | ||
allowCompression: false, | ||
allowMultiple: false, | ||
allowedExtensions: [ | ||
'png', | ||
'jpg', | ||
'pdf', | ||
], | ||
), | ||
); | ||
} | ||
|
||
Future<OcrTextRecognizerResult?> _startStaticScanProcess(FilePickerResult? result) async { | ||
if (result == null) { | ||
return null; | ||
} | ||
String? path = result.files.first.path; | ||
if (path == null) { | ||
return null; | ||
} | ||
return await startScanProcess( | ||
File(path), | ||
); | ||
} | ||
|
||
Future<OcrTextRecognizerResult?> startScanProcess( | ||
File file, | ||
) async { | ||
String extension = path.extension(file.path).toLowerCase(); | ||
|
||
assert(extension == '.pdf' || extension == '.png' || extension == '.jpg' || extension == '.jpeg'); | ||
if (extension == '.pdf') { | ||
final PdfDocument document = await PdfDocument.openFile( | ||
file.path, | ||
); | ||
return await _processStaticPDF( | ||
document, | ||
scanModules, | ||
); | ||
} else if (extension == '.png' || extension == '.jpg' || extension == '.jpeg') { | ||
return await _processStaticImage( | ||
file, | ||
scanModules, | ||
); | ||
} | ||
return null; | ||
} | ||
|
||
// Process image from camera stream | ||
Future<OcrTextRecognizerResult?> _processStaticPDF( | ||
PdfDocument pdfDocument, | ||
List<ScanModule> scanModules, | ||
) async { | ||
ImagePDF? imagePDF = await PDFHelper.convertToPDFImage(pdfDocument); | ||
if (imagePDF == null) { | ||
return null; | ||
} | ||
|
||
ui.Image background = await decodeImageFromList(await imagePDF.file.readAsBytes()); | ||
|
||
return await processImage( | ||
InputImage.fromFilePath(imagePDF.file.path), | ||
Size( | ||
background.width.toDouble(), | ||
background.height.toDouble(), | ||
), | ||
background, | ||
Mode.static, | ||
scanModules, | ||
null, | ||
); | ||
} | ||
|
||
Future<OcrTextRecognizerResult?> _processStaticImage( | ||
File file, | ||
List<ScanModule> scanModules, | ||
) async { | ||
final cmd = img.Command()..decodeImageFile(file.path); | ||
await cmd.executeThread(); | ||
img.Image? image = cmd.outputImage; | ||
if (image == null) { | ||
return null; | ||
} | ||
ui.Image background = await decodeImageFromList(await file.readAsBytes()); | ||
|
||
return await processImage( | ||
InputImage.fromFilePath(file.path), | ||
Size( | ||
image.width.toDouble(), | ||
image.height.toDouble(), | ||
), | ||
background, | ||
Mode.static, | ||
scanModules, | ||
null, | ||
); | ||
} | ||
|
||
/// Launch the search for results from the image for all the modules started | ||
Future<OcrTextRecognizerResult?> processImage( | ||
InputImage inputImage, | ||
Size imageSize, | ||
ui.Image? background, | ||
Mode mode, | ||
List<ScanModule> scanModules, | ||
TextRecognizer? recognizer, | ||
) async { | ||
_actualMode = mode; | ||
TextRecognizer textRecognizer = recognizer ?? TextRecognizer(); | ||
|
||
/// Ask MLKit to return the list of TextBlocks in the image | ||
final recognizedText = await textRecognizer.processImage(inputImage); | ||
|
||
/// create a global String corresponding to the texts found by MLKIt | ||
String scannedText = ''; | ||
List<TextElement> textBlocks = []; | ||
for (final textBlock in recognizedText.blocks) { | ||
for (final element in textBlock.lines) { | ||
for (final textBlock in element.elements) { | ||
textBlocks.add(textBlock); | ||
scannedText += " ${textBlock.text}"; | ||
} | ||
} | ||
} | ||
|
||
/// Start the text search for each module | ||
Map<ScanModule, List<MatchedCounter>> mapModule = <ScanModule, List<MatchedCounter>>{}; | ||
for (var scanModule in scanModules) { | ||
if (!scanModule.started) { | ||
continue; | ||
} | ||
|
||
/// Generate the results of each module | ||
List<MatchedCounter> scanLines = await scanModule.generateResult( | ||
recognizedText.blocks, | ||
scannedText, | ||
imageSize, | ||
); | ||
|
||
mapModule.putIfAbsent( | ||
scanModule, | ||
() => scanLines, | ||
); | ||
} | ||
|
||
/// Create a ScanRenderer to display the visual rendering of the results found | ||
var painter = ScanRenderer( | ||
mapScanModules: mapModule, | ||
imageRotation: inputImage.metadata?.rotation ?? InputImageRotation.rotation90deg, | ||
imageSize: imageSize, | ||
background: background, | ||
); | ||
|
||
Map<ScanModule, List<ScanResult>> mapResult = <ScanModule, List<ScanResult>>{}; | ||
mapModule.forEach((key, matchCounterList) { | ||
List<ScanResult> list = matchCounterList | ||
.where( | ||
(matchCounter) => matchCounter.validated == true, | ||
) | ||
.map<ScanResult>((e) => e.scanResult) | ||
.toList(); | ||
|
||
if (list.isNotEmpty) { | ||
mapResult.putIfAbsent(key, () => list); | ||
} | ||
}); | ||
|
||
await textRecognizer.close(); | ||
if (mapResult.isEmpty) { | ||
return null; | ||
} | ||
|
||
return OcrTextRecognizerResult( | ||
CustomPaint( | ||
painter: painter, | ||
), | ||
mapResult, | ||
); | ||
} | ||
} | ||
|
||
class OcrTextRecognizerResult { | ||
CustomPaint customPaint; | ||
Map<ScanModule, List<ScanResult>> mapResult; | ||
|
||
OcrTextRecognizerResult(this.customPaint, this.mapResult); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.