ARCoreのLight estimationを利用
ARCoreに初期から搭載されているLight estimation機能を触ってみました。
なお、AndroidビルドのためのUnity設定等々は実施済みです。
キーワード
ARCore, Unity, AR, ビデオシースルー, 環境光推定, Light estimation
Light estimationとは
Light estimation などを参照ください。
カメラ画像から環境光の強さや色合いを推定する機能です。
バージョン情報など
- バージョン情報
機能 | バージョン |
---|---|
ARCore | 1.1.0 |
Unity | 2017.3.0f3 |
OS | Windows 10 バージョン1709 |
端末 | Galaxy S8 SC-02J (docomoのやつです) |
-
作業日
2017年4月上旬 21:30頃(外光はほぼない状態)
環境光推定を利用したアプリ作成
SDK導入
ダウンロードページより、arcore-unity-sdk-v1.1.0.unitypackageをダウンロードしました。
新規プロジェクトを作成し、SDKを全てインポートしました。
プレハブ確認
Assets > GoogleARCore > Prefabs > Environment Light を確認してみました。
EnvironmentalLightなるスクリプトがアタッチされていますので、開いて確認してみたところ、
Frame.LightEstimate.PixelIntensity
Frame.LightEstimate.ColorCorrection
あたりで環境光の推定結果を取得しているようでした。
公式のリファレンスによるとLightEstimateは3つのプロパティを持っているようでした。
PixelIntensityがピクセル強度の平均を0から1の範囲で算出しているので、明るさはこの値を利用できるはずです。
なお、ピクセル強度については強度が低い=より暗い、強度が強い=より明るい程度の理解でいます。
PixelIntensityの確認
とりあえずPixelIntensityの値を確認を行いました。
ARCoreが提供しているプレハブである、ARCore Deviceをシーンに配置しました。
環境光推定値を出力するスクリプトShowPixelIntensity.csを作成し、生成した空のGameObjectにアタッチしました。
方法
シーン上にuGUIのtextを配置し、ここにPixelIntensityの値を表示させました。
また、ARCore内のプレハブに含まれていたEnvironmentalLightで計算されている、
Frame.LightEstimate.ColorCorrectionと最終的にシェーダに適用されている値も表示してみました。
using UnityEngine;
using GoogleARCore;
using UnityEngine.UI;
public class ShowPixelIntensity : MonoBehaviour
{
[SerializeField]
private Text pixelIntensityText;
[SerializeField]
private Text colorCorrectionText;
[SerializeField]
private Text globalColorText;
private void Update()
{
if (Frame.LightEstimate.State == LightEstimateState.NotValid)
return;
pixelIntensityText.text = Frame.LightEstimate.PixelIntensity.ToString("#.000");
colorCorrectionText.text = Frame.LightEstimate.ColorCorrection.ToString("#.000");
const float middleGray = 0.466f;
float normalizedIntensity = Frame.LightEstimate.PixelIntensity / middleGray;
globalColorText.text = (Frame.LightEstimate.ColorCorrection * normalizedIntensity).ToString("#.000");
}
}
表示用のUIをシーンに追加し、ビルド設定を行いビルドしました。
結果
部屋の明かりを変化させ、値の変化を確認しました。
蛍光灯の状態 | 条件備考 | PixelIntensity |
---|---|---|
全点灯 | 最もPixelIntensityが高かった場所 | 0.75 |
全点灯 | 机見下ろし | 0.5 |
全点灯 | 平均 | 0.65 |
常夜灯 | 0.13 | |
消灯 | モニタの明かりのみ | 0.1 |
消灯 | 0.08 | |
全点灯 | カメラを完全にふさいだ状態 | 0.08 |
以下、それぞれの状態のカメラ映像になります。
|0.75付近(全点灯)|0.60付近|0.50付近|0.40付近|0.20付近(常夜灯)|0.15付近(側面にモニタ光)|0.08付近|
|:--|:--|:--|:--|:--|:--|:--|:--|
|||||||
|
注意点
画像から明るさを類推しているため、白に近いカーテンを見ているときと、黒に近いカーテンを見ている時では、恐らくPixelIntensityの値は変化します。
オブジェクト追加
スケルトン(BSHGAME Skeletons Pack)をお呼びし、明るさに応じて目を光らせて頂きました。
目の光らせ方は、テラシュールブログ様の記事、目やパーツの一部を光らせるを参照します。
スケさんの眼窩付近にFlareSmallを設定したPoint lightを配置しました。
LightEstimate.PixelIntensityが小さくなるほどライトを強くするスクリプトを作成し、先ほど作成したライトを参照しておきます。
[SerializeField]
private Light light;
light.intensity = 1f - (Frame.LightEstimate.PixelIntensity);
感想
-
最後のライト部分がかなり適当ですが、外界の明るさに応じた処理を作成できました。
外部の影響によって動きが変わるものは、単純でも意外に面白かったです。 -
ARCoreではカメラが光量を自動的に調節してしまうので、必ずしも光源に向かった状態がPixelIntensity最大ではありません。
実際に利用する際は実地でのテストが必須だと思われます。
参考:光源を向いた場合のPixelIntensity
同様の理由で、昼間と夜間の室内を比較した場合、昼間のPixelIntensityの方が常に高いとは限りません。
-
夜間だけ火のつく燈篭とか作れればカッコイイ。
-
Motion trackingと組み合わせ、特定の地点から特定の方向を向いた場合の光量を記憶できれば、明るい場所に向かって動くゾンビとか作れそうな気もしました。
-
ARCore1.1.0から搭載のInstant Previewが超便利です。
特に設定していなくてもポップアップが出現し、それに従っていけば勝手に利用できる環境が構築されていました。
二回目以降はAndroid側でARCore Instant Previewを起動しておく必要があるようです。