3

リリース ノートには、Unity でカラー データにアクセスすることはまだできないと記載されていますが、ビデオ オーバーレイ リスナーにコールバックをアタッチし、Unity で YUV12 バイト配列を受け取り、それを手動で RGB565 に変換して画面に表示できると思います。シェーダー付き。

Unity でカラー データ (AR オーバーレイなど) にアクセスして表示することに成功した人はいますか? もしそうなら、始める方法についていくつかのポインタ/コードを共有できますか?

4

4 に答える 4

3

ビデオ オーバーレイ コールバックは Unity で機能します。理論的には、YUV から RGBA へのシェーダーを使用して、Unity でレンダリングすることができます。これを行うことの唯一の欠点は、Unity のテクスチャ/色のフォーマットのために、複数の「memcpy」が必要になることです。

Tango の YV12 データ パッキングは、C-API ヘッダーで説明されています: https://developers.google.com/project-tango/apis/c/struct_tango_image_buffer

「幅 x 高さの Y サンプルが最初にあり、次に V サンプルが続き、Y データのストライドの半分とラインの半分が続き、V サンプルと同じ寸法の U サンプルが続きます。」

したがって、3 つの Unity テクスチャにそれぞれ Y、U、V チャネルの 1 つを含め、それらを 1 つのシェーダーに渡して RGBA カラーを計算できると思います。

YUV 画像と変換の詳細: http://en.wikipedia.org/wiki/YUV

于 2014-11-27T21:15:44.037 に答える
3

次のスクリプトを使用して、Unity クアッド メッシュにビデオ オーバーレイを表示します。Tango タブレットで動作します。ただ、fpsが低いのはカラーカメラの解像度(1280×720)のせいかな。

using UnityEngine;
using UnityEngine.UI;
using System;
using System.Collections;
using System.Runtime.InteropServices;
using Tango;

public class CameraBackgorund : VideoOverlayListener
{
    Texture2D backgroundTexture = null;

    // texture data
    bool    isDirty = false;
    byte[]  yuv12   = null;
    int     width;
    int     height;

    private void Update() 
    {
        if (isDirty)
        {
            if (backgroundTexture == null)
                backgroundTexture = new Texture2D (width, height);

            // convert from YV12 to RGB
            int size = (int)(width * height);
            for (int i = 0; i < height; ++i)
            {
                for (int j = 0; j < width; ++j)
                {      
                    byte y = yuv12[i * width + j];
                    byte v = yuv12[(i / 2) * (width / 2) + (j / 2) + size];
                    byte u = yuv12[(i / 2) * (width / 2) + (j / 2) + size + (size / 4)];
                    backgroundTexture.SetPixel(j, height - i - 1, YUV2Color(y, u, v));
                }
            }

            // update texture
            backgroundTexture.Apply(true);
            GetComponent<MeshRenderer> ().material.mainTexture = backgroundTexture;

            isDirty = false;
        }
    }

    protected override void _OnImageAvailable(IntPtr callbackContext,
                                              Tango.TangoEnums.TangoCameraId cameraId, 
                                              Tango.TangoImageBuffer imageBuffer)
    {
        if (cameraId != Tango.TangoEnums.TangoCameraId.TANGO_CAMERA_COLOR)
            return;

        // allocate for the first time
        width = (int)imageBuffer.width;
        height = (int)imageBuffer.height;
        if (yuv12 == null)
            yuv12 = new byte[width * height * 2];

        // copy data in yv12 format
        IntPtr dataPtr = imageBuffer.data;
        int    offset  = 0;
        Int64  stride  = (Int64)imageBuffer.stride;
        for (int i = 0; i < height; ++i, dataPtr = new IntPtr(dataPtr.ToInt64() + stride), offset += width)
            Marshal.Copy(dataPtr, yuv12, offset, width);
        for (int i = 0; i < height / 2; ++i, dataPtr = new IntPtr(dataPtr.ToInt64() + stride / 2), offset += width / 2)
            Marshal.Copy(dataPtr, yuv12, offset, width / 2);
        for (int i = 0; i < height / 2; ++i, dataPtr = new IntPtr(dataPtr.ToInt64() + stride / 2), offset += width / 2)
            Marshal.Copy(dataPtr, yuv12, offset, width / 2);
        isDirty = true;
    }

    public static Color YUV2Color(byte y, byte u, byte v)
    {
        // http://en.wikipedia.org/wiki/YUV
        const float Umax = 0.436f;
        const float Vmax = 0.615f;

        float y_scaled = y / 255.0f;
        float u_scaled = 2 * (u / 255.0f - 0.5f) * Umax;
        float v_scaled = 2 * (v / 255.0f - 0.5f) * Vmax; 

        return new Color(y_scaled + 1.13983f * v_scaled,
                         y_scaled - 0.39465f * u_scaled - 0.58060f * v_scaled,
                         y_scaled + 2.03211f * u_scaled);
    }
}

Unity WebCamTexture を使用すると、色は正常に取得されますが、深度プロバイダーが壊れます。

于 2014-12-27T02:39:29.003 に答える