EloiStree / HelloUnityKeywordForJunior

List of word nice to learn for Unity3D
0 stars 0 forks source link

Keyword: Homography #44

Open EloiStree opened 4 months ago

EloiStree commented 4 months ago

J'ai eu besoin d'utilise cette technique 2-3 fois dans ma vie ^^ sans savoir son nom.

image

EloiStree commented 4 months ago

Disponible en Open CV et autre plugin payant. A l'époque je n'avais trouvé qu'un option gratuit sur Python:


using Eloi;
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;

public class FourPointPythonHomographyMono : MonoBehaviour
{

    public UI_CropStaticImageConfigurationMono m_cropAndExtract;

    public Texture2D m_sentImage;
    public Texture2D m_recoverImage;
    public LocalCropInfo m_cropInfo;
    public Eloi.AbstractMetaAbsolutePathFileMono m_pythonFile;
    public Eloi.AbstractMetaAbsolutePathFileMono m_origineImage;
    public Eloi.AbstractMetaAbsolutePathFileMono m_destinationImage;
    public int m_wantedResolutionWidth=1920 ;
    public int m_wantedResolutionHeight=1080;
    public bool m_debugDrawLine = true;

    //https://youtu.be/jvgmnJspjoA
    [TextArea(0,10)]
     string m_scriptPattern = ""
+ "\nimport cv2                                                         \n "
+ "\nimport numpy as np                                                 \n "
+ "\nimage = cv2.imread([[IMAGEPATHIN]])                                \n     "
+ "\nimage= cv2.resize(image, ([[WIDTH]],[[HEIGHT]]))                       \n          "
+ "\npts1 = np.float32( [[COORDINATE]])  \n"
+ "\npts2 = np.float32([[0, [[HEIGHT]]],[[[WIDTH]], [[HEIGHT]]],[0, 0],[[[WIDTH]], 0]])  \n          "
+ "\nmatrix= cv2.getPerspectiveTransform(pts1, pts2)                     \n"
+ "\nfinal = cv2.warpPerspective(image, matrix, ([[WIDTH]], [[HEIGHT]])) " 
+ "\nfinal= cv2.resize(final, ([[OUTWIDTH]],[[OUTHEIGHT]])) \n "
+ "\ncv2.imwrite([[IMAGEPATHOUT]], final) \n ";

    [TextArea(0, 10)]
    public string pythonScriptResult;

    public string GetFilePath(Eloi.IMetaAbsolutePathFileGet file) {
        //string r = "os.path.join('{0}', '{1}.{2}')";
        //Eloi.E_FileAndFolderUtility.SplitInfoAsString(in file, out string directory, out string filename, out string ext);
        //return string.Format(r, directory, filename, ext);

        file.GetPath(out string p);
        return "\""+p.Replace("\\", "/").Replace("/", "\\\\")+ "\"";
    }

    public string GetCoordinateFromPoint(in LocalCropInfo local)
    {
        //[[20, 133], [361, 18], [133, 487], [469, 367]]
        string format = "[[{0},{1}], [{2}, {3}], [{4}, {5}], [{6}, {7}]]";
        return string.Format(format,
            //DownLeft
            local.m_downLeftCorner.m_left2RightPixel,
            local.m_height - local.m_downLeftCorner.m_bot2TopPixel,

            local.m_downRightCorner.m_left2RightPixel,
            local.m_height - local.m_downRightCorner.m_bot2TopPixel,

            local.m_topLeftCorner.m_left2RightPixel,
            local.m_height - local.m_topLeftCorner.m_bot2TopPixel,

            local.m_topRightCorner.m_left2RightPixel,
            local.m_height - local.m_topRightCorner.m_bot2TopPixel
            );
    }

    [ContextMenu("Test Reload")]
    public void LoadPreviousImage() {

        LoadImage();
    }

