using o0; using o0.Geometry2D.Float; using o0.Project; using System; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; using ZIM; using Color = UnityEngine.Color; [RequireComponent(typeof(Canvas))] public class ScreenLocate : MonoBehaviour { enum Mode { InfraredLocate, ScreenMap, ScreenLocateManual } // 2个灯,顺序根据红外灯的大小 由大到小, 坐标通过 InfraredSpot.ScreenUV 和 InfraredSpot.CameraLocation 获得 public InfraredSpot[] InfraredSpots { get; private set; } public ZIMWebCamera WebCamera; public Text Info; public List CrosshairInCamera; public List CrosshairInScreen; public RectTransform ScreenQuad; public Toggle SaveToggle; public bool ShowScreenQuad = false; public RawImage rawImage; public RawImage rawImage1; public RawImage rawImage2; public RawImage rawImage3; public RawImage rawImage4; public RawImage rawImage5; public RawImage FullScreenImage; public InfraredSpotSettings InfraredSpotSettings; public Texture2D DebugScreenImage; InfraredLocate infraredLocate; RectTransform canvas; Mode mode; List pointManual = new List(); //o0.Project.WebCam o0WebCam = null; o0.Project.ScreenIdentification screenIdentification; static public ScreenLocate Main; static public List DebugImage = new List(); static public RectTransform BackQuad = null; static public void DebugTexture(int index, Texture texture) { Destroy(DebugImage[index].texture); DebugImage[index].texture = texture; } static public void SetScreen(UnityEngine.Color? color = null) { if (BackQuad == null) { var canvas = GameObject.Find("WebCameraView").GetComponent(); var background = canvas.Find("Background"); BackQuad = background.GetChild(0).GetComponent(); } BackQuad.parent.gameObject.SetActive(color != null); BackQuad.GetComponent().color = color ?? Color.black; } static public void SetScreen(Rect rect, UnityEngine.Color? color = null) { if (BackQuad == null) { var canvas = GameObject.Find("WebCameraView").GetComponent(); var background = canvas.Find("Background"); BackQuad = background.GetChild(0).GetComponent(); } BackQuad.parent.gameObject.SetActive(color != null); BackQuad.anchorMin = rect.min; BackQuad.anchorMax = rect.max; BackQuad.GetComponent().color = color ?? Color.black; } static void DebugBackQuad(Rect? rect = null) { if (BackQuad) { BackQuad.parent.GetComponent().enabled = false; BackQuad.GetComponent().color = Color.white; BackQuad.parent.gameObject.SetActive(!BackQuad.parent.gameObject.activeSelf); if (rect.HasValue) { BackQuad.anchorMin = rect.Value.min; BackQuad.anchorMax = rect.Value.max; } } } void Awake() { //var quad = new Quadrilateral(new Vector2(0, 0), new Vector2(89, 0), new Vector2(0, 95), new Vector2(100, 100)); //var x = quad.InterpolationFactors(new Vector2(-1, -1)); //Debug.Log(x); } void Start() { Main = this; DebugImage.Add(rawImage); DebugImage.Add(rawImage1); DebugImage.Add(rawImage2); DebugImage.Add(rawImage3); DebugImage.Add(rawImage4); DebugImage.Add(rawImage5); DebugImage.Add(FullScreenImage); if (WebCamera.webCamTexture) screenIdentification = new o0.Project.ScreenIdentification(WebCamera.webCamTexture); //crosshairInCamera = rawImage1.transform.GetChild(0).GetComponent(); canvas = transform.GetComponent(); mode = Mode.InfraredLocate; if (DebugScreenImage) { screenIdentification = new o0.Project.ScreenIdentification(new o0.Geometry2D.Vector(DebugScreenImage.width, DebugScreenImage.height)); screenIdentification.LocateScreen(); } //screenIdentification = new o0.Project.ScreenIdentification(WebCamera.webCamTexture); //infraredLocate = new InfraredLocate(WebCamera, screenIdentification, InfraredSpotSettings); } void Update() { WebCamTexture texture = WebCamera?.webCamTexture; if (texture == null) return; if (screenIdentification == null) screenIdentification = new o0.Project.ScreenIdentification(WebCamera.webCamTexture); if (infraredLocate == null) infraredLocate = new InfraredLocate(WebCamera, screenIdentification, InfraredSpotSettings); if (mode == Mode.ScreenLocateManual) { //var newTex = WebCamera.webCamTexture.AutoLight(10); //DebugTexture(6, newTex); if (Input.GetMouseButtonDown(0)) { var mouse = Input.mousePosition; var u = mouse.x / Screen.width; var v = mouse.y / Screen.height; //Debug.Log(u + ", " + v); u = Math.Clamp(u, 0, 1); v = Math.Clamp(v, 0, 1); pointManual.Add(new Vector2(u * WebCamera.width, v * WebCamera.height)); var obj = Instantiate(Resources.Load("Point")) as GameObject; obj.transform.SetParent(FullScreenImage.transform); obj.transform.localPosition = new Vector2(u, v).pixelToLocalPosition_AnchorCenter(new Vector2(1, 1), FullScreenImage.rectTransform.rect); if (pointManual.Count == 1) Info.text = "左键单击屏幕 右下角"; else if (pointManual.Count == 2) Info.text = "左键单击屏幕 右上角"; else if (pointManual.Count == 3) Info.text = "左键单击屏幕 左上角"; else if (pointManual.Count == 4) { screenIdentification.LocateScreenManual(new Quadrilateral(pointManual[0].o0Vector(), pointManual[1].o0Vector(), pointManual[3].o0Vector(), pointManual[2].o0Vector())); pointManual.Clear(); ShowScreen(screenIdentification.Screen.Quad); foreach (Transform i in FullScreenImage.transform) Destroy(i.gameObject); ToMode(Mode.InfraredLocate); } } return; } /* New*/ if (texture.didUpdateThisFrame) // 检查camera是否更新帧 { if (!screenIdentification.Update(WebCamera.webCamTexture)) { var pixels = texture.GetPixels(); // 从左往右、从下往上 if (mode == Mode.InfraredLocate) { if (!screenIdentification.Screen.Active) { var newTex = pixels.zimAutoLightSimple(texture.width, texture.height); DebugTexture(1, newTex); } else { //var newTex = pixels.zimAutoLightSimple(texture.width, texture.height); //DebugTexture(1, newTex); // 成功定位屏幕后才做红外识别 InfraredSpots = infraredLocate.Update(pixels); for (int i = 0; i < InfraredSpots.Length; i++) { if (InfraredSpots[i].CameraLocation != null) { // 检测到光点 var posInCanvas = InfraredSpots[i].CameraLocation.Value.pixelToLocalPosition_AnchorCenter(WebCamera.Size, rawImage.rectTransform.rect); CrosshairInCamera[i].gameObject.SetActive(true); CrosshairInCamera[i].anchoredPosition = posInCanvas; } else CrosshairInCamera[i].gameObject.SetActive(false); } } } else if (mode == Mode.ScreenMap) { InfraredSpots = infraredLocate.Update(pixels); for (int i = 0; i < InfraredSpots.Length; i++) { if (InfraredSpots[i].ScreenUV != null) { // 检测到光点 var posInCanvas = InfraredSpots[i].ScreenUV.Value.pixelToLocalPosition_AnchorCenter(new Vector2(1, 1), canvas.rect); CrosshairInScreen[i].gameObject.SetActive(true); CrosshairInScreen[i].anchoredPosition = posInCanvas; } else CrosshairInScreen[i].gameObject.SetActive(false); } } } } /**/ if (Input.GetKeyDown(KeyCode.Alpha1)) BtnScreenLocate(); if (Input.GetKeyDown(KeyCode.Alpha2)) SetScreen(Color.white); if (Input.GetKeyDown(KeyCode.Alpha3)) SetScreen(Color.black); if (Input.GetKeyDown(KeyCode.Alpha4)) SetScreen(null); //if (Input.GetKeyDown(KeyCode.Alpha5)) // DebugScreen(new Quadrilateral(Vector2.zero, new Vector2(600,300), new Vector2(0, 0), new Vector2(1000, 700))); if (Input.GetKeyDown(KeyCode.Escape)) ToMode(Mode.InfraredLocate); if (Input.GetKeyDown(KeyCode.Alpha8)) DebugBackQuad(); if (Input.GetKeyDown(KeyCode.Alpha9)) DebugBackQuad(new Rect(0, 0, 1, 1)); if (Input.GetKeyDown(KeyCode.Alpha0)) ShowScreenQuad = true; /* Old if (texture.didUpdateThisFrame) // 检查camera是否更新帧 { if (!o0InfraredIdentification2.Update(WebCamera.webCamTexture)) { var pixels = texture.GetPixels(); // 从左往右、从下往上 var infraredLocation = infraredLocate.Get(pixels); if (mode == Mode.InfraredLocate) { //if (rawImage1.IsActive()) //{ //var newTex = WebCamera.webCamTexture.zimAutoLight(); //DebugTexture(1, newTex); //} int i = 0; if (infraredLocation != null) { for (; i < infraredLocation.Count; i++) { // 检测到光点 var posInCanvas = infraredLocation[i].pixelToLocalPosition_AnchorCenter(WebCamera.Size, rawImage.rectTransform.rect); CrosshairInCamera[i].gameObject.SetActive(true); CrosshairInCamera[i].anchoredPosition = posInCanvas; //Debug.Log("location: " + posInCanvas); } } for (; i < CrosshairInCamera.Count; i++) { CrosshairInCamera[i].gameObject.SetActive(false); } } else if (mode == Mode.ScreenMap) { int i = 0; if (infraredLocation != null) { for (; i < infraredLocation.Count; i++) { var uv = o0InfraredIdentification2.Quad.InterpolationFactors(infraredLocation[i].o0Vector()); if (uv.x > 0 && uv.x < 1 && uv.y > 0 && uv.y < 1) { var posInScreen = uv.UnityVector().pixelToLocalPosition_AnchorCenter(new Vector2(1, 1), canvas.rect); CrosshairInScreen[i].anchoredPosition = posInScreen; } CrosshairInScreen[i].gameObject.SetActive(true); } } for (; i < CrosshairInScreen.Count; i++) { CrosshairInScreen[i].gameObject.SetActive(false); } } } } /**/ } public void BtnScreenLocate() { if (WebCamera?.webCamTexture) screenIdentification.LocateScreen(); } public void BtnScreenMap() { if (WebCamera?.webCamTexture) ToMode(Mode.ScreenMap); } public void BtnScreenLocateManual() { if (WebCamera?.webCamTexture) ToMode(Mode.ScreenLocateManual); } // 标记屏幕的四个角 public void ShowScreen(Quadrilateral quad) { if (quad == null) { Info.text = "识别屏幕失败"; return; } Info.text = "已识别到屏幕"; if (ShowScreenQuad) { ScreenQuad.gameObject.SetActive(true); for (int i = 0; i < 4; i++) { RectTransform t = ScreenQuad.GetChild(i) as RectTransform; t.anchoredPosition = quad[i].UnityVector().pixelToLocalPosition_AnchorCenter(WebCamera.Size, ScreenQuad.rect); } } } void ToMode(Mode mode) { if (this.mode == mode) return; if (mode == Mode.ScreenMap) { if (!screenIdentification.Screen.Active) { Info.text = "先定位屏幕"; return; } Info.text = "按ESC退出"; SetScreen(Color.black); Info.transform.SetAsLastSibling(); this.mode = Mode.ScreenMap; } else if (mode == Mode.InfraredLocate) { Info.text = screenIdentification.Screen.Active ? "已定位屏幕" : "定位屏幕失败"; //Info.text = "已识别到屏幕"; SetScreen(null); foreach (var i in CrosshairInScreen) i.gameObject.SetActive(false); FullScreenImage.gameObject.SetActive(false); Info.transform.SetSiblingIndex(transform.childCount - 4); this.mode = Mode.InfraredLocate; DebugTexture(1, null); } else if (mode == Mode.ScreenLocateManual) { Info.text = "左键单击屏幕 左下角"; FullScreenImage.gameObject.SetActive(true); Info.transform.SetSiblingIndex(transform.childCount - 1); //var newTex = WebCamera.webCamTexture.AutoLight(10); var newTex = WebCamera.webCamTexture.zimAutoLightSimple(); DebugTexture(6, newTex); this.mode = Mode.ScreenLocateManual; } } }