> ## Documentation Index
> Fetch the complete documentation index at: https://docs.abbyy.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Nearest と FuzzyQuality を使用した要素の検索

> FlexiLayout Studio における Nearest 関数と FuzzyQuality 関数を比較し、半構造化文書で請求書番号 field と日付フィールドを検出する方法を説明します。

<Note>
  簡単にするため、このサンプルでは 1 ページの文書を使用します。
</Note>

文書処理では、要素の位置をほかの要素に対して「上 - 下 - 右 - 左」のような関係だけで表すのでは不十分な場合がよくあります。たとえば、検索領域内に検索制約に一致するオブジェクトが複数存在する場合です。

このような場合には、それらのオブジェクトを区別するための追加の属性、具体的にはオブジェクト間の距離が必要になります。そのために、FlexiLayout Studio には `FuzzyQuality` 関数と、`Nearest` グループの関数 (`Nearest`、`NearestX`、`NearestY`) が用意されています。

<div id="how-the-nearest-and-fuzzyquality-functions-differ">
  ## Nearest 関数と FuzzyQuality 関数の違い
</div>

これらの関数の用途は異なります。

`Nearest` 関数は、**Advanced pre-search relations** field でのみ使用できます。この関数は、要素の複数の仮説のうち、`Nearest` 関数のプロパティで設定された画像上の特定の要素または点に最も近いものを FlexiLayout Studio が選択することを指定します。

要素の **Advanced pre-search relations** field では、`Nearest` グループの関数は 1 つしか使用できません。これを実行すると、残る仮説は 1 つだけになり、これは仮説生成の段階、つまり **Advanced post-search relations** field で指定されたコードが実行される前に行われます。

要素の仮説の最小 品質 を指定する **Minimum quality** parameter は、**Static Text**、**Character String**、**Paragraph**、**Date**、**Separator** の各要素に対して指定できます。

ただし、残った仮説が最良であり (画像内の目的のオブジェクトに対応している) とは限りません。というのも、仮説に 品質 値を割り当てるうえで **Advanced post-search relations** は非常に重要だからです。`Nearest` 関数を使用する場合、仮説の選択は仮説生成の段階で行われ、その基準は特定の点への近さであり、仮説の 品質 ではありません。

そのため、**Advanced post-search relations** セクションで指定するプロパティが仮説を正しく選択するうえで重要である場合は、`Nearest` グループの関数ではなく `FuzzyQuality` 関数を使用する必要があります。

`FuzzyQuality` 関数は、**Advanced post-search relations** セクション でのみ使用できます。`Nearest` グループの関数とは異なり、単一の仮説を選択するのではなく、生成されたすべての仮説のプロパティと `FuzzyQuality` 関数の parameters に基づいて、各仮説の overall 品質 に影響を与えます。

さらに、`FuzzyQuality` 関数は、1 つの要素に対して **Advanced post-search relations** field 内で複数回使用できます。これは、異なる 品質 値を持つ複数の制約を 1 つの仮説に適用できることを意味します。仮説の Post-search 品質 を決定するために、すべての値が乗算されます。

`FuzzyQuality` 関数は次のようになります:

```text theme={null}
FuzzyQuality: x, {f1, f2, f3, f4};
```

アルゴリズムは次のとおりです。この関数は、parameter x の値が、パラメーター f1、f2、f3、f4 で定義される区間に含まれるかどうかを確認します。このファジー区間の意味は、**Character String** 要素の一部のパラメーターに指定されるファジー区間と似ています。

<div id="the-fuzzyandnearest-sample-project">
  ## FuzzyAndNearest sample Project
</div>

このサンプルでは、`Nearest` 関数と `FuzzyQuality` 関数を次の画像でどのように使用できるかを示します。

