Flutter光学字符识别插件flutter_tesseract_ocr的使用
Flutter光学字符识别插件flutter_tesseract_ocr的使用
Tesseract OCR 4.0 for flutter 是一个基于 Tesseract OCR 4 的Flutter插件,它在Android上使用 Tesseract4Android,在iOS上使用 SwiftyTesseract。这个插件可以帮助你在Flutter应用中实现光学字符识别(OCR)功能。
安装
添加依赖
在pubspec.yaml
文件中添加flutter_tesseract_ocr
依赖:
dev_dependencies:
...
flutter_tesseract_ocr:
Web环境
对于Web项目,在./web/index.html
中引入Tesseract.js:
<body>
<script src='https://unpkg.com/tesseract.js@v4.0.2/dist/tesseract.min.js'></script>
<script>
async function _extractText(imagePath, mapData){
var worker = await Tesseract.createWorker();
await worker.load();
await worker.loadLanguage(mapData.language)
await worker.initialize(mapData.language)
await worker.setParameters(mapData.args)
var rtn = await worker.recognize(imagePath, {}, worker.id);
await worker.terminate();
if(mapData.args["tessjs_create_hocr"]){
return rtn.data.hocr;
}
return rtn.data.text;
}
</script>
...
..
.
</body>
配置训练数据
为了使OCR插件能够识别特定语言的文字,你需要为项目添加相应的训练数据和配置文件。
- 在assets目录下创建
tessdata
文件夹,并将需要的语言包(如eng.traineddata
等)放入其中。 - 在assets目录下创建
tessdata_config.json
文件,内容如下:{ "files": [ "eng.traineddata", "<other_language>.traineddata" ] }
- 确保在
pubspec.yaml
中正确配置了资源路径:flutter: assets: - assets/tessdata/ - assets/tessdata_config.json
对于iOS平台,如果遇到初始化失败的问题,可以尝试将tessdata
文件夹从assets拖放到Xcode中的Runner文件夹,并选择“Create folder references”。
使用示例
下面是一个完整的Flutter应用示例,展示了如何使用flutter_tesseract_ocr
进行OCR操作。此示例允许用户通过图像选择器选择图片或输入图片URL来执行OCR,并支持多语言识别。
import 'dart:async';
import 'dart:typed_data';
import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart';
import 'package:path_provider/path_provider.dart';
import 'package:flutter_tesseract_ocr/flutter_tesseract_ocr.dart';
import 'dart:io';
import 'package:flutter/foundation.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Tesseract Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Tesseract Demo'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key? key, required this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
String _ocrText = '';
Map<String, String> tessimgs = {
"kor": "https://raw.githubusercontent.com/khjde1207/tesseract_ocr/master/example/assets/test1.png",
"en": "https://tesseract.projectnaptha.com/img/eng_bw.png",
"ch_sim": "https://tesseract.projectnaptha.com/img/chi_sim.png",
"ru": "https://tesseract.projectnaptha.com/img/rus.png",
};
var LangList = ["kor", "eng", "deu", "chi_sim"];
var selectList = ["eng"];
String path = "";
bool bload = false;
Future<void> writeToFile(ByteData data, String path) async {
final buffer = data.buffer;
return File(path).writeAsBytes(
buffer.asUint8List(data.offsetInBytes, data.lengthInBytes));
}
void runFilePicker() async {
final pickedFile = await ImagePicker().pickImage(source: ImageSource.gallery);
if (pickedFile != null) {
_ocr(pickedFile.path);
}
}
void _ocr(String url) async {
if (selectList.isEmpty) {
print("Please select language");
return;
}
path = url;
if (!kIsWeb && (url.startsWith("http://") || url.startsWith("https://"))) {
Directory tempDir = await getTemporaryDirectory();
HttpClient httpClient = HttpClient();
HttpClientRequest request = await httpClient.getUrl(Uri.parse(url));
HttpClientResponse response = await request.close();
Uint8List bytes = await consolidateHttpClientResponseBytes(response);
String dir = tempDir.path;
File file = File('$dir/test.jpg');
await file.writeAsBytes(bytes);
url = file.path;
}
var langs = selectList.join("+");
bload = true;
setState(() {});
_ocrText = await FlutterTesseractOcr.extractText(url, language: langs, args: {
"preserve_interword_spaces": "1",
});
bload = false;
setState(() {});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Stack(
children: [
Padding(
padding: EdgeInsets.all(10),
child: Column(
children: [
Row(
children: [
ElevatedButton(
onPressed: () {
showDialog(
context: context,
builder: (BuildContext context) {
return SimpleDialog(
title: const Text('Select Url'),
children: tessimgs.entries.map((entry) {
return SimpleDialogOption(
onPressed: () {
TextEditingController().text = entry.value;
setState(() {});
Navigator.pop(context);
},
child: Row(
children: [
Text(entry.key),
Text(" : "),
Flexible(child: Text(entry.value)),
],
));
}).toList(),
);
});
},
child: Text("urls")),
Expanded(
child: TextField(
decoration: InputDecoration(
border: OutlineInputBorder(),
labelText: 'input image url',
),
controller: TextEditingController(),
),
),
ElevatedButton(
onPressed: () {
_ocr(TextEditingController().text);
},
child: Text("Run")),
],
),
Row(
children: LangList.map((e) {
return Row(children: [
Checkbox(
value: selectList.contains(e),
onChanged: (v) async {
if (!kIsWeb) {
Directory dir = Directory(await FlutterTesseractOcr.getTessdataPath());
if (!dir.existsSync()) {
dir.createSync();
}
bool isInstalled = dir.listSync().any((element) => element.path.endsWith('$e.traineddata'));
if (!isInstalled) {
HttpClient httpClient = HttpClient();
HttpClientRequest request = await httpClient.getUrl(Uri.parse('https://github.com/tesseract-ocr/tessdata/raw/main/${e}.traineddata'));
HttpClientResponse response = await request.close();
Uint8List bytes = await consolidateHttpClientResponseBytes(response);
String dir = await FlutterTesseractOcr.getTessdataPath();
File file = File('$dir/${e}.traineddata');
await file.writeAsBytes(bytes);
}
}
if (selectList.contains(e)) {
selectList.remove(e);
} else {
selectList.add(e);
}
setState(() {});
}),
Text(e)
]);
}).toList(),
),
Expanded(
child: ListView(
children: [
path.isEmpty
? Container()
: path.startsWith("http")
? Image.network(path)
: Image.file(File(path)),
bload
? CircularProgressIndicator()
: Text('$_ocrText'),
],
))
],
),
),
],
),
floatingActionButton: kIsWeb
? Container()
: FloatingActionButton(
onPressed: () {
runFilePicker();
},
tooltip: 'OCR',
child: Icon(Icons.add),
),
);
}
}
请注意,上述代码片段中的一些逻辑已经被简化以提高可读性。例如,TextEditingController()
应替换为实际的控制器实例,以便正确处理用户输入。此外,对于动态加载语言包的部分,确保网络请求和文件写入操作都在异步上下文中执行,以避免阻塞主线程。
更多关于Flutter光学字符识别插件flutter_tesseract_ocr的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter光学字符识别插件flutter_tesseract_ocr的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,以下是一个关于如何在Flutter项目中使用flutter_tesseract_ocr
插件进行光学字符识别(OCR)的示例代码。这个插件允许你从图像中提取文本。
首先,确保你的Flutter项目中已经添加了flutter_tesseract_ocr
依赖。在你的pubspec.yaml
文件中添加以下依赖:
dependencies:
flutter:
sdk: flutter
flutter_tesseract_ocr: ^0.3.2 # 请检查最新版本号
然后运行flutter pub get
来安装依赖。
接下来,你需要确保在Android和iOS项目中配置了必要的权限和设置。
Android配置
在android/app/src/main/AndroidManifest.xml
中添加权限:
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
iOS配置
在ios/Runner/Info.plist
中添加权限:
<key>NSPhotoLibraryUsageDescription</key>
<string>App needs access to photo library to perform OCR</string>
<key>NSCameraUsageDescription</key>
<string>App needs access to camera to capture images for OCR</string>
Flutter代码示例
以下是一个完整的Flutter应用示例,展示如何使用flutter_tesseract_ocr
插件从图像中提取文本:
import 'package:flutter/material.dart';
import 'package:flutter_tesseract_ocr/flutter_tesseract_ocr.dart';
import 'package:image_picker/image_picker.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: OcrScreen(),
);
}
}
class OcrScreen extends StatefulWidget {
@override
_OcrScreenState createState() => _OcrScreenState();
}
class _OcrScreenState extends State<OcrScreen> {
final ImagePicker _picker = ImagePicker();
File? _imageFile;
String _ocrResult = '';
Future<void> _pickImage() async {
final pickedFile = await _picker.pickImage(source: ImageSource.camera);
if (pickedFile != null) {
setState(() {
_imageFile = File(pickedFile.path);
});
_performOCR();
}
}
Future<void> _performOCR() async {
if (_imageFile != null) {
try {
String result = await TesseractOcr.recognizeText(
image: _imageFile!,
language: 'eng' // 你可以指定其他语言代码,比如 'chi_sim' 表示简体中文
);
setState(() {
_ocrResult = result;
});
} catch (e) {
print('OCR error: $e');
}
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Flutter Tesseract OCR Example'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
_imageFile == null
? Text('No image selected.')
: Image.file(_imageFile!),
SizedBox(height: 20),
Text('OCR Result:'),
Text(_ocrResult, style: TextStyle(fontSize: 18)),
SizedBox(height: 20),
ElevatedButton(
onPressed: _pickImage,
child: Text('Pick Image'),
),
],
),
),
);
}
}
注意事项
- 权限处理:在实际应用中,你需要处理权限请求,特别是在Android 6.0及以上版本和iOS 10.0及以上版本中。
- 错误处理:示例代码中的错误处理非常基础,在实际应用中你可能需要更详细的错误处理逻辑。
- 语言支持:
flutter_tesseract_ocr
插件支持多种语言,你可以根据需要调整language
参数。
这个示例应该能帮助你开始在Flutter项目中使用flutter_tesseract_ocr
插件进行光学字符识别。如果你遇到任何问题,请查阅该插件的官方文档或相关资源。