AI Builderを使って何らかアプリを作ってみよう!となった時、真っ先に思いつくのはテキスト認識を利用した画像の文字抽出かなと思います。 テキスト認識には事前構築済みのAIモデルがあり、頑張ってサンプル画像を大量に用意してトレーニングをさせることなく、パッと使い始めることができ、かつ日本語に対応しています。
テキスト認識をPower Apps上で利用する場合には、専用のコントロールを追加してあげるだけです。
このコントロールには画像のアップロードボタンがあり、ここから画像を選択すればすぐに事前構築済みのモデルを利用しての文字抽出が開始されます。
読み取った結果は、TextRecognizer.Resultsというプロパティに一覧で格納されており、例えばこれをギャラリーコントロールに設定すれば読み取り結果の一覧をアプリで表示させることができます。
ここで表示しているような文章を読み取るのであれば、これで特に問題はないでしょう。一方でよくあるユースケース、レシートの読み取りなどを実行すると少しこまった一覧になります。
お判りでしょうか? テキスト認識では、ある程度文字が離れていても同じブロックとして認識してくれますが、レシートのように品名が左詰めで金額が右詰めというレイアウトだとどうしても品名と金額が2つの結果として出力されてしまいます。
今回はこのちょっと使いづらい感じを少し改善して、ある程度行ごとにまとめるようにする方法を紹介します。
考え方
幸いなことにテキスト認識の結果には各ブロックの座標 (左上のXY座標)と幅+高さが含まれています。 TextRecognizer.Results の中に BoundingBox というプロパティがあり、ここに Top, Left, Height, Width の4つの値が格納されています。
レシートの行ごとにまとめたいので、Topの座標でグループ化すればいいか!と思うんですが実際やってみるとあまりうまくいきません。小数点以下8桁とかまで持っているのでそろわないんですね。
そこで、下図のようなアプローチをとります。
読み取り結果の座標を利用して、結果を左から右、上から下となるように並び替えます。
並び替え後、隣接する結果の右端と左端の座標を比べて、折り返しがあるかの判定を行います。
それほど難しくはないですね。
Power Appsでの実装
Power Appsでの実装はそれほど複雑ではないです。
やることは...
BoundingBox.Top
など、階層が深いところにある座標をAddColumns
で階層をあげるSortByColumns
を使って、左から右、上から下にソートする- 各アイテムに連番を振る
- 条件判定をして改行文字を入れて、最後に改行文字でSplit
です。
GalleryのItemsに以下をセットしてみましょう。
With( { //まずはここで各座標の階層をあげて、ソートまで実行 src: SortByColumns( AddColumns( TextRecognizer1.Results, "top", BoundingBox.Top, "left", BoundingBox.Left, "right", (BoundingBox.Left + BoundingBox.Width) ), "top", Ascending, "left", Ascending ) }, With( { //各アイテムに連番を振る tmp: AddColumns( Sequence(CountRows(src)), "val", Last(FirstN(src, Value)) ) }, //残りの処理。各アイテムの右端と次のアイテムの左端を比べながら、改行文字をいれてConcatで結合 //さらに出来上がった結果を改行文字でSplit Split( Concat( AddColumns( RenameColumns(tmp, "Value", "id"), "txt", If( val.right > LookUp(tmp, Value = id + 1).val.left, val.Text & "<br>", val.Text & " " ) ), txt, "" ), "<br>" ) ) )
設定したギャラリーコントロールで結果を表示させてみると
なんとなくうまく各行を再構成できていますね。
ということで、便利なAI Builderのテキスト認識の結果をちょっといい感じに再構成する方法をご紹介しました。
とにかく左から右、上からしたに並び替えするのが重要だということですね。
注意
最後に書くことでもないですが、AI Builderは有償ライセンスが必要ですので、そこだけご注意ください。