Как нарисовать объект (например, панель или куб) на обнаруженном маркере с помощью aruco? - PullRequest
0 голосов
/ 29 мая 2019

Я использовал Unity с OpenCVSharp, и я обнаружил маркеры с функцией CvAruco.DetectMarkers(...), поэтому получил markerCorners.

Я хочу создать ДИНАМИЧНО объект на этом обнаруженноммаркер, использующий markerCorners в качестве координат, это возможно?

Я пытался использовать угол маркера в качестве координат для куба, но он отображается в другой точке, а не на маркере ...

Не могли бы вы помочь мне?

РЕДАКТИРОВАТЬ: enter image description here

using OpenCvSharp;
using OpenCvSharp.Aruco;
using OpenCvSharp.Util;
using UnityEngine;
using static OpenCvSharp.Unity;
using OpenCvSharp.Tracking;
using System.Linq;
using System.Collections.Generic;
using System.Collections;
using System;


public class ActivationScript : MonoBehaviour //WebCamera
{


private WebCamTexture webCamTexture;

//MARKER DETECTOR
private Mat img;
private int[] markerIds;
Point2f[][] markerCorners, rejectedCandidates;
Dictionary dictionary;

//COLOR
Mesh mesh;
MeshRenderer mr;
Vector3[] vertices;
int[] triangles;
public Material mat;
GameObject markerObj;
GameObject camPlane;
private bool create_flag = false;
private object punti;


List<Point> lista = new List<Point>();


private void Start()
{
    Debug.Log("Start LiveSketch");

    webCamTexture = new WebCamTexture(WebCamTexture.devices[0].name);
    camPlane = GameObject.Find("CameraPlane");
    camPlane.GetComponent<MeshRenderer>().material.mainTexture = webCamTexture;
    //camPlane.transform.position = new Vector3(w/2,h/2,0);
    webCamTexture.Play();

    //
    dictionary = CvAruco.GetPredefinedDictionary(PredefinedDictionaryName.Dict4X4_100);
}

private void Update()
{
    if (webCamTexture.didUpdateThisFrame && webCamTexture.isPlaying)
    {

        Texture2D text = ScreenCapture.CaptureScreenshotAsTexture();

        img = TextureToMat(text);

        DetectorParameters parameters = DetectorParameters.Create();

        CvAruco.DetectMarkers(img, dictionary, out markerCorners, out markerIds, parameters, out rejectedCandidates);

        if (markerIds.Length > 0)
        {

            Debug.Log("DETECTED");
            //void circle(Mat&img, Point center, int radius, const Scalar&color, int thickness = 1, int lineType = 8, int shift = 0)
            //Cv2.DrawChessboardCorners(img,img.Size(),img,true);
            //CvAruco.DrawDetectedMarkers(img, markerCorners, markerIds);
            /* DRAW AN PLANE OR CUBE ON DETECTED MARKER

             .....

             */
            Point tl = new Point(markerCorners[0][0].X,markerCorners[0][0].Y);
            Point br = new Point(markerCorners[0][2].X, markerCorners[0][2].Y);
            Cv2.Rectangle(img, tl, br, new Scalar(0,255,0),-1);
            Cv2.ImShow(this.camPlane.name,img);

            //SetColor_2(markerCorners,1);
            return;

        }
    }
}

/*markerCorners è l'elenco degli angoli dei marker rilevati. 
 * Per ogni marker, i suoi quattro angoli vengono restituiti nel loro ordine originale 
 * (che è in senso orario a partire da in alto a sinistra). 
 * Quindi, il primo angolo è l'angolo in alto a sinistra, seguito da in alto a destra, in basso a destra e in basso a sinistra.*/

public void SetColor_2(Point2f[][] markerCorners, int nMarker)
{
    float x = markerCorners[0][1].X;
    float y = markerCorners[0][1].Y;
    float i,j;


    if (create_flag==false)
        markerObj = Helper.CreatePlane(markerCorners, 0, camPlane);

    i=camPlane.transform.position.x + 26.7f;
    j = camPlane.transform.position.y - 13.3f;

    markerObj.GetComponent<MeshRenderer>().material.SetTexture("txt", SetTxt());
    //markerObj.transform.Rotate(new Vector3(0, 180, 0));
    create_flag = true;
    //markerObj.transform.SetPositionAndRotation(new Vector3(i,j),Quaternion.identity);
}

private Texture2D SetTxt()
{
    Texture2D texture = new Texture2D(12, 12);
    markerObj.GetComponent<Renderer>().material.mainTexture = texture;
    for (int y = 0; y < texture.height; y++)
    {
        for (int x = 0; x < texture.width; x++)
        {
            Color color = Color.red;
            texture.SetPixel(x, y, color);
        }
    }
    texture.Apply();
    Debug.Log("SetTxt finished");
    return texture;
}

private void Calibration()
{
    //Cv2.CalibrateCamera(img,img.Size,);
}

public void Print(Point2f[][] markerCorners, int nMarker)
{
    int i = 0, j = 0;
    Debug.Log("Length: " + markerCorners.Length);
    for (i = 0; i <=nMarker; i++)
    {
        for (j = 0; j <4; j++)
        {
            Debug.Log("Coordinate con i= " + i + "j= " + j + ": " + markerCorners[i][j]);
        }
    }
}



public static Mat TextureToMat(Texture2D texture, TextureConversionParams parameters = null)
{
    if (null == parameters)
        parameters = TextureConversionParams.Default;

    Color32[] pixels32 = texture.GetPixels32();
    return PixelsToMat(pixels32, texture.width, texture.height, parameters.FlipVertically, parameters.FlipHorizontally, parameters.RotationAngle);
}  
}

