メインコンテンツへスキップ
このシナリオは Windows でのみ利用できます。
このシナリオでは、ABBYY FineReader Engine を「スキャン用コンピューター」で使用して画像をスキャンし、ファイルとして保存します。 このシナリオは、文書処理の前段階として、他のシナリオの一部として使用できます。つまり、後続の処理に備えて文書の電子版を取得するために使用されます。たとえば、保管用に文書をスキャンする場合、文書の編集可能な版を取得する場合、文書から特定のデータを抽出する場合などに利用できます。 紙の文書をスキャンして画像を電子形式で保存することで、印刷文書の高品質な電子版を作成できます。 文書は、次の処理段階を経る場合があります。
  1. スキャン
文書は、スキャナーで利用可能な 2 種類のスキャンインターフェース (TWAIN または WIA) のいずれかを使用してスキャンすることも、ABBYY 独自のスキャンインターフェースを使用してスキャンすることも、スキャンインターフェースを使用せずにスキャンすることもできます。
  1. スキャン画像の前処理
スキャン後、画像には前処理を施すことができます。前処理には、ノイズ除去、ゆがんだテキスト行の補正、色の反転、黒い余白の削除、画像の向きや解像度の補正が含まれます。見開きページは、2 つの別々の画像に分割できます。処理後の画像は、JPEG、TIFF、BMP などのさまざまな画像形式で保存できます。

シナリオの実装

以下では、このシナリオにおける ABBYY FineReader Engine 12 の推奨される使用方法について詳しく説明します。このシナリオの実装案では、画像準備のフェーズは省略されています。画像準備の実装に関するヒントについては、以下の追加の最適化を参照してください。
ABBYY FineReader Engine の使用を開始するには、Engine オブジェクトを作成する必要があります。Engine オブジェクトは、ABBYY FineReader Engine オブジェクト階層の最上位にあるオブジェクトで、さまざまなグローバル設定、一部の処理メソッド、および他のオブジェクトを作成するためのメソッドを提供します。Engine オブジェクトを作成するには、InitializeEngine 関数を使用できます。あわせて、Engine オブジェクトを読み込むその他の方法 (Win) も参照してください。

C#

