web-dev-qa-db-ja.com

小さなc ++プロジェクトでtesseractocr(または他の無料のocr)を使用するにはどうすればよいですか?

ですから、調査後に聞いたのは、無料のOCRオプションは Tesseract またはCuneiFormのいずれかだけだということです。

さて、Tesseractのドキュメントは非常に恐ろしいものであり、それらが提供するのはVisual Studioコードの束(Windowsの私にとって)だけであり、そこからあなたは彼らのAPIの海に一人でいます。できることは、コンパイルするexeを使用してから、tiffイメージで使用することだけです。

少なくとも小さな例では、API呼び出しをプルしてOCRを使用する方法を説明する短いドキュメントを期待していましたが、ドキュメントにはそのようなものはありません。

CuneiForm:私はそれをダウンロードしました、そして「素晴らしい」すべてはロシア語です。 :(

それらの人が小さな例を引き出すのは本当に難しいですか?代わりに彼らはおそらく90%の人々が到達しないであろうたくさんの無関係な情報を私たちに提供します、どうすれば小さなことから始めずにそこに到達できますか?彼らはそれのどれも説明しません!

だから私はたくさんのAPIを持っていますが、それがどこにも説明されていない場合、どうやってそれを使用することになっていますか?...誰かが私にアドバイスと解決策を提供できるかもしれませんか?私は奇跡を求めているのではなく、物事がどのように機能するかを私に示すための小さな何かを求めています。

27
Marko29

あなたはあきらめたかもしれませんが、まだ試みている他の人がいるかもしれません。だからここにあなたがtesseractから始める必要があるものがあります:

まず、正八胞体に関するすべてのドキュメントを読む必要があります。 wiki が便利なものだと思うかもしれません。

API(v 3.0.1、現在トランク内)の使用を開始するには、READMEおよびChangeLogfrom trunk )もお読みください。_baseapi.h_を確認する必要があります。 。APIの使用方法のドキュメントはすぐそこにあり、各関数の上にコメントがあります。

手始めに:

  • _baseapi.h_をインクルードし、TessBaseAPIオブジェクトを構築します
  • Init()を呼び出す
  • のようなオプション
    • SetVariable()関数でいくつかのパラメータを変更します。 PrintVariables() funcを使用してファイルに出力すると、すべてのパラメーターとその値を確認できます。
    • SetPageSegMode()でセグメンテーションモードを変更します。 OCRしようとしている画像が何を表しているかをtesseractに伝えます-テキストのブロックまたは行、単語または文字。
  • SetImage()
  • GetUTF8Text()

(繰り返しますが、それは初心者向けです。)

あなたはすでに答えられた質問のためにtesseractのコミュニティをチェックするか、あなた自身に尋ねることができます ここ

28
zkunov

私はそれを掘り下げています..これまで私はそれのためにDoxyGenコードを生成しました..それは助けになります。それでもすべてのドキュメントを読んでいます。

私を助けるいくつかのリンク:

Googleコードからsvnをダウンロードしたもの: http://code.google.com/p/tesseract-ocr/

それを作成してインストールし、doxygenを使用して独自のAPIリファレンスドキュメントを生成しました。非常に便利。

私がそれをした方法は次のとおりです。

  1. 'make install'を使用し、/ usr/include/tesseractにいくつかのものを配置しました
  2. そのディレクトリをホームディレクトリにコピーしました
  3. doxygen -g doxygen.conf; #doxygenファイルを生成するには
  4. 生成されたファイルを調べて、出力ディレクトリやプロジェクト名などを設定します。出力ディレクトリとして「doxy-dox」を使用しました
  5. doxygen -g doxygen.conf
  6. クロムブラウザクロムブラウザdoxy-doc/html/index.html

それが少し役立つことを願っています。

4
matiu

Visual Studio 2010を使用していて、Windowsフォーム/デザイナーを使用している場合は、この方法で問題なく簡単に追加できることがわかりました。

  1. 次のプロジェクトをプロジェクトに追加します(自分を嫌うのが好きでない限り、一度警告します。tesseractソリューションを追加したり、追加したプロジェクトの設定を変更したりしないでください)

    ccmain ccstructccutil分類キューブcutildict画像libtesseractnutral_networkstextordビューアwordrec

