0
0

GoでOCR試してみた

Posted at

ひょんなことからOCRについて気になったので簡易的なものを実装してみた。
オープンソースのtesseractというOCRエンジンがあり、今回はgo向けのラッパーgosseractを利用させてもらいました。
otiai10/gosseract

構成

  • go
  • echo
  • react
  • typescript
  • docker
  • tesseract
  • gosseract

Go

main.go
package main

import (
	"fmt"
	"io"
	"net/http"
	"os"
	"strings"

	"github.com/labstack/echo"
	"github.com/labstack/echo/middleware"
	"github.com/otiai10/gosseract/v2"
)

func main() {
	e := echo.New()
	e.Use(middleware.CORSWithConfig(middleware.CORSConfig{
		AllowOrigins:     []string{"http://localhost:3000"},
		AllowHeaders:     []string{echo.HeaderOrigin, echo.HeaderContentType, echo.HeaderAccept, echo.HeaderAccessControlAllowHeaders, echo.HeaderXCSRFToken},
		AllowMethods:     []string{"GET", "POST", "PUT", "DELETE"},
		AllowCredentials: true,
	}))
	e.POST("/", analysisMedia)
	e.POST("/movie", analysisMovie)
	e.Logger.Fatal(e.Start(":8080"))
}

func analysisMedia(c echo.Context) error {
	file, err := c.FormFile("file")
	if err != nil {
		return nil
	}
	src, err := file.Open()
	if err != nil {
		return nil
	}
	defer src.Close()

	fileModel := strings.Split(file.Filename, ".")
	fileName := fileModel[0]
	extension := fileModel[1]

	f, err := os.Create(fmt.Sprintf("%s_out.%s", fileName, extension))
	if err != nil {
		panic(err)
	}

	if _, err = io.Copy(f, src); err != nil {
		return err
	}
	defer os.Remove(f.Name())

	client := gosseract.NewClient()
	defer client.Close()
	client.SetLanguage("eng", "jpn")
	client.SetImage(f.Name())
	text, _ := client.Text()

	return c.String(http.StatusOK, text)
}

結果

以下の画像のような結果となった。
スクリーンショット 2024-06-07 15.25.10.png

スキャンされたデータはそこそこの精度で解析できた。
スマホで撮影したレシート画像では、お話にならないデータが返却された。

感想

結論、実験程度であればかなり良いのではと思った。
出力される結果を使いたいなら整形が必要でchatGPTなどのAIで整形して使うのが一連の流れになりそう。
他のocrエンジンとしては、Google Cloud Vision APIやAzure Computer Visionなどがあり、調べたところGoogle Cloud Vision APIが一番精度良さそう。

おまけ

chatGPT-4oで画像アップロードできるようになり、画像を解析してJSONを出力できるようになった。
先ほどの画像と同じものをアップロードしJSONで出力をお願いすると、以下の内容が返っていきた。

chatGPT4o
{
  "store": {
    "name": "FamilyMart",
    "branch": "一の橋店",
    "address": "東京都港区麻布十番1-2-10",
    "phone": "03-3560-3895"
  },
  "receipt": {
    "date": "2016年9月29日",
    "day_of_week": "木",
    "time": "12:45",
    "items": [
      {
        "name": "十六茶",
        "price": 151,
        "discount": -22
      },
      {
        "name": "吊るしベーコン",
        "price": 198,
        "discount": 0
      },
      {
        "name": "茶碗蒸し",
        "price": 133,
        "discount": 0
      }
    ],
    "totals": {
      "subtotal": 460,
      "discount": -22,
      "total": 460,
      "tax": 34
    },
    "payment": {
      "given": 510,
      "change": 50
    }
  },
  "transaction": {
    "register_id": "2-4986",
    "clerk_id": "No. 022"
  }
}

完璧ですね。。。

APIでこの実装ができるか試していないが、選択の一つになり得るかもしれない。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0