|
| 1 | + |
| 2 | +#if UNITY_STANDALONE_WIN |
| 3 | +using System; |
| 4 | +using OpenCVForUnity.CoreModule; |
| 5 | +using OpenCVForUnity.ImgprocModule; |
| 6 | +using OpenCVForUnity.UnityIntegration; |
| 7 | +using OpenCVForUnity.UnityIntegration.Helper.Source2Mat; |
| 8 | +using RenderHeads.Media.AVProLiveCamera; |
| 9 | +using UnityEngine; |
| 10 | +using UnityEngine.SceneManagement; |
| 11 | +using UnityEngine.UI; |
| 12 | + |
| 13 | +namespace AVProWithOpenCVForUnityExample |
| 14 | +{ |
| 15 | + /// <summary> |
| 16 | + /// AVProLiveCamera AsyncGPUReadback2MatHelper Example |
| 17 | + /// </summary> |
| 18 | + [RequireComponent(typeof(AsyncGPUReadback2MatHelper))] |
| 19 | + public class AVProLiveCameraAsyncGPUReadback2MatHelperExample : MonoBehaviour |
| 20 | + { |
| 21 | + // Enums |
| 22 | + public enum FPSPreset : int |
| 23 | + { |
| 24 | + _0 = 0, |
| 25 | + _1 = 1, |
| 26 | + _5 = 5, |
| 27 | + _10 = 10, |
| 28 | + _15 = 15, |
| 29 | + _30 = 30, |
| 30 | + _60 = 60, |
| 31 | + } |
| 32 | + |
| 33 | + // Constants |
| 34 | + |
| 35 | + // Public Fields |
| 36 | + [Header("AVProLiveCamera")] |
| 37 | + /// <summary> |
| 38 | + /// The AVProLiveCamera. |
| 39 | + /// </summary> |
| 40 | + public AVProLiveCamera _camera; |
| 41 | + |
| 42 | + [Header("Output")] |
| 43 | + /// <summary> |
| 44 | + /// The RawImage for previewing the result. |
| 45 | + /// </summary> |
| 46 | + public RawImage ResultPreview; |
| 47 | + |
| 48 | + [Space(10)] |
| 49 | + |
| 50 | + /// <summary> |
| 51 | + /// The requested mat update FPS dropdown. |
| 52 | + /// </summary> |
| 53 | + public Dropdown RequestedMatUpdateFPSDropdown; |
| 54 | + |
| 55 | + /// <summary> |
| 56 | + /// The requested mat update FPS. |
| 57 | + /// </summary> |
| 58 | + public FPSPreset RequestedMatUpdateFPS = FPSPreset._30; |
| 59 | + |
| 60 | + /// <summary> |
| 61 | + /// The rotate 90 degree toggle. |
| 62 | + /// </summary> |
| 63 | + public Toggle Rotate90DegreeToggle; |
| 64 | + |
| 65 | + /// <summary> |
| 66 | + /// The flip vertical toggle. |
| 67 | + /// </summary> |
| 68 | + public Toggle FlipVerticalToggle; |
| 69 | + |
| 70 | + /// <summary> |
| 71 | + /// The flip horizontal toggle. |
| 72 | + /// </summary> |
| 73 | + public Toggle FlipHorizontalToggle; |
| 74 | + |
| 75 | + // Private Fields |
| 76 | + /// <summary> |
| 77 | + /// The texture. |
| 78 | + /// </summary> |
| 79 | + private Texture2D _texture; |
| 80 | + |
| 81 | + /// <summary> |
| 82 | + /// The async GPU readback to mat helper. |
| 83 | + /// </summary> |
| 84 | + private AsyncGPUReadback2MatHelper _asyncGPUReadback2MatHelper; |
| 85 | + |
| 86 | + /// <summary> |
| 87 | + /// The FPS monitor. |
| 88 | + /// </summary> |
| 89 | + private FpsMonitor _fpsMonitor; |
| 90 | + |
| 91 | + /// <summary> |
| 92 | + /// The AVProLiveCamera device. |
| 93 | + /// </summary> |
| 94 | + private AVProLiveCameraDevice _device; |
| 95 | + |
| 96 | + // Unity Lifecycle Methods |
| 97 | + private void Start() |
| 98 | + { |
| 99 | + _fpsMonitor = GetComponent<FpsMonitor>(); |
| 100 | + |
| 101 | + // Get the AsyncGPUReadback2MatHelper component attached to the current game object |
| 102 | + _asyncGPUReadback2MatHelper = gameObject.GetComponent<AsyncGPUReadback2MatHelper>(); |
| 103 | + |
| 104 | + // Update GUI state |
| 105 | + string[] enumNames = System.Enum.GetNames(typeof(FPSPreset)); |
| 106 | + int index = Array.IndexOf(enumNames, RequestedMatUpdateFPS.ToString()); |
| 107 | + RequestedMatUpdateFPSDropdown.value = index; |
| 108 | + Rotate90DegreeToggle.isOn = _asyncGPUReadback2MatHelper.Rotate90Degree; |
| 109 | + FlipVerticalToggle.isOn = _asyncGPUReadback2MatHelper.FlipVertical; |
| 110 | + FlipHorizontalToggle.isOn = _asyncGPUReadback2MatHelper.FlipHorizontal; |
| 111 | + } |
| 112 | + |
| 113 | + private void Update() |
| 114 | + { |
| 115 | + if (_camera != null) |
| 116 | + _device = _camera.Device; |
| 117 | + |
| 118 | + if (_device != null && _device.IsActive && !_device.IsPaused && _device.OutputTexture != null) |
| 119 | + { |
| 120 | + // Update source texture if it has changed |
| 121 | + if (_asyncGPUReadback2MatHelper.SourceTexture != _device.OutputTexture) |
| 122 | + { |
| 123 | + _asyncGPUReadback2MatHelper.SourceTexture = _device.OutputTexture; |
| 124 | + _asyncGPUReadback2MatHelper.Initialize(); |
| 125 | + } |
| 126 | + } |
| 127 | + |
| 128 | + // Check if the async GPU readback is playing and if a new frame was updated |
| 129 | + if (_asyncGPUReadback2MatHelper.IsPlaying() && _asyncGPUReadback2MatHelper.DidUpdateThisFrame()) |
| 130 | + { |
| 131 | + // Retrieve the current frame as a Mat object |
| 132 | + Mat rgbaMat = _asyncGPUReadback2MatHelper.GetMat(); |
| 133 | + |
| 134 | + // Add text overlay on the frame |
| 135 | + Imgproc.putText(rgbaMat, "AVPro With OpenCV for Unity Example", new Point(50, rgbaMat.rows() / 2), Imgproc.FONT_HERSHEY_SIMPLEX, 2.0, new Scalar(255, 0, 0, 255), 5, Imgproc.LINE_AA, false); |
| 136 | + Imgproc.putText(rgbaMat, "W:" + rgbaMat.width() + " H:" + rgbaMat.height() + " SO:" + Screen.orientation, new Point(5, rgbaMat.rows() - 10), Imgproc.FONT_HERSHEY_SIMPLEX, 1.0, new Scalar(255, 255, 255, 255), 2, Imgproc.LINE_AA, false); |
| 137 | + |
| 138 | + // Convert the Mat to a Texture2D to display it on a texture |
| 139 | + OpenCVMatUtils.MatToTexture2D(rgbaMat, _texture); |
| 140 | + } |
| 141 | + } |
| 142 | + |
| 143 | + private void OnDestroy() |
| 144 | + { |
| 145 | + // Dispose of the asyncGPUReadback2MatHelper object and release any resources held by it. |
| 146 | + _asyncGPUReadback2MatHelper?.Dispose(); |
| 147 | + } |
| 148 | + |
| 149 | + // Public Methods |
| 150 | + /// <summary> |
| 151 | + /// Raises the async GPU readback to mat helper initialized event. |
| 152 | + /// </summary> |
| 153 | + public void OnAsyncGPUReadback2MatHelperInitialized() |
| 154 | + { |
| 155 | + Debug.Log("OnAsyncGPUReadback2MatHelperInitialized"); |
| 156 | + |
| 157 | + // Retrieve the current frame from the AsyncGPUReadback2MatHelper as a Mat object |
| 158 | + Mat asyncGPUReadbackMat = _asyncGPUReadback2MatHelper.GetMat(); |
| 159 | + asyncGPUReadbackMat.setTo(new Scalar(0, 0, 0, 255)); |
| 160 | + |
| 161 | + // Create a new Texture2D with the same dimensions as the Mat and RGBA32 color format |
| 162 | + _texture = new Texture2D(asyncGPUReadbackMat.cols(), asyncGPUReadbackMat.rows(), TextureFormat.RGBA32, false); |
| 163 | + |
| 164 | + // Convert the Mat to a Texture2D, effectively transferring the image data |
| 165 | + OpenCVMatUtils.MatToTexture2D(asyncGPUReadbackMat, _texture); |
| 166 | + |
| 167 | + // Set the Texture2D as the texture of the RawImage for preview. |
| 168 | + ResultPreview.texture = _texture; |
| 169 | + ResultPreview.GetComponent<AspectRatioFitter>().aspectRatio = (float)_texture.width / _texture.height; |
| 170 | + |
| 171 | + if (_fpsMonitor != null) |
| 172 | + { |
| 173 | + _fpsMonitor.Add("SourceTexture", _asyncGPUReadback2MatHelper.SourceTexture != null ? _asyncGPUReadback2MatHelper.SourceTexture.name : "null"); |
| 174 | + _fpsMonitor.Add("Width", _asyncGPUReadback2MatHelper.GetWidth().ToString()); |
| 175 | + _fpsMonitor.Add("Height", _asyncGPUReadback2MatHelper.GetHeight().ToString()); |
| 176 | + _fpsMonitor.Add("Rotate90Degree", _asyncGPUReadback2MatHelper.Rotate90Degree.ToString()); |
| 177 | + _fpsMonitor.Add("FlipVertical", _asyncGPUReadback2MatHelper.FlipVertical.ToString()); |
| 178 | + _fpsMonitor.Add("FlipHorizontal", _asyncGPUReadback2MatHelper.FlipHorizontal.ToString()); |
| 179 | + _fpsMonitor.Add("Orientation", Screen.orientation.ToString()); |
| 180 | + |
| 181 | + // Add AVProLiveCamera information |
| 182 | + if (_device != null) |
| 183 | + { |
| 184 | + _fpsMonitor.Add("CameraWidth", _device.CurrentWidth.ToString()); |
| 185 | + _fpsMonitor.Add("CameraHeight", _device.CurrentHeight.ToString()); |
| 186 | + _fpsMonitor.Add("CameraFrameRate", _device.CurrentFrameRate.ToString()); |
| 187 | + } |
| 188 | + } |
| 189 | + } |
| 190 | + |
| 191 | + /// <summary> |
| 192 | + /// Raises the async GPU readback to mat helper disposed event. |
| 193 | + /// </summary> |
| 194 | + public void OnAsyncGPUReadback2MatHelperDisposed() |
| 195 | + { |
| 196 | + Debug.Log("OnAsyncGPUReadback2MatHelperDisposed"); |
| 197 | + |
| 198 | + // Destroy the texture and set it to null |
| 199 | + if (_texture != null) Texture2D.Destroy(_texture); _texture = null; |
| 200 | + } |
| 201 | + |
| 202 | + /// <summary> |
| 203 | + /// Raises the async GPU readback to mat helper error occurred event. |
| 204 | + /// </summary> |
| 205 | + /// <param name="errorCode">Error code.</param> |
| 206 | + /// <param name="message">Message.</param> |
| 207 | + public void OnAsyncGPUReadback2MatHelperErrorOccurred(Source2MatHelperErrorCode errorCode, string message) |
| 208 | + { |
| 209 | + Debug.Log("OnAsyncGPUReadback2MatHelperErrorOccurred " + errorCode + ":" + message); |
| 210 | + |
| 211 | + // if (_fpsMonitor != null) |
| 212 | + // { |
| 213 | + // _fpsMonitor.consoleText = "ErrorCode: " + errorCode + ":" + message; |
| 214 | + // } |
| 215 | + } |
| 216 | + |
| 217 | + /// <summary> |
| 218 | + /// Raises the back button click event. |
| 219 | + /// </summary> |
| 220 | + public void OnBackButtonClick() |
| 221 | + { |
| 222 | + // Load the specified scene when the back button is clicked |
| 223 | + SceneManager.LoadScene("AVProWithOpenCVForUnityExample"); |
| 224 | + } |
| 225 | + |
| 226 | + /// <summary> |
| 227 | + /// Raises the play button click event. |
| 228 | + /// </summary> |
| 229 | + public void OnPlayButtonClick() |
| 230 | + { |
| 231 | + _asyncGPUReadback2MatHelper.Play(); |
| 232 | + } |
| 233 | + |
| 234 | + /// <summary> |
| 235 | + /// Raises the pause button click event. |
| 236 | + /// </summary> |
| 237 | + public void OnPauseButtonClick() |
| 238 | + { |
| 239 | + _asyncGPUReadback2MatHelper.Pause(); |
| 240 | + } |
| 241 | + |
| 242 | + /// <summary> |
| 243 | + /// Raises the stop button click event. |
| 244 | + /// </summary> |
| 245 | + public void OnStopButtonClick() |
| 246 | + { |
| 247 | + _asyncGPUReadback2MatHelper.Stop(); |
| 248 | + } |
| 249 | + |
| 250 | + /// <summary> |
| 251 | + /// Raises the requested mat update FPS dropdown value changed event. |
| 252 | + /// </summary> |
| 253 | + public void OnRequestedMatUpdateFPSDropdownValueChanged(int result) |
| 254 | + { |
| 255 | + string[] enumNames = Enum.GetNames(typeof(FPSPreset)); |
| 256 | + int value = (int)System.Enum.Parse(typeof(FPSPreset), enumNames[result], true); |
| 257 | + |
| 258 | + if ((int)RequestedMatUpdateFPS != value) |
| 259 | + { |
| 260 | + RequestedMatUpdateFPS = (FPSPreset)value; |
| 261 | + |
| 262 | + _asyncGPUReadback2MatHelper.RequestedMatUpdateFPS = (int)RequestedMatUpdateFPS; |
| 263 | + } |
| 264 | + } |
| 265 | + |
| 266 | + /// <summary> |
| 267 | + /// Raises the rotate 90 degree toggle value changed event. |
| 268 | + /// </summary> |
| 269 | + public void OnRotate90DegreeToggleValueChanged() |
| 270 | + { |
| 271 | + if (Rotate90DegreeToggle.isOn != _asyncGPUReadback2MatHelper.Rotate90Degree) |
| 272 | + { |
| 273 | + _asyncGPUReadback2MatHelper.Rotate90Degree = Rotate90DegreeToggle.isOn; |
| 274 | + |
| 275 | + if (_fpsMonitor != null) |
| 276 | + _fpsMonitor.Add("Rotate90Degree", _asyncGPUReadback2MatHelper.Rotate90Degree.ToString()); |
| 277 | + } |
| 278 | + } |
| 279 | + |
| 280 | + /// <summary> |
| 281 | + /// Raises the flip vertical toggle value changed event. |
| 282 | + /// </summary> |
| 283 | + public void OnFlipVerticalToggleValueChanged() |
| 284 | + { |
| 285 | + if (FlipVerticalToggle.isOn != _asyncGPUReadback2MatHelper.FlipVertical) |
| 286 | + { |
| 287 | + _asyncGPUReadback2MatHelper.FlipVertical = FlipVerticalToggle.isOn; |
| 288 | + |
| 289 | + if (_fpsMonitor != null) |
| 290 | + _fpsMonitor.Add("FlipVertical", _asyncGPUReadback2MatHelper.FlipVertical.ToString()); |
| 291 | + } |
| 292 | + } |
| 293 | + |
| 294 | + /// <summary> |
| 295 | + /// Raises the flip horizontal toggle value changed event. |
| 296 | + /// </summary> |
| 297 | + public void OnFlipHorizontalToggleValueChanged() |
| 298 | + { |
| 299 | + if (FlipHorizontalToggle.isOn != _asyncGPUReadback2MatHelper.FlipHorizontal) |
| 300 | + { |
| 301 | + _asyncGPUReadback2MatHelper.FlipHorizontal = FlipHorizontalToggle.isOn; |
| 302 | + |
| 303 | + if (_fpsMonitor != null) |
| 304 | + _fpsMonitor.Add("FlipHorizontal", _asyncGPUReadback2MatHelper.FlipHorizontal.ToString()); |
| 305 | + } |
| 306 | + } |
| 307 | + |
| 308 | + } |
| 309 | +} |
| 310 | +#endif |
| 311 | + |
0 commit comments