TECH PLAY

ゲーム

イベント

マガジン

技術ブログ

みなさん、こんにちは。ソリューションアーキテクトの戸塚です。今週も 週刊AWS をお届けします。 だんだんと春めいてきて、花粉症に悩まされている方も多いのではないでしょうか。私はというと、今年はなぜか症状がほとんど出ず、久しぶりに快適に仕事ができています。 NRF 2026 で注目されたリテール AI の最新動向を扱う流通・小売・消費財むけイベントを 4月20日 に開催します。 「リテールの現場では「AIエージェントが“主”、人間が“従”」に AWSジャパン・五十嵐氏に聞く小売業界におけるマルチエージェントの台頭」 こちらの記事 をご参照いただき、AWS メンバーへ気軽にお声がけください。 それでは、先週の主なアップデートについて振り返っていきましょう。 2026年3月23日週の主要なアップデート 3/25(水) Amazon Bedrock AgentCore Runtime が永続的なエージェントファイルシステム状態のためのマネージドセッションストレージをサポート開始 (プレビュー) Amazon Bedrock AgentCore Runtime で、エージェントのファイルシステム状態を永続化できる機能がプレビュー開始されました。これまで AI エージェントがコードを書いたりパッケージをインストールしても、セッション終了時に全て失われていました。新機能により、エージェントが作成したファイルやインストールしたパッケージが自動的に保存され、次回のセッションでも継続して作業できるようになります。最大 1GB まで、14 日間データを保持します。詳細は こちらのドキュメントをご参照ください。 Amazon SageMaker HyperPod が Slurm オーケストレーションクラスターの継続プロビジョニングをサポート Amazon SageMaker HyperPod の Slurm 環境で連続プロビジョニング機能が利用可能になりました。従来は一部のインスタンスグループでプロビジョニングが失敗すると、クラスター全体の作成や拡張が失敗してロールバックされていました。今回のアップデートにより、利用可能なインスタンスで即座に AI/ML トレーニングを開始でき、バックグラウンドで残りの容量を自動的にプロビジョニングします。失敗したノードは非同期で再試行され、複数のインスタンスグループでの同時スケーリングも可能です。CreateCluster API で NodeProvisioningMode を Continuous に設定することで有効化できます。詳細は こちらのドキュメントをご参照ください。 P6-B300 と Slurm 25.11 をサポートした AWS ParallelCluster 3.15 AWS ParallelCluster 3.15 が一般提供開始となり、最新の NVIDIA Blackwell GPU を搭載した P6-B300 インスタンスと Slurm 25.11 をサポートしました。これにより AI/ML や高性能コンピューティング (HPC) ワークロードをより高性能な環境で実行できるようになります。EFA ネットワーク設定の改善や大規模クラスターでの密結合ワークロードの性能向上も実現し、科学技術計算がより効率的に処理できます。詳細は こちらのリリースノートをご参照ください。 AWS Transfer Family Applicability Statement 2 (AS2) が MDN の非同期受信をサポート AWS Transfer Family の AS2 で、非同期での MDN (Message Disposition Notifications) 受信がサポートされました。従来は同期のみでしたが、取引先の処理時間やネットワーク遅延に関係なく AS2 ワークフローを移行できます。ヘルスケアや製造業などでパートナーとの安全なデータ交換が可能になります。詳細は こちらのドキュメントをご参照ください。 Amazon SageMaker AI が 12 の追加モデルに対してサーバーレス強化学習ファインチューニングをサポート Amazon SageMaker AI で 12 の新しいモデルに対してサーバーレス強化学習ファインチューニングが利用可能になりました。これまではインフラの準備や管理が必要でしたが、今回のアップデートにより Qwen や DeepSeek シリーズなどの最新モデルを手軽にカスタマイズできます。特にコード生成や数学的推論など、従来の教師あり学習では難しかった複雑なタスクに対応可能で、従量課金制のため小規模な実験からでも始められます。バージニア北部、オレゴン、東京、アイルランドリージョンで提供中です。 Amazon Aurora PostgreSQL が数秒でのデータベース作成と接続をサポート Amazon Aurora PostgreSQL で Express Configuration という新機能が登場し、サーバーレスデータベースを数秒で作成・接続できるようになりました。従来は VPC やネットワーク設定に時間がかかっていましたが、事前設定済みの構成により初期セットアップが大幅に高速化されています。インターネットアクセスゲートウェイが自動で設定され、 VPN や AWS Direct Connect なしで開発ツールから直接接続可能です。また IAM 認証がデフォルトで有効化されるため、パスワード不要でセキュアにアクセスできます。 AWS Free Tier でも利用可能なので、 PostgreSQL を手軽に試したい開発者には最適です。詳細は こちらの Blog 記事をご参照ください。 Amazon Aurora PostgreSQL が AWS 無料利用枠で利用可能になりました Amazon Aurora PostgreSQL が AWS 無料枠で利用可能になりました。新規ユーザーはサインアップ時に 100 ドルのクレジットを取得でき、追加で 100 ドルのクレジットも獲得できます。従来は有料プランでしか利用できなかった高性能な PostgreSQL データベースを、無料で試すことができるようになったのが大きなメリットです。express configuration を使えば数秒でデータベースを作成・クエリ実行が可能で、学習コストを大幅に削減できます。詳細は こちらをご参照ください。 Amazon Route 53 Profiles がリソースと VPC 関連付けに対する詳細な IAM 権限をサポート Amazon Route 53 Profiles で細かい IAM 権限設定が可能になりました。これまでは Profile 全体への権限管理でしたが、今回のアップデートでプライベートホストゾーンや DNS Firewall ルールなど、特定のリソースタイプごとに権限を制御できます。例えば、特定の VPC への関連付け操作のみを許可したり、特定のドメイン名のルールだけ編集権限を与えるといった細かな権限設定が実現できます。組織内で DNS 管理の責任を分散させつつ、セキュリティを保てるため大規模な環境での運用が格段に楽になります。詳細は こちらのドキュメントをご参照ください。 3/26(木) AWS Advanced JDBC Wrapper が Valkey による自動クエリキャッシュをサポート AWS Advanced JDBC Wrapper が Valkey を使った自動クエリキャッシュ機能をサポートしました。従来は JDBC クエリの結果をキャッシュするために、開発者が手動でコードを書く必要がありましたが、今回のアップデートで数ステップの簡単な設定だけで自動化できるようになりました。Aurora や RDS の PostgreSQL、MySQL、MariaDB データベースのクエリ結果を Amazon ElastiCache for Valkey に保存し、頻繁にアクセスするデータの読み取り遅延を削減できます。これによりデータベースへの読み取り回数が減り、パフォーマンス向上とコスト削減を実現できます。Hibernate や Spring Data といった人気フレームワークにも対応しているため、既存のアプリケーションへの導入も簡単です。詳細は こちらのドキュメントをご参照ください。 AWS AppConfig がフィーチャーフラグロールアウト中の拡張ターゲティングを追加 AWS AppConfig にフィーチャーフラグの段階的ロールアウト中に特定のユーザーやセグメントをターゲットできる新機能が追加されました。従来は段階的デプロイメント中に特定のユーザーグループだけに絞って配信することが難しかったのですが、今回のアップデートにより個別の ユーザー ID やセグメント単位での細かい制御が可能になります。これにより新機能のリリース時のリスクを大幅に削減でき、A/B テストや段階的な機能展開がより安全に実施できるようになります。詳細は こちらのドキュメントをご参照ください。 Writer の Palmyra Vision 7B が Amazon Bedrock で利用可能に Amazon Bedrock で Writer の Palmyra Vision 7B モデルが利用開始されました。このモデルは画像を理解してテキストを生成する AI で、文書分析やチャート解釈、手書き文字の抽出などが可能です。これまで画像内容を理解するには別のツールが必要でしたが、Bedrock 上で簡単に画像理解機能を組み込めるようになります。詳細は こちらのドキュメントをご参照ください。 3/27(金) Amazon GameLift Servers が次世代 EC2 インスタンスファミリーでインスタンスサポートを拡張 Amazon GameLift Servers が EC2 第 5 ~ 8 世代インスタンスに対応しました。これまでより新しい世代の EC2 インスタンスを利用できるようになり、ゲームサーバーのホスティングにおいて価格性能比の向上と効率性が実現されます。汎用 (M シリーズ)、コンピューティング最適化 (C シリーズ)、メモリ最適化 (R シリーズ) の 3 つのインスタンスファミリーから、ゲームの負荷特性に応じて最適な選択が可能です。詳細は こちらのドキュメントをご参照ください。 AWS Management Console でサービスとリージョンの表示を制御する設定をサポート開始 AWS Management Console で、表示するサービスとリージョンを制御できる設定が一般提供開始されました。これまで全てのサービスやリージョンが表示されていましたが、必要なもののみを表示することでナビゲーションが簡素化され、チームメンバーが利用可能なリソースを素早く特定できます。アカウント設定の Unified Settings から設定でき、CLI や SDK からのプログラム設定にも対応しています。詳細は こちらのドキュメント をご参照ください。 AWS Lambda が Lambda マネージドインスタンスで最大 32 GB のメモリと 16 vCPU をサポート AWS Lambda Managed Instances で最大 32 GB のメモリと 16 vCPU がサポートされるようになりました。これまでは 10 GB メモリと約 6 vCPU が上限でしたが、大規模なデータ処理やメディア変換などの計算集約的なワークロードも実行可能になります。メモリ対 vCPU の比率 (2:1、4:1、8:1) も選択でき、ワークロードの特性に合わせて最適なリソース配分を設定できます。詳細は こちらのドキュメントをご参照ください。 Amazon CloudWatch Logs が Infrequent Access 取り込みクラスでデータ保護、OpenSearch PPL、OpenSearch SQL をサポート開始 Amazon CloudWatch Logs の Infrequent Access (IA) クラスで、データ保護機能と OpenSearch PPL / SQL クエリがサポートされました。従来は Logs Insights のみでしたが、今回のアップデートにより SQL ベースの高度な分析が可能になります。また、ログ内の機密情報を自動検出・マスキングできるため、セキュリティ要件を満たしながらコスト効率的にログを統合できます。詳細は こちらのドキュメントをご参照ください。 今週はアップデートの内容に少し偏りがあり、月・火は落ち着いていた一方で、週の後半に多くの更新が集中しました。 Bedrock まわりのアップデートが引き続き活発に行われる中、Webアプリ構築でよく使う基本サービスにも多くの改良がありました。特に、Amazon Aurora PostgreSQL がついに無料利用枠で使えるようになったのは大きな変化で、今後は Aurora を活用したアプリ開発がさらに進みそうだと感じています。 それでは、また来週お会いしましょう! 著者について 戸塚 智哉(Tomoya Tozuka) / @tottu22 飲食やフィットネス、ホテル業界全般のお客様をご支援しているソリューション アーキテクトで、AI/ML、IoT を得意としています。最近では AWS を活用したサステナビリティについてお客様に訴求することが多いです。 趣味は、パデルというスペイン発祥のスポーツで、休日は仲間とよく大会に出ています。
はじめに はじめまして。 KINTO テクノロジーズで KINTO Unlimited Android アプリを開発している JR.Liang です。 本記事では、KINTO Unlimited アプリにて提供する「これなにガイド」スキャン機能の AR エフェクトについて、Android における技術的な検証を紹介します。 特に MediaPipe のソリューションを用いて幅広い Android デバイスで AR エフェクトを実現した実装にフォーカスします。 これなにガイドとは 「これなにガイド」は AR(拡張現実)を活用して、車内スイッチの用途や使い方をテキストと動画で案内する機能です。紹介動画をご覧ください。 https://youtube.com/watch?v=E8zfNzuHr7g&embeds_referring_euri=https%3A%2F%2Fcorp.kinto-jp.com%2F&source_ve_path=MjM4NTE 上記の紹介動画は iOS アプリでの動作を示しています。スイッチ上に表示された黄色の丸 🟡 が、AR 技術で実現した仮想コンテンツです。 機能全体の仕組みは以下の流れです。本記事では 3 番目(描画)に関する内容を扱います。 1. アプリのカメラを起動、カメラ画像を取得 2. 機械学習における物体認識を用いて、車内のスイッチを検出 3. 検出した座標を元に、ボタンとテキストをフレーム上に描画 4. ボタンをタップして、当該スイッチのテキストと動画を表示 Android AR 技術検証の経緯 当初の Android 版「これなにガイド」のスキャン機能では、Canvas を利用して毎フレーム検出される座標に描画する実装でした。そのため検出の時間差により、スマホ(カメラ)を動かすと描画のズレが生じていました。 2D Canvas 幸い、MediaPipe のソリューションである Instant Motion Tracking モジュールで 素早くかつ安定した AR エフェクトを実現できることがわかり、Android への導入を検証しました。 3D OpenGL MediaPipe Instant Motion Tracking MediaPipe は Google が開発したオープンソースの ML フレームワークで、顔検出・手のトラッキング・姿勢推定などリアルタイム映像処理のソリューションを提供します。 その中の Instant Motion Tracking は、現実世界のシーン上に 3D 仮想コンテンツをリアルタイムで正確に配置できる AR トラッキング機能です。初期化や厳密なキャリブレーションが不要で、静止面や動いている面の上にコンテンツを置くことが可能です。 @ card Android + MediaPipe AR アーキテクチャ graph TB A(Android CameraX) --> |Camera Frame| B(Instant Motion Tracking) B --> |Camera Image| C(TensorFlow Object Detection) C --> |Detections Information| B(Instant Motion Tracking) B --> |Output Stream| D(Android Surface Rendering) CameraX で取得したフレームを Instant Motion Tracking に渡し、TensorFlow Lite で物体検出した情報を元に AR コンテンツを描画・追従させるパイプラインです。 MediaPipe ライブラリの作成 MediaPipe では Bazel を使用してパッケージをビルドします。Android に適合する AAR として書き出してアプリに組み込みます。 https://chuoling.github.io/mediapipe/getting_started/android_archive_library.html AAR をビルドする BUILD ファイルを作成し、 instant_motion_tracking を基盤とした定義を記述します。 load("//mediapipe/java/com/google/mediapipe:mediapipe_aar.bzl", "mediapipe_aar") mediapipe_aar( name = "mediapipe_ar", calculators = ["//mediapipe/graphs/instant_motion_tracking:instant_motion_tracking_deps"] ) MediaPipe は C++ が中核のため、C++ ランタイムである libc++_shared.so を AAR に同梱する必要があります。 https://github.com/google-ai-edge/mediapipe/blob/v0.10.32/third_party/BUILD#L399-L403 また Instant Motion Tracking では画像処理ライブラリ OpenCV を利用し、AR トラッキングを行います。 https://github.com/google-ai-edge/mediapipe/blob/v0.10.32/WORKSPACE#L649-L655 上記サードパーティのライブラリを含めて、以下のコマンドで AAR をビルドします。 bazel build -c opt --strip=ALWAYS \ --host_crosstool_top=@bazel_tools//tools/cpp:toolchain \ --fat_apk_cpu=arm64-v8a \ --linkopt=-Wl,-z,max-page-size=16384 \ //path/to/the/aar/build/mediapipe_ar:mediapipe_ar.aar 市場に流通している Android デバイスは主に arm64-v8a アーキテクチャのため、AAR のサイズを抑える目的で fat_apk_cpu=arm64-v8a にします。 C++ ライブラリの 16KB page-size に対応するため、 max-page-size=16384 を追加します。 また AAR を利用するにはグラフ構造を定義するファイル( binarypb )が必要です。 bazel build -c opt mediapipe/graphs/instant_motion_tracking:instant_motion_tracking.binarypb Instant Motion Tracking の導入 AAR をアプリに組み込んで、Android 側の実装を解説していきます。 下記は AAR に組み込んだ instant_motion_tracking の全体構造です。 instant_motion_tracking.pbtxt の構成 グラフ定義ファイル instant_motion_tracking.pbtxt は、Calculator(処理ノード)・入出力ストリーム・サイドパケットの 3 要素で構成されます。 Calculator 各 Calculator がパイプライン上でどの処理を担うかを示します。 Calculator 役割 ImageTransformationCalculator カメラフレームを 320×320(FIT)にリサイズ。物体検出モデルの入力サイズに合わせる GpuBufferToImageFrameCalculator GPU テクスチャを CPU の ImageFrame に変換。TensorFlow Lite 推論に使用 StickerManagerCalculator Sticker Proto をパースし、初期アンカーの座標・回転・スケール・レンダリング種別に分解 RegionTrackingSubgraph ボックストラッキングでアンカー位置を追従。内部に TrackedAnchorManagerCalculator (アンカー管理)と BoxTrackingSubgraphGpu (GPU トラッキング)を持つ MatricesManagerCalculator トラッキング結果・回転・スケール・FOV・アスペクト比から OpenGL 用 4×4 モデル行列を生成 GlAnimationOverlayCalculator モデル行列とテクスチャを用いて、元のカメラフレーム上に AR コンテンツを OpenGL で描画し output_video として出力 input_stream / output_stream input_stream はフレームごとに Android 側から送信するデータ、 output_stream はグラフの処理結果です。 ストリーム名 C++ 型 方向 用途 input_video GpuBuffer Input カメラフレーム sticker_proto_string String(Serialized Proto) Input ステッカーの座標・スケール等(Sticker Proto) sticker_sentinels vector Input 座標をリセットするステッカー ID の配列 gif_textures vector Input AR コンテンツの Bitmap テクスチャ配列 gif_aspect_ratios vector Input 各テクスチャのアスペクト比 output_video GpuBuffer Output AR 描画済みフレーム input_side_packet input_side_packet は初期化時に一度だけ渡す定数で、グラフ実行中は変化しません。 パケット名 用途 vertical_fov_radians カメラの垂直 FOV(ラジアン) aspect_ratio カメラのアスペクト比 width / height カメラ解像度 gif_texture デフォルトテクスチャ(1x1 プレースホルダ) gif_asset_name AR テクスチャ描画用のポリゴンメッシュ( .obj )ファイル名 Android への導入に当たって、公式サンプルのコードを参考にします。 https://github.com/google-ai-edge/mediapipe/tree/master/mediapipe/examples/android/src/java/com/google/mediapipe/apps/instantmotiontracking 1. 初期化 MediaPipe を使用する前に、ネイティブライブラリの読み込みとアセットマネージャーの初期化が必要です。 companion object { init { System.loadLibrary("mediapipe_jni") System.loadLibrary("opencv_java4") } } // onCreate 相当の処理 AndroidAssetUtil.initializeNativeAssetManager(context) mediapipe_jni : MediaPipe のコア処理を行う JNI ライブラリ opencv_java4 : AR トラッキングに使用する OpenCV ライブラリ initializeNativeAssetManager : ネイティブコードからアセット(binarypb 等)にアクセスするために必要 2. カメラを起動する 公式サンプルを参考に、以下の順序でパイプラインを構築します。 データフロー: CameraX → ExternalTextureConverter → FrameProcessor → SurfaceView 2.1 EGL 環境と FrameProcessor の初期化 val eglManager = EglManager(null) val frameProcessor = FrameProcessor( context, eglManager.nativeContext, "instant_motion_tracking.binarypb", "input_video", "output_video" ).apply { videoSurfaceOutput.setFlipY(true) setInputSidePackets( mapOf( "gif_asset_name" to packetCreator.createString("gif.obj.uuu"), "vertical_fov_radians" to packetCreator.createFloat32(fovRadians), "aspect_ratio" to packetCreator.createFloat32(resolution.width.toFloat() / resolution.height.toFloat()), "width" to packetCreator.createInt32(resolution.width), "height" to packetCreator.createInt32(resolution.height), "gif_texture" to packetCreator.createRgbaImageFrame(createBitmap(1, 1)) ) ) } EglManager : OpenGL ES の EGL コンテキストを作成・管理。MediaPipe のグラフ内 GPU Calculator( GlAnimationOverlayCalculator 等)が OpenGL で描画するために必要 FrameProcessor : EGL コンテキストを受け取り、グラフの読み込み・入出力ストリームの管理・フレームごとのグラフ実行を行う instant_motion_tracking.binarypb : .pbtxt を Bazel でコンパイルしたグラフ定義バイナリ input_video : MediaPipe グラフへカメラフレームを入力 output_video : グラフで処理(AR 描画など)された映像を出力 videoSurfaceOutput.setFlipY(true) : OpenGL とカメラの Y 軸方向が逆のため、出力映像を上下反転して正しい向きにする setInputSidePackets : グラフの input_side_packet に対応する定数をまとめて設定。カメラの FOV・アスペクト比・解像度など、グラフ実行中に変化しない値を初期化時に一度だけ渡す gif_asset_name は AR テクスチャを描画するための ポリゴンメッシュ(頂点データ) 、ここでは公式サンプルの gif.obj.uuu を利用 2.2 カメラ映像の変換パイプライン構築 val externalTextureConverter = ExternalTextureConverter(eglManager.context, 2).apply { setFlipY(true) setConsumer(frameProcessor) setDestinationSize(resolution.width, resolution.height) } val cameraHelper = object : CameraXPreviewHelper() { override fun getCameraCharacteristics(context: Context?, lensFacing: Int?) = cameraCharacteristics }.apply { setOnCameraStartedListener(onCameraStartedListener) startCamera( context, lifecycleOwner, CameraHelper.CameraFacing.BACK, externalTextureConverter.surfaceTexture, Size(resolution.height, resolution.width) ) } ExternalTextureConverter : カメラの GL_EXTERNAL_OES テクスチャを MediaPipe が処理できる標準テクスチャに変換 setFlipY(true) : カメラ映像の上下反転を補正 setDestinationSize(resolution.width, resolution.height) : パイプラインの処理サイズはポートレート座標(例: 960×1280 )で指定 CameraXPreviewHelper : CameraX でバックカメラを起動し、Converter の SurfaceTexture に出力 startCamera(targetSize = Size(resolution.height, resolution.width)) : CameraX はセンサー座標(ランドスケープ)を期待するため、width と height を入れ替えて渡す 公式サンプルでは CameraXPreviewHelper をそのまま使用し、内部で CameraManager からカメラ特性を取得します。 https://github.com/google-ai-edge/mediapipe/blob/v0.10.32/mediapipe/java/com/google/mediapipe/components/CameraXPreviewHelper.java#L558-L560 本実装では getCameraCharacteristics をオーバーライドし、事前に取得済みの CameraCharacteristics を直接渡します。これにより FOV やアスペクト比の算出に使うカメラ情報を、アプリ側で一元管理できます。 2.3 出力先SurfaceViewの設定 SurfaceView(context).apply { holder.addCallback(object : SurfaceHolder.Callback { override fun surfaceCreated(holder: SurfaceHolder) { frameProcessor.videoSurfaceOutput.setSurface(holder.surface) } override fun surfaceChanged(holder: SurfaceHolder, format: Int, width: Int, height: Int) { val displaySize = cameraHelper.computeDisplaySizeFromViewSize(Size(width, height)) val (displayWidth, displayHeight) = if (cameraHelper.isCameraRotated) { displaySize.height to displaySize.width } else { displaySize.width to displaySize.height } externalTextureConverter.setDestinationSize(displayWidth, displayHeight) } override fun surfaceDestroyed(holder: SurfaceHolder) { frameProcessor.videoSurfaceOutput.setSurface(null) } }) } SurfaceHolder.Callback : SurfaceView のライフサイクルに応じて FrameProcessor の出力先を管理 surfaceCreated : FrameProcessor の出力先として Surface を設定 surfaceChanged : 画面回転・サイズ変更時に出力解像度を調整 surfaceDestroyed : リソース解放 3. 検出座標をグラフに渡す 物体検出(TensorFlow Lite 等)で得られた座標を MediaPipe グラフに渡し、AR コンテンツを配置します。 3.1 グラフから変換済み画像を取得 MediaPipe グラフ内で ImageTransformationCalculator と GpuBufferToImageFrameCalculator によって変換された画像を addPacketCallback で受け取り、物体検出に使用します。 frameProcessor.addPacketCallback("transformed_input_video_cpu") { packet -> packet ?: return@addPacketCallback // 変換済み画像を物体検出(TensorFlow Lite)に渡す val bitmap = PacketGetter.getBitmapFromRgba(packet) objectDetector.detect(bitmap) { detections -> // 検出結果を処理 } } transformed_input_video_cpu : 変換後の画像を出力するストリーム名 3.2 座標の正規化 物体検出結果のピクセル座標を、MediaPipe が期待する正規化座標に変換します。 // ピクセル座標 → 正規化座標 (0.0〜1.0) val normalizedX = pixelX / imageWidth.toFloat() val normalizedY = pixelY / imageHeight.toFloat() 3.3 Sticker Proto の構造 Instant Motion Tracking では、AR オブジェクトの位置情報を Protocol Buffers 形式で定義します。 message Sticker { int32 id = 1; // ユニークID float x = 2; // 正規化X座標 (0.0〜1.0) float y = 3; // 正規化Y座標 (0.0〜1.0) float rotation = 4; // 回転角度 float scale = 5; // スケール int32 render_id = 6; // レンダリングID } message StickerRoll { repeated Sticker sticker = 1; } 3.4 フレームごとにパケットを送信 setOnWillAddFrameListener を使用して、各フレーム処理前に検出座標をグラフへ送信します。 frameProcessor.setOnWillAddFrameListener { timestamp -> with(frameProcessor.graph) { // 検出された物体の座標情報をパケットとして送信 val stickerRoll = StickerRoll.newBuilder() .addAllSticker(detectedObjects.map { detection -> Sticker.newBuilder() .setId(detection.id) .setX(detection.normalizedX) // 0.0〜1.0 .setY(detection.normalizedY) // 0.0〜1.0 .setScale(detection.scale) .build() }) .build() val stickersPacket = packetCreator.createSerializedProto(stickerRoll) addPacketToInputStream("sticker_proto_string", stickersPacket, timestamp) } } FrameProcessor.setOnWillAddFrameListener : 各フレームがグラフに送られる直前に呼ばれるコールバック FrameProcessor.graph.addPacketToInputStream : 入力ストリームにパケットを追加 sticker_proto_string : グラフ定義で指定された入力ストリーム名 4. テクスチャ(Bitmap)の描画と送信 位置情報と同時に、AR コンテンツとして描画する Bitmap テクスチャもグラフに渡します。 4.1 Bitmap テクスチャの生成 検出された各スイッチに対して、丸アイコンとラベルテキストを含む Bitmap を生成します。 val bitmap = createBitmap(width.toInt(), height.toInt()).apply { with(Canvas(this)) { concat(Matrix().apply { preScale(-1.0f, 1.0f, width / 2f, height / 2f) // X軸を反転して描画 }) drawCircle(circleX, circleY, CIRCLE_RADIUS, circlePaint) drawRect(rectLeft, rectTop, rectRight, rectBottom, backgroundPaint) } } Matrix().preScale(-1.0f, 1.0f) で Bitmap を左右反転しています。以下の IMU 行列に合わせるためです。 float imu_matrix[9] = { -1.0f, 0.0f, 0.0f, // X軸 → 反転(-X) 0.0f, 0.0f, 1.0f, // Y軸 → Z軸へ 0.0f, 1.0f, 0.0f // Z軸 → Y軸へ }; この行列は OpenGL モデル行列(4x4)の回転成分として使われ、Y/Z 軸の入れ替えと X 軸反転でテクスチャをカメラ平面に平行に固定します。 本来はデバイスの IMU センサーから回転行列を受け取り、端末の傾きに追従させます。 https://github.com/google-ai-edge/mediapipe/blob/0.10.32/mediapipe/examples/android/src/java/com/google/mediapipe/apps/instantmotiontracking/MainActivity.java#L218-L220 本実装では固定値にすることで 常にカメラ正面を向く (ビルボード効果)ようにし、 (0,0) の -1.0 による X 軸反転を Bitmap 側の preScale(-1.0f, 1.0f) で打ち消します。 4.2 テクスチャの送信 // テクスチャ画像(Bitmap配列) val texturesPacket = packetCreator.createRgbaImageFrameVector( renderStickers.map { it.bitmap }.toTypedArray() ) addPacketToInputStream("gif_textures", texturesPacket, timestamp) // アスペクト比(テクスチャの縦横比) val aspectRatiosPacket = packetCreator.createFloat32Vector( renderStickers.map { it.aspectRatio }.toFloatArray() ) addPacketToInputStream("gif_aspect_ratios", aspectRatiosPacket, timestamp) PacketCreator.createRgbaImageFrameVector : 複数の Bitmap を RGBA 形式のパケットに変換 gif_textures : テクスチャ画像の入力ストリーム gif_aspect_ratios : 各テクスチャのアスペクト比(正しいスケーリングに必要) 公式サンプルでは createRgbaImageFrame を使用して 単一のテクスチャ をグラフに渡します。 https://github.com/google-ai-edge/mediapipe/blob/0.10.32/mediapipe/examples/android/src/java/com/google/mediapipe/apps/instantmotiontracking/MainActivity.java#L608-L610 本実装では、複数の検出オブジェクトに対応するため createRgbaImageFrameVector で 複数テクスチャを同時に送信 し、 gif_aspect_ratios も createFloat32Vector で 各テクスチャに対応するアスペクト比の配列 を渡すよう拡張します。これにより、検出された各スイッチに異なるラベル(テキスト付きBitmap)を正しい縦横比で表示できます。 ここまでで AR コンテンツをカメラ上に表示できました。 5. 座標の更新 トラッキング中のステッカー座標を更新するには、新しい座標を持つ sticker_proto_string と、リセット対象の ID を含む sticker_sentinels を同一 timestamp で送信します。 TrackedAnchorManagerCalculator が該当 ID のトラッキングボックスを破棄し、新しい座標でトラッキングを再開します。 // 更新した座標で Sticker Proto を再構築 val stickersPacket = packetCreator.createSerializedProto(stickerRoll) addPacketToInputStream("sticker_proto_string", stickersPacket, timestamp) // リセット対象のステッカー ID を送信 val stickerSentinels = packetCreator.createInt32Vector(updateIds) addPacketToInputStream("sticker_sentinels", stickerSentinels, timestamp) 公式サンプルでは sticker_sentinel で 単一のステッカー ID を送信します。 https://github.com/google-ai-edge/mediapipe/blob/0.10.32/mediapipe/examples/android/src/java/com/google/mediapipe/apps/instantmotiontracking/MainActivity.java#L342-L344 本実装では sticker_sentinels として createInt32Vector で 複数のステッカー ID を配列 で渡すよう拡張し、物体検出で座標が更新された複数のステッカーを同時にリセットできるようにします。 最後に 以上が MediaPipe Instant Motion Tracking を用いた技術的な実装解説でした。決して容易に導入できる手法ではありませんが、本機能の要件に対して Android に最も適した解決策だと考えています。 以前に ARCore の検証も行いましたが、ARCore は SLAM 技術による事前の 3D マッピングに時間を要し、 素早くかつ安定した AR エフェクトの実現には適さなかったため、検証を断念しました。 両フレームワークの違いを以下にまとめます。AR 技術の検討で参考になれば幸いです。 項目 Instant Motion Tracking ARCore 仕組み 2D ボックストラッキング + OpenGL 描画 環境マッピング + 平面検出(SLAM) デバイス要件 OpenGL ES 対応であれば動作 ARCore 対応デバイスのみ(Google 認定必須) 安定性 検出座標に依存するため補正が必要 空間認識が高精度で安定 導入コスト Bazel ビルド・C++ Calculator のカスタマイズが必要 SDK 導入のみで比較的容易 オープンソース あり(Apache 2.0) なし(プロプライエタリ) カスタマイズ性 Calculator の追加・変更で柔軟に拡張可能 SDK の API 範囲内に限定 パフォーマンス 軽量(2D トラッキングベースのため CPU/GPU 負荷が低い) 高負荷(環境の 3D 空間マッピングを常時実行) 学習コスト 高い(Bazel・C++・OpenGL・Protocol Buffers の知識が必要) 低い(Android SDK の知見で導入可能)
本日、 Amazon Quick が AWS アジアパシフィック (東京) リージョンで利用可能になったことをお知らせします。 このローンチにより、日本のお客様は 日本国内でホストされるデータと機械学習モデルを活用しながら Amazon Quick のエージェント型 AI 機能を利用できるようになりました。(注: 本日時点では Web 検索機能のみ日本国外のモデルを利用しています。) Amazon Quick は、一つのUIからデータから迅速に回答を取得し、そのインサイトを業務アクションへとつなげることができる AI ベースのデジタルワークスペース です。 東京リージョンでの提供開始により、日本のお客様は 低レイテンシー、国内データレジデンシー、エンタープライズレベルの AI 機能 を活用できるようになります。 Amazon Quick の概要 Amazon Quick は、 リサーチ、ビジネスインテリジェンス、そして自動化機能を統合したエージェンティック AI ワークスペース を提供します。 従来、ユーザーはデータ収集、分析、業務実行のために複数のアプリケーションを切り替える必要がありました。Quick を利用することで、これらの機能を 1 つのプラットフォーム上で統合的に利用可能 です。 ユーザーは自然言語で質問するだけで、 データからインサイトを取得 ダッシュボードやレポートを生成 アプリケーションや業務システムを横断してワークフローを自動化 することが可能になります。 Amazon Quick の主な機能 Amazon Quick は、次の 5 つの主要機能で構成されています。 Quick Index 組織内のドキュメント、ファイル、アプリケーションデータを横断的に統合し、検索可能なナレッジベースを構築します。 Quick Research 組織内のデータに加え、Web や外部データソースを組み合わせて分析し、インサイトやレポートを生成する AI リサーチエージェントです。 Quick Sight データをダッシュボードや可視化、自然言語による要約へと変換する AI ビジネスインテリジェンス機能です。 Quick Flows 自然言語で日常業務のワークフローを作成し、Web アプリケーションやサービス全体に渡るステップを自動化できる機能です。 Quick Automate 複数の専門的な AI エージェントを活用し、ガバナンスコントロールと人間による承認ステップを備え、複雑な業務プロセスを自動化してエンタープライズシステム全体の高度なオーケストレーションを実現する機能です。 これらの機能により、Amazon Quick は ビジネスユーザーのための AI アシスタント として活用できます。 例えば Quick を使用すると、 社内データと外部情報を横断検索 データから可視化やサマリーを生成 チケット作成や承認ワークフローなどの業務アクションを実行 これらすべてを会話型インターフェースで実現し、組織全体でのAI導入の障壁を下げます。 エンタープライズグレードのセキュリティとデータプライバシー Amazon Quick は、エンタープライズ利用を前提に セキュリティとデータプライバシーを重視して設計 されています。 お客様のデータやクエリは 基盤モデルのトレーニングに使用されることはありません 。組織は、AWS マネジメントコンソールを通じて、 データ、権限、統合を完全に管理が可能 です。 また、東京リージョンで利用することで、 データを日本国内の AWS インフラストラクチャ内に保持することが可能 になります。 日本国内でのサービス提供によるメリット Amazon Quick が東京リージョンで利用可能になったことで、日本のお客様は データを日本国内にとどめつつ、低レイテンシ―で AI 分析や自動化機能を利用可能 です。 国内データレジデンシー データを日本国内の AWS インフラストラクチャに留めることができ、組織が規制や内部ガバナンスの要件を満たすのに役立ちます。 低レイテンシー 日本国内ユーザーのネットワークレイテンシーが改善され、AI 応答やダッシュボード表示、ワークフローの応答などのパフォーマンスが向上します。 高可用性 東京リージョンの複数のアベイラビリティーゾーンをに展開され、高い可用性とレジリエンシ―を提供します。 まとめ Amazon Quick が東京リージョンで利用可能になったことで、日本のお客様は AI を活用した分析、リサーチ、自動化機能を国内インフラ上で利用できるようになりました。 Amazon Quick は、質問からインサイトの取得、そして業務アクションの実行までを 1 つのワークスペースで実現 します。 ぜひ東京リージョンで Amazon Quick をお試しください。 Amazon Quick の開始方法 お客様は、AWS マネジメントコンソールを通じて、 東京リージョン (ap-northeast-1) で今すぐ Amazon Quick を使い始めることが可能です。 始めるには: AWS アカウントで Amazon Quick を有効にします Amazon S3 や Microsoft SharePoint、Slack、その他のビジネスアプリケーションなどのデータソースを接続します Quick Index を設定してナレッジベースを構築します Quick Research 、 Quick Sight 、 Quick Flows を使って洞察を生み出し、ワークフローを自動化します 新規のお客様は、 最大 25 ユーザーまでの 30 日間の無料トライアル も利用可能です。 筆者について 溝渕 匡 (Masa Mizobuchi) AWS Japan のソリューションアーキテクトとして、様々なお客様に日々クラウド活用の技術支援を行なっています。ソフトウェアの設計、開発、データ分析、Scrum などが好きで、Scrum は好きが高じて導入プログラムを開発して複数企業への導入実績があります。趣味はゲームで遊んだりゲームを作ったりすることです。

動画

書籍