영주머니의 개발주머니

[Flutter] google_ml_kit로 Text Recognition 해보기 본문

Flutter/Flutter 위젯

[Flutter] google_ml_kit로 Text Recognition 해보기

영주머니 2023. 2. 2. 02:11

google_ml_kit 패키지에는 Text Recognition, Face Detection, Image Labeling 등의 다양한 기능을 지원한다. 그 중 Text Recognition을 사용해보자.

 

google_ml_kit | Flutter Package

A Flutter plugin to use all APIs from Google's standalone ML Kit for mobile platforms.

pub.dev

 

아래의 예시코드는 직전 포스트의 image_picker 사용 예제에 텍스트 인식 기능을 추가해서 만들었다.

 

[Flutter] image_picker로 카메라 및 갤러리에서 이미지 가져오기

Flutter에서 카메라로 촬영한 사진이나 갤러리의 이미지를 가져오는 것은 image_picker 패키지로 간단히 구현할 수 있다. image_picker | Flutter Package Flutter plugin for selecting images from the Android and iOS image libr

youngjumoney.tistory.com

Text Recognition 사용 예시

예시 코드

void getRecognizedText(XFile image) async {
  // XFile 이미지를 InputImage 이미지로 변환
  final InputImage inputImage = InputImage.fromFilePath(image.path);

  // textRecognizer 초기화, 이때 script에 인식하고자하는 언어를 인자로 넘겨줌
  // ex) 영어는 script: TextRecognitionScript.latin, 한국어는 script: TextRecognitionScript.korean
  final textRecognizer =
      GoogleMlKit.vision.textRecognizer(script: TextRecognitionScript.latin);

  // 이미지의 텍스트 인식해서 recognizedText에 저장
  RecognizedText recognizedText =
      await textRecognizer.processImage(inputImage);

  // Release resources
  await textRecognizer.close();

  // 인식한 텍스트 정보를 scannedText에 저장
  scannedText = "";
  for (TextBlock block in recognizedText.blocks) {
    for (TextLine line in block.lines) {
      scannedText = scannedText + line.text + "\n";
    }
  }

  setState(() {});
}

getRecognizedText() 함수에서 이미지의 텍스트를 인식하는 동작을 수행한다.

참고로 위의 코드에서 텍스트 인식의 결과로 return되는 RecognizedText는 Block > Line > Element의 구조이다. 위 코드에서는 줄 바꿈을 그대로 유지하기 위해 for문을 이용해서 Line 끝에 개행 문자를 추가해서 저장했다.

RecognizedText 타입의 구조, 출처:https://developers.google.com/ml-kit/vision/text-recognition?hl=ko

 

한국어 텍스트 인식 기능을 사용하고자하면 위 코드에서 textRecognizer의 script 값을 변경해준다. 또한 기본적으로는 영어 텍스트 인식만이 지원되기 때문에 다른 언어 텍스트 인식을 사용하고자 하는 경우에는 android > app > build.gradle 파일에 dependencies를 직접 추가해야한다.

dependencies {
    implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
    implementation 'com.google.mlkit:text-recognition-korean:16.0.0-beta5'  //이 줄을 추가
}

중국어, 일본어의 경우도 위와 같은 방법으로 인식할 수 있다. 자세한 정보는 아래의 링크에서 확인할 수 있다.

 

google_mlkit_text_recognition | Flutter Package

A Flutter plugin to use Google's ML Kit Text Recognition to recognize text in any Chinese, Devanagari, Japanese, Korean and Latin character set.

pub.dev

 

전체 코드

import 'dart:io';

import 'package:flutter/material.dart';
import 'package:google_ml_kit/google_ml_kit.dart';
import 'package:image_picker/image_picker.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatefulWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  XFile? _image; //이미지를 담을 변수 선언
  final ImagePicker picker = ImagePicker(); //ImagePicker 초기화
  String scannedText = "";  // textRecognizer로 인식된 텍스트를 담을 String

  //이미지를 가져오는 함수
  Future getImage(ImageSource imageSource) async {
    //pickedFile에 ImagePicker로 가져온 이미지가 담긴다.
    final XFile? pickedFile = await picker.pickImage(source: imageSource);
    if (pickedFile != null) {
      setState(() {
        _image = XFile(pickedFile.path); //가져온 이미지를 _image에 저장
      });
      getRecognizedText(_image!); // 이미지를 가져온 뒤 텍스트 인식 실행
    }
  }

  void getRecognizedText(XFile image) async {
    // XFile 이미지를 InputImage 이미지로 변환
    final InputImage inputImage = InputImage.fromFilePath(image.path);

    // textRecognizer 초기화, 이때 script에 인식하고자하는 언어를 인자로 넘겨줌
    // ex) 영어는 script: TextRecognitionScript.latin, 한국어는 script: TextRecognitionScript.korean
    final textRecognizer =
        GoogleMlKit.vision.textRecognizer(script: TextRecognitionScript.latin);

    // 이미지의 텍스트 인식해서 recognizedText에 저장
    RecognizedText recognizedText =
        await textRecognizer.processImage(inputImage);

    // Release resources
    await textRecognizer.close();

    // 인식한 텍스트 정보를 scannedText에 저장
    scannedText = "";
    for (TextBlock block in recognizedText.blocks) {
      for (TextLine line in block.lines) {
        scannedText = scannedText + line.text + "\n";
      }
    }

    setState(() {});
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: Text("Camera Test")),
        body: Column(
          crossAxisAlignment: CrossAxisAlignment.center,
          children: [
            SizedBox(height: 30, width: double.infinity),
            _buildPhotoArea(),
            _buildRecognizedText(),
            SizedBox(height: 20),
            _buildButton(),
          ],
        ),
      ),
    );
  }

  Widget _buildPhotoArea() {
    return _image != null
        ? Container(
            width: 300,
            height: 300,
            child: Image.file(File(_image!.path)), //가져온 이미지를 화면에 띄워주는 코드
          )
        : Container(
            width: 300,
            height: 300,
            color: Colors.grey,
          );
  }

  Widget _buildRecognizedText() {
    return Text(scannedText); //getRecognizedText()에서 얻은 scannedText 값 출력
  }

  Widget _buildButton() {
    return Row(
      mainAxisAlignment: MainAxisAlignment.center,
      children: [
        ElevatedButton(
          onPressed: () {
            getImage(ImageSource.camera); //getImage 함수를 호출해서 카메라로 찍은 사진 가져오기
          },
          child: Text("카메라"),
        ),
        SizedBox(width: 30),
        ElevatedButton(
          onPressed: () {
            getImage(ImageSource.gallery); //getImage 함수를 호출해서 갤러리에서 사진 가져오기
          },
          child: Text("갤러리"),
        ),
      ],
    );
  }
}

 

직접 사용해본 결과 워드나 한글 문서에 작성된 정자체 글자들은 잘 인식하지만 손글씨 이미지는 인식률이 매우 떨어진다.

Comments