public class EngineLoader : IDisposable
{
    public EngineLoader()
    {
        // これらの変数は、FREngine.dll へのフルパス、Customer Project ID、
        // および該当する場合は Online License トークンファイルへのパスと Online License パスワードで初期化してください
        string enginePath = "";
        string customerProjectId = "";
        string licensePath = "";
        string licensePassword = "";
        // FREngine.dll ライブラリを読み込む
        dllHandle = LoadLibraryEx(enginePath, IntPtr.Zero, LOAD_WITH_ALTERED_SEARCH_PATH);
           
        try
        {
            if (dllHandle == IntPtr.Zero)
            {
                throw new Exception("Can't load " + enginePath);
            }
            IntPtr initializeEnginePtr = GetProcAddress(dllHandle, "InitializeEngine");
            if (initializeEnginePtr == IntPtr.Zero)
            {
                throw new Exception("Can't find InitializeEngine function");
            }
            IntPtr deinitializeEnginePtr = GetProcAddress(dllHandle, "DeinitializeEngine");
            if (deinitializeEnginePtr == IntPtr.Zero)
            {
                throw new Exception("Can't find DeinitializeEngine function");
            }
            IntPtr dllCanUnloadNowPtr = GetProcAddress(dllHandle, "DllCanUnloadNow");
            if (dllCanUnloadNowPtr == IntPtr.Zero)
            {
                throw new Exception("Can't find DllCanUnloadNow function");
            }
            // ポインターをデリゲートに変換する
            initializeEngine = (InitializeEngine)Marshal.GetDelegateForFunctionPointer(
                initializeEnginePtr, typeof(InitializeEngine));
            deinitializeEngine = (DeinitializeEngine)Marshal.GetDelegateForFunctionPointer(
                deinitializeEnginePtr, typeof(DeinitializeEngine));
            dllCanUnloadNow = (DllCanUnloadNow)Marshal.GetDelegateForFunctionPointer(
                dllCanUnloadNowPtr, typeof(DllCanUnloadNow));
            // InitializeEngine 関数を呼び出し、 
            // Online License ファイルへのパスと Online License パスワードを渡す
            int hresult = initializeEngine(customerProjectId, licensePath, licensePassword, 
                "", "", false, ref engine);
            Marshal.ThrowExceptionForHR(hresult);
        }
        catch (Exception)
        {
            // FREngine.dll ライブラリを解放する
            engine = null;
            // FreeLibrary の呼び出し前にすべてのオブジェクトを削除する
            GC.Collect();
            GC.WaitForPendingFinalizers();
            GC.Collect();
            FreeLibrary(dllHandle);
            dllHandle = IntPtr.Zero;
            initializeEngine = null;
            deinitializeEngine = null;
            dllCanUnloadNow = null;
            throw;
        }
    }
    // Kernel32.dll 関数
    [DllImport("kernel32.dll")]
    private static extern IntPtr LoadLibraryEx(string dllToLoad, IntPtr reserved, uint flags);
    private const uint LOAD_WITH_ALTERED_SEARCH_PATH = 0x00000008;
    [DllImport("kernel32.dll")]
    private static extern IntPtr GetProcAddress(IntPtr hModule, string procedureName);
    [DllImport("kernel32.dll")]
    private static extern bool FreeLibrary(IntPtr hModule);
    // FREngine.dll 関数
    [UnmanagedFunctionPointer(CallingConvention.StdCall, CharSet = CharSet.Unicode)]
    private delegate int InitializeEngine(string customerProjectId, string licensePath, 
        string licensePassword, string tempFolder, string dataFolder, bool isSharedCPUCoresMode, 
        ref FREngine.IEngine engine);
    [UnmanagedFunctionPointer(CallingConvention.StdCall)]
    private delegate int DeinitializeEngine();
    [UnmanagedFunctionPointer(CallingConvention.StdCall)]
    private delegate int DllCanUnloadNow();
    // 非公開変数
    private FREngine.IEngine engine = null;
    // FREngine.dll へのハンドル
    private IntPtr dllHandle = IntPtr.Zero;
    private InitializeEngine initializeEngine = null;
    private DeinitializeEngine deinitializeEngine = null;
    private DllCanUnloadNow dllCanUnloadNow = null;
}
ABBYY FineReader Engine には、スキャンソースを管理するための ScanManager オブジェクトが用意されています。このオブジェクトの ScanSources プロパティでは、利用可能なすべてのスキャナーの一覧にアクセスできます。また、FindScanSources メソッドを使用すると、スキャナーが提供する API タイプおよびスキャンオプションの設定に使用するユーザーインターフェースの種類に基づいて、スキャナーを絞り込むことができます。ファイルをスキャンしてディスクに保存するには、ScanSource オブジェクトの以下の2つのメソッドのいずれかを使用します。スキャンが完了するまで処理を返さない Scan メソッドと、非同期スキャン操作を開始して即座に処理を返す BeginScan メソッドです。IScanCallback インターフェースを実装することで、スキャンの進行状況に関する通知を取得できます。ABBYY FineReader Engine 12 APIからアクセス可能なパラメーターには、明るさ、カラー、解像度、画像圧縮タイプ、画像の回転角度、スキャン領域のサイズ、両面スキャンモード、自動フィーダーモード、ページ間の一時停止などがあります。スキャンパラメーターは、ScanSourceオブジェクトのScanSettingsプロパティを使用して設定します。このプロパティを使用してScanSourceSettingsオブジェクトにアクセスでき、そこからスキャンソースのスキャン設定を参照・変更できます。画像を同期的にスキャンするには:
  1. ScanManager オブジェクトを作成します。スキャンログを出力するかどうかは、CreateScanManager メソッドの入力パラメーターで指定できます。
  2. スキャナーがサポートするAPIとUIの種類を指定して、ScanManagerオブジェクトのFindScanSourcesメソッドを使用してスキャンソースを選択します。
  3. ユーザー自身がスキャン オプションを設定するためのダイアログを表示しない場合は、選択したScanSourceScanSettingsプロパティを使用してスキャン オプションを調整します。明るさ、解像度、その他のパラメーターには、ScanSourceSettings オブジェクトの対応するプロパティで適切な値を設定します。このスキャナーで使用可能な設定は、ScanSource の Capabilities プロパティで確認できます。
  4. スキャンしたページの保存先フォルダー名を指定します。フォルダー名には、たとえば ScanFolder のような BSTR 変数を指定する必要があります。
  5. ユーザーに表示するダイアログの種類 (何も表示しない場合は SSUIT_None 定数を渡します) と、結果の保存先フォルダーの ScanFolder パスをパラメーターとして指定して、ScanSource オブジェクトの Scan メソッドを実行します。
  6. このメソッドは、画像ファイル名を StringsCollection オブジェクトで返します。この StringsCollection オブジェクトから画像ファイル名を取得し、それらのファイルを通常の画像ファイルと同様に処理できます。
