Unity 中兩個ImageTarget之間的相對座標換算以及前景圖片穿透

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

public class ImageRelativePos : MonoBehaviour {

    public GameObject backImage;
    public GameObject foreImage;
    public GameObject cube;



    // Use this for initialization
    void Start()
    {

    }

    // Update is called once per frame
    void Update()
    {
        if (foreImage.GetComponent<DefaultTrackableEventHandler>().imageTargetIsFound && backImage.GetComponent<DefaultTrackableEventHandler>().imageTargetIsFound)
        {
            Matrix4x4 Road2World = GetExtrinsic(backImage.transform);
            Matrix4x4 Wood2World = GetExtrinsic(foreImage.transform);

            //獲得wood到road的轉換矩陣
            Matrix4x4 Wood2Road = Road2World.inverse*Wood2World;


            //    Matrix4x4 Road2World=GetExtrinsic()


            Vector4 vy = Wood2Road.GetColumn(1);
            Vector4 vz = Wood2Road.GetColumn(2);

            Quaternion newQ = Quaternion.LookRotation(new Vector3(vz.x, vz.y, vz.z), new Vector3(vy.x, vy.y, vy.z));
            cube.transform.position = new Vector3(Wood2Road.m03, Wood2Road.m13, Wood2Road.m23);
            cube.transform.rotation = newQ;
            //獲取road到世界座標系的轉換

        }
    }
    Matrix4x4 GetExtrinsic(Transform trans)
    {
        Matrix4x4 rot = new Matrix4x4();
        rot.SetTRS(trans.position, trans.rotation, new Vector3(1, 1, 1));
        return rot;
    }
}

 

原圖片:

消除前景後的圖片:

 

using OpenCVForUnity.CoreModule;
using OpenCVForUnity.UnityUtils;
using OpenCVForUnity.ImgprocModule;

using System.Collections;
using UnityEngine;

public class Foreground : MonoBehaviour
{
    public GameObject backImage;
    public GameObject foreImage;
    public Mat imageMat;
    private MeshRenderer renderer;

    Texture2D imgTexture;
    Texture2D texture2d;

    float relativeAngle;
    Vector2 tr;
    Vector2 tl;
    Vector2 bl;
    Vector2 br;

    float tr_x;
    float tr_y;

    float offsetPixel_x = 0;
    float offsetPixel_y = 0;




    int foreImageSize = 1024 / 3;

    OpenCVForUnity.CoreModule.Rect rectCrop;
    Mat srcRectMat = new Mat(4, 1, CvType.CV_32FC2);
    Mat dstRectMat = new Mat(4, 1, CvType.CV_32FC2);

    Mat croppedImage;
    Mat outputMat0;
    void Start()
    {
        imgTexture = Resources.Load("background") as Texture2D;
        renderer = this.GetComponent<MeshRenderer>();
        imageMat = new Mat(imgTexture.height, imgTexture.width, CvType.CV_8UC4);
        Utils.texture2DToMat(imgTexture, imageMat);

        // croppedImage = new Mat(1024/ 3, 1024 / 3, CvType.CV_8UC4);
        texture2d = new Texture2D(foreImageSize, foreImageSize, TextureFormat.RGBA32, false);
        renderer.material.mainTexture = texture2d;


        outputMat0 = imageMat.clone();
        rectCrop = new OpenCVForUnity.CoreModule.Rect(0, 0, foreImageSize, foreImageSize);


    }
    void OnGUI()
    {
        if (foreImage.GetComponent<DefaultTrackableEventHandler>().imageTargetIsFound && backImage.GetComponent<DefaultTrackableEventHandler>().imageTargetIsFound)
        {

            //獲得wood到road的轉換矩陣
            Matrix4x4 Wood2Road = GetExtrinsic(backImage.transform).inverse * GetExtrinsic(foreImage.transform);




            //   cube.transform.position = new Vector3(Wood2Road.m03, Wood2Road.m13, Wood2Road.m23);
            //  cube.transform.rotation = newQ;

            //其次獲得小碼圖像中心相對於大碼圖像中心的圖像座標,X向右,Z向上
            // relativePosition = (new Vector3(Wood2Road.m03, Wood2Road.m13, Wood2Road.m23)) * 1024 / 0.3f;
            offsetPixel_x = Wood2Road.m03 * 1024 / 0.3f;
            offsetPixel_y = Wood2Road.m23 * 1024 / 0.3f;


            //由於是左手座標系,此處的旋轉角度要取負值
            Quaternion newQ = Quaternion.LookRotation(new Vector3(Wood2Road.m02, Wood2Road.m12, Wood2Road.m22), new Vector3(Wood2Road.m01, Wood2Road.m11, Wood2Road.m21));
            relativeAngle = newQ.eulerAngles.y;



            //先獲得右上角相對於圖像中心的座標,其餘各頂點的座標通過加正負號獲得
            tr_x = 170 * Mathf.Cos(relativeAngle * Mathf.PI / 180) + 170 * Mathf.Sin(relativeAngle * Mathf.PI / 180);
            tr_y = -170 * Mathf.Sin(relativeAngle * Mathf.PI / 180) + 170 * Mathf.Cos(relativeAngle * Mathf.PI / 180);



            //獲得各頂點相對於大碼中心的圖像座標
            //             tr = new Vector2(relativePosition.x + tr_x, relativePosition.z + tr_y);
            //             tl = new Vector2(relativePosition.x - tr_y, relativePosition.z + tr_x);
            //             bl = new Vector2(relativePosition.x - tr_x, relativePosition.z - tr_y);
            //             br = new Vector2(relativePosition.x + tr_y, relativePosition.z - tr_x);




            //將大碼的座標系從中心的X向右,Z向上,轉換成標準圖像座標系
            tr.x = 512 + offsetPixel_x + tr_x;
            tl.x = 512 + offsetPixel_x - tr_y;
            bl.x = 512 + offsetPixel_x - tr_x;
            br.x = 512 + offsetPixel_x + tr_y;

            tr.y = 512 - offsetPixel_y - tr_y;
            tl.y = 512 - offsetPixel_y - tr_x;
            bl.y = 512 - offsetPixel_y + tr_y;
            br.y = 512 - offsetPixel_y + tr_x;





            srcRectMat.put(0, 0, bl.x, bl.y, br.x, br.y, tr.x, tr.y, tl.x, tl.y);
            dstRectMat.put(0, 0, foreImageSize - 1, 0, 0, 0, 0, foreImageSize - 1, foreImageSize - 1, foreImageSize - 1);

            Mat perspectiveTransform = Imgproc.getPerspectiveTransform(srcRectMat, dstRectMat);




            //獲取放射變換後的全部圖像,隨後從中摳圖
            Imgproc.warpPerspective(imageMat, outputMat0, perspectiveTransform, outputMat0.size());



            croppedImage = new Mat(outputMat0, rectCrop);


            //OpenCVForUnity.CoreModule.Rect rectCrop2 = new OpenCVForUnity.CoreModule.Rect(1024/3,1024/3, 1024 / 3, 1024 / 3); // 調試小心,超出取值範圍,unity會奔潰
            //      Mat croppedImage2 = new Mat(imageMat, rectCrop2);

            Utils.matToTexture2D(croppedImage, texture2d);

        }
    }


    Matrix4x4 rot = new Matrix4x4();

    Matrix4x4 GetExtrinsic(Transform trans)
    {
        rot.SetTRS(trans.position, trans.rotation, new Vector3(1, 1, 1));
        return rot;
    }
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章