機械学習基礎理論独習

誤りがあればご指摘いただけると幸いです。数式が整うまで少し時間かかります。リンクフリーです。

勉強ログです。リンクフリーです
目次へ戻る

【VS2022】Tesseract の導入方法【C++】

Tesseract のインストール方法

1. Tesseract の github のページ からダウンロードする。

2. tesseract-ocr-w64-setup-5.5.0.20241111.exe を起動する。

3. Language は English を選択する。

4. Addtional script data を開いて Japanese を含むチェックを True にする。Addtional language data も同様。

それに加えて Addtional language data > Math equation module にもチェックした。

5. Do not create shortcuts にチェックを入れる。

6. インストールが完了したら環境変数の Path に C:\Program Files\Tesseract-OCR を追加する。

Tesseract の動作確認

Tesseract がインストールされたか cmd から確認します。
tesseract --vesion と打って、以下のようになればインストールされています。

Tesseract の .dll はインストールされましたが、ヘッダーファイルや .lib ファイルがまだインストールされていない為
以下で vcpkg を導入して開発向けの Teserract をインストールします。

vcpkg を導入する

cmd で以下を実行する。私は cドライブに移動してからコマンドを実行しました。

cd c:\
git clone https://github.com/microsoft/vcpkg
cd vcpkg
.\bootstrap-vcpkg.bat

これで c:\vcpkg\vcpkg.exe ができる

vcpkg を使って Tesseract をインストール

以下のコマンドで実行できます。

vcpkg install tesseract:x64-windows

スナップショットを取っていないが、私は"vcpkg を使って Tesseract をインストール"を失敗した。
vcpkg を git pull して再度インストールしたら成功した。成功すると緑色の文字で成功したという意のメッセージが表示されたと記憶している。

インストールが完了したら、環境変数の Path に C:\vcpkg\installed\x64-windows\bin を追加してください。

MFC Application(Dialog Based) による Sample Program

1. SampleTesseract という名前で MFC の Dailog Based を作成する。
2. 後はいつも通りです。
ヘッダーの設定、.libフォルダの指定, lib ファイルの指定(tesseract55.lib, leptonica-1.85.0.lib)をしてください。
3. .h, .cpp にのコードを載せておきます。

// SampleTesseractDlg.h : header file
//

#pragma once

#include <tesseract/baseapi.h>
#include <leptonica/allheaders.h>

// CSampleTesseractDlg dialog
class CSampleTesseractDlg : public CDialogEx
{
// Construction
public:
	CSampleTesseractDlg(CWnd* pParent = nullptr);	// standard constructor

// Dialog Data
#ifdef AFX_DESIGN_TIME
	enum { IDD = IDD_SAMPLETESSERACT_DIALOG };
#endif

	protected:
	virtual void DoDataExchange(CDataExchange* pDX);	// DDX/DDV support


// Implementation
protected:
	HICON m_hIcon;

	// Generated message map functions
	virtual BOOL OnInitDialog();
	afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
	afx_msg void OnPaint();
	afx_msg HCURSOR OnQueryDragIcon();
	DECLARE_MESSAGE_MAP()
};
BOOL CSampleTesseractDlg::OnInitDialog()
{
	CDialogEx::OnInitDialog();

	// Add "About..." menu item to system menu.

	// IDM_ABOUTBOX must be in the system command range.
	ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
	ASSERT(IDM_ABOUTBOX < 0xF000);

	CMenu* pSysMenu = GetSystemMenu(FALSE);
	if (pSysMenu != nullptr)
	{
		BOOL bNameValid;
		CString strAboutMenu;
		bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
		ASSERT(bNameValid);
		if (!strAboutMenu.IsEmpty())
		{
			pSysMenu->AppendMenu(MF_SEPARATOR);
			pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
		}
	}

	// Set the icon for this dialog.  The framework does this automatically
	//  when the application's main window is not a dialog
	SetIcon(m_hIcon, TRUE);			// Set big icon
	SetIcon(m_hIcon, FALSE);		// Set small icon

	// TODO: Add extra initialization here
	// OCR対象画像のパス
	const char* imagePath = "sample.png";

	// Leptonicaで画像を読み込む
	Pix* image = pixRead(imagePath);
	if (!image) {
		AfxMessageBox(_T("画像の読み込みに失敗しました"));
		return FALSE;
	}

	// Tesseract OCRエンジンの初期化(英語)
	//tesseract::TessBaseAPI ocr;
	tesseract::TessBaseAPI* api = new tesseract::TessBaseAPI();
	if (api->Init("C:\\Program Files\\Tesseract-OCR\\tessdata", "eng")) {
		AfxMessageBox(_T("Failed to initialize Tesseract."));
		pixDestroy(&image);
		return FALSE;
	}

	// OCR対象画像を設定
	api->SetImage(image);
	api->Recognize(0);
	tesseract::ResultIterator* ri = api->GetIterator();
	tesseract::PageIteratorLevel level = tesseract::RIL_SYMBOL;
	if (ri != 0) {
		do {
			const char* word = ri->GetUTF8Text(level);
			float conf = ri->Confidence(level);
			int x1, y1, x2, y2;
			ri->BoundingBox(level, &x1, &y1, &x2, &y2);
			CStringW wstrWord(CA2W(word, CP_UTF8)); // UTF-8 → UTF-16(Unicode)
			TRACE(_T("word: '%s';  \tconf: %.2f; BoundingBox: %d,%d,%d,%d;\n"),
				wstrWord.GetString(), conf, x1, y1, x2, y2);
		} while (ri->Next(level));
	}

	//// テキスト抽出
	//char* outText = api->GetUTF8Text(level); // Tesseract が返す char*	

	// 後処理
	api->End();
	//delete api; // <- ここですら落ちる
	//delete[] outText; // ✅ Tesseract が malloc した領域を解放 <- これでエラーが発生する api->End() で開放するので 
	pixDestroy(&image);

	return TRUE;  // return TRUE  unless you set the focus to a control
}

注意
下から2,3行目は敢えてコメントアウトしています。そうしないと自分の環境では落ちたので。
Googleで検索すると delete outText はすべきでないと言われ、Copilot は削除すべきと言ってきます・とりあえず落ちないようにしています。
Tesseract のサンプルコードでも delete
outText;していますが、落ちます。delete して落ちる原因がわかる人は是非コメントで教えてください。
私の場合、api はそもそも new しないので delete しないし、outText が仮にメモリリークしたとしても高々文字列なので、アプリの開発に関しては影響ないと考え、本件に関してこれ以上調べるのをやめました。

実際に動かした例


上の画像を上記のコードで動かすと、以下のようなログが出力されます。

私のコードは一文字の場所を調べるコードですが、まとめて文字列を取得することもできます。
Tesseract のサンプルコードが参考になります。

目次へ戻る