他のものを追加することはできますが、プロジェクトにすべてを組み込みたくないですか? naaa、それらを別々に構築する

  1. プロジェクトのプロパティに移動し、参照としてlibtesseractを追加します。これで、プロジェクトとして表示できるようになります。これにより、tesseract内の何百万もの警告を調べることなく、プロジェクトを高速にビルドできます。 [共通のプロパティ]-> [参照を追加]

  2. ソリューションエクスプローラーでプロジェクトを右クリックし、プロジェクトの依存関係をクリックして、libtesseractまたはそれらすべてに依存していることを確認します。これは、プロジェクトの前にビルドされることを意味します。

  3. tesseract 2010 Visual Studioプロジェクトには、release、release.dll、debug、debug.dllなどの構成設定が多数含まれています。release.dll設定によって適切なファイルが生成されるようです。まず、ソリューションの出力をrelease.dllに設定します。プロジェクトのプロパティをクリックします。次に、構成マネージャーをクリックします。それが利用できない場合は、これを実行し、ソリューションツリーでソリューションのプロパティをクリックして[構成]タブをクリックすると、プロジェクトのリストと関連する構成設定が表示されます。出力がリリースされていても、プロジェクトがrelease.dllに設定されていないことに気付くでしょう。 2番目のルートを使用した場合でも、構成マネージャーをクリックする必要があります。次に、設定を編集し、プロジェクト設定で[新規]をクリックしてrelease.dllと呼びます...他の設定とまったく同じで、リリースから設定をコピーします。デバッグについても同じことを行い、デバッグ設定からdebug.dll名をコピーします。ふぅ...ほぼ完了

  4. 自分の設定に合わせて正八胞体の設定を変更しようとしないでください....それは機能しません....そして新しいリリースがリリースされたとき、あなたはただ「それを投入」して行くことができなくなります。この状態では、新しいモードはRelease.dllとDebug.dllであるという事実を受け入れます。ストレスを感じないでください...終了したら戻って、ソリューションからプロジェクトを削除できます。

  5. ライブラリとdllがどこから出てくるかを推測しますか?プロジェクトでは、ライブラリディレクトリを追加する必要がある場合とない場合があります。一部の人々は、すべてのヘッダーを1つのフォルダーにダンプするため、インクルードに1つのフォルダーを追加するだけでよく、私は追加しないと言います。 tesseractフォルダーを削除して、余​​分な作業をせずにzipから再読み込みできるようにしたいのですが、コードを台無しにした場合は、1回の移動で更新するか、復元する準備ができています。少し手間がかかり、設定の代わりにコードを使用して行うことができますが、2010 tesseractプロジェクトフォルダー内にヘッダーファイルを含むすべてのフォルダーを含め、そのままにしておく必要があります。

  6. プロジェクトにファイルを追加する必要はありません。これらのコード行だけ.....ファイルを保存/ロードする必要なしに、1つの外部データセットからtiff対応バージョンに変換する追加のコードをいくつか含めました。いいじゃない?

  7. これで、debug.dllとrelease.dllで完全にデバッグできます。プロジェクトに正常にビルドできたら、追加したすべてのプロジェクトを削除できても、完全にデバッグできます。余分なコンパイルやエラーはありません。完全にデバッグ可能で、すべて自然です。

  8. 私の記憶が正しければ、2008/lib /のファイルをプロジェクトのリリースフォルダーにコピーしなければならなかったという事実を回避することはできませんでした…。

私のプロジェクト「functions.h」に

#pragma comment (lib, "liblept.lib" )
#define _USE_TESSERACT_
#ifdef _USE_TESSERACT_
#pragma comment (lib, "libtesseract.lib" )
#include <baseapi.h>
#endif
#include <allheaders.h>

私のメインプロジェクトでは、これをメンバーとしてクラスに入れました。

tesseract::TessBaseAPI *readSomeNombers;

もちろん、どこかに「functions.h」を含めました

次に、これをクラスコンストラクターに入れます。

readSomeNombers = new tesseract::TessBaseAPI();
readSomeNombers ->Init(NULL, "eng" );
readSomeNombers ->SetVariable( "tessedit_char_whitelist", "0123456789,." );

次に、このクラスメンバー関数を作成しました。出力として機能するクラスメンバーは、嫌いではありません。変数を返すのは好きではありません。私のスタイルではありません。このようにメンバー関数内で使用する場合、pixのメモリを破棄する必要はありません。私のテストでは、これがこれらの関数を呼び出す安全な方法であることが示されています。しかし、どうしても、あなたは何でもすることができます。

void Gaara::scanTheSpot()
{
    Pix *someNewPix;
    char* outText;
    ostringstream tempStream;
    RECT tempRect;
    someNewPix = pixCreate( 200 , 40 , 32 );
    convertEasyBmpToPix( &scanImage, someNewPix, 87, 42 );

    readSomeNombers ->SetImage(someNewPix);
    outText = readSomeNombers ->GetUTF8Text();
    tempStream.str("");
    tempStream << outText;
    classMemeberVariable = tempStream.str();
//pixWrite( "test.bmp", someNewPix, IFF_BMP );
}

スキャンしたい情報を持つオブジェクトはメモリ内にあり、&scanImageによってポイントされています。これは「EasyBMP」ライブラリからのものですが、それは重要ではありません。

ちなみに「functions.h」/「functions.cpp」の関数で扱っているのですが、ループ内で少し余分な処理を行っています。つまり、文字を細くして白黒にし、反転させます。不要な白黒。私の開発のこの段階では、私はまだ認識を改善する方法を探しています。私の提案では、これはまだ悪いデータを生み出していませんが。私の見解は、簡単にするためにデフォルトのTessデータを使用することです。私は非常に複雑な問題を解決するためにヒューリスティックに行動しています。