| <img src="https://mintcdn.com/abbyy/r-nfa7jujx5b9gKX/images/flexi-capture/fls/invoice5.gif?s=be300b44adb9037412f61842b965f067" alt="1 つのレイアウト内に請求書番号フィールドと請求日フィールドがある半構造化請求書文書のサンプル" width="321" height="147" data-path="images/flexi-capture/fls/invoice5.gif" /> | <img src="https://mintcdn.com/abbyy/r-nfa7jujx5b9gKX/images/flexi-capture/fls/invoice6.gif?s=41550e7e99c2a5242ed0c9ae180fa628" alt="異なるレイアウト内に請求書番号フィールドと請求日フィールドがある半構造化請求書文書のサンプル" width="351" height="147" data-path="images/flexi-capture/fls/invoice6.gif" /> |
| --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| <img src="https://mintcdn.com/abbyy/r-nfa7jujx5b9gKX/images/flexi-capture/fls/invoice7.gif?s=0f48ef5a6d6b2bf085402d60a6f9c0b7" alt="異なるレイアウト内に請求書番号フィールドと請求日フィールドがある半構造化請求書文書のサンプル" width="319" height="201" data-path="images/flexi-capture/fls/invoice7.gif" />  | <img src="https://mintcdn.com/abbyy/r-nfa7jujx5b9gKX/images/flexi-capture/fls/invoice8.gif?s=bcb1575ef777663dc35cbb74e9337f0f" alt="異なるレイアウト内に請求書番号フィールドと請求日フィールドがある半構造化請求書文書のサンプル" width="349" height="146" data-path="images/flexi-capture/fls/invoice8.gif" /> |

画像からわかるように、この請求書は半構造化されており、field の配置は画像ごとに異なります。目的は、"請求書番号" フィールドと "請求日" フィールドを検出することです。

これは `1.fsp` Project (フォルダー `%public%\ABBYY\FlexiCapture\12.0\Samples\FLS\Tips and Tricks\FuzzyAndNearest \Project1`) で行います。

FlexiLayout の構造を最適化し、文書内で対象フィールドがどのように配置されているかというロジックに沿うため、このProjectでは対象となるすべての要素を **InvoiceGroup** という複合要素にまとめています。

FlexiLayout の作成は、"請求書番号" というフィールド名の検索制約を記述する要素から始めることもできます。しかし、画像を解析すると、その名前を構成する "Invoice" という単語は文書内に複数回現れることがわかります。

各フィールドの相対的な位置は毎回変化するため、"Invoice" という単語を確実に正しく検出できるような条件を指定することはできません。たとえば、この単語は "請求日" という名前の中にも見つかる可能性があります。

このような混同を避けるため、記述は日付フィールド名から始めます。ここでは、**DateHeader** という名前の **Static Text** 要素を使用します。**Search text** フィールドには、名前の 2 つの値 **Invoicedate:|Invoicedate** を指定します (画像内で実際に現れる表記の候補を列挙しています) 。名前の大文字と小文字の違いは関係ありません。

<Note>
  両方の候補を指定する必要がある理由について詳しくは、[field 名の候補に対して複数の Static Text 値を設定する](/ja/flexi-capture/fls/tips-tricks/date3) を参照してください。
</Note>

<div id="search-for-the-date-field-with-an-array-of-rectangles">
  ## 矩形の配列を使用して日付フィールドを検索する
</div>

日付フィールドの検索は、field名に基づいて行われます。このProjectには **DateAlternative** グループがあり、2 つの要素で構成されています。1 つは、指定された形式のいずれかで日付フィールドを検索するための **Date** 要素、もう 1 つは、検索対象のフィールドの形式が異なる場合に備えた **Character String** 要素です。

<Note>
  日付検索用の FlexiLayout の作成方法について詳しくは、[認識品質が高い場合または低い場合の日付検索](/ja/flexi-capture/fls/tips-tricks/date2)を参照してください。
</Note>

画像に示すように、日付フィールドは "Invoice date" という名前の右側または下側に配置される場合があります。

