UiPath Document Understanding Process日本向けテンプレートの作り方（#2 フォーム抽出 CJK-OCR対策）

# はじめに

[UiPath Document Understanding Process日本向けテンプレートの作り方（#1 初期設定）](https://qiita.com/Jun96427231/items/0ab0c0c7d47b834714aa)の「5.7 フォーム抽出 CJK-OCR対策」の詳細を解説した記事です。

フォーム抽出で帳票が画像であった場合、CJK OCRの仕様で、日本文字コードの前後に半角スペースが挿入されています。そこでデータ抽出から検証までの間で、データ抽出結果のデータを変換して格納し直すためのカスタマイズについて解説します。

::: note warn
***前提***
2023年8月時点の仕様ですので、今後、UiPathのバージョンアップで日本語の単語が認識され、本対応は不要になる可能性があります。
:::

# 本記事のCJK-OCR対策前と対策後の比較

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/639319/6a088346-5898-ace8-0174-f21a4256f156.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/639319/aa670df0-1d6a-608a-b2c7-6d5865f1fdfa.png)

# CJK-OCRで日本語を読み取った時の仕様

単に半角スペースを削除してしまうと、サンプルの現住所にある"PARK CITY 110号"が"PARKCITY110号"になってしまい、元々、英単語は正しく読み取れているのに変換によって、劣化させてしまいます。CJK OCR(中日韓)の仕様に即した変換が必要です。

:::note warn
CJK OCR(中日韓)の読取りの仕様が公開されていないので、実際に使って見て蓄積するしかなさそうです。まだ、これ以外にあるかも知れませんが、参考として見てください。
:::

漢字、ひらがな、カタカナと
。、・「」
の文字を便宜上、CJK文字として表現します。

| 読取り対象 | 読取り後 |
|:-----------|:-----------|
| 英数字（半角）| ○ |
| 英数字（全角）| 全て半角に変換される。変換された数字の間には半角スペースが入る。 |
| CJK文字 | 文字の間に半角スペースが入る。 |
| カタカナ（半角） | カタカナ（全角）に変換される。文字の間に半角スペースが入る。 |
| 英数字（半角）の直後にCJK文字 | 半角スペースが入る。 |
| CJK文字の直後に英数字（半角） | 半角スペースが入る。 |
| CJK文字の間に連続したスペースを入れる | 半角スペース１つに変換される。 |
| 英数字（半角）の間に連続したスペースを入れる | 半角スペース１つに変換される。 |

# 変換するための正規表現
```ruby:正規表現
\x20(?=[ぁ-んァ-ヶー一-龯。、・「」])|(?<=[ぁ-んァ-ヶー一-龯。、・「」])\x20
```
**＜アクティビティを利用した正規表現による変換例＞**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/639319/c0acc200-4782-45cb-fb60-93279ee34729.png)

# Document Understanding Processで変換する場所

検証ステーションで人が確認してから変換されると２回確認する羽目になってしまいます。ですので、検証ステーションの前にデータを変換して置く必要があります。データ変換は、抽出している50_Extractに入れても良いですが、データ変換処理を通して、信頼度のチェックもできるので、ここではビジネスルールも兼ね、55_ExtractionBusinessRuleValidationに入れます。Document Understanding Processの全体構成から見た場所は下記の赤枠の部分です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/639319/a275e9ea-a853-6e65-541a-72b1c13e5932.png)



# 55_ExtractionBusinessRuleValidationで変換する箇所
ドキュメント処理する帳票がフォーム抽出なのか、タクソノミーマネージャのグループ名で判断できます。グループ名が「Structured Documents」の場合は、構造化ドキュメントのため、フォーム抽出であると、ここではルール付けさせて頂きました。グループ名はio_ExtractionResults.ResultsDocument.DocumentGroupで取得できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/639319/75c6f703-f609-d7a2-91ec-d32da357d3b6.png)

# UiPath.DocumentProcessing.Contracts下のコントラクト関連クラスについて

変換するデータはio_ExtractionResultsに格納されています。このUiPath.DocumentProcessing.Contracts下のコントラクト関連クラスにはカスタマイズに必要な各種情報が定義されているので、理解しておくと、今後のカスタマイズにとても有用です。

**＜ UiPathドキュメントポータルでの掲載場所 ＞**

https://docs.uipath.com/ja/activities/other/latest/document-understanding/document-processing-contracts-classes


# 変換すべきかの判定と、変換して格納し直す変数