void convertEasyBmpToPix( BMP *sourceImage, PIX *outputImage, unsigned startX, unsigned startY )
{
    int endX = startX + ( pixGetWidth( outputImage ) );
    int endY = startY + ( pixGetHeight( outputImage ) );
    unsigned destinationX;
    unsigned destinationY = 0;
    for( int yLoop = startY; yLoop < endY; yLoop++ )
    {
        destinationX = 0;
        for( int xLoop = startX; xLoop < endX; xLoop++ )
        {
            if( isWhite( &( sourceImage->GetPixel( xLoop, yLoop ) ) ) )
            {
                pixSetRGBPixel( outputImage, destinationX, destinationY, 0,0,0 );
            }
            else
            {
                pixSetRGBPixel( outputImage, destinationX, destinationY, 255,255,255 );
            }
            destinationX++;
        }
        destinationY++;
    }
}
bool isWhite( RGBApixel *image )
{
    if(
        //destination->SetPixel( x, y, source->GetPixel( xLoop, yLoop ) );
        ( image->Red   < 50 ) ||
        ( image->Blue  < 50 ) ||
        ( image->Green < 50 )
        )
    {
        return false;
    }
    else
    {
        return true;
    }
}

私が気に入らないことの1つは、関数の外でpixのサイズを宣言する方法です。関数内で実行しようとすると、予期しない結果が発生するようです。メモリが割り当てられているときにメモリが割り当てられると、離れるとメモリが破壊されます。

g m a i l確かに私の最もエレガントな作品ではありませんが、簡単にするためにそれを根絶しました。なぜ私はこれをわざわざ共有するのかわかりません。私はそれを自分自身に留めるべきだった。私の名前は何ですか?影・さばく・我愛羅

手放す前に、Windowsフォームアプリとデフォルト設定の微妙な違いについて説明する必要があります。つまり、「マルチバイト」文字セットを使用します。プロジェクトのプロパティ...そしてそのような..犬に骨を与える、多分投票?

p.p.s.言いたくないのですが、64ビットを使用している場合はHost.cに1つの変更を加えました。同じことができます。そうでなければあなた自身で.....しかし私の理由はあなたがする必要がない少し狂気でした

typedef unsigned int uinT32;
#if (_MSC_VER >= 1200)            //%%% vkr for VC 6.0
typedef _int64 inT64;
typedef unsigned _int64 uinT64;
#else
typedef long long int inT64;
typedef unsigned long long int uinT64;
#endif                           //%%% vkr for VC 6.0
typedef float FLOAT32;
typedef double FLOAT64;
typedef unsigned char BOOL8;
3
Kage_Gaara

Marko、Tesseractを使用して簡単なC++アプリを作成しようとしましたが、同じ問題が発生しました。

一言で言えば、私はそれが小さな例/ドキュメントと混同していることに気づきました、しかし私は製品を責めません、一体、それはオープンソースであり、貢献者はおそらくマーケティングよりもそれを改善することに興味があります。

ソースコードをざっと見てみると、時間をかけて理解できるかもしれませんが、私はあなたの欲求不満に完全に関係することができます。

幸運を!

2
Mark Kadlec

Windows 10を使用している場合は、OCRAPIがあります。何もインストールする必要はありません。

物事はそれを正しくするのは非常に難しいです。ドキュメントの操作は非常に簡単ではありませんでした。

しかし、私はそれを正しく理解しました。

Windows 10OCRエンジンAPIを使用する簡単な関数は次のとおりです。


// For the Windows 10 OCR API
#include "winrt/Windows.Storage.Streams.h"
#include "winrt/Windows.Graphics.Imaging.h"
#include "winrt/Windows.Media.Ocr.h"
#include "winrt/Windows.Networking.Sockets.h"
#include "winrt/Windows.Globalization.h"
#pragma comment(lib, "pathcch")
#pragma comment(lib,"windowsapp.lib")

std::string ExtractTextFromImage(byte* pixels, int xSize, int ySize)
{
    using namespace winrt;

    Windows::Globalization::Language lang = Windows::Globalization::Language(L"en");
    Windows::Media::Ocr::OcrEngine engine = Windows::Media::Ocr::OcrEngine::TryCreateFromLanguage(lang);
    //OcrEngine engine = OcrEngine::TryCreateFromUserProfileLanguages();


    int pixels_size = xSize * ySize * 4;

    Windows::Storage::Streams::InMemoryRandomAccessStream stream = { 0 };
    Windows::Storage::Streams::DataWriter writer(stream);


    array_view<const byte> bytes(pixels, pixels + pixels_size);

    writer.WriteBytes(winrt::array_view<const byte>(bytes));

    Windows::Storage::Streams::IBuffer buffer = writer.DetachBuffer();



    Windows::Graphics::Imaging::SoftwareBitmap bitmap = Windows::Graphics::Imaging::SoftwareBitmap::CreateCopyFromBuffer
    (
        buffer,
        Windows::Graphics::Imaging::BitmapPixelFormat::Bgra8,
        xSize,
        ySize
    );

    Windows::Media::Ocr::OcrResult result = engine.RecognizeAsync(bitmap).get();
    std::string output = winrt::to_string(result.Text());

    bitmap.Close();
    writer.Close();



    return output;
}


0
gil123