**Relations** field に標準の 検索制約 を設定すると (これらは Project 内に表示されますが、無効になっています) 、search area が広くなりすぎて、日付フィールドと誤認される可能性のある一部の field まで含んでしまうことがあります (例は画像に示されています) 。これは、たとえば日付が **Date** 要素に指定された形式と一致しない場合に発生することがあります。

<Frame>
  <img src="https://mintcdn.com/abbyy/r-nfa7jujx5b9gKX/images/flexi-capture/fls/nearestandfuzzy.png?fit=max&auto=format&n=r-nfa7jujx5b9gKX&q=85&s=6e2d2ace9787bf8ea56d437c9bac4fe7" alt="ABBYY FlexiLayout Studio のスクリーンショット。標準の Relations 制約により、日付フィールドの search area が広くなりすぎ、Invoice date field と誤認される可能性のある他の field まで含まれてしまう様子を示しています。" width="617" height="491" data-path="images/flexi-capture/fls/nearestandfuzzy.png" />
</Frame>

FlexiLayout Studio が不要な領域を解析しないようにするため、この Project では別のメソッドを使用します。**Advanced pre-search relations** field には、次のコードが含まれています。

```text theme={null}
let Header = InvoiceGroup.DateHeader;
if not Header.IsNull then
{ let rect1 = Rect (Header.Rect.Right, Header.Rect.Top-20dt,
PageRect.Right, Header.Rect.Bottom+20dt);
let rect2 = Rect (Header.Rect.Left - 200dt, Header.Rect.Bottom,
Header.Rect.Right + 150dt, Header.Rect.Bottom+200dt);
RectArray ar;
ar = RectArray ( rect1 );
ar.Add ( rect2 );
RestrictSearchArea( ar );
}
else
{ Above: PageRect.Top + PageRect.Height/2;
}
```

このコードは、日付フィールドの名前が見つかったかどうかを確認します。見つかった場合は、検索領域が矩形の配列として指定されます (この例では 2 つの矩形) 。1 つの矩形では名前の右側にある日付を検索し、もう 1 つでは名前の下にある日付を検索します。

名前が見つからない場合は、画像の上半分で検索が実行されます。

ページの **Relations** セクションで検索制約が指定されている場合、このコードの実行後の検索領域の形状は矩形ではなくなります。図が示すように、不要なオブジェクトはすべてそこから削除されています。

<Note>
  コードの 1 行目 (`let Header = InvoiceGroup.DateHeader;`) では、変数 `Header` を定義し、要素 **DateHeader** の値を割り当てることで、コードを簡潔にしています。
</Note>

<Frame>
  <img src="https://mintcdn.com/abbyy/r-nfa7jujx5b9gKX/images/flexi-capture/fls/nearestand_fuzzy2.png?fit=max&auto=format&n=r-nfa7jujx5b9gKX&q=85&s=59dfee169cac721291c34a41bec94a44" alt="ABBYY FlexiLayout Studio のスクリーンショット。RestrictSearchArea コードによって生成された非矩形の日付フィールド検索領域が表示されており、不要なオブジェクトはすべてそこから削除されています。" width="617" height="491" data-path="images/flexi-capture/fls/nearestand_fuzzy2.png" />
</Frame>

このコードは **DateAsString** 要素に対しては重複していません。代わりに、その **Advanced pre-search relations** セクションには次の検索条件が含まれています。

```text theme={null}
if not Date.IsNull then Dontfind();
else RestrictSearchArea (Date.Rect);
```

これは、**Date** 要素が検出されない場合、**Date** 要素の検索領域を囲む矩形内で検索が実行されることを意味します。

<Note>
  **DateAsString** 要素の検索領域を矩形の配列として指定するには、`RestrictSearchArea (Date.Rect)` を呼び出す代わりに、**Date** 要素の Advanced pre-search relations セクションにある対応するコードを複製します。
</Note>

<div id="detect-the-invoice-field-name-with-exclude-and-nearesty">
  ## Exclude と NearestY を使用して Invoice フィールド名を検出する
</div>