КЛАСС ПОМОЩИ:

using OpenCvSharp;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public static class Helper
{
public static GameObject CreatePlane(Point2f[][] markerCorners, int ind, GameObject Parent)
{
    GameObject plane = new GameObject("Plane");
    MeshFilter mf = plane.AddComponent(typeof(MeshFilter)) as MeshFilter;
    MeshRenderer mr = plane.AddComponent(typeof(MeshRenderer)) as MeshRenderer;

    plane.transform.parent = Parent.transform.parent;

    float width = (markerCorners[0][1].X - markerCorners[0][0].X);
    float height = (markerCorners[0][3].Y - markerCorners[0][0].Y);
    //plane.transform.localScale = new Vector3(1,1,1);
    //Debug.Log("Altezza e Larghezza: "+height+", "+width);

    Mesh m = new Mesh();
    m.vertices = new Vector3[]
    {
        new Vector3(markerCorners[ind][0].X, markerCorners[ind][0].Y, 1),                           //alto sx
        new Vector3(markerCorners[ind][1].X, markerCorners[ind][1].Y, 1),                           //alto dx
        new Vector3(markerCorners[ind][1].X, markerCorners[ind][2].Y, 1),                           //basso dx
        new Vector3(markerCorners[ind][0].X, markerCorners[ind][3].Y, 1)                            //basso sx

        //new Vector3(0,0,0),
        //new Vector3(width,0,0),
        //new Vector3(width,height,0),
        //new Vector3(0,height,0),
    };
    m.uv = new Vector2[]
    {
        new Vector2(0,0),
        new Vector2(0,1),
        new Vector2(1,1),
        new Vector2(1,0),
    };
    m.triangles = new int[] { 3, 0, 2, 2, 0, 1 };//{ 0, 1, 2, 0, 2, 3 }; //

    mf.mesh = m;
    m.RecalculateBounds();
    m.RecalculateNormals();

    plane.transform.Rotate(new Vector3(0,180,0));
    return plane;
}
}

Я создал класс помощниканарисовать прямоугольник на обнаруженном маркере, но он отображается в другой точке, а не на маркере.

Затем я использовал cv2.Rectangle (...), чтобы нарисовать прямоугольник на маркере, кажется, что это работает, но яхотел бы показать этот прямоугольник на главной сцене на Unity, поэтому без команды «imshow».

Спасибо всем!

...