この章では、低品質の画像上の日付フィールドを検索する FlexiLayout を作成する、代表的ないくつかの方法について説明します。このような画像は非常によく見られ、多くの場合、誤ったスキャン設定に起因するさまざまなスキャン不良を含んでいます。たとえば、明るさの設定が適切でないと、画像が明るすぎたり暗すぎたりすることがあります。その結果、画像内の一部の情報が失われたり、画像の一部にノイズが生じたりすることがあります。
FlexiLayout Studio には、日付を検出するための特別な Date 要素があります。ただし、FlexiLayout を作成する際に、この要素だけでは不十分な場合があります。これは、ドキュメント上の日付が Date 要素で使用可能なフォーマットのいずれにも一致しない場合に起こります。たとえば、FlexiLayout Studio では、日付フィールド内の月を指定する際に、次の言語を使用できます: English、Czech、Danish、Dutch、Estonian、Finnish、French、German、Greek、Hungarian、Italian、Latvian、Lithuanian、Norwegian、Polish、Portuguese、Russian、Spanish、Swedish、Turkish。そのため、月がこれら以外の言語で単語として記載されている場合、その日付は使用可能なフォーマットのいずれにも該当せず、したがって Date 要素では検出できません。
また、画像に除去できない要素がある場合にも、日付検索エラーが発生することがあります。たとえば、日付に下線が引かれていて日付と下線の間に目に見える隙間がない場合、取り消し線が引かれている場合、または黒い区切り線 (フレーム、コーム) 付きの character cells に記入されている場合です。さらに、検索領域内の斑点ノイズや、日付がタイプ入力ではなく手書きで記入されていることも、日付検索に Date 要素を使用できない原因になります。
日付フィールドの検索を構成する最適な方法は、サンプルプロジェクト SearchOfDate.fsp (フォルダー %public%\ABBYY\FlexiCapture\12.0\Samples\FLS\Tips and Tricks\Date) で説明されています。
このプロジェクトには 5 つのページがあります。
- ページ 1 - 日付フォーマットを Date 要素で記述できます。
- ページ 2 - 日付内の月がフランス語で記載されています。
- ページ 3 - 日付に下線が引かれています。
- ページ 4 - 日付フィールドにノイズがあります。
- ページ 5 - 日付が手書きで記入されています。
それでは、Date 型の要素でサポートされていない日付フォーマットの画像も含めて、すべての画像上の日付を探してみましょう。
日付フィールドを記述するすべての要素は、DateGroup 要素にまとめられています。まず、このグループには日付フィールドの名前を検索する要素があります。このプロジェクトでは、これは DateHeader という名前の Static Text 型の要素で、唯一の値は ‘Date:’ です。
Relations セクションですべての要素の検索条件を設定するのは難しくないため、ここでは説明しません。詳細はプロジェクト内で直接確認できます。
次に、DateField という名前の Date 型の要素を作成します。この要素は、Date 要素でサポートされているフォーマットの日付フィールドを検索します。
プロジェクトを見ると、Date 要素で日付を検出できるのは最初のページだけです。
他のページ上の日付を検索するために、Character String 型の要素を作成します。このプロジェクトでは、この要素の名前は DateAsString です。画像上に現れる可能性のあるすべての文字は、この要素内でアルファベットによって表現されます。
データフィールドの内容が構造化可能で、しかも Date 要素ではサポートされていない形式である場合は、アルファベットを指定する代わりに、正規表現を使用してその形式を記述することをお勧めします。ただし、正規表現ではフィールドと記述した構造が 100% 一致していることが前提となるため、処理対象の画像の品質が十分に高いことを確認しておく必要があります (一方、アルファベットでは一定割合の誤りが許容され、その値は要素のプロパティで指定されます)。したがって、認識精度を保証できない場合は、アルファベットのほうがより柔軟な手段です。日付内の月が、事前認識言語と同じ言語の単語で記載されることがわかっている場合は、日付フィールドを 3 つのセクション (日、月、年) に分割し、Static Text 型の要素を使って月フィールドを個別に検索する方法が適していることがあります。このような Static Text 要素では、その言語における月のすべての表記パターン (たとえば、正式名称と省略形) を記述する必要があります。その後、日フィールドと年フィールドは、Character String 型の要素を使って、月の右側と左側から検索されます。
FlexiLayout のマッチングを最適化するため、DateAsString 要素の Advanced pre-search relations field には、次の条件が指定されています。
if (DateField.IsNull == FALSE) then Dontfind();
これは次と同じです。
if not DateField.IsNull then Dontfind();
この条件は、Date 要素を使用して日付を検出できない場合にのみ、文字列としての日付の検索が開始されることを意味します。
プロジェクトを見ると、DateAsString 要素は、Date 型の要素では検出できなかったプロジェクト内の残りのページで日付を見つけています。
ただし、4 ページ目では、検出された文字列には日付フィールドの一部しか含まれていません。日付フィールドの事前認識結果を確認すると (ツールバーの Show Raw Objects をクリック) 、部分的にしか検出されなかった理由が明らかになります。検索領域には text objects だけでなく、Picture や Punctuation mark など、ほかの型のオブジェクトも含まれています。このような状況は低品質の画像ではよく見られ、事前認識の段階で text objects が常に認識されるとは限りません。
日付フィールドに関連するすべてのオブジェクトを見つけるため、Object Collection 型の要素を作成し、DateAsObjectCollection という名前を付けます。事前認識中に日付フィールドで検出されたすべてのオブジェクト型を、その要素のプロパティで指定します。FlexiLayout のマッチングを最適化するため、DateAsObjectCollection 要素と DateAsString 要素の Advanced pre-search relations field には、次の条件が指定されています。
if (DateField.IsNull == FALSE) then Dontfind();
条件 if (DateAsString.IsNull == FALSE) then Dontfind() は、DateAsObjectCollection 要素の Advanced properties には追加できません。これは、例からもわかるように、検出された文字列に日付の一部しか含まれない場合があるためです。
この段階で、日付フィールドの検索条件を記述する要素の作成は完了したと考えてよいでしょう。DateField、DateAsString、DateAsObjectCollection の各要素で構成される Group 要素 SearchElements.DateGroup.AlternativeDateGroup は、プロジェクトツリーで Date ブロックの Source 要素として指定されます。DateAsString 要素と DateAsObjectCollection 要素のプロパティの記述には Dontfind() メソッドが使用されているため、実際に検出されたブロックの Region は、Date 要素の 仮説 で見つかった Region、または DateAsObjectCollection 要素と DateAsString 要素を組み合わせた Region のいずれかになります。後者の場合、DateAsString 要素の Region は DateAsObjectCollection 要素の Region の一部であることが想定されるため、最終的な Region は DateAsObjectCollection 要素の Region になります。
この場合は状況が比較的単純なため、Group 要素 SearchElements.DateGroup.AlternativeDateGroup を Source 要素として指定できます。グループの Region は、検出された subelement の Region を組み合わせたものです。Dontfind() メソッドを使うと、一部の subelement の検索をスキップできます。そのため、Group 要素 SearchElements.DateGroup.AlternativeDateGroup の Region は subelement の Region と一致します。この例では、Dontfind() メソッドは FlexiLayout のマッチングの最適化に役立つだけでなく、ブロックの記述も簡潔にします。
別の方法として、Expression セクションで指定したコードを使用することもできます。
Rect OutputRect;
let dateGroup = SearchElements.DateGroup.AlternativeDateGroup;
if (dateGroup.DateField.IsNull == FALSE) then
outputRect = dateGroup.DateField.Rect;
else
outputRect = dateGroup.DateAsObjectCollection.Rect;
OutputRegion = outputRect;
Expression を使用すると、追加のオプションを利用できます。たとえば、DateAsString 要素の region が実際に DateAsObjectCollection の region の一部であるかどうかを確認できます。
文字列形式を定義せず、また、例にあるような Object Collection 型の要素を使用せずに、日付フィールドを探すために Character String 要素を使用しても、日付フィールドの検索領域を明確に定義できる場合は、良好な結果が得られることがあります。ただし、検索領域内に複数の文字列がある場合は、正規表現またはより限定的なアルファベットを使用して文字列形式を指定する必要があります。そうしないと、最終的な仮説が不十分なものになる可能性があります。Character String 型の要素を使用すると、ユーザーは文字列内の文字数、単語末尾の数、空白の長さを制限して、誤った仮説を除外できます。Object Collection 型の要素を使用した場合、仮説には、検索領域内にあり、オブジェクトサイズの制約を満たすすべてのオブジェクトが画像上から含まれます。