このプロジェクトには、フィールド名 "請求書番号" を検出するための **Static Text** 要素 (**InvoiceHeader** という名前) も含まれており、検索対象の値は "Invoice" です。ドキュメントは構造化されていないため、特定の検索制約は指定できません。

FlexiLayout のマッチング処理が完了すると、この名前が正確に検出されたのは最初のページだけであることがわかります。2 ページ目と 4 ページ目では、単語 "Invoice" が日付フィールドの名前の中で誤って検出されました。

3 ページ目では、ページの下部で見つかりました。また、最適化アルゴリズムにより、画像内に単語 "Invoice" が 3 回出現しているにもかかわらず、この名前の他の仮説は生成されませんでした。

<Note>
  グループ内の要素の最適な検索について詳しくは、[グループ要素検索の最適化](/ja/flexi-capture/fls/tips-tricks/date10)を参照してください。
</Note>

これらの問題を解決するために、次のメソッドを使用します。日付フィールド名の Region をフィールド名 "Invoice" の検索領域から除外するには、**DateHeader** 要素を Exclude regions of elements セクションに追加します (次の図を参照) 。

<Note>
  FlexiLayout が **DateHeader** ではなく **InvoiceHeader** から開始されていた場合、`Exclude` function は使用できません。この function では、プロジェクトツリー内で現在の要素より上にある要素しか除外できないためです。
</Note>

ページ下部にある単語 "Invoice" の不要な検出を除外するために、次のコードを Advanced pre-search relations セクションに記述します。

```text theme={null}
NearestY: PageRect.Top;
```

このコードは、ページ上端に最も近い要素を検索するようプログラムに指示します。

<Frame>
  <img src="https://mintcdn.com/abbyy/r-nfa7jujx5b9gKX/images/flexi-capture/fls/prop_search_elements_invoic.gif?s=98b8524b283103633782bb4befc0c383" alt="ページ上端に最も近い Invoice field 名要素を検索する NearestY: PageRect.Top コードを示した、ABBYY FlexiLayout Studio の Advanced pre-search relations セクションのスクリーンショット。" width="427" height="454" data-path="images/flexi-capture/fls/prop_search_elements_invoic.gif" />
</Frame>

FlexiLayout の照合が完了すると、このメソッドがページ 2 で失敗したことがわかります。ここでは日付フィールドの名前にノイズが非常に多く、検出されなかったためです。

このページでは、`Nearest` 関数で指定した制約は、同じ高さに配置されているため、2 つの "Invoice" 文字列の両方に当てはまります。また、どちらの "Invoice" 文字列も認識精度が高いため、最適化アルゴリズムは 2 つの別個の仮説ではなく、1 つの仮説を生成しました。残念ながら、この仮説は正しくありません。

<div id="search-for-the-invoice-number-with-nearest">
  ## Nearest を使用して請求書番号を検索する
</div>

「請求書番号」field を検出するために、この Project では **InvoiceNumber** という名前の **Character String** 要素を使用します。日付フィールドの要素と同様に、「請求書番号」field の検索制約は **Advanced pre-search relations** セクションで指定します。この要素の検索領域は、矩形の array です。

```text theme={null}
let Header = InvoiceGroup.InvoiceHeader;
if not Header.IsNull then
{ let rect1 = Rect (Header.Rect.Right, Header.Rect.Top-20dt,
PageRect.Right, Header.Rect.Bottom+20dt);
let rect2 = Rect (Header.Rect.Left - 200dt, Header.Rect.Bottom,
Header.Rect.Right + 150dt, Header.Rect.Bottom+200dt);
RectArray ar;
ar = RectArray( rect1 );
ar.Add( rect2 );
RestrictSearchArea( ar );
}
else
{ Above: PageRect.Top + PageRect.Height/2;
}
Nearest: Header;
```

さらに、このコードにはもう 1 つ制約があり、**InvoiceNumber** 要素が name 要素に最も近いことを FlexiLayout Studio に伝えます。

