/GoodScanner

Primary LanguageC++OtherNOASSERTION

GoodScanner

Text Recognition Details

  • Text Recognition 동작 과정

    • StillImageActivity.kt
      • onGlobalLayout(), onActivityResult()에서 호출되는 **tryReloadAndDetectInImage()**로부터 시작
      • tryReloadAndDetectInImage()
        • imageUri에 저장된 image의 주소를 이용하여 BitmapUtils.getBitmapFromContentUri()로 image의 Bitmap을 추출한다
        • Bitmap의 size를 옵션에 따라 맞추고 Text Recognition용 AI model에서 사용하는 input size에 맞게 resize하여 resizedBitmap에 저장.
        • imageProcessor!!.processBitmap(resizedBitmap, graphicOverlay)를 이용해서 resizedBitmap에 대한 결과를 graphicOverlay에 나타낸다.
          • imageProcessor = TextRecognitionProcessor(this, KoreanTextRecognizerOptions.Builder().build())
          • processBitmap()은 VisionProcessorBase.kt에 존재함
    • VisionProcessorBase.kt
      • processBitmap()
        • requestDetectInImage() 호출
      • requestDetectInImage()
        • tryReloadAndDetectInImage()의 resizedBitmap을 input(image: InputImage)으로 사용
        • setUpListener호출
    • TextRecognitionProcessor.kt
      • detectInImage()
        • VisionProcessorBase.kt는 abstract fun이고 실제 구현은 TextRecognitionProcessor.kt에 존재함
        • textRecognizer.process(image) 호출
        • textRecognizer: TextRecognizer = TextRecognition.getClient(textRecognizerOptions)
      • process()
        • 실제 AI model을 돌린다
        • 코드는 아마 JNI를 이용하여 Native code를 돌리는 것일 것이기 때문에 볼 수는 없고 우리는 OnSuccessListner인 onSuccess()와 OnFailureListner인 onFailure()만 살펴보면된다
      • onSuccess()
        • graphicOverlay에 TextGraphic(graphicOverlay, text, shouldGroupRecognizedTextInBlocks)로 인식한 text정보 추가
        • text 정보들이 모두 add 되면 TextGraphic.kt의 draw()를 이용하여 화면에 출력한다
  • Text Recognition 결과가 들어있는 변수들

    • VisionProcessorBase.kt
    • TextRecognitionProcessor.kt
      • onSuccess(text: Text, graphicOverlay: com.good.scanner.GraphicOverlay)
    • TextGraphic.kt
      • private val text: Text
      • 여기서 Text의 class 형태를 대충 볼 수 있다.
  • Text class 정보

    • text.text: 확인필요

    • text.textBlocks에 실제 detection된 여러개의 textblock들이 존재하고 이를 for문으로 받아서 정보를 추출

      for (textBlock in text.textBlocks) { // Renders the text at the bottom of the box.
        Log.d(TAG, "TextBlock text is: " + textBlock.text)
        Log.d(TAG, "TextBlock boundingbox is: " + textBlock.boundingBox)
        Log.d(TAG, "TextBlock cornerpoint is: " + Arrays.toString(textBlock.cornerPoints))
    • 각 textblock안에는 다시 lines가 존재하여 for문으로 받아서 정보를 추출한다

      for (line in textBlock.lines) {
        Log.d(TAG, "Line text is: " + line.text)
        Log.d(TAG, "Line boundingbox is: " + line.boundingBox)
        Log.d(TAG, "Line cornerpoint is: " + Arrays.toString(line.cornerPoints))
    • 각 line안에는 다시 elements가 존재하여 for문으로 받아서 정보를 추출한다

      for (element in line.elements) {
        Log.d(TAG, "Element text is: " + element.text)
        Log.d(TAG, "Element boundingbox is: " + element.boundingBox)
        Log.d(TAG, "Element cornerpoint is: " + Arrays.toString(element.cornerPoints))
        Log.d(TAG, "Element language is: " + element.recognizedLanguage)

개발 방향

  1. StillImageActivity.kt에서 imageProcessor.!!processBitmap()으로 Text Recognition을 수행하기 전에 bitmap을 가지고 OpenCV의 기능을 이용해서 bitmap(image)에서 문서를 찾고 정면화한 bitmap을 만들어내야합니다

    • 이 bitmap을 이용하여 pdf 파일을 만들면 스캐너 완성!

    • 이 bitmap을 processBitmap의 parameter로 넘겨주면 text recognition까지 가능!

  2. Text Recognition 결과를 예쁘게 visualization합니다

    • 시작은 그냥 일반 web에서 textblock처럼 visualization

    • Best는 docx 파일처럼 layout까지 따라서 visualization(?)

      • Text의 size를 bounding box의 크기로 유추해서 layout을 비슷하게 맞춰주는 기능 구현
      • bounding box에 해당되지 않는 부분은 그대로 두어 image와 표 같은 것들은 제 layout 위치에 두도록 한다

      image