フィールド単位でOCRの信頼度を見て変換すべきか判定します。文字取得できた場合は、OCRは機能せず、OCR信頼度は1なので、置き換えは不要です。もし、1より小さい場合はOCRが機能しているため、変換対象です。(PDFファイルでも、画像とテキストが混在する場合もあるので、フィールド単位で見ていく必要があります。)
OCRが機能していた場合は、人による検証はした方が良いので、信頼度フラグをFalseで返す様にして、変換後に検証できる様にします。

## フィールド内の文字列変換 ##
フィールドのOCR信頼度が1より小さい場合はOCRが機能しているのでデータを変換します。
```ruby:OCR信頼度
io_ExtractionResults.ResultsDocument.Fields(CurrentIFields).Values(CurrentValues).OcrConfidence
```

抽出したデータの信頼度も取得できます。1より小さい場合は、人による検証はした方が良いので、信頼度フラグをFalseで返す様にして、必ず検証する様に返します。

```ruby:抽出データの信頼度
io_ExtractionResults.ResultsDocument.Fields(CurrentIFields).Values(CurrentValues).Confidence
```
置き換えるデータの格納場所は下記でアクセスできます。
```ruby:データ格納場所
io_ExtractionResults.ResultsDocument.Tables(CurrentITables).Values(CurrentValues).Cells(CurrentCells).Values(CurrentItem).Value
```

## テーブル内の文字列変換 ##
帳票内のテーブルもフィールドと同じ様に処理します。

テーブル内にあるセルのデータのOCR信頼度が1より小さい場合はOCRが機能しているのでデータを変換します。

```ruby:OCR信頼度
io_ExtractionResults.ResultsDocument.Tables(CurrentITables).Values(CurrentValues).Cells(CurrentCells).Values(CurrentItem).OcrConfidence
```

抽出したセルのデータの信頼度が1より小さい場合は、人による検証はした方が良いので、信頼度フラグをFalseで返す様にして、必ず検証する様に返します。

```ruby:抽出データの信頼度
io_ExtractionResults.ResultsDocument.Tables(CurrentITables).Values(CurrentValues).Cells(CurrentCells).Values(CurrentItem).Confidence
```

置き換えるデータの格納場所は下記でアクセスできます。

```ruby:データ格納場所
io_ExtractionResults.ResultsDocument.Tables(CurrentITables).Values(CurrentValues).Cells(CurrentCells).Values(CurrentItem).Value
```

# サンプル帳票（厚生労働省様式の履歴書）におけるビジネスルールの考察
このサンプル（厚生労働省の履歴書様式）の場合で考察します。
文書の種類が今回定義した厚生労働省の履歴書テンプレートであった場合は、フォーム抽出が実行されますが、全てのフィールドとテーブルのOCR信頼度が1（全て文字取得可のファイル）、抽出信頼度も1(信頼度が100%)であった場合は、人による検証をスキップさせるビジネスルールとした場合は、下記の様に追加します。
out_AutoExtractionSuccessをFalseにすると、呼び出し側のMainワークフローで人による検証が実行され、Trueにすると人による検証がスキップされます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/639319/4da559cf-e62e-3586-226b-d0b0deb6c640.png)

:::note info

***補足***
1. アセット「AlwaysValidateExtraction」の値がTrueのままでは、常に手動による検証が行われます。
1. out_AutoExtractionSuccessに設定しているConfidence値は「変換すべきかの判定と、変換して格納し直す」処理を行う際に設定しています。
1. 文書の種類は、io_ExtractionResults.ResultsDocument.DocumentTypeIdで識別でき、判定する値はタクソノミーマネージャから取得できます。

***タクソノミーマネージャでの取得場所***
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/639319/3ef0ab75-7696-6523-8175-6367dff06215.png)

:::

# おわりに
本記事の対策を入れることにより、検証時の手修正は、かなり減らせます。
ただし、完璧に変換されると言うものではありません。例えば上記のサンプルで言うと、氏名の苗字と名前の間にスペースがなくなってしまうと言う課題が残ります。この様な対策はロジックで対応が難しいため、検証時に人による判断でスペースを入れる修正を行うか、AIに補助させるか、どちらかになると思います。
尚、氏名の苗字と名前の間にスペースを入れた変換をChatGPTも組み合わせて改善する方法を下記の記事で紹介しています。

https://qiita.com/Jun96427231/items/bfff4bbb58de5289ae68