Преобразовать координаты Unity xrcpuimage в координаты Viewport для Android AR FoundationC#

Место общения программистов C#
Ответить Пред. темаСлед. тема
Anonymous
 Преобразовать координаты Unity xrcpuimage в координаты Viewport для Android AR Foundation

Сообщение Anonymous »

Я пытаюсь обнаружить края бумаги с помощью камеры, используя мой плагин OpenCV C ++ в Unity. Плагин, который я написал, обнаруживает угловые координаты пикселей плавно, я протестировал его повсюду, так что это не должно быть проблемой. сокращен. Больше, но это не совсем исправлено, потому что даже соотношение все еще немного отключено. Я не понимаю, DisplayMatrix должен составить сопоставление координат Texel с дисплеем, верно? (Он всегда нажимает на самолет, так что это нормально)private Vector2 fromRawCpuToViewport(Matrix4x4 displayMatrix, Vector2 cord)
{
float u = cord.x / camTex.width;
float v = cord.y / camTex.height;

Vector4 uv = new Vector4(u, v, 1f, 0f);
Vector4 mapped = displayMatrix.transpose * uv;

//if (mapped.w != 0f) //
Проективный разрыв прокомментируется, потому что в этом случае он не помогает, w всегда 0. < /p>
Весь код, который создает верхний прямоугольник в изображении: < /p>
// PaperDetector.cs
using System;
using System.Linq;
using System.Collections.Generic;
using Unity.Collections;
using UnityEngine;
using UnityEngine.XR.ARFoundation;
using UnityEngine.XR.ARSubsystems;
using UnityEngine.UI;

[RequireComponent(typeof(ARCameraManager))]
public class PaperDetector : MonoBehaviour
{
/* ---------- Inspector refs ---------- */
[SerializeField] ARCameraManager cameraManager;
[SerializeField] ARRaycastManager raycastManager;
[SerializeField] ARPlaneManager arPlaneManager;
[SerializeField] RawImage debugImage;

[Header("Line Settings")]
[SerializeField] Material lineMaterial;
[SerializeField] float lineWidth = 0.005f;

/* ---------- internals ---------- */
Texture2D camTex;
lineSegment[] segments = new lineSegment[4];
static readonly List hits = new();
Vector3[] prevPos = new Vector3[4];

struct lineSegment
{
public LineRenderer lr;
public bool end0Fallback;
public bool end1Fallback;
}

void Awake()
{
InitLines();
arPlaneManager.planePrefab.active = true;
lineMaterial.renderQueue = 3100;
Debug.Log("PaperDetector initialized.");
}

void OnEnable() => cameraManager.frameReceived += OnFrame;
void OnDisable() => cameraManager.frameReceived -= OnFrame;

void OnFrame(ARCameraFrameEventArgs args)
{

Debug.Log("--------------------------------NEW FRAME---------------------------------\n"+
"--------------------------------------------------------------------------");

if (!cameraManager.TryAcquireLatestCpuImage(out var cpu))
return;

UpdateTexture(cpu);

byte[] rgba = camTex.GetRawTextureData().ToArray();
if (!PaperPlugin.FindPaperCorners(rgba, camTex.width, camTex.height, out Vector2[] imgCorners))
{
foreach (var seg in segments)
seg.lr.enabled = false;

Debug.LogWarning(" No paper corners detected.");
return;
}

Matrix4x4 displayMatrix;
if (!args.displayMatrix.HasValue)
{
Debug.LogWarning(" No display matrix available.");
return;
}
else
{
displayMatrix = args.displayMatrix.Value;
}

// 2) convert each raw image‐space corner → normalized UV → into the same UV space
Vector2[] viewportCorners = new Vector2[imgCorners.Length];
for(int i = 0; i < imgCorners.Length; i++)
{

viewportCorners = fromRawCpuToViewport(displayMatrix, imgCorners);
}

Vector2[] ordered = OrderCorners(viewportCorners);

for (int i = 0; i < viewportCorners.Length; ++i)
Debug.Log($"vp[{i}] = {viewportCorners}"); // should stay between 0-1
PlaceLinesFromViewport(ordered);
}

private Vector2 fromRawCpuToViewport(Matrix4x4 displayMatrix, Vector2 cord)
{
float u = cord.x / camTex.width;
float v = cord.y / camTex.height;

Vector4 uv = new Vector4(u, v, 1f, 0f);
Vector4 mapped = displayMatrix.transpose * uv;

//if (mapped.w != 0f) // a + b) / 4f;
return c.OrderBy(p => Mathf.Atan2(p.y - center.y, p.x - center.x)).ToArray();
}

void InitLines()
{
for (int i = 0; i < 4; ++i)
{
var go = new GameObject($"PaperEdge_{i}");
var lr = go.AddComponent();
lr.material = lineMaterial;
lr.useWorldSpace = true;
lr.loop = false;
lr.positionCount = 2;
lr.startWidth = lr.endWidth = lineWidth;
segments.lr = lr;
}

Debug.Log("LineRenderers initialized.");
}

void UpdateTexture(XRCpuImage img)
{
var p = new XRCpuImage.ConversionParams
{
inputRect = new RectInt(0, 0, img.width, img.height),
outputDimensions = new Vector2Int(img.width, img.height),
outputFormat = TextureFormat.RGBA32

};

if (camTex == null || camTex.width != img.width || camTex.height != img.height)
{
camTex = new Texture2D(img.width, img.height, TextureFormat.RGBA32, false);
Debug.Log($"Created camTex: {img.width}x{img.height}");
}

using var buf = new NativeArray(img.GetConvertedDataSize(p), Allocator.Temp);
img.Convert(p, buf);
camTex.LoadRawTextureData(buf);
camTex.Apply();

debugImage.texture = camTex;
img.Dispose();
}

void PlaceLinesFromViewport(Vector2[] vpCorners)
{
Vector3[] worldPos = new Vector3[vpCorners.Length];
bool[] usedFallback = new bool[vpCorners.Length];

for (int i = 0; i < vpCorners.Length; i++)
{
Vector2 vp = vpCorners;
var ray = Camera.main.ViewportPointToRay(vp);
Vector3 hitPt;
bool hitPlane = false;

if (raycastManager.Raycast(ray, hits, TrackableType.PlaneWithinPolygon))
{
var chosen = hits[0];
var plane = arPlaneManager.GetPlane(chosen.trackableId);
hitPt = chosen.pose.position;
hitPlane = true;
}
else
{
hitPt = ray.GetPoint(1.0f);
}

worldPos = hitPt;
prevPos = worldPos;
usedFallback = !hitPlane;

Debug.Log($" Corner[{i}] to World: {worldPos:F2} {(hitPlane ? "YES" : "NO")}");
}

for (int i = 0; i < 4; i++)
{
int j = (i + 1) % 4;
var seg = segments[i];
seg.lr.enabled = true;
seg.lr.SetPosition(0, worldPos[i]);
seg.lr.SetPosition(1, worldPos[j]);

bool anyFallback = usedFallback[i] || usedFallback[j];
Color col = anyFallback ? Color.yellow : Color.blue;
seg.lr.startColor = seg.lr.endColor = col;

Debug.Log($"Segment[{i}] From {worldPos[i]:F2} to {worldPos[j]:F2} Color: {(anyFallback ? "YELLOW" : "BLUE")}");
}
}
}


Подробнее здесь: https://stackoverflow.com/questions/796 ... id-ar-foun
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение

Вернуться в «C#»