みなさん、こんにちは!業務ハックLabの「よう」です。
5月に入って、デスクの上の付箋が増えてきた今日このごろ。「この付箋、全部PCに打ち込まなきゃな…」と思いながら放置した経験、ありませんか?
今回はその「打ち直し地獄」を、Power AppsとGeminiの画像認識で解決する構成を実機検証してきました!
📋 この記事の要点
※ 2026年5月時点の情報です
- Power Apps のカメラ + Power Automate + Gemini 3.1 Flash Lite を組み合わせると、手書き付箋の内容を Microsoft Planner タスクとして自動登録できます。
Camera1.PhotoとCamera1.Streamの使い分けを間違えると Base64 が空になります。実装パターンを図解で解説します。- プロンプトで JSON 形式・日付形式を明示しないと、Power Automate のタスク登録がエラーになります。
- API 送信後、画面が止まったように見える場合がありますが正常動作です。Gemini が内部で思考プロセスを走らせているためです。
こんな方におすすめ: 手書きメモや付箋の打ち直し作業に時間を取られている非エンジニアの方、AI の画像認識を自分の業務アプリに組み込む方法を探している市民開発者・情シスの方。
AIの「目」をPower Platformに実装しよう
「画像認識 AI」というと、なんだか難しそうに聞こえますよね?
でも今回やることは、とてもシンプルです。Power Apps のカメラで付箋を撮影して、その画像を Gemini に「これ何て書いてある?JSON で返して」と聞く。返ってきた JSON を Power Automate が解析して、Planner にタスクを登録する——それだけです。
ノーコードで「AIの目」を業務アプリに組み込む、その具体的な構成をこの記事でまるっと解説します!

なぜ今Geminiなのか?マルチモーダルとJSON出力の強み
画像を含む複数のデータ形式をまとめて処理できる AI を「マルチモーダル AI」と呼びます。今回 Gemini を選んだ理由は主に 2 つです。
まず、JSON 形式での出力精度が高いこと。Power Automate でそのまま扱えるデータ形式を、プロンプト一発で返してくれます。あとでデータ整形する手間が激減します。
次に、Google AI Studio の無料枠で試せること。APIキーをすぐに発行できるため、検証コストゼロでスタートできます。ただし、無料枠は RPM(1分あたりのリクエスト数)と TPD(1日あたりのトークン数)に制限があります。画像認識+思考トークンの組み合わせはトークン消費が多く、連続して何度も実行するとレート制限に達しやすいです。本番運用を見据えた段階で有料枠への移行を検討してください。
💡 Tips: 今回使用した Gemini 3.1 Flash-Lite は「思考トークン」という内部推論プロセスを持っています。画像タスクではテキストのみの処理と比べて思考量が増えるため、レスポンスに多少の待ち時間が発生します。送信後に画面が止まったように見えても、フローは正常に動作しています。
⚠️ 業務データの取り扱いに注意:
Google AI Studio の無料枠では、送信した画像やプロンプトが Google の AI モデル改善に使用される場合があります。人間のレビュアーが確認するケースもあるため、業務上の機密情報・個人情報・顧客データを含む画像は絶対に送信しないでください。
本番運用で業務データを扱う場合は、必ず有料枠を使いましょう!
絶対ですよ!!
検証準備:コネクタを試したら落とし穴があった
まず Google AI Studio で API キーを取得します。Google AI Studio にアクセスし、「Get API key」から発行してください。発行したキーは後ほど Power Automate の HTTP アクションで使います。
さて、ここで正直に話します。(最初からうまくいかなかったんです)
当初は Power Automate の Google Gemini(Independent Publisher)コネクタの「Generate multi modal content」アクションを使う予定でした。コネクタなら設定も楽だし、いい感じだろうと。
ところが!実際に試したところ、全然うまくいかず・・・
たぶん僕の設定方法がおかしかったのかなと思うのですが色々試してみたけどうまくいかず・・・
(使ったことがある方おしえてください!)
いつまでも悩んでいてもしょうがないのでHTTPアクションを使う方法に切り替えました!
HTTP アクション直接呼び出しのほうが、むしろ自由度が高い。
コネクタを経由しないため、モデル名の変更も本文 JSON の構造変更も自在です。今後 Gemini のモデルがアップデートされても URI を書き換えるだけで追従できます。「コネクタの制限を回避するための次善策」ではなく、本番運用ではこちらが本命の構成と考えていいと思います。
HTTP アクションで呼び出すエンドポイントは以下です。
https://generativelanguage.googleapis.com/v1beta/models/gemini-3.1-flash-lite:generateContent?key=【APIキー】
僕の前回の記事を見ている方は「カスタムコネクタにしてしまってもいいんじゃない?」という方もいるのではないかと思います。
カスタムコネクタの作り方が気になる方は下記記事を読んでいただければと思います!(記事はClaudeのカスタムコネクタだけどね)