画像を非同期でスキャンするには:
  1. IScanCallback インターフェイスを実装するオブジェクトを作成します。非同期スキャン処理では、コールバック インターフェイスからの通知が非常に役立ちます。
  2. ScanManager オブジェクトを作成します。スキャンログを出力するかどうかは、CreateScanManager メソッドの入力パラメーターで指定できます。
  3. スキャナーがサポートするAPIとUIの種類を指定し、ScanManager オブジェクトの FindScanSources メソッドを使用してスキャンソースを選択します。
  4. ユーザー自身がスキャン オプションを設定するためのダイアログを表示しない場合は、選択した ScanSource の ScanSettings プロパティを使用してスキャン オプションを調整します。明るさ、解像度、その他のパラメーターについては、ScanSourceSettings オブジェクトの対応するプロパティで適切な値を選択します。このスキャナーで使用可能な設定は、ScanSource の Capabilities プロパティを使用して確認できます。
  5. スキャンしたページの保存先となるフォルダー名を指定します。フォルダー名は、たとえば ScanFolder のような BSTR 型の変数で指定する必要があります。
  6. ScanSource オブジェクトの BeginScan メソッドを実行し、パラメーターとして、ユーザーに表示するダイアログの種類 (ダイアログを表示しない場合は SSUIT_None 定数を渡します) 、および結果を格納するフォルダーの ScanFolder パスを指定します。さらに、作成したコールバック オブジェクトへのポインターも渡す必要があります。
  7. 画像ファイルへのパスは、IScanCallbackインターフェイスのOnImageScanned通知で返され、処理の完了はOnScanComplete通知で通知されます。これらのメソッドの実装は自分で行うため、それぞれの状況でどのように処理するかを選択できます。たとえば、画像ファイルへのパスを受け取ったら、ディスク上の他のファイルと同じように扱い、通常どおりFineReader Engineで処理するために読み込むことができます。
スキャンが完了し、OnScanComplete 通知を受信するまでは、別のスキャナーであっても BeginScan や Scan を実行することはできません。非同期スキャンの利点は、複数のスキャン処理を同時に実行できることではなく、新しい画像がスキャンされている間に、すでに受信した画像を処理できる点にあります。
非同期スキャンシナリオのサンプルコードを以下に示します。

C#