    public void ApplyTexture(RenderTexture texture)
    {
        Eloi.E_Texture2DUtility.RenderTextureToTexture2D(texture, out Texture2D copy);
        ApplyTexture(copy);
    }
        public void ApplyTexture(Texture2D texture) { 

        m_cropAndExtract.GetPourcentCoordinate(out TextureCropCoordinate current);
        Texture2D textureToDealWith = (Texture2D)texture;
        Eloi.E_Texture2DUtility.TextureToTexture2DCopy(textureToDealWith, out Texture2D outte);
        TextureCropCoordinateUtility.CropFromFourPoints(in outte, in current, out m_sentImage, out m_cropInfo);

        if (m_debugDrawLine) { 
            Color [] c = m_sentImage.GetPixels();
            DrawLine(ref c, m_cropInfo.m_topLeftCorner, m_cropInfo.m_topRightCorner, m_sentImage.width);
            DrawLine(ref c, m_cropInfo.m_topRightCorner, m_cropInfo.m_downLeftCorner, m_sentImage.width);
            DrawLine(ref c, m_cropInfo.m_downLeftCorner, m_cropInfo.m_downRightCorner, m_sentImage.width);
            DrawLine(ref c, m_cropInfo.m_downRightCorner, m_cropInfo.m_topLeftCorner, m_sentImage.width);
            DrawLine(ref c, m_cropInfo.m_downLeftCorner, m_cropInfo.m_topLeftCorner, m_sentImage.width);
            DrawLine(ref c, m_cropInfo.m_downRightCorner, m_cropInfo.m_topRightCorner, m_sentImage.width);
            m_sentImage.SetPixels(c);
            m_sentImage.Apply();
        }

        m_origineImage.GetPath(out string originePath);
        m_destinationImage.GetPath(out string destinationPath);
        pythonScriptResult = m_scriptPattern;
        pythonScriptResult = pythonScriptResult.Replace("[[COORDINATE]]", GetCoordinateFromPoint(in m_cropInfo));
        pythonScriptResult = pythonScriptResult.Replace("[[WIDTH]]", ""+m_sentImage.width);
        pythonScriptResult = pythonScriptResult.Replace("[[HEIGHT]]", "" + m_sentImage.height);
        pythonScriptResult = pythonScriptResult.Replace("[[IMAGEPATHIN]]", GetFilePath(m_origineImage));
        pythonScriptResult = pythonScriptResult.Replace("[[IMAGEPATHOUT]]", GetFilePath(m_destinationImage));
        pythonScriptResult = pythonScriptResult.Replace("[[OUTWIDTH]]", ""+ m_wantedResolutionWidth);
        pythonScriptResult = pythonScriptResult.Replace("[[OUTHEIGHT]]", "" + m_wantedResolutionHeight);

        Eloi.E_FileAndFolderUtility.DeleteFile( m_destinationImage);
        Eloi.E_FileAndFolderUtility.CreateFile(m_pythonFile, pythonScriptResult);
        Eloi.E_FileAndFolderUtility.ExportTexture(m_origineImage, m_sentImage);
        LaunchPython(m_pythonFile);
        if (m_coroutine != null)
            StopCoroutine(m_coroutine);
        m_coroutine = StartCoroutine(CoroutineCallPython());
    }

    private void LaunchPython(IMetaAbsolutePathFileGet pythonFile)
    {
        pythonFile.GetPath(out string p);
        E_FileAndFolderUtility.GetDirectoryPathFromPath(pythonFile,
            out  IMetaAbsolutePathDirectoryGet d);
        E_LaunchWindowBat.ExecuteCommandHiddenWithReturn(
                d, "python \"" + p + "\"", out string o,
               out string e, out int exit);
    }

    public Coroutine m_coroutine;
    public Eloi.ClassicUnityEvent_Texture2D m_newHomographyImage;
    public UnityEvent m_convertionFailed;
    public IEnumerator CoroutineCallPython() {
        bool found = false;
        for (int i = 0; i < 10 && !found; i++)
        {
            yield return new WaitForSeconds(0.5f);
            if (Eloi.E_FileAndFolderUtility.Exists(m_destinationImage))
               // && Eloi.E_FileAndFolderUtility.IsNotLock(m_destinationImage))
            {
                if (!found)
                {
                    found = true;

                    LoadImage();
                    yield return null;
                }
            }
        }
        if(!found)
            m_convertionFailed.Invoke();
       // Eloi.E_FileAndFolderUtility.DeleteFile(m_destinationImage);

    }

    private void LoadImage()
    {
        m_destinationImage.GetPath(out string  path);
        if (File.Exists( path))
        {
            byte[] buffer = File.ReadAllBytes(path);
            Texture2D texture = new Texture2D(m_wantedResolutionWidth, m_wantedResolutionHeight, TextureFormat.RGBA32, true, false);
             texture.LoadImage(buffer);
             texture.Apply();
            m_recoverImage = texture;
            m_newHomographyImage.Invoke(texture);
        }

    }

    public void DrawLine(ref Color[] c, TextureCropCoordinate.PixelBL2TR pt,
        TextureCropCoordinate.PixelBL2TR pt2, in int width) {
        Eloi.E_Texture2DColorUtility.DrawLine(ref c,
            pt.m_left2RightPixel,
            pt.m_bot2TopPixel,
             pt2.m_left2RightPixel,
            pt2.m_bot2TopPixel,
            Color.red,
            width
               ) ;
    }

}