マッチングを実行すると、"請求書番号" field がページ 2 と 4 で誤って検出されていることがわかります。ページ 4 では、field 名は正しく検出されているにもかかわらず、誤検出されています。

<Note>
  代替案として (現在の Project の画像では) 、`Nearest: Header;` の代わりに `NearestY: Header.Rect.YCenter;` と記述し、目的の field が name の中心に対して垂直方向に最も近いことを FlexiLayout Studio に伝えることもできます。

  これにより、ページ 4 の "請求書番号" field の誤検出は解消できる可能性があります。ただし、ページ 5 では効果がありません。これは、"請求書番号" という名前が誤って検出された後、目的の field が日付フィールド内で検出されてしまうためです。
</Note>

<div id="replace-nearest-with-fuzzyquality-penalties">
  ## Nearest を FuzzyQuality ペナルティに置き換える
</div>

ここでは、このような状況で `FuzzyQuality` 関数をどのように使用できるかを見ていきます。

これは、`2.fsp` Project (`FuzzyAndNearest\Project2` フォルダー) で示されています。

この Project の設定は、前述の Project の設定とほぼ同じです。

ただし、重要な違いが 1 つあります。**Advanced pre-search relations** セクションでは `Nearest` 関数を使用していません。代わりに、**Advanced post-search relations** セクションには次のコードが含まれています。

```text theme={null}
if not IsNull then
{ FuzzyQuality: Rect.Top - PageRect.Top, {0,0,0,50000} * dt;
FuzzyQuality: 500dt-Width, {0,0,0,100000} * dt;
if not InvoiceHeader.IsNull then
{ FuzzyQuality: Rect.XCenter - InvoiceHeader.Rect.XCenter, {-10000,0,0,50000} *dt;
FuzzyQuality: Rect.YCenter - InvoiceHeader.Rect.YCenter, {-10000,0,0,10000} *dt;
}
}
```

このメソッドは、どの仮説も除外することなく、すべての仮説の品質に影響を与えます。最適なチェーンは各チェーンごとに個別に選択され、その要素を構成するすべての仮説の品質値を掛け合わせて決定されます。

行 `FuzzyQuality: Rect.Top - PageRect.Top, {0,0,0,50000} * dt;` は、null ではない仮説が生成された場合 (最初に `if not IsNull` チェックが実行されます) に、要素の位置とページ上端との距離が求められることを意味します。つまり、差分 (`Rect.Top - PageRect.Top`) が計算され、FlexiLayout Studio はその差分が区間 \{0, 0, 0, 50000}\*dt に含まれるかどうかを確認します。

このような区間の記述は、品質ペナルティが要素とページ上端との距離に直接依存することを意味します。距離が長いほど、ペナルティは大きくなります。

図 (a) に示すように、指定されたパラメーター値では、最大ペナルティ (1) は 50000dt の距離に対応します。一方、1000 ドット (1 ドットは 1/300 インチ) の距離ではペナルティは 0.02、100dt の距離では 0.002 になります。

<Note>
  区間の境界を設定するパラメーターを選択する際は (特に `FuzzyQuality` 関数による要素チェックが複数ある場合) 、正しい仮説に過剰なペナルティを与えて、その最終的な品質がヌル仮説の品質より低くならないようにしてください。

  すべての仮説 (正しいものを含む) の品質がヌル仮説の品質値より低い場合、ヌル仮説が選択されることがあります。つまり、要素は検出されません。
</Note>

<Frame caption="(a)">
  <img src="https://mintcdn.com/abbyy/lqYknuOmCa79141v/images/flexi-capture/fls/graf.gif?s=30e5384081ef5c8c6a7671d33fb15fb5" alt="要素とページ上端の距離が大きくなるほど品質ペナルティが増加し、距離が 50000dt のときに最大ペナルティ 1 になることを示す図。" width="584" height="532" data-path="images/flexi-capture/fls/graf.gif" />
</Frame>