// IScanCallbackインターフェースを実装する
class ScanningCallback :FREngine.IScanCallback
{
  // コンストラクター
  public ScanningCallback() {}
  ...
  // IScanCallbackメソッドの実装を提供する
  public void OnError(string sourceName, string message) { // ここでエラーを報告または処理する }
  public void OnImageScanned(string sourceName, string Path, ref bool cancel) { // 画像スキャン時に必要な処理をここに記述する }
  public void OnScanComplete() { // スキャン完了後に実行したい処理をここに記述する }
  // プライベート変数
  ...
}
// ログを無効にしてスキャンマネージャーを作成する
scanManager = engineLoader.Engine.CreateScanManager(false);
// APIタイプとUIタイプでフィルタリングしたスキャンソースの一覧を作成する
FREngine.IScanSources sources = scanManager.FindScanSources(UIType, APIType);
// 例として、コレクションの先頭のスキャンソースを選択する
FREngine.IScanSource selectedSource = sources[0];
// スキャンソースの設定と機能を取得する
FREngine.IScanSourceSettings settings = selectedSource.ScanSettings;
FREngine.IScanSourceCapabilities capabilities = selectedSource.Capabilities;
// スキャナーが両面モードをサポートしている場合、スキャンオプションを両面モードに設定する
settings.DuplexMode = capabilities.HasDuplexMode;
// 複数ページスキャンとページ間の10秒の遅延を設定する
settings.MultipleImagesEnabled = true;
settings.PauseBetweenPagesMode = FREngine.ScanPauseModeEnum.SPM_PresetDelay;
settings.Delay = 10;
// 結果を保存するフォルダーのパスを設定する
string scanFolder = "D:\\SampleImages";
// コールバックオブジェクトを作成する
IScanningCallback callback = new ScanningCallback();
// スキャンを開始する
selectedSource.BeginScan(SSUIT_None, scanFolder, callback);
ABBYY FineReader Engine の使用を終えたら、Engine オブジェクトをアンロードする必要があります。そのためには、エクスポート関数 DeinitializeEngine を使用します。

C#

public class EngineLoader : IDisposable
{
    // FineReader Engine をアンロードする
    public void Dispose()
    {
        if (engine == null)
        {
            // Engine はロードされていない
            return;
        }
        engine = null;
        // FreeLibrary の呼び出し前にすべてのオブジェクトを削除する
        GC.Collect();
        GC.WaitForPendingFinalizers();
        GC.Collect();
        int hresult = deinitializeEngine();
 
        hresult = dllCanUnloadNow();
        if (hresult == 0)
        {
            FreeLibrary(dllHandle);
        }
        dllHandle = IntPtr.Zero;
        initializeEngine = null;
        deinitializeEngine = null;
        dllCanUnloadNow = null;
        // クリーンアップ後に例外をスローする
        Marshal.ThrowExceptionForHR(hresult);
    }
    // Kernel32.dll の関数
    [DllImport("kernel32.dll")]
    private static extern IntPtr LoadLibraryEx(string dllToLoad, IntPtr reserved, uint flags);
    private const uint LOAD_WITH_ALTERED_SEARCH_PATH = 0x00000008;
    [DllImport("kernel32.dll")]
    private static extern IntPtr GetProcAddress(IntPtr hModule, string procedureName);
    [DllImport("kernel32.dll")]
    private static extern bool FreeLibrary(IntPtr hModule);
    // FREngine.dll の関数
    [UnmanagedFunctionPointer(CallingConvention.StdCall, CharSet = CharSet.Unicode)]
    private delegate int InitializeEngine( string customerProjectId, string LicensePath, string LicensePassword, , , , ref FREngine.IEngine engine);
    [UnmanagedFunctionPointer(CallingConvention.StdCall)]
    private delegate int DeinitializeEngine();
    [UnmanagedFunctionPointer(CallingConvention.StdCall)]
    private delegate int DllCanUnloadNow();
    // プライベート変数
    private FREngine.IEngine engine = null;
    // FREngine.dll へのハンドル
    private IntPtr dllHandle = IntPtr.Zero;
    private InitializeEngine initializeEngine = null;
    private DeinitializeEngine deinitializeEngine = null;
    private DllCanUnloadNow dllCanUnloadNow = null;
}

必要なリソース

FREngineDistribution.csv ファイルを使用すると、アプリケーションの動作に必要なファイルのリストを自動的に作成できます。このシナリオで処理を行うには、5 列目 (RequiredByModule) で次の値を選択します。 Core Core.Resources Opening Opening, Processing Opening.Scanning 標準シナリオを変更する場合は、それに応じて必要なモジュールも変更してください。また、インターフェース言語、認識言語、およびアプリケーションで使用する追加機能も指定する必要があります (たとえば、CJK 言語 のテキストを認識する必要がある場合は、Processing.OCR.CJK など) 。詳細については、Working with the FREngineDistribution.csv File を参照してください。

追加の最適化

各処理段階のパラメーター設定についてさらに詳しくは、ヘルプファイルの以下のセクションを参照してください。
  • 文書の分割
    • このシナリオでは、入力される画像の流れを文書単位にグループ化する必要が生じることがあります。たとえば、各文書のページ数があらかじめ分かっている場合や、最初の文書の最終ページと次の文書の先頭ページの間に、バーコード付きの区切りページが入るようにする場合です。詳しくは、バーコード認識シナリオを参照してください。

関連項目

基本的な使用シナリオの実装方法