vcpkg+Qt5+tesseract+Visual Studio 2022 でのOCR読取

意外とすんなりできたので記事にします。

今回の目標

 OCR読取をオープンソースライブラリで記述してみる

事前準備

tesseractデータを取得すること

git clone https://github.com/tesseract-ocr/tessdata

サンプルコード

CMakeList.txt

# CMakeList.txt : CMakeSample の CMake プロジェクト。ソースを含めて、次を定義します:
# プロジェクト専用ロジックはこちらです。
#

cmake_minimum_required(VERSION 3.10)

# Vcpkg toolchain file 
set(CMAKE_TOOLCHAIN_FILE "${CMAKE_SOURCE_DIR}/vcpkg/scripts/buildsystems/vcpkg.cmake" CACHE STRING "Vcpkg toolchain file")

# C++標準の設定 
set(CMAKE_CXX_STANDARD 17) 
set(CMAKE_CXX_STANDARD_REQUIRED ON) 

# Qt5パッケージの検索 
find_package(Qt5 COMPONENTS Core Widgets REQUIRED) 
find_package(Tesseract CONFIG REQUIRED)

# ソースファイルの追加 
set(SOURCES 
	CMakeSample.cpp
	CMakeSample.h
)

# ソースをこのプロジェクトの実行可能ファイルに追加します。
add_executable (CMakeSample ${SOURCES})

# Qt5ライブラリのリンク 
target_link_libraries(CMakeSample PRIVATE Qt5::Core Qt5::Widgets Tesseract::libtesseract)

if (CMAKE_VERSION VERSION_GREATER 3.12)
  set_property(TARGET CMakeSample PROPERTY CXX_STANDARD 20)
endif()

# TODO: テストを追加し、必要な場合は、ターゲットをインストールします。

ソースコード

// CMakeSample.cpp : アプリケーションのエントリ ポイントを定義します。
//
//

#include "CMakeSample.h"
#include <QApplication>
#include <QWidget>
#include <QPushButton>
#include <QLabel>
#include <QVBoxLayout>
#include <QFileDialog>
#include <QImage>
#include <QPixmap>
#include <tesseract/baseapi.h>
#include <leptonica/allheaders.h>

#ifdef _WIN32
    #define setenv(var, value, overwrite) _putenv_s(var, value)
#endif

void performOCR(const QString& imagePath, QLabel* resultLabel) {
    tesseract::TessBaseAPI tess;
    if (tess.Init(nullptr, "eng")) {
        resultLabel->setText("Tesseractの初期化に失敗しました");
        return;
    }

    Pix* image = pixRead(imagePath.toStdString().c_str());
    tess.SetImage(image);
    char* outText = tess.GetUTF8Text();

    resultLabel->setText(outText);
    tess.End();
    pixDestroy(&image);
}

int main(int argc, char* argv[]) {
    QApplication app(argc, argv);

    // 環境変数を設定 
#ifdef _WIN32
    std::string currentPath = std::filesystem::current_path().string() + "\\..\\..\\..\\..\\tessdata\\";
#else
    std::string currentPath = std::filesystem::current_path().string() + "/tessdata/";
#endif
    setenv("TESSDATA_PREFIX", currentPath.c_str(), 1);

    QWidget window;
    window.setWindowTitle("OCR Sample");
    window.setFixedSize(400, 300);

    QVBoxLayout* layout = new QVBoxLayout(&window);

    QLabel* imageLabel = new QLabel(&window);
    imageLabel->setFixedSize(200, 200);
    layout->addWidget(imageLabel);

    QPushButton* button = new QPushButton("画像を選択", &window);
    layout->addWidget(button);

    QLabel* resultLabel = new QLabel(&window);
    layout->addWidget(resultLabel);

    QObject::connect(button, &QPushButton::clicked, [&]() {
        QString imagePath = QFileDialog::getOpenFileName(&window, "画像を選択", "", "画像ファイル (*.png *.jpg *.bmp)");
        if (!imagePath.isEmpty()) {
            QImage image(imagePath);
            imageLabel->setPixmap(QPixmap::fromImage(image).scaled(imageLabel->size(), Qt::KeepAspectRatio));
            performOCR(imagePath, resultLabel);
        }
        });

    window.show();

    return app.exec();
}

注意点

ファイル選択時のパスに日本語があると文字変換に失敗して読み取れないこと

いいなと思ったら応援しよう!