行 `FuzzyQuality: 500dt - Width, {0,0,0,100000}*dt;` は、FlexiLayout Studio が 500dt と、仮説に対応する検出済みオブジェクトの幅との差を考慮することを意味します。つまり、差分 (`500dt - Width`) が計算され、FlexiLayout Studio はその差分が区間 \{0, 0, 0, 100000}\*dt に含まれるかどうかを確認します。

オブジェクトの幅が狭いほどペナルティは大きくなるため、より長い請求書番号が優先されます。この制約は、画像にノイズがある場合に使用できます。ノイズが指定されたアルファベットの文字として認識された場合 (たとえばページ 2 で確認できます) 、以降の解析から除外するために、その仮説にペナルティを与える必要があります。

<Note>
  500dt という値は、field "請求書番号" 内の文字列長がこの値を超えないと仮定して、目視で選ばれています。ここで指定されているパラメーターは、field "請求書番号" の幅が 0 の場合に最大ペナルティ (0.005) に対応することを定義しています。0 から 500dt の間のそれ以外の幅では、品質ペナルティはより小さくなります。
</Note>

行 `FuzzyQuality: Rect.XCenter - InvoiceHeader.Rect.XCenter, {-10000,0,0,50000} *dt;` は、「請求書番号」field名の要素に対してヌルでない仮説が生成された場合 (最初に `if not InvoiceHeader.IsNull` チェックが実行されます) 、検出された **InvoiceNumber** 要素の中心と **InvoiceHeader** 名の中心の間の距離を判定することを意味します。差分 (`Rect.XCenter - InvoiceHeader.Rect.XCenter`) が計算され、FlexiLayout Studio はこの差分が区間 \{-10000, 0, 0, 50000}\*dt に含まれるかどうかを確認します。

この説明では、field「請求書番号」が名前の下に配置される可能性も考慮しています。この場合、要素同士の距離が離れるほど、対応する仮説に対するペナルティは大きくなります。

番号が名前の右側にあると仮定する仮説は、番号が名前の下にあると仮定する仮説ほど大きなペナルティを受けません。これは、field「請求書番号」とその名前が「右側」に配置されるほうが、はるかに一般的だからです。

図(b)に示すように、区間の左境界と右境界に指定したパラメーターでは、最大ペナルティ (1) は、field「請求書番号」が名前fieldから左に10000dt、または右に50000dtずれた場合に対応します。

1000ドットのずれには、「左」へのずれであれば0.1、「右」へのずれであれば0.02のペナルティが課されます。同様に、100ドットのずれには、「左」へのずれであれば0.01、「右」へのずれであれば0.002のペナルティが課されます。

<Frame caption="(b)">
  <img src="https://mintcdn.com/abbyy/lqYknuOmCa79141v/images/flexi-capture/fls/graf2.gif?s=b17e957fd3f77e3ff8114dc14fe59d16" alt="請求書番号 field がその名前から水平方向にずれた場合の品質ペナルティを示す図。最大ペナルティ 1 は、左に10000dt、または右に50000dtずれた場合に対応します。" width="591" height="516" data-path="images/flexi-capture/fls/graf2.gif" />
</Frame>

行 `FuzzyQuality: Rect.YCenter - InvoiceHeader.Rect.YCenter, {-10000,0,0,10000} *dt;` は前のものと同じです。ただし、これは field「請求書番号」が名前のfieldと同じ高さにある場合、またはわずかに上にある場合のために用意されています。ここでのペナルティは、上下方向のずれであればどの場合も同じです。

区間の境界も、データfieldがその名前の右側で見つかる仮説を優先するという同じ考え方に従って設定されています。ただし、このプロジェクトでは、こうした設定を行っても、請求書番号が名前の下に配置されている場合 (3ページ目) でも正しく検出できることが示されています。

すべてのページに対してFlexiLayoutとのマッチングを行うと、探していた2つのfieldが正常に検出されていることがわかります。

結論として、`FuzzyQuality` 関数は `Nearest` グループの関数よりも効率的で柔軟性が高く、これは半構造化文書を処理する際に特に重要です。