検証①:手書き付箋を撮ってPlannerにタスク自動登録
ここからが本題です。全体の流れは Power Apps でカメラ撮影 → Power Automate で Gemini API 呼び出し → Planner へタスク登録の 5 ステップです。
Step 1:Power Apps でカメラ撮影と Base64 取得
Power Apps にカメラコントロールとボタンを配置し、撮影した画像を Base64 文字列として取得します。ここはちょっとハマりポイントがあるので、丁寧に説明します。

Power Apps のカメラコントロールには Camera1.Photo と Camera1.Stream という 2 つのプロパティがあります。この使い分けを間違えると、Base64 の値が空になってフローが壊れます。
Camera1.Photo:カメラコントロール自身のOnSelect(シャッター)でしか値を持たない。ボタンのOnSelectから参照すると空になる。Camera1.Stream:現在のカメラフレームをリアルタイムで参照できる。ボタンのOnSelectからも値を取得できる。
正しい実装パターンはこちらです。
パターン A:カメラで撮影してから送信するケース
// カメラコントロールの OnSelect
Set(varPhoto, Camera1.Photo)
// 送信ボタンの OnSelect
Set(varBase64, JSON(varPhoto, JSONFormat.IncludeBinaryData));
PowerAutomateFlow.Run(varBase64)
パターン B:ボタン 1 つで撮影〜送信をまとめるケース
// ボタンの OnSelect(Camera1.Stream を直接使用)
Set(varBase64, JSON(Camera1.Stream, JSONFormat.IncludeBinaryData));
PowerAutomateFlow.Run(varBase64)
⚠️ 注意:
JSON()関数の戻り値は、外側にダブルクォーテーションが付いた形式になります。例:"data:image/png;base64,iVBORw0KGgo..."。フォーマットは JPEG ではなく PNG(data:image/png;base64,)です。この 2 点が後の Base64 除去処理に影響します。
但し環境によってはPNGではなくJPEGになる場合も有ります。
今回はPNG決め打ちで以降のPower Automateも設定していますが本番運用するならこの部分も動的に設定できるようにした方が良いかもしれません。

Step 2:Power Automate で Base64 プレフィックスを除去する
Gemini API に渡す Base64 文字列は、プレフィックス(data:image/png;base64,)を除去した純粋な Base64 データである必要があります。Power Apps から受け取った文字列を整形するために、以下の式を使います。
last(split(replace(triggerBody()['text'], '"', ''), 'base64,'))
「なぜこんなに複雑なのか」と思いますよね。理由は JSON() 関数の戻り値に外側のダブルクォーテーションが含まれているからです。
split(',')や split('base64,') だけ使っても、末尾に "(ダブルクォーテーション)が残ります。この状態で Gemini API に送ると Base64 decoding failed(400 エラー)が発生します。
そのため、①まず replace() でダブルクォーテーションを除去 → ②その後 base64, で split するという 2 段階処理が必要です。また、Gemini API に渡す mimeType には image/jpeg ではなく image/png を指定してください。
Step 3:HTTP アクションで Gemini 3.1 Flash-Lite に画像を送信する
HTTP アクションを追加し、以下の設定を行います。
- メソッド:
POST - URI:
https://generativelanguage.googleapis.com/v1beta/models/gemini-3.1-flash-lite:generateContent?key=【APIキー】 - ヘッダー:
Content-Type: application/json
本文の JSON 構造はこちらです。
{
"contents": [
{
"parts": [
{
"inline_data": {
"mime_type": "image/png",
"data": "[Step2で除去したBase64文字列]"
}
},
{
"text": "この画像に書かれている手書きのメモからタスク内容を抽出し、以下のJSON配列形式のみで出力してください。説明文は不要です。タスクが1件の場合も必ず配列形式にしてください。\n[{\"taskName\": \"タスク名\", \"deadline\": \"YYYY-MM-DDT00:00:00Z\"}]\n期限は必ずYYYY-MM-DDT00:00:00Z形式で出力してください。年が読み取れない場合は現在年(2026年)を使用してください。期限が読み取れない場合は\"未記載\"としてください。"
}
]
}
]
}
⚠️ ハマりポイント: 本文 JSON の中にプロンプトを書く際、プロンプト内のダブルクォーテーション(
")は必ず\"にエスケープしてください。エスケープを忘れると「適切な JSON を入力してください」と保存時エラーになります。

フローを実行すると、Gemini 3.1 Flash-Lite が画像を解析して結果を返します。
送信後、画面が止まったように見える場合がありますが正常です。Gemini は内部で思考プロセスを走らせてから回答を生成するため、画像タスクでは多少の待ち時間が発生します。フローがタイムアウトせずに完了するまでお待ちください。

Step 4:レスポンスのコードブロックを除去して JSON として解析する
Gemini のレスポンスには、JSON データが ```json と ``` で囲まれた状態で返ってくるケースが有ります。このままでは「JSON の解析」アクションがエラーになるため、除去処理が必須です。
プロンプトで制御しても良いのですが今回は関数で除去処理をしてしまいましょう。
「作成」アクションを追加し、以下の式を設定します。
replace(replace(outputs('HTTP')?['body']['candidates'][0]['content']['parts'][0]['text'], '```json', ''), '```', '')

続けて「JSON の解析」アクションを追加し、スキーマを配列型で定義します。
{
"type": "array",
"items": {
"type": "object",
"properties": {
"taskName": {"type": "string"},
"deadline": {"type": "string"}
}
}
}

Step 5:Planner にタスクを自動登録する
「Apply to each」コントロールで解析済み配列をループし、Planner の「タスクの作成」アクションを呼び出します。
ひとつ注意点があります。Planner の dueDateTime は ISO 8601 形式(YYYY-MM-DDT00:00:00Z)しか受け付けません。プロンプトで形式を明示指定しているため基本的には正しい形式で返ってきますが、deadline が「未記載」の場合は dueDateTime に値をセットしない条件分岐が必要です。
Apply to each の中に「条件」コントロールを追加し、deadline が 未記載 と等しくない 場合のみ日付をセットする分岐を作ります。

設定が完了したら実際に付箋を撮影してフローを実行してみます。
……無事に動きました!
Planner を開くと、付箋に書いたタスク名と期限がそのまま登録されています。

「AIへの指示が曖昧だとPower Automateが壊れる」——プロンプトエンジニアリングの重要性
今回の構成で気づいた重要な事実があります。Gemini へのプロンプトが曖昧だと、Power Automate 側でエラーが発生するということです。
具体的には、以下の 3 つのエラーを踏み、すべてプロンプトの改善で解決しました。
① コードブロック混入問題
Gemini は何も指定しないと JSON を ```json ~ ``` で包んで返します。「JSON 配列形式のみで出力してください。説明文は不要です。」と明記することで、余計な装飾が減ります(ただし完全にゼロにはならないため、除去処理は必須です)。
② タスク 1 件のときに配列にならない問題
タスクが 1 件だと Gemini が単体オブジェクト {...} で返す場合があり、配列を前提とした「JSON の解析」アクションがエラーになります。「タスクが 1 件の場合も必ず配列形式にしてください」をプロンプトに追記することで解決します。
③ 日付形式エラー
何も指定しないと Gemini は「5/7」のような日本語慣用形式で日付を返します。Planner の API は ISO 8601 形式のみ受け付けるため、プロンプトで YYYY-MM-DDT00:00:00Z 形式を明示指定する必要があります。
Power Automate と AI を繋ぐとき、「AI がどんなフォーマットで返すか」まで設計しないとフローは壊れます。プロンプトエンジニアリングはフロー設計の一部と考えるのが正解です。
📋 仕様メモ
・使用モデル: Gemini 3.1 Flash-Lite
・リリース状態: GA(2026年5月時点)
・APIエンドポイント: https://generativelanguage.googleapis.com/v1beta/models/gemini-3.1-flash-lite:generateContent
・mimeType: image/png
・参考: Google AI — Gemini API: Generate Content
まとめ:手書き転記から解放される未来、そして応用可能性
今回やってみて感じたのは、「AIの目」を業務アプリに組み込むハードルが想像より低かったということです。
Power Apps のカメラ + Power Automate の HTTP アクション + Gemini 3.1 Flash-Lite の組み合わせで、手書き付箋を Planner タスクとして自動登録する仕組みが作れました。Google Gemini コネクタの制限という予想外の壁がありましたが、HTTP アクション直接呼び出しという「本命の構成」にたどり着けたのは収穫でした。
そして、この構成は付箋タスクだけに留まりません。同じ仕組みで、冷蔵庫の中身を撮影して在庫リストを作ったり、棚卸し票を写真に撮ってスプレッドシートに転記したりといった用途にも応用できます。
ひとつ現実的な期待値設定をしておきます。カメラのピントが合っていないと手書き文字の認識精度は落ちます。「手入力ゼロを実現する魔法のツール」ではなく、「入力工数を 80% 削減する道具」として使う意識が長続きのコツです。残り 20% を人が確認する運用設計を最初から組み込んでおくと、現場での定着がスムーズになりますよ。
まずは Google AI Studio で API キーを取得して、Power Apps にカメラコントロールを置くところから始めてみてください!
今回はPower Automate × Gemini APIでしたがMicrosoft のエコシステム内で実行するのも面白そうですね。それについてはまた後日試して記事化してみたいと思います。
ちょっと宣伝
Geminiですが単体で契約することもできますがGoogle Workspaceとの連携をするとさらに便利に利用できます。
まだGoogle Workspaceを利用したことが無い、興味あるけど契約を迷っているという方はこの機に個人検証環境を構築してみてはどうでしょうか?
※注意:今回利用しているGemini APIはGoogle Workspaceを契約してもその月額内で利用できるものではないので要注意です。
あくまでGoogle Workspaceの契約内で使えるのはチャットベースのGeminiですのであしからず。
過去記事でGoogle Workspace環境の初期構築手順をまとめてますのでこちらも是非見てみてください。
Google Workspace Business Standard 導入手順|個人開発者が検証環境を作る全プロセス
また記事内にもありますがライセンス購入する際に下記紹介リンク経由で申し込むと10%OFFになりますのでよかったら使ってください!
それでは皆さん、良い業務ハックライフを~!

コメント