├── AllowUnsafeCode.png
├── Assets
├── NatDeviceWithOpenCVForUnityExample.meta
└── NatDeviceWithOpenCVForUnityExample
│ ├── IntegrationWithNatShareExample.meta
│ ├── IntegrationWithNatShareExample
│ ├── ComicFilter.cs
│ ├── ComicFilter.cs.meta
│ ├── IntegrationWithNatShareExample.cs
│ ├── IntegrationWithNatShareExample.cs.meta
│ ├── IntegrationWithNatShareExample.unity
│ └── IntegrationWithNatShareExample.unity.meta
│ ├── NatDeviceCamPreviewOnlyExample.meta
│ ├── NatDeviceCamPreviewOnlyExample
│ ├── NatDeviceCamPreviewOnlyExample.cs
│ ├── NatDeviceCamPreviewOnlyExample.cs.meta
│ ├── NatDeviceCamPreviewOnlyExample.unity
│ └── NatDeviceCamPreviewOnlyExample.unity.meta
│ ├── NatDeviceCamPreviewToMatExample.meta
│ ├── NatDeviceCamPreviewToMatExample
│ ├── NatDeviceCamPreviewToMatExample.cs
│ ├── NatDeviceCamPreviewToMatExample.cs.meta
│ ├── NatDeviceCamPreviewToMatExample.unity
│ └── NatDeviceCamPreviewToMatExample.unity.meta
│ ├── NatDeviceCamPreviewToMatHelperExample.meta
│ ├── NatDeviceCamPreviewToMatHelperExample
│ ├── ExampleMaterial.mat
│ ├── ExampleMaterial.mat.meta
│ ├── NatDeviceCamPreviewToMatHelperExample.cs
│ ├── NatDeviceCamPreviewToMatHelperExample.cs.meta
│ ├── NatDeviceCamPreviewToMatHelperExample.unity
│ └── NatDeviceCamPreviewToMatHelperExample.unity.meta
│ ├── NatDeviceWithOpenCVForUnityExample.cs
│ ├── NatDeviceWithOpenCVForUnityExample.cs.meta
│ ├── NatDeviceWithOpenCVForUnityExample.unity
│ ├── NatDeviceWithOpenCVForUnityExample.unity.meta
│ ├── Scripts.meta
│ ├── Scripts
│ ├── ExampleBase.cs
│ ├── ExampleBase.cs.meta
│ ├── ICameraSource.cs
│ ├── ICameraSource.cs.meta
│ ├── NatDeviceCamSource.cs
│ ├── NatDeviceCamSource.cs.meta
│ ├── Utils.meta
│ ├── Utils
│ │ ├── FpsMonitor.cs
│ │ ├── FpsMonitor.cs.meta
│ │ ├── NatDeviceCamPreviewToMatHelper.cs
│ │ ├── NatDeviceCamPreviewToMatHelper.cs.meta
│ │ ├── RuntimePermissionHelper.cs
│ │ └── RuntimePermissionHelper.cs.meta
│ ├── WebCamMatSource.cs
│ ├── WebCamMatSource.cs.meta
│ ├── WebCamSource.cs
│ └── WebCamSource.cs.meta
│ ├── ShowLicense.cs
│ ├── ShowLicense.cs.meta
│ ├── ShowLicense.unity
│ ├── ShowLicense.unity.meta
│ ├── ShowSystemInfo.cs
│ ├── ShowSystemInfo.cs.meta
│ ├── ShowSystemInfo.unity
│ ├── ShowSystemInfo.unity.meta
│ ├── WebCamTextureOnlyExample.meta
│ ├── WebCamTextureOnlyExample
│ ├── WebCamTextureOnlyExample.cs
│ ├── WebCamTextureOnlyExample.cs.meta
│ ├── WebCamTextureOnlyExample.unity
│ └── WebCamTextureOnlyExample.unity.meta
│ ├── WebCamTextureToMatExample.meta
│ ├── WebCamTextureToMatExample
│ ├── WebCamTextureToMatExample.cs
│ ├── WebCamTextureToMatExample.cs.meta
│ ├── WebCamTextureToMatExample.unity
│ └── WebCamTextureToMatExample.unity.meta
│ ├── link.xml
│ └── link.xml.meta
├── README.md
├── Use_UnsafeCode.png
├── screenshot01.jpg
├── screenshot02.jpg
└── screenshot03.jpg
/AllowUnsafeCode.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EnoxSoftware/NatDeviceWithOpenCVForUnityExample/4bf5536abc1a2088686e63e375128af84d8454d9/AllowUnsafeCode.png
--------------------------------------------------------------------------------
/Assets/NatDeviceWithOpenCVForUnityExample.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 66597862d10556b4096fef8f3680a3ab
3 | folderAsset: yes
4 | timeCreated: 1521821567
5 | licenseType: Free
6 | DefaultImporter:
7 | userData:
8 | assetBundleName:
9 | assetBundleVariant:
10 |
--------------------------------------------------------------------------------
/Assets/NatDeviceWithOpenCVForUnityExample/IntegrationWithNatShareExample.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: a394dc9ddb1871f46991ea89223c9b72
3 | folderAsset: yes
4 | timeCreated: 1524389028
5 | licenseType: Free
6 | DefaultImporter:
7 | userData:
8 | assetBundleName:
9 | assetBundleVariant:
10 |
--------------------------------------------------------------------------------
/Assets/NatDeviceWithOpenCVForUnityExample/IntegrationWithNatShareExample/ComicFilter.cs:
--------------------------------------------------------------------------------
1 | using OpenCVForUnity.CoreModule;
2 | using OpenCVForUnity.ImgprocModule;
3 | using OpenCVForUnity.UtilsModule;
4 | using System;
5 |
6 | namespace NatDeviceWithOpenCVForUnityExample
7 | {
8 |
9 | public class ComicFilter
10 | {
11 |
12 | Mat grayMat;
13 | Mat maskMat;
14 | Mat screentoneMat;
15 | Mat grayDstMat;
16 |
17 | Mat grayLUT;
18 | Mat contrastAdjustmentsLUT;
19 | Mat kernel_dilate;
20 | Mat kernel_erode;
21 | Size blurSize;
22 | int blackThresh;
23 | bool drawMainLine;
24 | bool useNoiseFilter;
25 |
26 |
27 | public ComicFilter(int blackThresh = 60, int grayThresh = 120, int thickness = 5, bool useNoiseFilter = true)
28 | {
29 | this.blackThresh = blackThresh;
30 | this.drawMainLine = (thickness != 0);
31 | this.useNoiseFilter = useNoiseFilter;
32 |
33 | grayLUT = new Mat(1, 256, CvType.CV_8UC1);
34 | byte[] lutArray = new byte[256];
35 | for (int i = 0; i < lutArray.Length; i++)
36 | {
37 | if (blackThresh <= i && i < grayThresh)
38 | lutArray[i] = 255;
39 | }
40 | MatUtils.copyToMat(lutArray, grayLUT);
41 |
42 | if (drawMainLine)
43 | {
44 | kernel_dilate = new Mat(thickness, thickness, CvType.CV_8UC1, new Scalar(1));
45 |
46 | int erode = (thickness >= 5) ? 2 : 1;
47 | kernel_erode = new Mat(erode, erode, CvType.CV_8UC1, new Scalar(1));
48 |
49 | int blur = (thickness >= 4) ? thickness - 1 : 3;
50 | blurSize = new Size(blur, blur);
51 |
52 | contrastAdjustmentsLUT = new Mat(1, 256, CvType.CV_8UC1);
53 | byte[] contrastAdjustmentsLUTArray = new byte[256];
54 | for (int i = 0; i < contrastAdjustmentsLUTArray.Length; i++)
55 | {
56 | int a = (int)(i * 1.5f);
57 | contrastAdjustmentsLUTArray[i] = (a > byte.MaxValue) ? (byte)255 : (byte)a;
58 |
59 | }
60 | MatUtils.copyToMat(contrastAdjustmentsLUTArray, contrastAdjustmentsLUT);
61 | }
62 | }
63 |
64 | public void Process(Mat src, Mat dst, bool isBGR = false)
65 | {
66 | if (src == null)
67 | throw new ArgumentNullException("src == null");
68 | if (dst == null)
69 | throw new ArgumentNullException("dst == null");
70 |
71 | if (grayMat != null && (grayMat.width() != src.width() || grayMat.height() != src.height()))
72 | {
73 | grayMat.Dispose();
74 | grayMat = null;
75 | maskMat.Dispose();
76 | maskMat = null;
77 | screentoneMat.Dispose();
78 | screentoneMat = null;
79 | grayDstMat.Dispose();
80 | grayDstMat = null;
81 | }
82 | grayMat = grayMat ?? new Mat(src.height(), src.width(), CvType.CV_8UC1);
83 | maskMat = maskMat ?? new Mat(src.height(), src.width(), CvType.CV_8UC1);
84 | grayDstMat = grayDstMat ?? new Mat(src.height(), src.width(), CvType.CV_8UC1);
85 |
86 | if (screentoneMat == null)
87 | {
88 | // create a striped screentone.
89 | screentoneMat = new Mat(src.height(), src.width(), CvType.CV_8UC1, new Scalar(255));
90 | for (int i = 0; i < screentoneMat.rows() * 2.5f; i = i + 4)
91 | {
92 | Imgproc.line(screentoneMat, new Point(0, 0 + i), new Point(screentoneMat.cols(), -screentoneMat.cols() + i), new Scalar(0), 1);
93 | }
94 | }
95 |
96 | if (src.type() == CvType.CV_8UC1)
97 | {
98 | src.copyTo(grayMat);
99 | }
100 | else if (dst.type() == CvType.CV_8UC3)
101 | {
102 | Imgproc.cvtColor(src, grayMat, (isBGR) ? Imgproc.COLOR_BGR2GRAY : Imgproc.COLOR_RGB2GRAY);
103 | }
104 | else
105 | {
106 | Imgproc.cvtColor(src, grayMat, (isBGR) ? Imgproc.COLOR_BGRA2GRAY : Imgproc.COLOR_RGBA2GRAY);
107 | }
108 |
109 |
110 | // binarize.
111 | Imgproc.threshold(grayMat, grayDstMat, blackThresh, 255.0, Imgproc.THRESH_BINARY);
112 |
113 | // draw striped screentone.
114 | Core.LUT(grayMat, grayLUT, maskMat);
115 | screentoneMat.copyTo(grayDstMat, maskMat);
116 |
117 | // draw main line.
118 | if (drawMainLine)
119 | {
120 | Core.LUT(grayMat, contrastAdjustmentsLUT, maskMat); // = grayMat.convertTo(maskMat, -1, 1.5, 0);
121 |
122 | if (useNoiseFilter)
123 | {
124 | Imgproc.blur(maskMat, grayMat, blurSize);
125 | Imgproc.dilate(grayMat, maskMat, kernel_dilate);
126 | }
127 | else
128 | {
129 | Imgproc.dilate(maskMat, grayMat, kernel_dilate);
130 | }
131 | Core.absdiff(grayMat, maskMat, grayMat);
132 | Imgproc.threshold(grayMat, maskMat, 25, 255.0, Imgproc.THRESH_BINARY);
133 | if (useNoiseFilter)
134 | {
135 | Imgproc.erode(maskMat, grayMat, kernel_erode);
136 | Core.bitwise_not(grayMat, maskMat);
137 | maskMat.copyTo(grayDstMat, grayMat);
138 | }
139 | else
140 | {
141 | Core.bitwise_not(maskMat, grayMat);
142 | grayMat.copyTo(grayDstMat, maskMat);
143 | }
144 | }
145 |
146 |
147 | if (dst.type() == CvType.CV_8UC1)
148 | {
149 | grayDstMat.copyTo(dst);
150 | }
151 | else if (dst.type() == CvType.CV_8UC3)
152 | {
153 | Imgproc.cvtColor(grayDstMat, dst, (isBGR) ? Imgproc.COLOR_GRAY2BGR : Imgproc.COLOR_GRAY2RGB);
154 | }
155 | else
156 | {
157 | Imgproc.cvtColor(grayDstMat, dst, (isBGR) ? Imgproc.COLOR_GRAY2BGRA : Imgproc.COLOR_GRAY2RGBA);
158 | }
159 | }
160 |
161 | public void Dispose()
162 | {
163 | foreach (var mat in new[] { grayMat, maskMat, screentoneMat, grayDstMat, grayLUT, kernel_dilate, kernel_erode, contrastAdjustmentsLUT })
164 | if (mat != null) mat.Dispose();
165 |
166 | grayDstMat =
167 | screentoneMat =
168 | maskMat =
169 | grayMat =
170 | grayLUT =
171 | kernel_dilate =
172 | kernel_erode =
173 | contrastAdjustmentsLUT = null;
174 | }
175 | }
176 | }
--------------------------------------------------------------------------------
/Assets/NatDeviceWithOpenCVForUnityExample/IntegrationWithNatShareExample/ComicFilter.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 08d77cc1cacdd0f42b35833496299c75
3 | timeCreated: 1524599498
4 | licenseType: Free
5 | MonoImporter:
6 | serializedVersion: 2
7 | defaultReferences: []
8 | executionOrder: 0
9 | icon: {instanceID: 0}
10 | userData:
11 | assetBundleName:
12 | assetBundleVariant:
13 |
--------------------------------------------------------------------------------
/Assets/NatDeviceWithOpenCVForUnityExample/IntegrationWithNatShareExample/IntegrationWithNatShareExample.cs:
--------------------------------------------------------------------------------
1 | using NatSuite.Devices;
2 | using NatSuite.Sharing;
3 | using OpenCVForUnity.CoreModule;
4 | using OpenCVForUnity.ImgprocModule;
5 | using OpenCVForUnity.UnityUtils;
6 | using System;
7 | using System.Threading.Tasks;
8 | using UnityEngine;
9 | using UnityEngine.UI;
10 |
11 | namespace NatDeviceWithOpenCVForUnityExample
12 | {
13 |
14 | ///
15 | /// Integration With NatShare Example
16 | /// An example of the native sharing and save to the camera roll using NatShare.
17 | ///
18 | public class IntegrationWithNatShareExample : ExampleBase
19 | {
20 | public bool applyComicFilter;
21 | public Toggle applyComicFilterToggle;
22 |
23 | Mat frameMatrix;
24 | Texture2D texture;
25 | ComicFilter comicFilter;
26 |
27 | FpsMonitor fpsMonitor;
28 |
29 | string exampleTitle = "";
30 | string exampleSceneTitle = "";
31 | string settingInfo1 = "";
32 | Scalar textColor = new Scalar(255, 255, 255, 255);
33 | Point textPos = new Point();
34 |
35 | protected override async void Start()
36 | {
37 | base.Start();
38 |
39 | fpsMonitor = GetComponent();
40 | if (fpsMonitor != null)
41 | {
42 | fpsMonitor.Add("Name", "IntegrationWithNatShareExample");
43 | fpsMonitor.Add("onFrameFPS", onFrameFPS.ToString("F1"));
44 | fpsMonitor.Add("drawFPS", drawFPS.ToString("F1"));
45 | fpsMonitor.Add("width", "");
46 | fpsMonitor.Add("height", "");
47 | fpsMonitor.Add("isFrontFacing", "");
48 | fpsMonitor.Add("orientation", "");
49 | }
50 |
51 | // Request camera permissions
52 | var permissionStatus = await MediaDeviceQuery.RequestPermissions();
53 | if (permissionStatus != PermissionStatus.Authorized)
54 | {
55 | Debug.LogError("User did not grant camera permissions");
56 | return;
57 | }
58 |
59 | // Load global camera benchmark settings.
60 | int width, height, framerate;
61 | NatDeviceWithOpenCVForUnityExample.CameraConfiguration(out width, out height, out framerate);
62 | // Create camera source
63 | cameraSource = new NatDeviceCamSource(width, height, framerate, useFrontCamera);
64 | if (cameraSource.activeCamera == null)
65 | cameraSource = new NatDeviceCamSource(width, height, framerate, !useFrontCamera);
66 | await cameraSource.StartRunning(OnStart, OnFrame);
67 |
68 | // Update GUI state
69 | applyComicFilterToggle.isOn = applyComicFilter;
70 |
71 | // Create comic filter
72 | comicFilter = new ComicFilter();
73 |
74 | exampleTitle = "[NatDeviceWithOpenCVForUnity Example] (" + NatDeviceWithOpenCVForUnityExample.GetNatDeviceVersion() + ")";
75 | exampleSceneTitle = "- Integration With NatShare Example";
76 | }
77 |
78 | protected override void OnStart()
79 | {
80 | base.OnStart();
81 |
82 | settingInfo1 = "- resolution: " + cameraSource.width + "x" + cameraSource.height;
83 |
84 | // Create matrices
85 | if (frameMatrix != null)
86 | frameMatrix.Dispose();
87 | frameMatrix = new Mat(cameraSource.height, cameraSource.width, CvType.CV_8UC4);
88 | // Create texture
89 | if (texture != null)
90 | Texture2D.Destroy(texture);
91 | texture = new Texture2D(
92 | cameraSource.width,
93 | cameraSource.height,
94 | TextureFormat.RGBA32,
95 | false,
96 | false
97 | );
98 | // Display preview
99 | rawImage.texture = texture;
100 | aspectFitter.aspectRatio = cameraSource.width / (float)cameraSource.height;
101 | Debug.Log("NatDevice camera source started with resolution: " + cameraSource.width + "x" + cameraSource.height + " isFrontFacing: " + cameraSource.isFrontFacing);
102 |
103 | if (fpsMonitor != null)
104 | {
105 | fpsMonitor.Add("width", cameraSource.width.ToString());
106 | fpsMonitor.Add("height", cameraSource.height.ToString());
107 | fpsMonitor.Add("isFrontFacing", cameraSource.isFrontFacing.ToString());
108 | fpsMonitor.Add("orientation", Screen.orientation.ToString());
109 | }
110 | }
111 |
112 | protected override void Update()
113 | {
114 | base.Update();
115 |
116 | if (updateCount == 0)
117 | {
118 | if (fpsMonitor != null)
119 | {
120 | fpsMonitor.Add("onFrameFPS", onFrameFPS.ToString("F1"));
121 | fpsMonitor.Add("drawFPS", drawFPS.ToString("F1"));
122 | fpsMonitor.Add("orientation", Screen.orientation.ToString());
123 | }
124 | }
125 | }
126 |
127 | protected override void UpdateTexture()
128 | {
129 | cameraSource.CaptureFrame(frameMatrix);
130 |
131 | if (applyComicFilter)
132 | comicFilter.Process(frameMatrix, frameMatrix);
133 |
134 | textPos.x = 5;
135 | textPos.y = frameMatrix.rows() - 50;
136 | Imgproc.putText(frameMatrix, exampleTitle, textPos, Imgproc.FONT_HERSHEY_SIMPLEX, 0.5, textColor, 1, Imgproc.LINE_AA, false);
137 | textPos.y = frameMatrix.rows() - 30;
138 | Imgproc.putText(frameMatrix, exampleSceneTitle, textPos, Imgproc.FONT_HERSHEY_SIMPLEX, 0.5, textColor, 1, Imgproc.LINE_AA, false);
139 | textPos.y = frameMatrix.rows() - 10;
140 | Imgproc.putText(frameMatrix, settingInfo1, textPos, Imgproc.FONT_HERSHEY_SIMPLEX, 0.5, textColor, 1, Imgproc.LINE_AA, false);
141 |
142 | // Convert to Texture2D
143 | Utils.fastMatToTexture2D(frameMatrix, texture, true, 0, false);
144 | }
145 |
146 | protected override void OnDestroy()
147 | {
148 | base.OnDestroy();
149 |
150 | if (frameMatrix != null)
151 | frameMatrix.Dispose();
152 | frameMatrix = null;
153 | Texture2D.Destroy(texture);
154 | texture = null;
155 | comicFilter.Dispose();
156 | comicFilter = null;
157 | }
158 |
159 | protected virtual async void OnApplicationPause(bool pauseStatus)
160 | {
161 | if (cameraSource == null || cameraSource.activeCamera == null)
162 | return;
163 |
164 | // The developer needs to do the camera suspend process oneself so that it is synchronized with the app suspend.
165 | if (pauseStatus)
166 | {
167 | if (cameraSource.isRunning)
168 | cameraSource.StopRunning();
169 | }
170 | else
171 | {
172 | if (!cameraSource.isRunning)
173 | await cameraSource.StartRunning(OnStart, OnFrame);
174 | }
175 | }
176 |
177 | public void OnApplyComicFilterToggleValueChanged()
178 | {
179 | if (applyComicFilter != applyComicFilterToggle.isOn)
180 | {
181 | applyComicFilter = applyComicFilterToggle.isOn;
182 | }
183 | }
184 |
185 | public async void OnShareButtonClick()
186 | {
187 | var mes = "";
188 |
189 | #if (UNITY_IOS || UNITY_ANDROID) && !UNITY_EDITOR
190 | try
191 | {
192 | SharePayload payload = new SharePayload();
193 | payload.AddText("User shared image! [NatDeviceWithOpenCVForUnity Example](" + NatDeviceWithOpenCVForUnityExample.GetNatDeviceVersion() + ")");
194 | payload.AddImage(texture);
195 | var success = await payload.Commit();
196 |
197 | mes = $"Successfully shared items: {success}";
198 | }
199 | catch (ApplicationException e)
200 | {
201 | mes = e.Message;
202 | }
203 | #else
204 | mes = "NatShare Error: SharePayload is not supported on this platform";
205 | await Task.Delay(100);
206 | #endif
207 |
208 | Debug.Log(mes);
209 | if (fpsMonitor != null) fpsMonitor.Toast(mes);
210 | }
211 |
212 | public async void OnSaveToCameraRollButtonClick()
213 | {
214 | var mes = "";
215 |
216 | #if (UNITY_IOS || UNITY_ANDROID) && !UNITY_EDITOR
217 | try
218 | {
219 | SavePayload payload = new SavePayload("NatDeviceWithOpenCVForUnityExample");
220 | payload.AddImage(texture);
221 | var success = await payload.Commit();
222 |
223 | mes = $"Successfully saved items: {success}";
224 | }
225 | catch (ApplicationException e)
226 | {
227 | mes = e.Message;
228 | }
229 | #else
230 | mes = "NatShare Error: SavePayload is not supported on this platform";
231 | await Task.Delay(100);
232 | #endif
233 |
234 | Debug.Log(mes);
235 | if (fpsMonitor != null) fpsMonitor.Toast(mes);
236 | }
237 | }
238 | }
--------------------------------------------------------------------------------
/Assets/NatDeviceWithOpenCVForUnityExample/IntegrationWithNatShareExample/IntegrationWithNatShareExample.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: f5ca190fc54d25e4a80601d2e5f9c573
3 | timeCreated: 1524389028
4 | licenseType: Free
5 | MonoImporter:
6 | serializedVersion: 2
7 | defaultReferences: []
8 | executionOrder: 0
9 | icon: {instanceID: 0}
10 | userData:
11 | assetBundleName:
12 | assetBundleVariant:
13 |
--------------------------------------------------------------------------------
/Assets/NatDeviceWithOpenCVForUnityExample/IntegrationWithNatShareExample/IntegrationWithNatShareExample.unity.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: f78ae37dff926a641be7ee414fcc2798
3 | timeCreated: 1524389028
4 | licenseType: Free
5 | DefaultImporter:
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/Assets/NatDeviceWithOpenCVForUnityExample/NatDeviceCamPreviewOnlyExample.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 7a91cc898012624429966da3089ef8fb
3 | folderAsset: yes
4 | timeCreated: 1522155379
5 | licenseType: Free
6 | DefaultImporter:
7 | userData:
8 | assetBundleName:
9 | assetBundleVariant:
10 |
--------------------------------------------------------------------------------
/Assets/NatDeviceWithOpenCVForUnityExample/NatDeviceCamPreviewOnlyExample/NatDeviceCamPreviewOnlyExample.cs:
--------------------------------------------------------------------------------
1 | using NatSuite.Devices;
2 | using System.Collections.Generic;
3 | using UnityEngine;
4 | using UnityEngine.EventSystems;
5 |
6 | namespace NatDeviceWithOpenCVForUnityExample
7 | {
8 |
9 | ///
10 | /// NatDeviceCamPreview Only Example
11 | /// An example of displaying the preview frame of camera only using NatDevice.
12 | ///
13 | public class NatDeviceCamPreviewOnlyExample : ExampleBase
14 | {
15 |
16 | Texture2D texture;
17 | byte[] pixelBuffer;
18 |
19 | FpsMonitor fpsMonitor;
20 |
21 | #region --ExampleBase--
22 |
23 | protected override async void Start()
24 | {
25 | base.Start();
26 |
27 | fpsMonitor = GetComponent();
28 | if (fpsMonitor != null)
29 | {
30 | fpsMonitor.Add("Name", "NatDeviceCamPreviewOnlyExample");
31 | fpsMonitor.Add("onFrameFPS", onFrameFPS.ToString("F1"));
32 | fpsMonitor.Add("drawFPS", drawFPS.ToString("F1"));
33 | fpsMonitor.Add("width", "");
34 | fpsMonitor.Add("height", "");
35 | fpsMonitor.Add("isFrontFacing", "");
36 | fpsMonitor.Add("orientation", "");
37 | }
38 |
39 | // Request camera permissions
40 | var permissionStatus = await MediaDeviceQuery.RequestPermissions();
41 | if (permissionStatus != PermissionStatus.Authorized)
42 | {
43 | Debug.LogError("User did not grant camera permissions");
44 | return;
45 | }
46 |
47 | // Load global camera benchmark settings.
48 | int width, height, framerate;
49 | NatDeviceWithOpenCVForUnityExample.CameraConfiguration(out width, out height, out framerate);
50 | // Create camera source
51 | cameraSource = new NatDeviceCamSource(width, height, framerate, useFrontCamera);
52 | if (cameraSource.activeCamera == null)
53 | cameraSource = new NatDeviceCamSource(width, height, framerate, !useFrontCamera);
54 | await cameraSource.StartRunning(OnStart, OnFrame);
55 | }
56 |
57 | protected override void OnStart()
58 | {
59 | base.OnStart();
60 |
61 | // Create pixel buffer
62 | pixelBuffer = new byte[cameraSource.width * cameraSource.height * 4];
63 | // Create texture
64 | if (texture != null)
65 | Texture2D.Destroy(texture);
66 | texture = new Texture2D(
67 | cameraSource.width,
68 | cameraSource.height,
69 | TextureFormat.RGBA32,
70 | false,
71 | false
72 | );
73 | // Display preview
74 | rawImage.texture = texture;
75 | aspectFitter.aspectRatio = cameraSource.width / (float)cameraSource.height;
76 | Debug.Log("NatDevice camera source started with resolution: " + cameraSource.width + "x" + cameraSource.height + " isFrontFacing: " + cameraSource.isFrontFacing);
77 |
78 | // Log camera properties
79 | var cameraProps = new Dictionary();
80 | var camera = cameraSource.activeCamera;
81 | if (camera != null)
82 | {
83 | cameraProps.Add("defaultForMediaType", camera.defaultForMediaType.ToString());
84 | cameraProps.Add("exposureBias", camera.exposureBias.ToString());
85 | cameraProps.Add("exposureBiasRange", camera.exposureBiasRange.min + "x" + camera.exposureBiasRange.max);
86 | cameraProps.Add("exposureDurationRange", camera.exposureDurationRange.min + "x" + camera.exposureDurationRange.max);
87 | cameraProps.Add("exposureMode", camera.exposureMode.ToString());
88 | cameraProps.Add("ExposureModeSupported:Continuous", camera.ExposureModeSupported(CameraDevice.ExposureMode.Continuous).ToString());
89 | cameraProps.Add("ExposureModeSupported:Locked", camera.ExposureModeSupported(CameraDevice.ExposureMode.Locked).ToString());
90 | cameraProps.Add("ExposureModeSupported:Manual", camera.ExposureModeSupported(CameraDevice.ExposureMode.Manual).ToString());
91 | cameraProps.Add("exposurePointSupported", camera.exposurePointSupported.ToString());
92 | cameraProps.Add("fieldOfView", camera.fieldOfView.width + "x" + camera.fieldOfView.height);
93 | cameraProps.Add("flashMode", camera.flashMode.ToString());
94 | cameraProps.Add("flashSupported", camera.flashSupported.ToString());
95 | cameraProps.Add("focusMode", camera.focusMode.ToString());
96 | cameraProps.Add("FocusModeSupported:Continuous", camera.FocusModeSupported(CameraDevice.FocusMode.Continuous).ToString());
97 | cameraProps.Add("FocusModeSupported:Locked", camera.FocusModeSupported(CameraDevice.FocusMode.Locked).ToString());
98 | cameraProps.Add("focusPointSupported", camera.focusPointSupported.ToString());
99 | cameraProps.Add("frameRate", camera.frameRate.ToString());
100 | cameraProps.Add("frontFacing", camera.frontFacing.ToString());
101 | cameraProps.Add("ISORange", camera.ISORange.min + "x" + camera.ISORange.max);
102 | cameraProps.Add("location", camera.location.ToString());
103 | cameraProps.Add("name", camera.name.ToString());
104 | cameraProps.Add("photoResolution", camera.photoResolution.width + "x" + camera.photoResolution.height);
105 | cameraProps.Add("previewResolution", camera.previewResolution.width + "x" + camera.previewResolution.height);
106 | cameraProps.Add("running", camera.running.ToString());
107 | cameraProps.Add("torchEnabled", camera.torchEnabled.ToString());
108 | cameraProps.Add("torchSupported", camera.torchSupported.ToString());
109 | cameraProps.Add("uniqueID", camera.uniqueID.ToString());
110 | cameraProps.Add("whiteBalanceLock", camera.whiteBalanceLock.ToString());
111 | cameraProps.Add("whiteBalanceLockSupported", camera.whiteBalanceLockSupported.ToString());
112 | cameraProps.Add("zoomRange", camera.zoomRange.max + "x" + camera.zoomRange.min);
113 | cameraProps.Add("zoomRatio", camera.zoomRatio.ToString());
114 | }
115 |
116 | Debug.Log("# Active Camera Properties #####################");
117 | foreach (string key in cameraProps.Keys)
118 | Debug.Log(key + ": " + cameraProps[key]);
119 | Debug.Log("#######################################");
120 |
121 | if (fpsMonitor != null)
122 | {
123 | fpsMonitor.Add("width", cameraSource.width.ToString());
124 | fpsMonitor.Add("height", cameraSource.height.ToString());
125 | fpsMonitor.Add("isFrontFacing", cameraSource.isFrontFacing.ToString());
126 | fpsMonitor.Add("orientation", Screen.orientation.ToString());
127 |
128 | fpsMonitor.boxWidth = 280;
129 | fpsMonitor.boxHeight = 1030;
130 | fpsMonitor.LocateGUI();
131 |
132 | foreach (string key in cameraProps.Keys)
133 | fpsMonitor.Add(key, cameraProps[key]);
134 | }
135 |
136 | // Add camera device disconnection event
137 | camera.onDisconnected += () =>
138 | {
139 | if (fpsMonitor != null)
140 | fpsMonitor.consoleText = "the camera device is disconnected.";
141 | };
142 | }
143 |
144 | protected override void Update()
145 | {
146 | base.Update();
147 |
148 | if (updateCount == 0)
149 | {
150 | if (fpsMonitor != null)
151 | {
152 | fpsMonitor.Add("onFrameFPS", onFrameFPS.ToString("F1"));
153 | fpsMonitor.Add("drawFPS", drawFPS.ToString("F1"));
154 | fpsMonitor.Add("orientation", Screen.orientation.ToString());
155 | }
156 | }
157 | }
158 |
159 | protected override void UpdateTexture()
160 | {
161 | cameraSource.CaptureFrame(pixelBuffer);
162 | ProcessImage(pixelBuffer, texture.width, texture.height, imageProcessingType);
163 | texture.LoadRawTextureData(pixelBuffer);
164 | texture.Apply();
165 | }
166 |
167 | protected override void OnDestroy()
168 | {
169 | base.OnDestroy();
170 |
171 | Texture2D.Destroy(texture);
172 | texture = null;
173 | pixelBuffer = null;
174 | }
175 |
176 | #endregion
177 |
178 | protected virtual async void OnApplicationPause(bool pauseStatus)
179 | {
180 | if (cameraSource == null || cameraSource.activeCamera == null)
181 | return;
182 |
183 | // The developer needs to do the camera suspend process oneself so that it is synchronized with the app suspend.
184 | if (pauseStatus)
185 | {
186 | if (cameraSource.isRunning)
187 | cameraSource.StopRunning();
188 | }
189 | else
190 | {
191 | if (!cameraSource.isRunning)
192 | await cameraSource.StartRunning(OnStart, OnFrame);
193 | }
194 | }
195 |
196 | public void FocusCamera(BaseEventData e)
197 | {
198 | if (cameraSource == null || cameraSource.activeCamera == null)
199 | return;
200 |
201 | var cameraDevice = cameraSource.activeCamera;
202 |
203 | // Check if focus is supported
204 | if (!cameraDevice.focusPointSupported)
205 | return;
206 | // Get the touch position in viewport coordinates
207 | var eventData = e as PointerEventData;
208 | var transform = eventData.pointerPress.GetComponent();
209 | if (!RectTransformUtility.ScreenPointToWorldPointInRectangle(
210 | transform,
211 | eventData.pressPosition,
212 | eventData.pressEventCamera,
213 | out var worldPoint
214 | ))
215 | return;
216 | var corners = new Vector3[4];
217 | transform.GetWorldCorners(corners);
218 | var point = worldPoint - corners[0];
219 | var size = new Vector2(corners[3].x, corners[1].y) - (Vector2)corners[0];
220 | // Focus camera at point
221 | cameraDevice.SetFocusPoint(point.x / size.x, point.y / size.y);
222 |
223 | if (fpsMonitor != null)
224 | fpsMonitor.Toast("Set Focus Point: " + point.x / size.x + " x " + point.y / size.y);
225 | }
226 | }
227 | }
--------------------------------------------------------------------------------
/Assets/NatDeviceWithOpenCVForUnityExample/NatDeviceCamPreviewOnlyExample/NatDeviceCamPreviewOnlyExample.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 7de64702992c67842b18b623410d3b42
3 | timeCreated: 1484195860
4 | licenseType: Store
5 | MonoImporter:
6 | serializedVersion: 2
7 | defaultReferences: []
8 | executionOrder: 0
9 | icon: {instanceID: 0}
10 | userData:
11 | assetBundleName:
12 | assetBundleVariant:
13 |
--------------------------------------------------------------------------------
/Assets/NatDeviceWithOpenCVForUnityExample/NatDeviceCamPreviewOnlyExample/NatDeviceCamPreviewOnlyExample.unity.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 45d5c81453669024799a34ff7a3d5b51
3 | timeCreated: 1477101412
4 | licenseType: Store
5 | DefaultImporter:
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/Assets/NatDeviceWithOpenCVForUnityExample/NatDeviceCamPreviewToMatExample.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 96db6872c06c0dd43b5374295f5c6c53
3 | folderAsset: yes
4 | timeCreated: 1522155392
5 | licenseType: Free
6 | DefaultImporter:
7 | userData:
8 | assetBundleName:
9 | assetBundleVariant:
10 |
--------------------------------------------------------------------------------
/Assets/NatDeviceWithOpenCVForUnityExample/NatDeviceCamPreviewToMatExample/NatDeviceCamPreviewToMatExample.cs:
--------------------------------------------------------------------------------
1 | using NatSuite.Devices;
2 | using OpenCVForUnity.CoreModule;
3 | using OpenCVForUnity.UnityUtils;
4 | using System.Collections.Generic;
5 | using UnityEngine;
6 | using UnityEngine.EventSystems;
7 |
8 | namespace NatDeviceWithOpenCVForUnityExample
9 | {
10 |
11 | ///
12 | /// NatDeviceCamPreview To Mat Example
13 | /// An example of converting a NatDevice camera preview image to OpenCV's Mat format.
14 | ///
15 | public class NatDeviceCamPreviewToMatExample : ExampleBase
16 | {
17 |
18 | Mat frameMatrix;
19 | Mat grayMatrix;
20 | Texture2D texture;
21 |
22 | FpsMonitor fpsMonitor;
23 |
24 | #region --ExampleBase--
25 |
26 | protected override async void Start()
27 | {
28 | base.Start();
29 |
30 | fpsMonitor = GetComponent();
31 | if (fpsMonitor != null)
32 | {
33 | fpsMonitor.Add("Name", "NatDeviceCamPreviewToMatExample");
34 | fpsMonitor.Add("onFrameFPS", onFrameFPS.ToString("F1"));
35 | fpsMonitor.Add("drawFPS", drawFPS.ToString("F1"));
36 | fpsMonitor.Add("width", "");
37 | fpsMonitor.Add("height", "");
38 | fpsMonitor.Add("isFrontFacing", "");
39 | fpsMonitor.Add("orientation", "");
40 | }
41 |
42 | // Request camera permissions
43 | var permissionStatus = await MediaDeviceQuery.RequestPermissions();
44 | if (permissionStatus != PermissionStatus.Authorized)
45 | {
46 | Debug.LogError("User did not grant camera permissions");
47 | return;
48 | }
49 |
50 | // Load global camera benchmark settings.
51 | int width, height, framerate;
52 | NatDeviceWithOpenCVForUnityExample.CameraConfiguration(out width, out height, out framerate);
53 | // Create camera source
54 | cameraSource = new NatDeviceCamSource(width, height, framerate, useFrontCamera);
55 | if (cameraSource.activeCamera == null)
56 | cameraSource = new NatDeviceCamSource(width, height, framerate, !useFrontCamera);
57 | await cameraSource.StartRunning(OnStart, OnFrame);
58 | }
59 |
60 | protected override void OnStart()
61 | {
62 | base.OnStart();
63 |
64 | // Create matrices
65 | if (frameMatrix != null)
66 | frameMatrix.Dispose();
67 | frameMatrix = new Mat(cameraSource.height, cameraSource.width, CvType.CV_8UC4);
68 | if (grayMatrix != null)
69 | grayMatrix.Dispose();
70 | grayMatrix = new Mat(cameraSource.height, cameraSource.width, CvType.CV_8UC1);
71 | // Create texture
72 | if (texture != null)
73 | Texture2D.Destroy(texture);
74 | texture = new Texture2D(
75 | cameraSource.width,
76 | cameraSource.height,
77 | TextureFormat.RGBA32,
78 | false,
79 | false
80 | );
81 | // Display preview
82 | rawImage.texture = texture;
83 | aspectFitter.aspectRatio = cameraSource.width / (float)cameraSource.height;
84 | Debug.Log("NatDevice camera source started with resolution: " + cameraSource.width + "x" + cameraSource.height + " isFrontFacing: " + cameraSource.isFrontFacing);
85 |
86 | // Log camera properties
87 | var cameraProps = new Dictionary();
88 | var camera = cameraSource.activeCamera as CameraDevice;
89 | if (camera != null)
90 | {
91 | cameraProps.Add("defaultForMediaType", camera.defaultForMediaType.ToString());
92 | cameraProps.Add("exposureBias", camera.exposureBias.ToString());
93 | cameraProps.Add("exposureBiasRange", camera.exposureBiasRange.min + "x" + camera.exposureBiasRange.max);
94 | cameraProps.Add("exposureDurationRange", camera.exposureDurationRange.min + "x" + camera.exposureDurationRange.max);
95 | cameraProps.Add("exposureMode", camera.exposureMode.ToString());
96 | cameraProps.Add("ExposureModeSupported:Continuous", camera.ExposureModeSupported(CameraDevice.ExposureMode.Continuous).ToString());
97 | cameraProps.Add("ExposureModeSupported:Locked", camera.ExposureModeSupported(CameraDevice.ExposureMode.Locked).ToString());
98 | cameraProps.Add("ExposureModeSupported:Manual", camera.ExposureModeSupported(CameraDevice.ExposureMode.Manual).ToString());
99 | cameraProps.Add("exposurePointSupported", camera.exposurePointSupported.ToString());
100 | cameraProps.Add("fieldOfView", camera.fieldOfView.width + "x" + camera.fieldOfView.height);
101 | cameraProps.Add("flashMode", camera.flashMode.ToString());
102 | cameraProps.Add("flashSupported", camera.flashSupported.ToString());
103 | cameraProps.Add("focusMode", camera.focusMode.ToString());
104 | cameraProps.Add("FocusModeSupported:Continuous", camera.FocusModeSupported(CameraDevice.FocusMode.Continuous).ToString());
105 | cameraProps.Add("FocusModeSupported:Locked", camera.FocusModeSupported(CameraDevice.FocusMode.Locked).ToString());
106 | cameraProps.Add("focusPointSupported", camera.focusPointSupported.ToString());
107 | cameraProps.Add("frameRate", camera.frameRate.ToString());
108 | cameraProps.Add("frontFacing", camera.frontFacing.ToString());
109 | cameraProps.Add("ISORange", camera.ISORange.min + "x" + camera.ISORange.max);
110 | cameraProps.Add("location", camera.location.ToString());
111 | cameraProps.Add("name", camera.name.ToString());
112 | cameraProps.Add("photoResolution", camera.photoResolution.width + "x" + camera.photoResolution.height);
113 | cameraProps.Add("previewResolution", camera.previewResolution.width + "x" + camera.previewResolution.height);
114 | cameraProps.Add("running", camera.running.ToString());
115 | cameraProps.Add("torchEnabled", camera.torchEnabled.ToString());
116 | cameraProps.Add("torchSupported", camera.torchSupported.ToString());
117 | cameraProps.Add("uniqueID", camera.uniqueID.ToString());
118 | cameraProps.Add("whiteBalanceLock", camera.whiteBalanceLock.ToString());
119 | cameraProps.Add("whiteBalanceLockSupported", camera.whiteBalanceLockSupported.ToString());
120 | cameraProps.Add("zoomRange", camera.zoomRange.max + "x" + camera.zoomRange.min);
121 | cameraProps.Add("zoomRatio", camera.zoomRatio.ToString());
122 | }
123 |
124 | Debug.Log("# Active Camera Properties #####################");
125 | foreach (string key in cameraProps.Keys)
126 | Debug.Log(key + ": " + cameraProps[key]);
127 | Debug.Log("#######################################");
128 |
129 | if (fpsMonitor != null)
130 | {
131 | fpsMonitor.Add("width", cameraSource.width.ToString());
132 | fpsMonitor.Add("height", cameraSource.height.ToString());
133 | fpsMonitor.Add("isFrontFacing", cameraSource.isFrontFacing.ToString());
134 | fpsMonitor.Add("orientation", Screen.orientation.ToString());
135 |
136 | fpsMonitor.boxWidth = 280;
137 | fpsMonitor.boxHeight = 1030;
138 | fpsMonitor.LocateGUI();
139 |
140 | //foreach (string key in cameraProps.Keys)
141 | // fpsMonitor.Add(key, cameraProps[key]);
142 | }
143 |
144 | // Add camera device disconnection event
145 | camera.onDisconnected += () =>
146 | {
147 | if (fpsMonitor != null)
148 | fpsMonitor.consoleText = "the camera device is disconnected.";
149 | };
150 | }
151 |
152 | protected override void Update()
153 | {
154 | base.Update();
155 |
156 | if (updateCount == 0)
157 | {
158 | if (fpsMonitor != null)
159 | {
160 | fpsMonitor.Add("onFrameFPS", onFrameFPS.ToString("F1"));
161 | fpsMonitor.Add("drawFPS", drawFPS.ToString("F1"));
162 | fpsMonitor.Add("orientation", Screen.orientation.ToString());
163 | }
164 | }
165 |
166 | // Update display of camera image metadata every frame.
167 | if (cameraSource.isRunning && fpsMonitor != null)
168 | {
169 | fpsMonitor.Add("timestamp", cameraSource.timestamp.ToString());
170 | fpsMonitor.Add("verticallyMirrored", cameraSource.verticallyMirrored.ToString());
171 | fpsMonitor.Add("intrinsics", "\n" + cameraSource.intrinsics.ToString());
172 | fpsMonitor.Add("exposureBias", cameraSource.exposureBias.ToString());
173 | fpsMonitor.Add("exposureDuration", cameraSource.exposureDuration.ToString());
174 | fpsMonitor.Add("ISO", cameraSource.ISO.ToString());
175 | fpsMonitor.Add("focalLength", cameraSource.focalLength.ToString());
176 | fpsMonitor.Add("fNumber", cameraSource.fNumber.ToString());
177 | fpsMonitor.Add("brightness", cameraSource.brightness.ToString());
178 | }
179 | }
180 |
181 | protected override void UpdateTexture()
182 | {
183 | // Get the matrix
184 | cameraSource.CaptureFrame(frameMatrix);
185 |
186 | ProcessImage(frameMatrix, grayMatrix, imageProcessingType);
187 |
188 | // Convert to Texture2D
189 | Utils.fastMatToTexture2D(frameMatrix, texture);
190 | }
191 |
192 | protected override void OnDestroy()
193 | {
194 | base.OnDestroy();
195 |
196 | if (frameMatrix != null)
197 | frameMatrix.Dispose();
198 | if (grayMatrix != null)
199 | grayMatrix.Dispose();
200 | frameMatrix =
201 | grayMatrix = null;
202 | Texture2D.Destroy(texture);
203 | texture = null;
204 | }
205 |
206 | #endregion
207 |
208 | protected virtual async void OnApplicationPause(bool pauseStatus)
209 | {
210 | if (cameraSource == null || cameraSource.activeCamera == null)
211 | return;
212 |
213 | // The developer needs to do the camera suspend process oneself so that it is synchronized with the app suspend.
214 | if (pauseStatus)
215 | {
216 | if (cameraSource.isRunning)
217 | cameraSource.StopRunning();
218 | }
219 | else
220 | {
221 | if (!cameraSource.isRunning)
222 | await cameraSource.StartRunning(OnStart, OnFrame);
223 | }
224 | }
225 |
226 | public void FocusCamera(BaseEventData e)
227 | {
228 | if (cameraSource == null || cameraSource.activeCamera == null)
229 | return;
230 |
231 | var cameraDevice = cameraSource.activeCamera;
232 |
233 | // Check if focus is supported
234 | if (!cameraDevice.focusPointSupported)
235 | return;
236 | // Get the touch position in viewport coordinates
237 | var eventData = e as PointerEventData;
238 | var transform = eventData.pointerPress.GetComponent();
239 | if (!RectTransformUtility.ScreenPointToWorldPointInRectangle(
240 | transform,
241 | eventData.pressPosition,
242 | eventData.pressEventCamera,
243 | out var worldPoint
244 | ))
245 | return;
246 | var corners = new Vector3[4];
247 | transform.GetWorldCorners(corners);
248 | var point = worldPoint - corners[0];
249 | var size = new Vector2(corners[3].x, corners[1].y) - (Vector2)corners[0];
250 | // Focus camera at point
251 | cameraDevice.SetFocusPoint(point.x / size.x, point.y / size.y);
252 |
253 | if (fpsMonitor != null)
254 | fpsMonitor.Toast("Set Focus Point: " + point.x / size.x + " x " + point.y / size.y);
255 | }
256 | }
257 | }
--------------------------------------------------------------------------------
/Assets/NatDeviceWithOpenCVForUnityExample/NatDeviceCamPreviewToMatExample/NatDeviceCamPreviewToMatExample.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 8ee1737701661f640b54a64e60ee8de5
3 | timeCreated: 1522098564
4 | licenseType: Free
5 | MonoImporter:
6 | serializedVersion: 2
7 | defaultReferences: []
8 | executionOrder: 0
9 | icon: {instanceID: 0}
10 | userData:
11 | assetBundleName:
12 | assetBundleVariant:
13 |
--------------------------------------------------------------------------------
/Assets/NatDeviceWithOpenCVForUnityExample/NatDeviceCamPreviewToMatExample/NatDeviceCamPreviewToMatExample.unity.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: b7a31f20bafa7a14997597b75d05ea78
3 | timeCreated: 1482683808
4 | licenseType: Store
5 | DefaultImporter:
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/Assets/NatDeviceWithOpenCVForUnityExample/NatDeviceCamPreviewToMatHelperExample.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: fc933a03de5fd314bac0848335d7ca1c
3 | folderAsset: yes
4 | timeCreated: 1524603639
5 | licenseType: Free
6 | DefaultImporter:
7 | userData:
8 | assetBundleName:
9 | assetBundleVariant:
10 |
--------------------------------------------------------------------------------
/Assets/NatDeviceWithOpenCVForUnityExample/NatDeviceCamPreviewToMatHelperExample/ExampleMaterial.mat:
--------------------------------------------------------------------------------
1 | %YAML 1.1
2 | %TAG !u! tag:unity3d.com,2011:
3 | --- !u!21 &2100000
4 | Material:
5 | serializedVersion: 6
6 | m_ObjectHideFlags: 0
7 | m_PrefabParentObject: {fileID: 0}
8 | m_PrefabInternal: {fileID: 0}
9 | m_Name: ExampleMaterial
10 | m_Shader: {fileID: 10750, guid: 0000000000000000f000000000000000, type: 0}
11 | m_ShaderKeywords:
12 | m_LightmapFlags: 5
13 | m_EnableInstancingVariants: 0
14 | m_CustomRenderQueue: -1
15 | stringTagMap: {}
16 | disabledShaderPasses: []
17 | m_SavedProperties:
18 | serializedVersion: 3
19 | m_TexEnvs:
20 | - _MainTex:
21 | m_Texture: {fileID: 2800000, guid: 9a89f0244015e104fb922e309d53caf1, type: 3}
22 | m_Scale: {x: 1, y: 1}
23 | m_Offset: {x: 0, y: 0}
24 | m_Floats: []
25 | m_Colors:
26 | - _Color: {r: 1, g: 1, b: 1, a: 1}
27 |
--------------------------------------------------------------------------------
/Assets/NatDeviceWithOpenCVForUnityExample/NatDeviceCamPreviewToMatHelperExample/ExampleMaterial.mat.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 6c6c3f29578c5fc438256e239d0e7273
3 | NativeFormatImporter:
4 | userData:
5 | assetBundleName:
6 | assetBundleVariant:
7 |
--------------------------------------------------------------------------------
/Assets/NatDeviceWithOpenCVForUnityExample/NatDeviceCamPreviewToMatHelperExample/NatDeviceCamPreviewToMatHelperExample.cs:
--------------------------------------------------------------------------------
1 | using NatDeviceWithOpenCVForUnity.UnityUtils.Helper;
2 | using NatSuite.Devices;
3 | using OpenCVForUnity.CoreModule;
4 | using OpenCVForUnity.ImgprocModule;
5 | using OpenCVForUnity.UnityUtils;
6 | using OpenCVForUnity.UnityUtils.Helper;
7 | using System;
8 | using System.Collections.Generic;
9 | using UnityEngine;
10 | using UnityEngine.SceneManagement;
11 | using UnityEngine.UI;
12 |
13 | namespace NatDeviceWithOpenCVForUnityExample
14 | {
15 | ///
16 | /// NatDeviceCamPreviewToMatHelper Example
17 | ///
18 | [RequireComponent(typeof(NatDeviceCamPreviewToMatHelper))]
19 | public class NatDeviceCamPreviewToMatHelperExample : MonoBehaviour
20 | {
21 | ///
22 | /// The requested resolution dropdown.
23 | ///
24 | public Dropdown requestedResolutionDropdown;
25 |
26 | ///
27 | /// The requested resolution.
28 | ///
29 | public ResolutionPreset requestedResolution = ResolutionPreset._1280x720;
30 |
31 | ///
32 | /// The requestedFPS dropdown.
33 | ///
34 | public Dropdown requestedFPSDropdown;
35 |
36 | ///
37 | /// The requestedFPS.
38 | ///
39 | public FPSPreset requestedFPS = FPSPreset._30;
40 |
41 | ///
42 | /// The rotate 90 degree toggle.
43 | ///
44 | public Toggle rotate90DegreeToggle;
45 |
46 | ///
47 | /// The flip vertical toggle.
48 | ///
49 | public Toggle flipVerticalToggle;
50 |
51 | ///
52 | /// The flip horizontal toggle.
53 | ///
54 | public Toggle flipHorizontalToggle;
55 |
56 | ///
57 | /// The texture.
58 | ///
59 | Texture2D texture;
60 |
61 | ///
62 | /// The webcam texture to mat helper.
63 | ///
64 | NatDeviceCamPreviewToMatHelper webCamTextureToMatHelper;
65 |
66 | ///
67 | /// The FPS monitor.
68 | ///
69 | FpsMonitor fpsMonitor;
70 |
71 | // Use this for initialization
72 | void Start()
73 | {
74 | fpsMonitor = GetComponent();
75 | if (fpsMonitor != null)
76 | {
77 | fpsMonitor.Add("deviceName", "");
78 | fpsMonitor.Add("width", "");
79 | fpsMonitor.Add("height", "");
80 | fpsMonitor.Add("camera fps", "");
81 | fpsMonitor.Add("isFrontFacing", "");
82 | fpsMonitor.Add("rotate90Degree", "");
83 | fpsMonitor.Add("flipVertical", "");
84 | fpsMonitor.Add("flipHorizontal", "");
85 | fpsMonitor.Add("orientation", "");
86 | }
87 |
88 | webCamTextureToMatHelper = gameObject.GetComponent();
89 | int width, height;
90 | Dimensions(requestedResolution, out width, out height);
91 | webCamTextureToMatHelper.requestedWidth = width;
92 | webCamTextureToMatHelper.requestedHeight = height;
93 | webCamTextureToMatHelper.requestedFPS = (int)requestedFPS;
94 | webCamTextureToMatHelper.Initialize();
95 |
96 | // Update GUI state
97 | requestedResolutionDropdown.value = (int)requestedResolution;
98 | string[] enumNames = System.Enum.GetNames(typeof(FPSPreset));
99 | int index = Array.IndexOf(enumNames, requestedFPS.ToString());
100 | requestedFPSDropdown.value = index;
101 | rotate90DegreeToggle.isOn = webCamTextureToMatHelper.rotate90Degree;
102 | flipVerticalToggle.isOn = webCamTextureToMatHelper.flipVertical;
103 | flipHorizontalToggle.isOn = webCamTextureToMatHelper.flipHorizontal;
104 | }
105 |
106 | ///
107 | /// Raises the webcam texture to mat helper initialized event.
108 | ///
109 | public void OnWebCamTextureToMatHelperInitialized()
110 | {
111 | Debug.Log("OnWebCamTextureToMatHelperInitialized");
112 |
113 | Mat webCamTextureMat = webCamTextureToMatHelper.GetMat();
114 |
115 | texture = new Texture2D(webCamTextureMat.cols(), webCamTextureMat.rows(), TextureFormat.RGBA32, false);
116 | Utils.fastMatToTexture2D(webCamTextureMat, texture);
117 |
118 | gameObject.GetComponent().material.mainTexture = texture;
119 |
120 | gameObject.transform.localScale = new Vector3(webCamTextureMat.cols(), webCamTextureMat.rows(), 1);
121 | Debug.Log("Screen.width " + Screen.width + " Screen.height " + Screen.height + " Screen.orientation " + Screen.orientation);
122 |
123 | if (fpsMonitor != null)
124 | {
125 | fpsMonitor.Add("deviceName", webCamTextureToMatHelper.GetDeviceName().ToString());
126 | fpsMonitor.Add("width", webCamTextureToMatHelper.GetWidth().ToString());
127 | fpsMonitor.Add("height", webCamTextureToMatHelper.GetHeight().ToString());
128 | fpsMonitor.Add("camera fps", webCamTextureToMatHelper.GetFPS().ToString());
129 | fpsMonitor.Add("isFrontFacing", webCamTextureToMatHelper.IsFrontFacing().ToString());
130 | fpsMonitor.Add("rotate90Degree", webCamTextureToMatHelper.rotate90Degree.ToString());
131 | fpsMonitor.Add("flipVertical", webCamTextureToMatHelper.flipVertical.ToString());
132 | fpsMonitor.Add("flipHorizontal", webCamTextureToMatHelper.flipHorizontal.ToString());
133 | fpsMonitor.Add("orientation", Screen.orientation.ToString());
134 | }
135 |
136 |
137 | float width = webCamTextureMat.width();
138 | float height = webCamTextureMat.height();
139 |
140 | float widthScale = (float)Screen.width / width;
141 | float heightScale = (float)Screen.height / height;
142 | if (widthScale < heightScale)
143 | {
144 | Camera.main.orthographicSize = (width * (float)Screen.height / (float)Screen.width) / 2;
145 | }
146 | else
147 | {
148 | Camera.main.orthographicSize = height / 2;
149 | }
150 |
151 | UpdateNatDeviceCameraProps(webCamTextureToMatHelper);
152 | }
153 |
154 | ///
155 | /// Raises the webcam texture to mat helper disposed event.
156 | ///
157 | public void OnWebCamTextureToMatHelperDisposed()
158 | {
159 | Debug.Log("OnWebCamTextureToMatHelperDisposed");
160 |
161 | if (texture != null)
162 | {
163 | Texture2D.Destroy(texture);
164 | texture = null;
165 | }
166 | }
167 |
168 | ///
169 | /// Raises the webcam texture to mat helper error occurred event.
170 | ///
171 | /// Error code.
172 | public void OnWebCamTextureToMatHelperErrorOccurred(WebCamTextureToMatHelper.ErrorCode errorCode)
173 | {
174 | Debug.Log("OnWebCamTextureToMatHelperErrorOccurred " + errorCode);
175 | }
176 |
177 | // Update is called once per frame
178 | void Update()
179 | {
180 | if (webCamTextureToMatHelper.IsPlaying() && webCamTextureToMatHelper.DidUpdateThisFrame())
181 | {
182 | Mat rgbaMat = webCamTextureToMatHelper.GetMat();
183 |
184 | //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);
185 |
186 | // Restore the coordinate system of the image by OpenCV's Flip function.
187 | Utils.fastMatToTexture2D(rgbaMat, texture);
188 | }
189 | }
190 |
191 | private void UpdateNatDeviceCameraProps(NatDeviceCamPreviewToMatHelper helper)
192 | {
193 | var cameraProps = new Dictionary();
194 | cameraProps.Add("defaultForMediaType", helper.defaultForMediaType.ToString());
195 | cameraProps.Add("exposureBias", helper.exposureBias_device.ToString());
196 | cameraProps.Add("exposureBiasRange", helper.exposureBiasRange.min + "x" + helper.exposureBiasRange.max);
197 | cameraProps.Add("exposureDurationRange", helper.exposureDurationRange.min + "x" + helper.exposureDurationRange.max);
198 | cameraProps.Add("exposureMode", helper.exposureMode.ToString());
199 | cameraProps.Add("ExposureModeSupported:Continuous", helper.ExposureModeSupported(CameraDevice.ExposureMode.Continuous).ToString());
200 | cameraProps.Add("ExposureModeSupported:Locked", helper.ExposureModeSupported(CameraDevice.ExposureMode.Locked).ToString());
201 | cameraProps.Add("ExposureModeSupported:Manual", helper.ExposureModeSupported(CameraDevice.ExposureMode.Manual).ToString());
202 | cameraProps.Add("exposurePointSupported", helper.exposurePointSupported.ToString());
203 | cameraProps.Add("fieldOfView", helper.fieldOfView.width + "x" + helper.fieldOfView.height);
204 | cameraProps.Add("flashMode", helper.flashMode.ToString());
205 | cameraProps.Add("flashSupported", helper.flashSupported.ToString());
206 | cameraProps.Add("focusMode", helper.focusMode.ToString());
207 | cameraProps.Add("FocusModeSupported:Continuous", helper.FocusModeSupported(CameraDevice.FocusMode.Continuous).ToString());
208 | cameraProps.Add("FocusModeSupported:Locked", helper.FocusModeSupported(CameraDevice.FocusMode.Locked).ToString());
209 | cameraProps.Add("focusPointSupported", helper.focusPointSupported.ToString());
210 | cameraProps.Add("frameRate", helper.frameRate.ToString());
211 | cameraProps.Add("frontFacing", helper.frontFacing.ToString());
212 | cameraProps.Add("ISORange", helper.ISORange.min + "x" + helper.ISORange.max);
213 | cameraProps.Add("location", helper.location.ToString());
214 | cameraProps.Add("name", helper.name_device);
215 | cameraProps.Add("photoResolution", helper.photoResolution.width + "x" + helper.photoResolution.height);
216 | cameraProps.Add("previewResolution", helper.previewResolution.width + "x" + helper.previewResolution.height);
217 | cameraProps.Add("running", helper.running.ToString());
218 | cameraProps.Add("torchEnabled", helper.torchEnabled.ToString());
219 | cameraProps.Add("torchSupported", helper.torchSupported.ToString());
220 | cameraProps.Add("uniqueID", helper.uniqueID.ToString());
221 | cameraProps.Add("whiteBalanceLock", helper.whiteBalanceLock.ToString());
222 | cameraProps.Add("whiteBalanceLockSupported", helper.whiteBalanceLockSupported.ToString());
223 | cameraProps.Add("zoomRange", helper.zoomRange.max + "x" + helper.zoomRange.min);
224 | cameraProps.Add("zoomRatio", helper.zoomRatio.ToString());
225 |
226 | if (fpsMonitor != null)
227 | {
228 | fpsMonitor.boxWidth = 280;
229 | fpsMonitor.boxHeight = 1080;
230 | fpsMonitor.LocateGUI();
231 |
232 | foreach (string key in cameraProps.Keys)
233 | fpsMonitor.Add(key, cameraProps[key]);
234 | }
235 | }
236 |
237 | ///
238 | /// Raises the destroy event.
239 | ///
240 | void OnDestroy()
241 | {
242 | webCamTextureToMatHelper.Dispose();
243 | }
244 |
245 | ///
246 | /// Raises the back button click event.
247 | ///
248 | public void OnBackButtonClick()
249 | {
250 | SceneManager.LoadScene("NatDeviceWithOpenCVForUnityExample");
251 | }
252 |
253 | ///
254 | /// Raises the play button click event.
255 | ///
256 | public void OnPlayButtonClick()
257 | {
258 | webCamTextureToMatHelper.Play();
259 | }
260 |
261 | ///
262 | /// Raises the pause button click event.
263 | ///
264 | public void OnPauseButtonClick()
265 | {
266 | webCamTextureToMatHelper.Pause();
267 | }
268 |
269 | ///
270 | /// Raises the stop button click event.
271 | ///
272 | public void OnStopButtonClick()
273 | {
274 | webCamTextureToMatHelper.Stop();
275 | }
276 |
277 | ///
278 | /// Raises the change camera button click event.
279 | ///
280 | public void OnChangeCameraButtonClick()
281 | {
282 | webCamTextureToMatHelper.requestedIsFrontFacing = !webCamTextureToMatHelper.requestedIsFrontFacing;
283 | }
284 |
285 | ///
286 | /// Raises the requested resolution dropdown value changed event.
287 | ///
288 | public void OnRequestedResolutionDropdownValueChanged(int result)
289 | {
290 | if ((int)requestedResolution != result)
291 | {
292 | requestedResolution = (ResolutionPreset)result;
293 |
294 | int width, height;
295 | Dimensions(requestedResolution, out width, out height);
296 |
297 | webCamTextureToMatHelper.Initialize(width, height);
298 | }
299 | }
300 |
301 | ///
302 | /// Raises the requestedFPS dropdown value changed event.
303 | ///
304 | public void OnRequestedFPSDropdownValueChanged(int result)
305 | {
306 | string[] enumNames = Enum.GetNames(typeof(FPSPreset));
307 | int value = (int)System.Enum.Parse(typeof(FPSPreset), enumNames[result], true);
308 |
309 | if ((int)requestedFPS != value)
310 | {
311 | requestedFPS = (FPSPreset)value;
312 |
313 | webCamTextureToMatHelper.requestedFPS = (int)requestedFPS;
314 | }
315 | }
316 |
317 | ///
318 | /// Raises the rotate 90 degree toggle value changed event.
319 | ///
320 | public void OnRotate90DegreeToggleValueChanged()
321 | {
322 | if (rotate90DegreeToggle.isOn != webCamTextureToMatHelper.rotate90Degree)
323 | {
324 | webCamTextureToMatHelper.rotate90Degree = rotate90DegreeToggle.isOn;
325 | }
326 |
327 | if (fpsMonitor != null)
328 | fpsMonitor.Add("rotate90Degree", webCamTextureToMatHelper.rotate90Degree.ToString());
329 | }
330 |
331 | ///
332 | /// Raises the flip vertical toggle value changed event.
333 | ///
334 | public void OnFlipVerticalToggleValueChanged()
335 | {
336 | if (flipVerticalToggle.isOn != webCamTextureToMatHelper.flipVertical)
337 | {
338 | webCamTextureToMatHelper.flipVertical = flipVerticalToggle.isOn;
339 | }
340 |
341 | if (fpsMonitor != null)
342 | fpsMonitor.Add("flipVertical", webCamTextureToMatHelper.flipVertical.ToString());
343 | }
344 |
345 | ///
346 | /// Raises the flip horizontal toggle value changed event.
347 | ///
348 | public void OnFlipHorizontalToggleValueChanged()
349 | {
350 | if (flipHorizontalToggle.isOn != webCamTextureToMatHelper.flipHorizontal)
351 | {
352 | webCamTextureToMatHelper.flipHorizontal = flipHorizontalToggle.isOn;
353 | }
354 |
355 | if (fpsMonitor != null)
356 | fpsMonitor.Add("flipHorizontal", webCamTextureToMatHelper.flipHorizontal.ToString());
357 | }
358 |
359 | public enum FPSPreset : int
360 | {
361 | _0 = 0,
362 | _1 = 1,
363 | _5 = 5,
364 | _10 = 10,
365 | _15 = 15,
366 | _30 = 30,
367 | _60 = 60,
368 | }
369 |
370 | public enum ResolutionPreset
371 | {
372 | Lowest,
373 | _640x480,
374 | _1280x720,
375 | _1920x1080,
376 | Highest,
377 | }
378 |
379 | private void Dimensions(ResolutionPreset preset, out int width, out int height)
380 | {
381 | switch (preset)
382 | {
383 | case ResolutionPreset.Lowest:
384 | width = height = 50;
385 | break;
386 | case ResolutionPreset._640x480:
387 | width = 640;
388 | height = 480;
389 | break;
390 | case ResolutionPreset._1920x1080:
391 | width = 1920;
392 | height = 1080;
393 | break;
394 | case ResolutionPreset.Highest:
395 | width = height = 9999;
396 | break;
397 | case ResolutionPreset._1280x720:
398 | default:
399 | width = 1280;
400 | height = 720;
401 | break;
402 | }
403 | }
404 | }
405 | }
--------------------------------------------------------------------------------
/Assets/NatDeviceWithOpenCVForUnityExample/NatDeviceCamPreviewToMatHelperExample/NatDeviceCamPreviewToMatHelperExample.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 7a2cd8859f80e4b4188b88f2442b1d3b
3 | MonoImporter:
4 | serializedVersion: 2
5 | defaultReferences: []
6 | executionOrder: 0
7 | icon: {instanceID: 0}
8 | userData:
9 | assetBundleName:
10 | assetBundleVariant:
11 |
--------------------------------------------------------------------------------
/Assets/NatDeviceWithOpenCVForUnityExample/NatDeviceCamPreviewToMatHelperExample/NatDeviceCamPreviewToMatHelperExample.unity.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: d6973b7cefe924f48a9b2f3e00c22c2a
3 | DefaultImporter:
4 | userData:
5 | assetBundleName:
6 | assetBundleVariant:
7 |
--------------------------------------------------------------------------------
/Assets/NatDeviceWithOpenCVForUnityExample/NatDeviceWithOpenCVForUnityExample.cs:
--------------------------------------------------------------------------------
1 | using System.Collections;
2 | using UnityEngine;
3 | using UnityEngine.SceneManagement;
4 | using UnityEngine.UI;
5 |
6 | namespace NatDeviceWithOpenCVForUnityExample
7 | {
8 |
9 | public class NatDeviceWithOpenCVForUnityExample : MonoBehaviour
10 | {
11 |
12 | public static string GetNatDeviceVersion()
13 | {
14 | return "1.2.0";
15 | }
16 |
17 | public enum FrameratePreset
18 | {
19 | _10,
20 | _15,
21 | _30,
22 | _60
23 | }
24 |
25 | public enum ResolutionPreset
26 | {
27 | Lowest,
28 | _640x480,
29 | _1280x720,
30 | _1920x1080,
31 | Highest,
32 | }
33 |
34 | [HeaderAttribute("Benchmark")]
35 | public Dropdown cameraResolutionDropdown;
36 | public Dropdown cameraFPSDropdown;
37 | private static ResolutionPreset cameraResolution = ResolutionPreset._1280x720;
38 | private static FrameratePreset cameraFramerate = FrameratePreset._30;
39 | private static bool performImageProcessingEachTime = false;
40 |
41 | [Header("UI")]
42 | public Text exampleTitle;
43 | public Text versionInfo;
44 | public ScrollRect scrollRect;
45 | private static float verticalNormalizedPosition = 1f;
46 |
47 | public static void CameraConfiguration(out int width, out int height, out int framerate)
48 | {
49 | switch (cameraResolution)
50 | {
51 | case ResolutionPreset.Lowest:
52 | width = height = 50;
53 | break;
54 | case ResolutionPreset._640x480:
55 | width = 640;
56 | height = 480;
57 | break;
58 | case ResolutionPreset._1920x1080:
59 | width = 1920;
60 | height = 1080;
61 | break;
62 | case ResolutionPreset.Highest:
63 | width = height = 9999;
64 | break;
65 | case ResolutionPreset._1280x720:
66 | default:
67 | width = 1280;
68 | height = 720;
69 | break;
70 | }
71 | switch (cameraFramerate)
72 | {
73 | case FrameratePreset._10:
74 | framerate = 10;
75 | break;
76 | case FrameratePreset._15:
77 | framerate = 15;
78 | break;
79 | case FrameratePreset._60:
80 | framerate = 60;
81 | break;
82 | case FrameratePreset._30:
83 | default:
84 | framerate = 30;
85 | break;
86 | }
87 | }
88 |
89 | public static void ExampleSceneConfiguration(out bool performImageProcessingEachTime)
90 | {
91 | performImageProcessingEachTime = NatDeviceWithOpenCVForUnityExample.performImageProcessingEachTime;
92 | }
93 |
94 | void Awake()
95 | {
96 | QualitySettings.vSyncCount = 0;
97 | Application.targetFrameRate = 60;
98 | }
99 |
100 | IEnumerator Start()
101 | {
102 |
103 | exampleTitle.text = "NatDeviceWithOpenCVForUnity Example " + Application.version;
104 |
105 | versionInfo.text = "NatDevice " + GetNatDeviceVersion();
106 | versionInfo.text += " / " + OpenCVForUnity.CoreModule.Core.NATIVE_LIBRARY_NAME + " " + OpenCVForUnity.UnityUtils.Utils.getVersion() + " (" + OpenCVForUnity.CoreModule.Core.VERSION + ")";
107 | versionInfo.text += " / UnityEditor " + Application.unityVersion;
108 | versionInfo.text += " / ";
109 | #if UNITY_EDITOR
110 | versionInfo.text += "Editor";
111 | #elif UNITY_STANDALONE_WIN
112 | versionInfo.text += "Windows";
113 | #elif UNITY_STANDALONE_OSX
114 | versionInfo.text += "Mac OSX";
115 | #elif UNITY_STANDALONE_LINUX
116 | versionInfo.text += "Linux";
117 | #elif UNITY_ANDROID
118 | versionInfo.text += "Android";
119 | #elif UNITY_IOS
120 | versionInfo.text += "iOS";
121 | #elif UNITY_WSA
122 | versionInfo.text += "WSA";
123 | #elif UNITY_WEBGL
124 | versionInfo.text += "WebGL";
125 | #endif
126 | versionInfo.text += " ";
127 | #if ENABLE_MONO
128 | versionInfo.text += "Mono";
129 | #elif ENABLE_IL2CPP
130 | versionInfo.text += "IL2CPP";
131 | #elif ENABLE_DOTNET
132 | versionInfo.text += ".NET";
133 | #endif
134 |
135 | scrollRect.verticalNormalizedPosition = verticalNormalizedPosition;
136 |
137 | // Update GUI state
138 | cameraResolutionDropdown.value = (int)cameraResolution;
139 | cameraFPSDropdown.value = (int)cameraFramerate;
140 |
141 |
142 | #if (UNITY_IOS || UNITY_ANDROID) && !UNITY_EDITOR
143 | RuntimePermissionHelper runtimePermissionHelper = GetComponent();
144 | yield return runtimePermissionHelper.hasUserAuthorizedCameraPermission();
145 | yield return runtimePermissionHelper.hasUserAuthorizedExternalStorageWritePermission(); // It works only with Android devices.
146 | #endif
147 |
148 | yield break;
149 | }
150 |
151 | public void OnCameraResolutionDropdownValueChanged(int result)
152 | {
153 | cameraResolution = (ResolutionPreset)result;
154 | }
155 |
156 | public void OnCameraFPSDropdownValueChanged(int result)
157 | {
158 | cameraFramerate = (FrameratePreset)result;
159 | }
160 |
161 | public void OnScrollRectValueChanged()
162 | {
163 | verticalNormalizedPosition = scrollRect.verticalNormalizedPosition;
164 | }
165 |
166 | public void OnShowSystemInfoButtonClick()
167 | {
168 | SceneManager.LoadScene("ShowSystemInfo");
169 | }
170 |
171 | public void OnShowLicenseButtonClick()
172 | {
173 | SceneManager.LoadScene("ShowLicense");
174 | }
175 |
176 | public void OnNatDeviceCamPreviewOnlyExampleButtonClick()
177 | {
178 | SceneManager.LoadScene("NatDeviceCamPreviewOnlyExample");
179 | }
180 |
181 | public void OnWebCamTextureOnlyExampleButtonClick()
182 | {
183 | SceneManager.LoadScene("WebCamTextureOnlyExample");
184 | }
185 |
186 | public void OnNatDeviceCamPreviewToMatExampleButtonClick()
187 | {
188 | SceneManager.LoadScene("NatDeviceCamPreviewToMatExample");
189 | }
190 |
191 | public void OnWebCamTextureToMatExampleButtonClick()
192 | {
193 | SceneManager.LoadScene("WebCamTextureToMatExample");
194 | }
195 |
196 | public void OnNatDeviceCamPreviewToMatHelperExampleButtonClick()
197 | {
198 | SceneManager.LoadScene("NatDeviceCamPreviewToMatHelperExample");
199 | }
200 |
201 | public void OnIntegrationWithNatShareExampleButtonClick()
202 | {
203 | SceneManager.LoadScene("IntegrationWithNatShareExample");
204 | }
205 | }
206 | }
--------------------------------------------------------------------------------
/Assets/NatDeviceWithOpenCVForUnityExample/NatDeviceWithOpenCVForUnityExample.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 3fc005588c60a0a4c827e3838c5f0e0d
3 | timeCreated: 1521862404
4 | licenseType: Free
5 | MonoImporter:
6 | serializedVersion: 2
7 | defaultReferences: []
8 | executionOrder: 0
9 | icon: {instanceID: 0}
10 | userData:
11 | assetBundleName:
12 | assetBundleVariant:
13 |
--------------------------------------------------------------------------------
/Assets/NatDeviceWithOpenCVForUnityExample/NatDeviceWithOpenCVForUnityExample.unity.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 70b98c90e8c1b7e40862f0229eb0d567
3 | timeCreated: 1521862404
4 | licenseType: Free
5 | DefaultImporter:
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/Assets/NatDeviceWithOpenCVForUnityExample/Scripts.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 21e9747b132986c4b8c0ebb383902e9f
3 | folderAsset: yes
4 | timeCreated: 1522155797
5 | licenseType: Free
6 | DefaultImporter:
7 | userData:
8 | assetBundleName:
9 | assetBundleVariant:
10 |
--------------------------------------------------------------------------------
/Assets/NatDeviceWithOpenCVForUnityExample/Scripts/ExampleBase.cs:
--------------------------------------------------------------------------------
1 | using OpenCVForUnity.CoreModule;
2 | using OpenCVForUnity.ImgprocModule;
3 | using System;
4 | using UnityEngine;
5 | using UnityEngine.SceneManagement;
6 | using UnityEngine.UI;
7 |
8 | namespace NatDeviceWithOpenCVForUnityExample
9 | {
10 |
11 | public abstract class ExampleBase : MonoBehaviour where T : ICameraSource
12 | {
13 |
14 | [Header("Preview")]
15 | public RawImage rawImage;
16 | public AspectRatioFitter aspectFitter;
17 |
18 | [Header("Camera")]
19 | public bool useFrontCamera;
20 |
21 | [Header("Processing")]
22 | public ImageProcessingType imageProcessingType = ImageProcessingType.None;
23 | public Dropdown imageProcessingTypeDropdown;
24 |
25 | protected T cameraSource;
26 |
27 | protected int updateCount, onFrameCount, drawCount;
28 | protected float elapsed, updateFPS, onFrameFPS, drawFPS;
29 |
30 |
31 | #region --Lifecycle--
32 |
33 | protected virtual void Start()
34 | {
35 | // Update UI
36 | if (imageProcessingTypeDropdown != null)
37 | imageProcessingTypeDropdown.value = (int)imageProcessingType;
38 | }
39 |
40 | protected virtual void Update()
41 | {
42 | updateCount++;
43 | elapsed += Time.deltaTime;
44 | if (elapsed >= 1f)
45 | {
46 | updateFPS = updateCount / elapsed;
47 | onFrameFPS = onFrameCount / elapsed;
48 | drawFPS = drawCount / elapsed;
49 | updateCount = onFrameCount = drawCount = 0;
50 | elapsed = 0f;
51 | }
52 | }
53 |
54 | protected virtual void OnStart()
55 | {
56 | //Debug.Log("##### OnStart() #####");
57 |
58 | useFrontCamera = cameraSource.isFrontFacing;
59 | }
60 |
61 | protected virtual void OnFrame()
62 | {
63 | //Debug.Log("##### OnFrame() #####");
64 |
65 | onFrameCount++;
66 | UpdateTexture();
67 | drawCount++;
68 | }
69 |
70 | protected virtual void OnDestroy()
71 | {
72 | if (cameraSource != null)
73 | {
74 | cameraSource.Dispose();
75 | cameraSource = default(T);
76 | }
77 | }
78 |
79 | #endregion
80 |
81 |
82 | #region --UI Callbacks--
83 |
84 | public void OnBackButtonClick()
85 | {
86 | SceneManager.LoadScene("NatDeviceWithOpenCVForUnityExample");
87 | }
88 |
89 | public async void OnPlayButtonClick()
90 | {
91 | //Debug.Log("##### OnPlayButton() #####");
92 |
93 | if (cameraSource == null) return;
94 |
95 | try
96 | {
97 | await cameraSource.StartRunning(OnStart, OnFrame);
98 | }
99 | catch (ApplicationException e)
100 | {
101 | Debug.LogError(e.Message);
102 | }
103 | }
104 |
105 | public void OnStopButtonClick()
106 | {
107 | //Debug.Log("##### OnStopButton() #####");
108 |
109 | if (cameraSource == null) return;
110 |
111 | cameraSource.StopRunning();
112 | }
113 |
114 | public async void OnChangeCameraButtonClick()
115 | {
116 | //Debug.Log("##### OnChangeCameraButton() #####");
117 |
118 | if (cameraSource == null) return;
119 |
120 | try
121 | {
122 | await cameraSource.SwitchCamera();
123 | }
124 | catch (ApplicationException e)
125 | {
126 | Debug.LogError(e.Message);
127 | }
128 | }
129 |
130 | public void OnImageProcessingTypeDropdownValueChanged(int result)
131 | {
132 | imageProcessingType = (ImageProcessingType)result;
133 | }
134 |
135 | #endregion
136 |
137 |
138 | #region --Operations--
139 |
140 | protected abstract void UpdateTexture();
141 |
142 | protected void ProcessImage(Color32[] buffer, int width, int height, ImageProcessingType imageProcessingType)
143 | {
144 | switch (imageProcessingType)
145 | {
146 | case ImageProcessingType.DrawLine:
147 | // Draw a diagonal line on our image
148 | float inclination = height / (float)width;
149 | for (int i = 0; i < 4; i++)
150 | {
151 | for (int x = 0; x < width; x++)
152 | {
153 | int y = (int)(-inclination * x) + height - 2 + i;
154 | y = Mathf.Clamp(y, 0, height - 1);
155 | int p = (x) + (y * width);
156 | // Set pixels in the buffer
157 | buffer.SetValue(new Color32(255, 0, 0, 255), p);
158 | }
159 | }
160 |
161 | break;
162 | case ImageProcessingType.ConvertToGray:
163 | // Convert a four-channel pixel buffer to greyscale
164 | // Iterate over the buffer
165 | for (int i = 0; i < buffer.Length; i++)
166 | {
167 | var p = buffer[i];
168 | // Get channel intensities
169 | byte r = p.r, g = p.g, b = p.b, a = p.a,
170 | // Use quick luminance approximation to save time and memory
171 | l = (byte)((r + r + r + b + g + g + g + g) >> 3);
172 | // Set pixels in the buffer
173 | buffer[i] = new Color32(l, l, l, a);
174 | }
175 | break;
176 | }
177 | }
178 |
179 | protected void ProcessImage(byte[] buffer, int width, int height, ImageProcessingType imageProcessingType)
180 | {
181 | switch (imageProcessingType)
182 | {
183 | case ImageProcessingType.DrawLine:
184 | // Draw a diagonal line on our image
185 | float inclination = height / (float)width;
186 | for (int i = 0; i < 4; i++)
187 | {
188 | for (int x = 0; x < width; x++)
189 | {
190 | int y = (int)(-inclination * x) + height - 2 + i;
191 | y = Mathf.Clamp(y, 0, height - 1);
192 | int p = (x * 4) + (y * width * 4);
193 | // Set pixels in the buffer
194 | buffer[p] = 255;
195 | buffer[p + 1] = 0;
196 | buffer[p + 2] = 0;
197 | buffer[p + 3] = 255;
198 | }
199 | }
200 |
201 | break;
202 | case ImageProcessingType.ConvertToGray:
203 | // Convert a four-channel pixel buffer to greyscale
204 | // Iterate over the buffer
205 | for (int i = 0; i < buffer.Length; i = i + 4)
206 | {
207 | // Get channel intensities
208 | byte r = buffer[i];
209 | byte g = buffer[i + 1];
210 | byte b = buffer[i + 2];
211 | byte a = buffer[i + 3];
212 | // Use quick luminance approximation to save time and memory
213 | byte l = (byte)((r + r + r + b + g + g + g + g) >> 3);
214 | // Set pixels in the buffer
215 | buffer[i] = buffer[i + 1] = buffer[i + 2] = l;
216 | buffer[i + 3] = a;
217 | }
218 | break;
219 | }
220 | }
221 |
222 | protected void ProcessImage(Mat frameMatrix, Mat grayMatrix, ImageProcessingType imageProcessingType)
223 | {
224 | switch (imageProcessingType)
225 | {
226 | case ImageProcessingType.DrawLine:
227 | Imgproc.line(
228 | frameMatrix,
229 | new Point(0, 0),
230 | new Point(frameMatrix.cols(), frameMatrix.rows()),
231 | new Scalar(255, 0, 0, 255),
232 | 4
233 | );
234 | break;
235 | case ImageProcessingType.ConvertToGray:
236 | Imgproc.cvtColor(frameMatrix, grayMatrix, Imgproc.COLOR_RGBA2GRAY);
237 | Imgproc.cvtColor(grayMatrix, frameMatrix, Imgproc.COLOR_GRAY2RGBA);
238 | break;
239 | }
240 | }
241 |
242 | #endregion
243 | }
244 |
245 | public enum ImageProcessingType
246 | {
247 | None,
248 | DrawLine,
249 | ConvertToGray,
250 | }
251 | }
--------------------------------------------------------------------------------
/Assets/NatDeviceWithOpenCVForUnityExample/Scripts/ExampleBase.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 7876b09c1405d4835a53efb593d78029
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Assets/NatDeviceWithOpenCVForUnityExample/Scripts/ICameraSource.cs:
--------------------------------------------------------------------------------
1 | using OpenCVForUnity.CoreModule;
2 | using System;
3 | using System.Threading.Tasks;
4 | using UnityEngine;
5 |
6 | namespace NatDeviceWithOpenCVForUnityExample
7 | {
8 |
9 | public interface ICameraSource
10 | {
11 |
12 | #region --Properties--
13 |
14 | int width { get; }
15 |
16 | int height { get; }
17 |
18 | bool isRunning { get; }
19 |
20 | bool isFrontFacing { get; }
21 |
22 | #endregion
23 |
24 |
25 | #region --Operations--
26 |
27 | Task StartRunning(Action startCallback, Action frameCallback);
28 |
29 | void StopRunning();
30 |
31 | void CaptureFrame(Mat matrix);
32 |
33 | void CaptureFrame(Color32[] pixelBuffer);
34 |
35 | void CaptureFrame(byte[] pixelBuffer);
36 |
37 | Task SwitchCamera();
38 |
39 | void Dispose();
40 |
41 | #endregion
42 | }
43 | }
--------------------------------------------------------------------------------
/Assets/NatDeviceWithOpenCVForUnityExample/Scripts/ICameraSource.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: d7f3d8ae972b34e85823d6cd3323bfe7
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Assets/NatDeviceWithOpenCVForUnityExample/Scripts/NatDeviceCamSource.cs:
--------------------------------------------------------------------------------
1 | using NatSuite.Devices;
2 | using NatSuite.Devices.Outputs;
3 | using OpenCVForUnity.CoreModule;
4 | using OpenCVForUnity.UtilsModule;
5 | using System;
6 | using System.Runtime.InteropServices;
7 | using System.Threading.Tasks;
8 | using UnityEngine;
9 |
10 | namespace NatDeviceWithOpenCVForUnityExample
11 | {
12 |
13 | public class NatDeviceCamSource : ICameraSource
14 | {
15 |
16 | #region --Op vars--
17 |
18 | private Action startCallback, frameCallback;
19 | private int requestedWidth, requestedHeight, requestedFramerate;
20 | private MediaDeviceQuery deviceQuery;
21 | private PixelBufferOutput previewPixelBufferOutput;
22 |
23 | #endregion
24 |
25 |
26 | #region --Client API--
27 |
28 | public int width { get; private set; }
29 |
30 | public int height { get; private set; }
31 |
32 | public long timestamp { get; private set; }
33 |
34 | public bool verticallyMirrored { get; private set; }
35 |
36 | public Matrix4x4 intrinsics { get; private set; }
37 |
38 | public float exposureBias { get; private set; }
39 |
40 | public float exposureDuration { get; private set; }
41 |
42 | public float ISO { get; private set; }
43 |
44 | public float focalLength { get; private set; }
45 |
46 | public float fNumber { get; private set; }
47 |
48 | public float brightness { get; private set; }
49 |
50 |
51 | public bool isRunning { get; private set; }
52 |
53 | public bool isFrontFacing { get { return activeCamera != null ? activeCamera.frontFacing : false; } }
54 |
55 | public CameraDevice activeCamera { get; private set; }
56 |
57 | public NatDeviceCamSource(int width, int height, int framerate = 30, bool front = false)
58 | {
59 | requestedWidth = width;
60 | requestedHeight = height;
61 | requestedFramerate = framerate;
62 |
63 | // Create a device query for device cameras
64 | deviceQuery = new MediaDeviceQuery(MediaDeviceCriteria.CameraDevice);
65 |
66 | // Pick camera
67 | if (deviceQuery.count == 0)
68 | {
69 | Debug.LogError("Camera device does not exist.");
70 | return;
71 | }
72 |
73 | for (var i = 0; i < deviceQuery.count; i++)
74 | {
75 | activeCamera = deviceQuery.current as CameraDevice;
76 | if (activeCamera != null && activeCamera.frontFacing == front) break;
77 | deviceQuery.Advance();
78 | activeCamera = null;
79 | }
80 |
81 | if (activeCamera == null)
82 | {
83 | Debug.LogError("Camera is null. Consider using " + (front ? "rear" : "front") + " camera.");
84 | return;
85 | }
86 |
87 | activeCamera.previewResolution = (width: requestedWidth, height: requestedHeight);
88 | activeCamera.frameRate = requestedFramerate;
89 | }
90 |
91 | public void Dispose()
92 | {
93 | StopRunning();
94 |
95 | activeCamera = null;
96 | }
97 |
98 | public async Task StartRunning(Action startCallback, Action frameCallback)
99 | {
100 | if (activeCamera == null || isRunning)
101 | return;
102 |
103 | this.startCallback = startCallback;
104 | this.frameCallback = frameCallback;
105 |
106 | if (previewPixelBufferOutput == null)
107 | previewPixelBufferOutput = new PixelBufferOutput();
108 |
109 | activeCamera.StartRunning(OnPixelBufferOutputReceived);
110 |
111 | await Task.Yield();
112 | }
113 |
114 | public void StopRunning()
115 | {
116 | if (activeCamera == null || !isRunning)
117 | return;
118 |
119 | isRunning = false;
120 |
121 | if (previewPixelBufferOutput != null)
122 | {
123 | previewPixelBufferOutput.Dispose();
124 | previewPixelBufferOutput = null;
125 | }
126 |
127 | if (activeCamera.running)
128 | activeCamera.StopRunning();
129 | }
130 |
131 | public void CaptureFrame(Mat matrix)
132 | {
133 | if (!isRunning) return;
134 |
135 | if (matrix.width() != previewPixelBufferOutput.width || matrix.height() != previewPixelBufferOutput.height)
136 | throw new ArgumentException("matrix and CamSource image need to be the same size.");
137 |
138 | MatUtils.copyToMat(previewPixelBufferOutput.pixelBuffer, matrix);
139 | Core.flip(matrix, matrix, 0);
140 | }
141 |
142 | public void CaptureFrame(Color32[] pixelBuffer)
143 | {
144 | if (!isRunning) return;
145 |
146 | if (pixelBuffer.Length * 4 != previewPixelBufferOutput.pixelBuffer.Length)
147 | throw new ArgumentException("pixelBuffer and CamSource image need to be the same size.");
148 |
149 | unsafe
150 | {
151 | GCHandle pin = GCHandle.Alloc(pixelBuffer, GCHandleType.Pinned);
152 | Buffer.MemoryCopy(Unity.Collections.LowLevel.Unsafe.NativeArrayUnsafeUtility.GetUnsafeReadOnlyPtr(previewPixelBufferOutput.pixelBuffer), (void*)pin.AddrOfPinnedObject(), pixelBuffer.Length * 4, previewPixelBufferOutput.pixelBuffer.Length);
153 | pin.Free();
154 | }
155 | }
156 |
157 | public void CaptureFrame(byte[] pixelBuffer)
158 | {
159 | if (!isRunning) return;
160 |
161 | if (pixelBuffer.Length != previewPixelBufferOutput.pixelBuffer.Length)
162 | throw new ArgumentException("pixelBuffer and CamSource image need to be the same size.");
163 |
164 | previewPixelBufferOutput.pixelBuffer.CopyTo(pixelBuffer);
165 | }
166 |
167 | public async Task SwitchCamera()
168 | {
169 | if (activeCamera == null)
170 | return;
171 |
172 | var _isRunning = isRunning;
173 |
174 | Dispose();
175 |
176 | deviceQuery.Advance();
177 | activeCamera = deviceQuery.current as CameraDevice;
178 |
179 | activeCamera.previewResolution = (width: requestedWidth, height: requestedHeight);
180 | activeCamera.frameRate = requestedFramerate;
181 |
182 | await StartRunning(startCallback, frameCallback);
183 |
184 | if (!_isRunning)
185 | StopRunning();
186 | }
187 |
188 | #endregion
189 |
190 |
191 | #region --Operations--
192 |
193 | private void OnPixelBufferOutputReceived(CameraImage image)
194 | {
195 | if (previewPixelBufferOutput == null)
196 | return;
197 |
198 | // Process only when the latest previewResolution and CameraImage size match.
199 | if (activeCamera == null || activeCamera.previewResolution.width != image.width || activeCamera.previewResolution.height != image.height)
200 | return;
201 |
202 | timestamp = image.timestamp;
203 | verticallyMirrored = image.verticallyMirrored;
204 | float[] intrinsics = image.intrinsics;
205 | this.intrinsics = (intrinsics != null) ?
206 | new Matrix4x4(
207 | new Vector4(intrinsics[0], intrinsics[3], intrinsics[6]),
208 | new Vector4(intrinsics[1], intrinsics[4], intrinsics[7]),
209 | new Vector4(intrinsics[2], intrinsics[5], intrinsics[8]),
210 | new Vector4())
211 | : Matrix4x4.zero;
212 | exposureBias = image.exposureBias ?? -1f;
213 | exposureDuration = image.exposureDuration ?? -1f;
214 | ISO = image.ISO ?? -1f;
215 | focalLength = image.focalLength ?? -1f;
216 | fNumber = image.fNumber ?? -1f;
217 | brightness = image.brightness ?? -1f;
218 |
219 |
220 | bool firstFrame = !previewPixelBufferOutput.pixelBuffer.IsCreated;
221 |
222 | previewPixelBufferOutput.Update(image);
223 |
224 | if (firstFrame)
225 | {
226 | width = previewPixelBufferOutput.width;
227 | height = previewPixelBufferOutput.height;
228 |
229 | isRunning = true;
230 |
231 | startCallback();
232 | }
233 | else
234 | {
235 | frameCallback();
236 | }
237 |
238 | }
239 |
240 | #endregion
241 | }
242 | }
--------------------------------------------------------------------------------
/Assets/NatDeviceWithOpenCVForUnityExample/Scripts/NatDeviceCamSource.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 84e02125237fe4d6f865b3862bfd52c3
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Assets/NatDeviceWithOpenCVForUnityExample/Scripts/Utils.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: a69a2a8276734bb4eb9e353b5b07354a
3 | folderAsset: yes
4 | timeCreated: 1522155806
5 | licenseType: Free
6 | DefaultImporter:
7 | userData:
8 | assetBundleName:
9 | assetBundleVariant:
10 |
--------------------------------------------------------------------------------
/Assets/NatDeviceWithOpenCVForUnityExample/Scripts/Utils/FpsMonitor.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using UnityEngine;
3 |
4 | namespace NatDeviceWithOpenCVForUnityExample
5 | {
6 | // v1.0.1
7 | public class FpsMonitor : MonoBehaviour
8 | {
9 | int tick = 0;
10 | float elapsed = 0;
11 | float fps = 0;
12 |
13 | public enum Alignment
14 | {
15 | LeftTop,
16 | RightTop,
17 | LeftBottom,
18 | RightBottom,
19 | }
20 |
21 | public Alignment alignment = Alignment.RightTop;
22 |
23 | const float GUI_WIDTH = 75f;
24 | const float GUI_HEIGHT = 30f;
25 | const float MARGIN_X = 10f;
26 | const float MARGIN_Y = 10f;
27 | const float INNER_X = 8f;
28 | const float INNER_Y = 5f;
29 | const float GUI_CONSOLE_HEIGHT = 50f;
30 |
31 | public Vector2 offset = new Vector2(MARGIN_X, MARGIN_Y);
32 | public bool boxVisible = true;
33 | public float boxWidth = GUI_WIDTH;
34 | public float boxHeight = GUI_HEIGHT;
35 | public Vector2 padding = new Vector2(INNER_X, INNER_Y);
36 | public float consoleHeight = GUI_CONSOLE_HEIGHT;
37 |
38 | GUIStyle console_labelStyle;
39 |
40 | float x, y;
41 | Rect outer;
42 | Rect inner;
43 |
44 | float console_x, console_y;
45 | Rect console_outer;
46 | Rect console_inner;
47 |
48 | int oldScrWidth;
49 | int oldScrHeight;
50 |
51 | Dictionary outputDict = new Dictionary();
52 |
53 | protected string _consoleText = null;
54 | public virtual string consoleText
55 | {
56 | get { return _consoleText; }
57 | set
58 | {
59 | _consoleText = value;
60 | toast_time = -1;
61 | }
62 | }
63 |
64 | int toast_time = -1;
65 |
66 | // Use this for initialization
67 | void Start()
68 | {
69 | console_labelStyle = new GUIStyle();
70 | console_labelStyle.fontSize = 32;
71 | console_labelStyle.fontStyle = FontStyle.Normal;
72 | console_labelStyle.wordWrap = true;
73 | console_labelStyle.normal.textColor = Color.white;
74 |
75 | oldScrWidth = Screen.width;
76 | oldScrHeight = Screen.height;
77 | LocateGUI();
78 | }
79 |
80 | // Update is called once per frame
81 | void Update()
82 | {
83 | tick++;
84 | elapsed += Time.deltaTime;
85 | if (elapsed >= 1f)
86 | {
87 | fps = tick / elapsed;
88 | tick = 0;
89 | elapsed = 0;
90 | }
91 |
92 | if (toast_time > 0)
93 | {
94 | toast_time = toast_time - 1;
95 | }
96 | }
97 |
98 | void OnGUI()
99 | {
100 | if (oldScrWidth != Screen.width || oldScrHeight != Screen.height)
101 | {
102 | LocateGUI();
103 | }
104 | oldScrWidth = Screen.width;
105 | oldScrHeight = Screen.height;
106 |
107 | if (boxVisible)
108 | {
109 | GUI.Box(outer, "");
110 | }
111 |
112 | GUILayout.BeginArea(inner);
113 | {
114 | GUILayout.BeginVertical();
115 | GUILayout.Label("fps : " + fps.ToString("F1"));
116 | foreach (KeyValuePair pair in outputDict)
117 | {
118 | GUILayout.Label(pair.Key + " : " + pair.Value);
119 | }
120 | GUILayout.EndVertical();
121 | }
122 | GUILayout.EndArea();
123 |
124 | if (!string.IsNullOrEmpty(consoleText))
125 | {
126 | if (toast_time != 0)
127 | {
128 | if (boxVisible)
129 | {
130 | GUI.Box(console_outer, "");
131 | }
132 |
133 | GUILayout.BeginArea(console_inner);
134 | {
135 | GUILayout.BeginVertical();
136 | GUILayout.Label(consoleText, console_labelStyle);
137 | GUILayout.EndVertical();
138 | }
139 | GUILayout.EndArea();
140 | }
141 | }
142 | }
143 |
144 | public void Add(string key, string value)
145 | {
146 | if (outputDict.ContainsKey(key))
147 | {
148 | outputDict[key] = value;
149 | }
150 | else
151 | {
152 | outputDict.Add(key, value);
153 | }
154 | }
155 |
156 | public void Remove(string key)
157 | {
158 | outputDict.Remove(key);
159 | }
160 |
161 | public void Clear()
162 | {
163 | outputDict.Clear();
164 | }
165 |
166 | public void LocateGUI()
167 | {
168 | x = GetAlignedX(alignment, boxWidth);
169 | y = GetAlignedY(alignment, boxHeight);
170 | outer = new Rect(x, y, boxWidth, boxHeight);
171 | inner = new Rect(x + padding.x, y + padding.y, boxWidth, boxHeight);
172 |
173 | console_x = GetAlignedX(Alignment.LeftBottom, Screen.width);
174 | console_y = GetAlignedY(Alignment.LeftBottom, consoleHeight);
175 | console_outer = new Rect(console_x, console_y, Screen.width - offset.x * 2, consoleHeight);
176 | console_inner = new Rect(console_x + padding.x, console_y + padding.y, Screen.width - offset.x * 2 - padding.x, consoleHeight);
177 | }
178 |
179 | public void Toast(string message, int time = 120)
180 | {
181 | _consoleText = message;
182 | toast_time = (time < 60) ? 60 : time;
183 | }
184 |
185 | float GetAlignedX(Alignment anchor, float w)
186 | {
187 | switch (anchor)
188 | {
189 | default:
190 | case Alignment.LeftTop:
191 | case Alignment.LeftBottom:
192 | return offset.x;
193 |
194 | case Alignment.RightTop:
195 | case Alignment.RightBottom:
196 | return Screen.width - w - offset.x;
197 | }
198 | }
199 |
200 | float GetAlignedY(Alignment anchor, float h)
201 | {
202 | switch (anchor)
203 | {
204 | default:
205 | case Alignment.LeftTop:
206 | case Alignment.RightTop:
207 | return offset.y;
208 |
209 | case Alignment.LeftBottom:
210 | case Alignment.RightBottom:
211 | return Screen.height - h - offset.y;
212 | }
213 | }
214 | }
215 | }
--------------------------------------------------------------------------------
/Assets/NatDeviceWithOpenCVForUnityExample/Scripts/Utils/FpsMonitor.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 9730a00114a61104b87dc34be31889c0
3 | timeCreated: 1521859037
4 | licenseType: Free
5 | MonoImporter:
6 | serializedVersion: 2
7 | defaultReferences: []
8 | executionOrder: 0
9 | icon: {instanceID: 0}
10 | userData:
11 | assetBundleName:
12 | assetBundleVariant:
13 |
--------------------------------------------------------------------------------
/Assets/NatDeviceWithOpenCVForUnityExample/Scripts/Utils/NatDeviceCamPreviewToMatHelper.cs:
--------------------------------------------------------------------------------
1 | using NatSuite.Devices;
2 | using NatSuite.Devices.Outputs;
3 | using OpenCVForUnity.CoreModule;
4 | using OpenCVForUnity.ImgprocModule;
5 | using OpenCVForUnity.UnityUtils.Helper;
6 | using OpenCVForUnity.UtilsModule;
7 | using System;
8 | using System.Collections;
9 | using UnityEngine;
10 |
11 | namespace NatDeviceWithOpenCVForUnity.UnityUtils.Helper
12 | {
13 | ///
14 | /// This is called every time there is the current frame image mat available.
15 | /// The Mat object's type is 'CV_8UC4' or 'CV_8UC3' or 'CV_8UC1' (ColorFormat is determined by the outputColorFormat setting).
16 | ///
17 | /// The recently captured frame image mat.
18 | /// Pixel buffer timestamp in nanoseconds.
19 | public delegate void FrameMatAcquiredCallback(Mat mat, long timestamp);
20 |
21 | ///
22 | /// NatDeviceCamPreview to mat helper.
23 | /// v 1.0.3
24 | /// Depends on NatDevice version 1.2.0 or later.
25 | /// Depends on OpenCVForUnity version 2.4.4 (WebCamTextureToMatHelper v 1.1.3 or later.
26 | ///
27 | public class NatDeviceCamPreviewToMatHelper : WebCamTextureToMatHelper
28 | {
29 | ///
30 | /// This will be called whenever the current frame image available is converted to Mat.
31 | /// The Mat object's type is 'CV_8UC4' or 'CV_8UC3' or 'CV_8UC1' (ColorFormat is determined by the outputColorFormat setting).
32 | /// You must properly initialize the NatDeviceCamPreviewToMatHelper,
33 | /// including calling Play() before this event will begin firing.
34 | ///
35 | public virtual event FrameMatAcquiredCallback frameMatAcquired;
36 |
37 |
38 | #region --NatDevice CameraDevice Properties--
39 |
40 | public virtual bool defaultForMediaType => GetNatDeviceCameraDevice() != null ? GetNatDeviceCameraDevice().defaultForMediaType : default;
41 |
42 | public virtual float exposureBias_device // exposureBias
43 | {
44 | get { return GetNatDeviceCameraDevice() != null ? GetNatDeviceCameraDevice().exposureBias : default; }
45 | set { if (GetNatDeviceCameraDevice() != null) GetNatDeviceCameraDevice().exposureBias = value; }
46 | }
47 |
48 | public virtual (float min, float max) exposureBiasRange
49 | {
50 | get { return GetNatDeviceCameraDevice() != null ? GetNatDeviceCameraDevice().exposureBiasRange : default; }
51 | }
52 |
53 | public virtual (float min, float max) exposureDurationRange
54 | {
55 | get { return GetNatDeviceCameraDevice() != null ? GetNatDeviceCameraDevice().exposureDurationRange : default; }
56 | }
57 |
58 | public virtual CameraDevice.ExposureMode exposureMode
59 | {
60 | get { return GetNatDeviceCameraDevice() != null ? GetNatDeviceCameraDevice().exposureMode : default; }
61 | set { if (GetNatDeviceCameraDevice() != null) GetNatDeviceCameraDevice().exposureMode = value; }
62 | }
63 |
64 | public virtual bool exposurePointSupported => GetNatDeviceCameraDevice() != null ? GetNatDeviceCameraDevice().exposurePointSupported : default;
65 |
66 | public virtual (float width, float height) fieldOfView
67 | {
68 | get { return GetNatDeviceCameraDevice() != null ? GetNatDeviceCameraDevice().fieldOfView : default; }
69 | }
70 |
71 | public virtual CameraDevice.FlashMode flashMode
72 | {
73 | get { return (GetNatDeviceCameraDevice() != null && GetNatDeviceCameraDevice().running) ? GetNatDeviceCameraDevice().flashMode : default; }
74 | set { if (GetNatDeviceCameraDevice() != null) GetNatDeviceCameraDevice().flashMode = value; }
75 | }
76 |
77 | public virtual bool flashSupported => GetNatDeviceCameraDevice() != null ? GetNatDeviceCameraDevice().flashSupported : default;
78 |
79 | public virtual CameraDevice.FocusMode focusMode
80 | {
81 | get { return GetNatDeviceCameraDevice() != null ? GetNatDeviceCameraDevice().focusMode : default; }
82 | set { if (GetNatDeviceCameraDevice() != null) GetNatDeviceCameraDevice().focusMode = value; }
83 | }
84 |
85 | public virtual bool focusPointSupported => GetNatDeviceCameraDevice() != null ? GetNatDeviceCameraDevice().focusPointSupported : default;
86 |
87 | public virtual int frameRate
88 | {
89 | get { return GetNatDeviceCameraDevice() != null ? GetNatDeviceCameraDevice().frameRate : default; }
90 | set { if (GetNatDeviceCameraDevice() != null) GetNatDeviceCameraDevice().frameRate = value; }
91 | }
92 |
93 | public virtual bool frontFacing => GetNatDeviceCameraDevice() != null ? GetNatDeviceCameraDevice().frontFacing : default;
94 |
95 | public virtual (float min, float max) ISORange
96 | {
97 | get { return GetNatDeviceCameraDevice() != null ? GetNatDeviceCameraDevice().ISORange : default; }
98 | }
99 |
100 | public virtual DeviceLocation location => GetNatDeviceCameraDevice() != null ? GetNatDeviceCameraDevice().location : default;
101 |
102 | public virtual string name_device => GetNatDeviceCameraDevice() != null ? GetNatDeviceCameraDevice().name : ""; // name
103 |
104 | public virtual (int width, int height) previewResolution
105 | {
106 | get { return GetNatDeviceCameraDevice() != null ? GetNatDeviceCameraDevice().previewResolution : default; }
107 | set { if (GetNatDeviceCameraDevice() != null) GetNatDeviceCameraDevice().previewResolution = (width: value.width, height: value.height); }
108 | }
109 |
110 | public virtual (int width, int height) photoResolution
111 | {
112 | get { return GetNatDeviceCameraDevice() != null ? GetNatDeviceCameraDevice().photoResolution : default; }
113 | set { if (GetNatDeviceCameraDevice() != null) GetNatDeviceCameraDevice().photoResolution = (width: value.width, height: value.height); }
114 | }
115 |
116 | public virtual bool running => GetNatDeviceCameraDevice() != null ? GetNatDeviceCameraDevice().running : default;
117 |
118 | public virtual bool torchEnabled
119 | {
120 | get { return GetNatDeviceCameraDevice() != null ? GetNatDeviceCameraDevice().torchEnabled : default; }
121 | set { if (GetNatDeviceCameraDevice() != null) GetNatDeviceCameraDevice().torchEnabled = value; }
122 | }
123 |
124 | public virtual bool torchSupported => GetNatDeviceCameraDevice() != null ? GetNatDeviceCameraDevice().torchSupported : default;
125 |
126 | public virtual string uniqueID => GetNatDeviceCameraDevice() != null ? GetNatDeviceCameraDevice().uniqueID : "";
127 |
128 | public virtual bool whiteBalanceLock
129 | {
130 | get { return GetNatDeviceCameraDevice() != null ? GetNatDeviceCameraDevice().whiteBalanceLock : default; }
131 | set { if (GetNatDeviceCameraDevice() != null) GetNatDeviceCameraDevice().whiteBalanceLock = value; }
132 | }
133 |
134 | public virtual bool whiteBalanceLockSupported => GetNatDeviceCameraDevice() != null ? GetNatDeviceCameraDevice().whiteBalanceLockSupported : default;
135 |
136 | public virtual (float min, float max) zoomRange
137 | {
138 | get { return GetNatDeviceCameraDevice() != null ? GetNatDeviceCameraDevice().zoomRange : default; }
139 | }
140 |
141 | public virtual float zoomRatio
142 | {
143 | get { return GetNatDeviceCameraDevice() != null ? GetNatDeviceCameraDevice().zoomRatio : default; }
144 | set { if (GetNatDeviceCameraDevice() != null) GetNatDeviceCameraDevice().zoomRatio = value; }
145 | }
146 |
147 | #endregion
148 |
149 |
150 | #region --NatDevice CameraDevice Functions--
151 |
152 | public virtual void CapturePhoto(Action handler)
153 | {
154 | if (GetNatDeviceCameraDevice() != null) GetNatDeviceCameraDevice().CapturePhoto(handler);
155 | }
156 |
157 | public virtual bool ExposureModeSupported(CameraDevice.ExposureMode exposureMode)
158 | {
159 | return GetNatDeviceCameraDevice() != null ? GetNatDeviceCameraDevice().ExposureModeSupported(exposureMode) : default;
160 | }
161 |
162 | public virtual bool FocusModeSupported(CameraDevice.FocusMode focusMode)
163 | {
164 | return GetNatDeviceCameraDevice() != null ? GetNatDeviceCameraDevice().FocusModeSupported(focusMode) : default;
165 | }
166 |
167 | public virtual void SetExposureDuration(float duration, float ISO)
168 | {
169 | if (GetNatDeviceCameraDevice() != null) GetNatDeviceCameraDevice().SetExposureDuration(duration, ISO);
170 | }
171 |
172 | public virtual void SetExposurePoint(float x, float y)
173 | {
174 | if (GetNatDeviceCameraDevice() != null) GetNatDeviceCameraDevice().SetExposurePoint(x, y);
175 | }
176 |
177 | public virtual void SetFocusPoint(float x, float y)
178 | {
179 | if (GetNatDeviceCameraDevice() != null) GetNatDeviceCameraDevice().SetFocusPoint(x, y);
180 | }
181 |
182 | #endregion
183 |
184 |
185 | #region --NatDevice CameraImage Properties--
186 |
187 | public long timestamp { get; private set; }
188 |
189 | public bool verticallyMirrored { get; private set; }
190 |
191 | public Matrix4x4 intrinsics { get; private set; }
192 |
193 | public float exposureBias { get; private set; }
194 |
195 | public float exposureDuration { get; private set; }
196 |
197 | public float ISO { get; private set; }
198 |
199 | public float focalLength { get; private set; }
200 |
201 | public float fNumber { get; private set; }
202 |
203 | public float brightness { get; private set; }
204 |
205 | #endregion
206 |
207 |
208 | #if (UNITY_STANDALONE_WIN || UNITY_STANDALONE_OSX || UNITY_IOS || UNITY_ANDROID) && !DISABLE_NATDEVICE_API
209 |
210 | public override float requestedFPS
211 | {
212 | get { return _requestedFPS; }
213 | set
214 | {
215 | _requestedFPS = Mathf.Clamp(value, -1f, float.MaxValue);
216 | if (hasInitDone)
217 | {
218 | Initialize();
219 | }
220 | }
221 | }
222 |
223 | protected bool isStartWaiting = false;
224 | protected bool didUpdateThisFrame = false;
225 | protected bool didUpdatePreviewPixelBufferInCurrentFrame = false;
226 | protected CameraDevice cameraDevice;
227 | protected PixelBufferOutput previewPixelBufferOutput;
228 | protected int previewWidth;
229 | protected int previewHeight;
230 |
231 | protected bool didCameraRunningBeforeSuspend = false;
232 |
233 | protected virtual void LateUpdate()
234 | {
235 | if (didUpdateThisFrame && !didUpdatePreviewPixelBufferInCurrentFrame)
236 | didUpdateThisFrame = false;
237 |
238 | didUpdatePreviewPixelBufferInCurrentFrame = false;
239 | }
240 |
241 | protected virtual IEnumerator OnApplicationPause(bool pauseStatus)
242 | {
243 | while (isStartWaiting)
244 | {
245 | yield return null;
246 | }
247 |
248 | if (!hasInitDone)
249 | yield break;
250 |
251 | // The developer needs to do the camera suspend process oneself so that it is synchronized with the app suspend.
252 | if (pauseStatus)
253 | {
254 | didCameraRunningBeforeSuspend = cameraDevice.running;
255 |
256 | if (cameraDevice.running)
257 | {
258 | cameraDevice.StopRunning();
259 | didUpdateThisFrame = false;
260 | didUpdatePreviewPixelBufferInCurrentFrame = false;
261 | }
262 | }
263 | else
264 | {
265 | if (!cameraDevice.running && didCameraRunningBeforeSuspend)
266 | {
267 | isStartWaiting = true;
268 | cameraDevice.StartRunning(OnPixelBufferReceived);
269 | }
270 | }
271 | }
272 |
273 | private void OnPixelBufferReceived(CameraImage image)
274 | {
275 | if (previewPixelBufferOutput == null)
276 | return;
277 |
278 | // Process only when the latest previewResolution and CameraImage size match.
279 | if (cameraDevice == null || cameraDevice.previewResolution.width != image.width || cameraDevice.previewResolution.height != image.height)
280 | return;
281 |
282 | timestamp = image.timestamp;
283 | verticallyMirrored = image.verticallyMirrored;
284 | float[] intrinsics = image.intrinsics;
285 | this.intrinsics = (intrinsics != null) ?
286 | new Matrix4x4(
287 | new Vector4(intrinsics[0], intrinsics[3], intrinsics[6]),
288 | new Vector4(intrinsics[1], intrinsics[4], intrinsics[7]),
289 | new Vector4(intrinsics[2], intrinsics[5], intrinsics[8]),
290 | new Vector4())
291 | : Matrix4x4.zero;
292 | exposureBias = image.exposureBias ?? -1f;
293 | exposureDuration = image.exposureDuration ?? -1f;
294 | ISO = image.ISO ?? -1f;
295 | focalLength = image.focalLength ?? -1f;
296 | fNumber = image.fNumber ?? -1f;
297 | brightness = image.brightness ?? -1f;
298 |
299 |
300 | bool firstFrame = !previewPixelBufferOutput.pixelBuffer.IsCreated;
301 | previewPixelBufferOutput.Update(image);
302 |
303 | if (firstFrame)
304 | {
305 | previewWidth = previewPixelBufferOutput.width;
306 | previewHeight = previewPixelBufferOutput.height;
307 | }
308 |
309 | if (isStartWaiting)
310 | {
311 | isStartWaiting = false;
312 | }
313 |
314 | didUpdateThisFrame = true;
315 | didUpdatePreviewPixelBufferInCurrentFrame = true;
316 |
317 | if (hasInitDone && frameMatAcquired != null)
318 | {
319 | frameMatAcquired.Invoke(GetMat(), timestamp);
320 | }
321 | }
322 |
323 |
324 | // Update is called once per frame
325 | protected override void Update()
326 | {
327 | if (hasInitDone)
328 | {
329 | // Catch the orientation change of the screen and correct the mat image to the correct direction.
330 | if (screenOrientation != Screen.orientation)
331 | {
332 | Initialize();
333 | }
334 | }
335 | }
336 |
337 | ///
338 | /// Raises the destroy event.
339 | ///
340 | protected override void OnDestroy()
341 | {
342 | Dispose();
343 |
344 | if (cameraDevice != null && cameraDevice.running)
345 | cameraDevice.StopRunning();
346 | cameraDevice = null;
347 | }
348 |
349 | ///
350 | /// Initializes this instance by coroutine.
351 | ///
352 | protected override IEnumerator _Initialize()
353 | {
354 | if (hasInitDone)
355 | {
356 | ReleaseResources();
357 |
358 | if (onDisposed != null)
359 | onDisposed.Invoke();
360 | }
361 |
362 | isInitWaiting = true;
363 |
364 | while (isStartWaiting)
365 | {
366 | yield return null;
367 | }
368 |
369 | if (cameraDevice != null && cameraDevice.running)
370 | cameraDevice.StopRunning();
371 | cameraDevice = null;
372 |
373 |
374 | // Checks camera permission state.
375 | IEnumerator coroutine = hasUserAuthorizedCameraPermission();
376 | yield return coroutine;
377 |
378 | if (!(bool)coroutine.Current)
379 | {
380 | isInitWaiting = false;
381 | initCoroutine = null;
382 |
383 | if (onErrorOccurred != null)
384 | onErrorOccurred.Invoke(ErrorCode.CAMERA_PERMISSION_DENIED);
385 |
386 | yield break;
387 | }
388 |
389 |
390 | // Creates the camera
391 | MediaDeviceQuery deviceQuery = new MediaDeviceQuery(MediaDeviceCriteria.CameraDevice);
392 |
393 | if (!String.IsNullOrEmpty(requestedDeviceName))
394 | {
395 | int requestedDeviceIndex = -1;
396 | if (Int32.TryParse(requestedDeviceName, out requestedDeviceIndex))
397 | {
398 | if (requestedDeviceIndex >= 0 && requestedDeviceIndex < deviceQuery.count)
399 | {
400 | cameraDevice = deviceQuery[requestedDeviceIndex] as CameraDevice;
401 | }
402 | }
403 | else
404 | {
405 | for (int cameraIndex = 0; cameraIndex < deviceQuery.count; cameraIndex++)
406 | {
407 | if (deviceQuery[cameraIndex].uniqueID == requestedDeviceName)
408 | {
409 | cameraDevice = deviceQuery[cameraIndex] as CameraDevice;
410 | break;
411 | }
412 | }
413 | }
414 | if (cameraDevice == null)
415 | Debug.Log("Cannot find camera device " + requestedDeviceName + ".");
416 | }
417 |
418 | if (cameraDevice == null)
419 | {
420 | // Checks how many and which cameras are available on the device
421 | for (int cameraIndex = 0; cameraIndex < deviceQuery.count; cameraIndex++)
422 | {
423 | cameraDevice = deviceQuery[cameraIndex] as CameraDevice;
424 |
425 | if (cameraDevice != null && cameraDevice.frontFacing == requestedIsFrontFacing)
426 | {
427 | break;
428 | }
429 | cameraDevice = null;
430 | }
431 | }
432 |
433 | if (cameraDevice == null)
434 | {
435 | if (deviceQuery.count > 0)
436 | {
437 | cameraDevice = deviceQuery[0] as CameraDevice;
438 | }
439 |
440 | if (cameraDevice == null)
441 | {
442 | isInitWaiting = false;
443 | initCoroutine = null;
444 |
445 | if (onErrorOccurred != null)
446 | onErrorOccurred.Invoke(ErrorCode.CAMERA_DEVICE_NOT_EXIST);
447 |
448 | yield break;
449 | }
450 | }
451 |
452 | // Set the camera's preview resolution and frameRate
453 | cameraDevice.previewResolution = (width: requestedWidth, height: requestedHeight);
454 | cameraDevice.frameRate = (int)requestedFPS;
455 |
456 | // Starts the camera
457 | isStartWaiting = true;
458 | didUpdateThisFrame = false;
459 | didUpdatePreviewPixelBufferInCurrentFrame = false;
460 |
461 | previewPixelBufferOutput = new PixelBufferOutput();
462 | cameraDevice.StartRunning(OnPixelBufferReceived);
463 |
464 | int initFrameCount = 0;
465 | bool isTimeout = false;
466 |
467 | while (true)
468 | {
469 | if (initFrameCount > timeoutFrameCount)
470 | {
471 | isTimeout = true;
472 | break;
473 | }
474 | else if (didUpdateThisFrame)
475 | {
476 | Debug.Log("NatDeviceCamPreviewToMatHelper:: " + "name:" + cameraDevice.name + " width:" + previewWidth + " height:" + previewHeight + " fps:" + cameraDevice.frameRate
477 | + " isFrongFacing:" + cameraDevice.frontFacing);
478 |
479 | baseMat = new Mat(previewHeight, previewWidth, CvType.CV_8UC4);
480 |
481 | if (baseColorFormat == outputColorFormat)
482 | {
483 | frameMat = baseMat;
484 | }
485 | else
486 | {
487 | frameMat = new Mat(baseMat.rows(), baseMat.cols(), CvType.CV_8UC(Channels(outputColorFormat)), new Scalar(0, 0, 0, 255));
488 | }
489 |
490 | screenOrientation = Screen.orientation;
491 | screenWidth = Screen.width;
492 | screenHeight = Screen.height;
493 |
494 | if (rotate90Degree)
495 | rotatedFrameMat = new Mat(frameMat.cols(), frameMat.rows(), CvType.CV_8UC(Channels(outputColorFormat)), new Scalar(0, 0, 0, 255));
496 |
497 | isInitWaiting = false;
498 | hasInitDone = true;
499 | initCoroutine = null;
500 |
501 | if (onInitialized != null)
502 | onInitialized.Invoke();
503 |
504 | break;
505 | }
506 | else
507 | {
508 | initFrameCount++;
509 | yield return null;
510 | }
511 | }
512 |
513 | if (isTimeout)
514 | {
515 | if (cameraDevice.running)
516 | cameraDevice.StopRunning();
517 | cameraDevice = null;
518 |
519 | isInitWaiting = false;
520 | initCoroutine = null;
521 |
522 | if (onErrorOccurred != null)
523 | onErrorOccurred.Invoke(ErrorCode.TIMEOUT);
524 | }
525 | }
526 |
527 | ///
528 | /// Starts the camera.
529 | ///
530 | public override void Play()
531 | {
532 | if (hasInitDone)
533 | StartCoroutine(_Play());
534 | }
535 |
536 | protected virtual IEnumerator _Play()
537 | {
538 | while (isStartWaiting)
539 | {
540 | yield return null;
541 | }
542 |
543 | if (!hasInitDone || cameraDevice.running) yield break;
544 |
545 | isStartWaiting = true;
546 |
547 | cameraDevice.StartRunning(OnPixelBufferReceived);
548 | }
549 |
550 | ///
551 | /// Pauses the active camera.
552 | ///
553 | public override void Pause()
554 | {
555 | if (hasInitDone)
556 | StartCoroutine(_Stop());
557 | }
558 |
559 | ///
560 | /// Stops the active camera.
561 | ///
562 | public override void Stop()
563 | {
564 | if (hasInitDone)
565 | StartCoroutine(_Stop());
566 | }
567 | protected virtual IEnumerator _Stop()
568 | {
569 | while (isStartWaiting)
570 | {
571 | yield return null;
572 | }
573 |
574 | if (!hasInitDone || !cameraDevice.running) yield break;
575 |
576 | cameraDevice.StopRunning();
577 | didUpdateThisFrame = false;
578 | didUpdatePreviewPixelBufferInCurrentFrame = false;
579 | }
580 |
581 | ///
582 | /// Indicates whether the active camera is currently playing.
583 | ///
584 | /// true, if the active camera is playing, false otherwise.
585 | public override bool IsPlaying()
586 | {
587 | return hasInitDone ? cameraDevice.running : false;
588 | }
589 |
590 | ///
591 | /// Indicates whether the active camera device is currently front facng.
592 | ///
593 | /// true, if the active camera device is front facng, false otherwise.
594 | public override bool IsFrontFacing()
595 | {
596 | return hasInitDone ? cameraDevice.frontFacing : false;
597 | }
598 |
599 | ///
600 | /// Returns the active camera device name.
601 | ///
602 | /// The active camera device name.
603 | public override string GetDeviceName()
604 | {
605 | return hasInitDone ? cameraDevice.name : "";
606 | }
607 |
608 | ///
609 | /// Returns the active camera framerate.
610 | ///
611 | /// The active camera framerate.
612 | public override float GetFPS()
613 | {
614 | return hasInitDone ? cameraDevice.frameRate : -1f;
615 | }
616 |
617 | ///
618 | /// Returns the active WebcamTexture.
619 | ///
620 | /// The active WebcamTexture.
621 | public override WebCamTexture GetWebCamTexture()
622 | {
623 | return null;
624 | }
625 |
626 | ///
627 | /// Indicates whether the video buffer of the frame has been updated.
628 | ///
629 | /// true, if the video buffer has been updated false otherwise.
630 | public override bool DidUpdateThisFrame()
631 | {
632 | if (!hasInitDone)
633 | return false;
634 |
635 | return didUpdateThisFrame;
636 | }
637 | #endif
638 |
639 | ///
640 | /// Returns the NatDevice camera device.
641 | ///
642 | /// The NatDevice camera device.
643 | public virtual CameraDevice GetNatDeviceCameraDevice()
644 | {
645 | #if (UNITY_STANDALONE_WIN || UNITY_STANDALONE_OSX || UNITY_IOS || UNITY_ANDROID) && !DISABLE_NATDEVICE_API
646 | return cameraDevice;
647 | #else
648 | return null;
649 | #endif
650 | }
651 |
652 | #if (UNITY_STANDALONE_WIN || UNITY_STANDALONE_OSX || UNITY_IOS || UNITY_ANDROID) && !DISABLE_NATDEVICE_API
653 | ///
654 | /// Gets the mat of the current frame.
655 | /// The Mat object's type is 'CV_8UC4' or 'CV_8UC3' or 'CV_8UC1' (ColorFormat is determined by the outputColorFormat setting).
656 | /// Please do not dispose of the returned mat as it will be reused.
657 | ///
658 | /// The mat of the current frame.
659 | public override Mat GetMat()
660 | {
661 | if (!hasInitDone || !cameraDevice.running || previewPixelBufferOutput == null)
662 | {
663 | return (rotatedFrameMat != null) ? rotatedFrameMat : frameMat;
664 | }
665 |
666 | if (baseColorFormat == outputColorFormat)
667 | {
668 | if (baseMat.IsDisposed)
669 | {
670 | baseMat = new Mat(previewHeight, previewWidth, CvType.CV_8UC4);
671 | frameMat = baseMat;
672 | }
673 |
674 | MatUtils.copyToMat(previewPixelBufferOutput.pixelBuffer, frameMat);
675 | }
676 | else
677 | {
678 | if (frameMat.IsDisposed)
679 | {
680 | frameMat = new Mat(baseMat.rows(), baseMat.cols(), CvType.CV_8UC(Channels(outputColorFormat)));
681 | }
682 |
683 | MatUtils.copyToMat(previewPixelBufferOutput.pixelBuffer, baseMat);
684 | Imgproc.cvtColor(baseMat, frameMat, ColorConversionCodes(baseColorFormat, outputColorFormat));
685 | }
686 |
687 | FlipMat(frameMat, flipVertical, flipHorizontal);
688 | if (rotatedFrameMat != null)
689 | {
690 | if (rotatedFrameMat.IsDisposed)
691 | {
692 | rotatedFrameMat = new Mat(frameMat.cols(), frameMat.rows(), CvType.CV_8UC(Channels(outputColorFormat)));
693 | }
694 |
695 | Core.rotate(frameMat, rotatedFrameMat, Core.ROTATE_90_CLOCKWISE);
696 | return rotatedFrameMat;
697 | }
698 | else
699 | {
700 | return frameMat;
701 | }
702 | }
703 |
704 | ///
705 | /// Flips the mat.
706 | ///
707 | /// Mat.
708 | protected override void FlipMat(Mat mat, bool flipVertical, bool flipHorizontal)
709 | {
710 | int flipCode = 0;
711 |
712 | if (flipVertical)
713 | {
714 | if (flipCode == int.MinValue)
715 | {
716 | flipCode = 0;
717 | }
718 | else if (flipCode == 0)
719 | {
720 | flipCode = int.MinValue;
721 | }
722 | else if (flipCode == 1)
723 | {
724 | flipCode = -1;
725 | }
726 | else if (flipCode == -1)
727 | {
728 | flipCode = 1;
729 | }
730 | }
731 |
732 | if (flipHorizontal)
733 | {
734 | if (flipCode == int.MinValue)
735 | {
736 | flipCode = 1;
737 | }
738 | else if (flipCode == 0)
739 | {
740 | flipCode = -1;
741 | }
742 | else if (flipCode == 1)
743 | {
744 | flipCode = int.MinValue;
745 | }
746 | else if (flipCode == -1)
747 | {
748 | flipCode = 0;
749 | }
750 | }
751 |
752 | if (flipCode > int.MinValue)
753 | {
754 | Core.flip(mat, mat, flipCode);
755 | }
756 | }
757 |
758 | ///
759 | /// To release the resources.
760 | ///
761 | protected override void ReleaseResources()
762 | {
763 | isInitWaiting = false;
764 | hasInitDone = false;
765 |
766 | if (previewPixelBufferOutput != null)
767 | {
768 | previewPixelBufferOutput.Dispose();
769 | previewPixelBufferOutput = null;
770 | }
771 |
772 | didUpdateThisFrame = false;
773 | didUpdatePreviewPixelBufferInCurrentFrame = false;
774 |
775 | if (frameMat != null)
776 | {
777 | frameMat.Dispose();
778 | frameMat = null;
779 | }
780 | if (baseMat != null)
781 | {
782 | baseMat.Dispose();
783 | baseMat = null;
784 | }
785 | if (rotatedFrameMat != null)
786 | {
787 | rotatedFrameMat.Dispose();
788 | rotatedFrameMat = null;
789 | }
790 | }
791 |
792 | ///
793 | /// Releases all resource used by the object.
794 | ///
795 | /// Call when you are finished using the . The
796 | /// method leaves the in an unusable state. After
797 | /// calling , you must release all references to the so
798 | /// the garbage collector can reclaim the memory that the was occupying.
799 | public override void Dispose()
800 | {
801 | if (colors != null)
802 | colors = null;
803 |
804 | if (isInitWaiting)
805 | {
806 |
807 | CancelInitCoroutine();
808 |
809 | frameMatAcquired = null;
810 |
811 | if (cameraDevice != null)
812 | {
813 | if (this != null && this.isActiveAndEnabled)
814 | StartCoroutine(_Dispose());
815 | }
816 |
817 | ReleaseResources();
818 | }
819 | else if (hasInitDone)
820 | {
821 | frameMatAcquired = null;
822 |
823 | if (this != null && this.isActiveAndEnabled)
824 | StartCoroutine(_Dispose());
825 |
826 | ReleaseResources();
827 |
828 | if (onDisposed != null)
829 | onDisposed.Invoke();
830 | }
831 | }
832 |
833 | protected virtual IEnumerator _Dispose()
834 | {
835 | while (isStartWaiting)
836 | {
837 | yield return null;
838 | }
839 |
840 | if (cameraDevice.running)
841 | cameraDevice.StopRunning();
842 | cameraDevice = null;
843 | }
844 | #endif
845 |
846 | }
847 | }
--------------------------------------------------------------------------------
/Assets/NatDeviceWithOpenCVForUnityExample/Scripts/Utils/NatDeviceCamPreviewToMatHelper.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: af1f30f564c42fd4a992788aa16ace23
3 | timeCreated: 1524605908
4 | licenseType: Free
5 | MonoImporter:
6 | serializedVersion: 2
7 | defaultReferences: []
8 | executionOrder: 0
9 | icon: {instanceID: 0}
10 | userData:
11 | assetBundleName:
12 | assetBundleVariant:
13 |
--------------------------------------------------------------------------------
/Assets/NatDeviceWithOpenCVForUnityExample/Scripts/Utils/RuntimePermissionHelper.cs:
--------------------------------------------------------------------------------
1 | using System.Collections;
2 | using UnityEngine;
3 |
4 | namespace NatDeviceWithOpenCVForUnityExample
5 | {
6 | public class RuntimePermissionHelper : MonoBehaviour
7 | {
8 |
9 | public virtual IEnumerator hasUserAuthorizedCameraPermission()
10 | {
11 | #if UNITY_IOS && UNITY_2018_1_OR_NEWER
12 | UserAuthorization mode = UserAuthorization.WebCam;
13 | if (!Application.HasUserAuthorization(mode))
14 | {
15 | yield return RequestUserAuthorization(mode);
16 | }
17 | yield return Application.HasUserAuthorization(mode);
18 | #elif UNITY_ANDROID && UNITY_2018_3_OR_NEWER
19 | string permission = UnityEngine.Android.Permission.Camera;
20 | if (!UnityEngine.Android.Permission.HasUserAuthorizedPermission(permission))
21 | {
22 | yield return RequestUserPermission(permission);
23 | }
24 | yield return UnityEngine.Android.Permission.HasUserAuthorizedPermission(permission);
25 | #else
26 | yield return true;
27 | #endif
28 | }
29 |
30 | public virtual IEnumerator hasUserAuthorizedMicrophonePermission()
31 | {
32 | #if UNITY_IOS && UNITY_2018_1_OR_NEWER
33 | UserAuthorization mode = UserAuthorization.Microphone;
34 | if (!Application.HasUserAuthorization(mode))
35 | {
36 | yield return RequestUserAuthorization(mode);
37 | }
38 | yield return Application.HasUserAuthorization(mode);
39 | #elif UNITY_ANDROID && UNITY_2018_3_OR_NEWER
40 | string permission = UnityEngine.Android.Permission.Microphone;
41 | if (!UnityEngine.Android.Permission.HasUserAuthorizedPermission(permission))
42 | {
43 | yield return RequestUserPermission(permission);
44 | }
45 | yield return UnityEngine.Android.Permission.HasUserAuthorizedPermission(permission);
46 | #else
47 | yield return true;
48 | #endif
49 | }
50 |
51 | public virtual IEnumerator hasUserAuthorizedExternalStorageWritePermission()
52 | {
53 | #if UNITY_ANDROID && UNITY_2018_3_OR_NEWER
54 | string permission = UnityEngine.Android.Permission.ExternalStorageWrite;
55 | if (!UnityEngine.Android.Permission.HasUserAuthorizedPermission(permission))
56 | {
57 | yield return RequestUserPermission(permission);
58 | }
59 | yield return UnityEngine.Android.Permission.HasUserAuthorizedPermission(permission);
60 | #else
61 | yield return true;
62 | #endif
63 | }
64 |
65 | #if (UNITY_IOS && UNITY_2018_1_OR_NEWER) || (UNITY_ANDROID && UNITY_2018_3_OR_NEWER)
66 | protected bool isUserRequestingPermission;
67 |
68 | protected virtual IEnumerator OnApplicationFocus(bool hasFocus)
69 | {
70 | yield return null;
71 |
72 | if (isUserRequestingPermission && hasFocus)
73 | isUserRequestingPermission = false;
74 | }
75 |
76 | #if UNITY_IOS
77 | protected virtual IEnumerator RequestUserAuthorization(UserAuthorization mode)
78 | {
79 | isUserRequestingPermission = true;
80 | yield return Application.RequestUserAuthorization(mode);
81 |
82 | float timeElapsed = 0;
83 | while (isUserRequestingPermission)
84 | {
85 | if (timeElapsed > 0.25f)
86 | {
87 | isUserRequestingPermission = false;
88 | yield break;
89 | }
90 | timeElapsed += Time.deltaTime;
91 |
92 | yield return null;
93 | }
94 | yield break;
95 | }
96 | #elif UNITY_ANDROID
97 | protected virtual IEnumerator RequestUserPermission(string permission)
98 | {
99 | isUserRequestingPermission = true;
100 | UnityEngine.Android.Permission.RequestUserPermission(permission);
101 |
102 | float timeElapsed = 0;
103 | while (isUserRequestingPermission)
104 | {
105 | if (timeElapsed > 0.25f)
106 | {
107 | isUserRequestingPermission = false;
108 | yield break;
109 | }
110 | timeElapsed += Time.deltaTime;
111 |
112 | yield return null;
113 | }
114 | yield break;
115 | }
116 | #endif
117 | #endif
118 | }
119 | }
--------------------------------------------------------------------------------
/Assets/NatDeviceWithOpenCVForUnityExample/Scripts/Utils/RuntimePermissionHelper.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 0e036a041bcf1924b912512e8bdf9bd2
3 | timeCreated: 1553402189
4 | licenseType: Free
5 | MonoImporter:
6 | externalObjects: {}
7 | serializedVersion: 2
8 | defaultReferences: []
9 | executionOrder: 0
10 | icon: {instanceID: 0}
11 | userData:
12 | assetBundleName:
13 | assetBundleVariant:
14 |
--------------------------------------------------------------------------------
/Assets/NatDeviceWithOpenCVForUnityExample/Scripts/WebCamMatSource.cs:
--------------------------------------------------------------------------------
1 | using OpenCVForUnity.CoreModule;
2 | using OpenCVForUnity.UnityUtils;
3 | using OpenCVForUnity.UtilsModule;
4 | using System;
5 | using System.Threading.Tasks;
6 | using UnityEngine;
7 |
8 | namespace NatDeviceWithOpenCVForUnityExample
9 | {
10 |
11 | public class WebCamMatSource : ICameraSource
12 | {
13 |
14 | #region --Op vars--
15 |
16 | private WebCamDevice cameraDevice;
17 | private Action startCallback, frameCallback;
18 | private Mat sourceMatrix, uprightMatrix;
19 | private Color32[] bufferColors;
20 | private int requestedWidth, requestedHeight, requestedFramerate;
21 | private int cameraIndex;
22 | private bool firstFrame;
23 | private DeviceOrientation orientation;
24 | private bool rotate90Degree;
25 |
26 | private WebCamMatSourceAttachment attachment;
27 | private class WebCamMatSourceAttachment : MonoBehaviour
28 | {
29 | public Action @delegate;
30 | void Awake() => DontDestroyOnLoad(this.gameObject);
31 | void Update() => @delegate?.Invoke();
32 | }
33 |
34 | #endregion
35 |
36 |
37 | #region --Client API--
38 |
39 | public int width { get { return uprightMatrix.width(); } }
40 |
41 | public int height { get { return uprightMatrix.height(); } }
42 |
43 | public bool isRunning { get { return (activeCamera && !firstFrame) ? activeCamera.isPlaying : false; } }
44 |
45 | public bool isFrontFacing { get { return activeCamera ? cameraDevice.isFrontFacing : false; } }
46 |
47 | public WebCamTexture activeCamera { get; private set; }
48 |
49 | public WebCamMatSource(int width, int height, int framerate = 30, bool front = false)
50 | {
51 | requestedWidth = width;
52 | requestedHeight = height;
53 | requestedFramerate = framerate;
54 | #if UNITY_ANDROID && !UNITY_EDITOR
55 | // Set the requestedFPS parameter to avoid the problem of the WebCamTexture image becoming low light on some Android devices. (Pixel, Pixel 2)
56 | // https://forum.unity.com/threads/released-opencv-for-unity.277080/page-33#post-3445178
57 | framerate = front ? 15 : framerate;
58 | #endif
59 | orientation = (DeviceOrientation)(int)Screen.orientation;
60 |
61 | // Pick camera
62 | var devices = WebCamTexture.devices;
63 | if (devices.Length == 0)
64 | {
65 | Debug.LogError("Camera device does not exist.");
66 | return;
67 | }
68 |
69 | for (; cameraIndex < devices.Length; cameraIndex++)
70 | if (devices[cameraIndex].isFrontFacing == front)
71 | break;
72 |
73 | if (cameraIndex == devices.Length)
74 | {
75 | Debug.LogError("Camera is null. Consider using " + (front ? "rear" : "front") + " camera.");
76 | return;
77 | }
78 |
79 | cameraDevice = devices[cameraIndex];
80 | activeCamera = new WebCamTexture(cameraDevice.name, requestedWidth, requestedHeight, framerate);
81 | }
82 |
83 | public void Dispose()
84 | {
85 | StopRunning();
86 |
87 | if (activeCamera != null)
88 | {
89 | WebCamTexture.Destroy(activeCamera);
90 | activeCamera = null;
91 | }
92 | if (sourceMatrix != null)
93 | sourceMatrix.Dispose();
94 | if (uprightMatrix != null)
95 | uprightMatrix.Dispose();
96 | sourceMatrix =
97 | uprightMatrix = null;
98 | bufferColors = null;
99 | }
100 |
101 | public Task StartRunning(Action startCallback, Action frameCallback)
102 | {
103 | var startTask = new TaskCompletionSource();
104 |
105 | if (activeCamera == null || (activeCamera != null && activeCamera.isPlaying))
106 | return startTask.Task;
107 |
108 | this.startCallback = startCallback;
109 | this.frameCallback = frameCallback;
110 | firstFrame = true;
111 | activeCamera.Play();
112 |
113 | attachment = new GameObject("NatDeviceWithOpenCVForUnityExample WebCamMatSource Helper").AddComponent();
114 | attachment.@delegate = () =>
115 | {
116 | OnFrame();
117 | };
118 |
119 | startTask.SetResult(true);
120 | return startTask.Task;
121 | }
122 |
123 | public void StopRunning()
124 | {
125 | if (activeCamera == null)
126 | return;
127 |
128 | if (attachment != null)
129 | {
130 | attachment.@delegate = default;
131 | WebCamMatSourceAttachment.Destroy(attachment.gameObject);
132 | attachment = default;
133 | }
134 |
135 | activeCamera.Stop();
136 | }
137 |
138 | public void CaptureFrame(Mat matrix)
139 | {
140 | if (uprightMatrix == null) return;
141 |
142 | if ((int)matrix.total() * (int)matrix.elemSize() != (int)uprightMatrix.total() * (int)uprightMatrix.elemSize())
143 | throw new ArgumentException("matrix and CamSource image need to be the same size.");
144 |
145 | uprightMatrix.copyTo(matrix);
146 | }
147 |
148 | public void CaptureFrame(Color32[] pixelBuffer)
149 | {
150 | if (uprightMatrix == null) return;
151 |
152 | if (pixelBuffer.Length * 4 != (int)uprightMatrix.total() * (int)uprightMatrix.elemSize())
153 | throw new ArgumentException("pixelBuffer and CamSource image need to be the same size.");
154 |
155 | MatUtils.copyFromMat(uprightMatrix, pixelBuffer);
156 | }
157 |
158 | public void CaptureFrame(byte[] pixelBuffer)
159 | {
160 | if (uprightMatrix == null) return;
161 |
162 | if (pixelBuffer.Length != (int)uprightMatrix.total() * (int)uprightMatrix.elemSize())
163 | throw new ArgumentException("pixelBuffer and CamSource image need to be the same size.");
164 |
165 | MatUtils.copyFromMat(uprightMatrix, pixelBuffer);
166 | }
167 |
168 | public async Task SwitchCamera()
169 | {
170 | if (activeCamera == null)
171 | return;
172 |
173 | var _isRunning = activeCamera.isPlaying;
174 |
175 | Dispose();
176 |
177 | var devices = WebCamTexture.devices;
178 | cameraIndex = ++cameraIndex % devices.Length;
179 | cameraDevice = devices[cameraIndex];
180 |
181 | bool front = cameraDevice.isFrontFacing;
182 | int framerate = requestedFramerate;
183 | #if UNITY_ANDROID && !UNITY_EDITOR
184 | // Set the requestedFPS parameter to avoid the problem of the WebCamTexture image becoming low light on some Android devices. (Pixel, Pixel 2)
185 | // https://forum.unity.com/threads/released-opencv-for-unity.277080/page-33#post-3445178
186 | framerate = front ? 15 : framerate;
187 | #endif
188 | activeCamera = new WebCamTexture(cameraDevice.name, requestedWidth, requestedHeight, framerate);
189 | await StartRunning(startCallback, frameCallback);
190 |
191 | if (!_isRunning)
192 | StopRunning();
193 | }
194 |
195 | #endregion
196 |
197 |
198 | #region --Operations--
199 |
200 | private void OnFrame()
201 | {
202 | if (!activeCamera.isPlaying || !activeCamera.didUpdateThisFrame)
203 | return;
204 |
205 | // Check matrix
206 | sourceMatrix = sourceMatrix ?? new Mat(activeCamera.height, activeCamera.width, CvType.CV_8UC4);
207 | uprightMatrix = uprightMatrix ?? new Mat();
208 | bufferColors = bufferColors ?? new Color32[activeCamera.width * activeCamera.height];
209 |
210 | // Update matrix
211 | Utils.webCamTextureToMat(activeCamera, sourceMatrix, bufferColors, false);
212 |
213 |
214 | if (firstFrame)
215 | {
216 | rotate90Degree = false;
217 |
218 | #if !UNITY_EDITOR && !(UNITY_STANDALONE || UNITY_WEBGL)
219 | switch (orientation)
220 | {
221 | case DeviceOrientation.LandscapeLeft:
222 | case DeviceOrientation.LandscapeRight:
223 | break;
224 | case DeviceOrientation.Portrait:
225 | case DeviceOrientation.PortraitUpsideDown:
226 | rotate90Degree = true;
227 | break;
228 | }
229 | #endif
230 | }
231 |
232 | int flipCode = 0;
233 | if (cameraDevice.isFrontFacing)
234 | {
235 | if (activeCamera.videoRotationAngle == 0 || activeCamera.videoRotationAngle == 90)
236 | {
237 | flipCode = -1;
238 | }
239 | else if (activeCamera.videoRotationAngle == 180 || activeCamera.videoRotationAngle == 270)
240 | {
241 | flipCode = int.MinValue;
242 | }
243 | }
244 | else
245 | {
246 | if (activeCamera.videoRotationAngle == 180 || activeCamera.videoRotationAngle == 270)
247 | {
248 | flipCode = 1;
249 | }
250 | }
251 |
252 | if (rotate90Degree && cameraDevice.isFrontFacing)
253 | {
254 | if (flipCode == int.MinValue)
255 | {
256 | flipCode = -1;
257 | }
258 | else if (flipCode == 0)
259 | {
260 | flipCode = 1;
261 | }
262 | else if (flipCode == 1)
263 | {
264 | flipCode = 0;
265 | }
266 | else if (flipCode == -1)
267 | {
268 | flipCode = int.MinValue;
269 | }
270 | }
271 |
272 | if (flipCode > int.MinValue)
273 | {
274 | Core.flip(sourceMatrix, sourceMatrix, flipCode);
275 | }
276 |
277 | if (rotate90Degree)
278 | {
279 | Core.rotate(sourceMatrix, uprightMatrix, Core.ROTATE_90_CLOCKWISE);
280 | }
281 | else
282 | {
283 | sourceMatrix.copyTo(uprightMatrix);
284 | }
285 |
286 |
287 | // Invoke client callbacks
288 | if (firstFrame)
289 | {
290 | startCallback();
291 | firstFrame = false;
292 | }
293 |
294 | frameCallback();
295 | }
296 |
297 | #endregion
298 | }
299 | }
--------------------------------------------------------------------------------
/Assets/NatDeviceWithOpenCVForUnityExample/Scripts/WebCamMatSource.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: c02e9458fdffa45a6a262ed1919b780e
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Assets/NatDeviceWithOpenCVForUnityExample/Scripts/WebCamSource.cs:
--------------------------------------------------------------------------------
1 | using OpenCVForUnity.CoreModule;
2 | using OpenCVForUnity.UtilsModule;
3 | using System;
4 | using System.Runtime.InteropServices;
5 | using System.Threading.Tasks;
6 | using UnityEngine;
7 |
8 | namespace NatDeviceWithOpenCVForUnityExample
9 | {
10 |
11 | public class WebCamSource : ICameraSource
12 | {
13 |
14 | #region --Op vars--
15 |
16 | private WebCamDevice cameraDevice;
17 | private Action startCallback, frameCallback;
18 | private Color32[] sourceBuffer, uprightBuffer;
19 | private int requestedWidth, requestedHeight, requestedFramerate;
20 | private int cameraIndex;
21 | private bool firstFrame;
22 | private DeviceOrientation orientation;
23 | private bool rotate90Degree;
24 |
25 | private WebCamSourceAttachment attachment;
26 | private class WebCamSourceAttachment : MonoBehaviour
27 | {
28 | public Action @delegate;
29 | void Awake() => DontDestroyOnLoad(this.gameObject);
30 | void Update() => @delegate?.Invoke();
31 | }
32 |
33 | #endregion
34 |
35 |
36 | #region --Client API--
37 |
38 | public int width { get; private set; }
39 |
40 | public int height { get; private set; }
41 |
42 | public bool isRunning { get { return (activeCamera && !firstFrame) ? activeCamera.isPlaying : false; } }
43 |
44 | public bool isFrontFacing { get { return activeCamera ? cameraDevice.isFrontFacing : false; } }
45 |
46 | public WebCamTexture activeCamera { get; private set; }
47 |
48 | public WebCamSource(int width, int height, int framerate = 30, bool front = false)
49 | {
50 | requestedWidth = width;
51 | requestedHeight = height;
52 | requestedFramerate = framerate;
53 | #if UNITY_ANDROID && !UNITY_EDITOR
54 | // Set the requestedFPS parameter to avoid the problem of the WebCamTexture image becoming low light on some Android devices. (Pixel, Pixel 2)
55 | // https://forum.unity.com/threads/released-opencv-for-unity.277080/page-33#post-3445178
56 | framerate = front ? 15 : framerate;
57 | #endif
58 | orientation = (DeviceOrientation)(int)Screen.orientation;
59 |
60 | // Pick camera
61 | var devices = WebCamTexture.devices;
62 | if (devices.Length == 0)
63 | {
64 | Debug.LogError("Camera device does not exist.");
65 | return;
66 | }
67 |
68 | for (; cameraIndex < devices.Length; cameraIndex++)
69 | if (devices[cameraIndex].isFrontFacing == front)
70 | break;
71 |
72 | if (cameraIndex == devices.Length)
73 | {
74 | Debug.LogError("Camera is null. Consider using " + (front ? "rear" : "front") + " camera.");
75 | return;
76 | }
77 |
78 | cameraDevice = devices[cameraIndex];
79 | activeCamera = new WebCamTexture(cameraDevice.name, requestedWidth, requestedHeight, framerate);
80 | }
81 |
82 | public void Dispose()
83 | {
84 | StopRunning();
85 |
86 | if (activeCamera != null)
87 | {
88 | WebCamTexture.Destroy(activeCamera);
89 | activeCamera = null;
90 | }
91 | sourceBuffer = null;
92 | uprightBuffer = null;
93 | }
94 |
95 | public Task StartRunning(Action startCallback, Action frameCallback)
96 | {
97 | var startTask = new TaskCompletionSource();
98 |
99 | if (activeCamera == null || (activeCamera != null && activeCamera.isPlaying))
100 | return startTask.Task;
101 |
102 | this.startCallback = startCallback;
103 | this.frameCallback = frameCallback;
104 | firstFrame = true;
105 | activeCamera.Play();
106 |
107 | attachment = new GameObject("NatDeviceWithOpenCVForUnityExample WebCamSource Helper").AddComponent();
108 | attachment.@delegate = () =>
109 | {
110 | OnFrame();
111 | };
112 |
113 | startTask.SetResult(true);
114 | return startTask.Task;
115 | }
116 |
117 | public void StopRunning()
118 | {
119 | if (activeCamera == null)
120 | return;
121 |
122 | if (attachment != null)
123 | {
124 | attachment.@delegate = default;
125 | WebCamSourceAttachment.Destroy(attachment.gameObject);
126 | attachment = default;
127 | }
128 |
129 | activeCamera.Stop();
130 | }
131 |
132 | public void CaptureFrame(Mat matrix)
133 | {
134 | if (uprightBuffer == null) return;
135 |
136 | if ((int)matrix.total() * (int)matrix.elemSize() != uprightBuffer.Length * 4)
137 | throw new ArgumentException("matrix and CamSource image need to be the same size.");
138 |
139 | MatUtils.copyToMat(uprightBuffer, matrix);
140 | Core.flip(matrix, matrix, 0);
141 | }
142 |
143 | public void CaptureFrame(Color32[] pixelBuffer)
144 | {
145 | if (uprightBuffer == null) return;
146 |
147 | if (pixelBuffer.Length != uprightBuffer.Length)
148 | throw new ArgumentException("pixelBuffer and CamSource image need to be the same size.");
149 |
150 | Array.Copy(uprightBuffer, pixelBuffer, uprightBuffer.Length);
151 | }
152 |
153 | public void CaptureFrame(byte[] pixelBuffer)
154 | {
155 | if (uprightBuffer == null) return;
156 |
157 | if (pixelBuffer.Length != uprightBuffer.Length * 4)
158 | throw new ArgumentException("pixelBuffer and CamSource image need to be the same size.");
159 |
160 | GCHandle pin = GCHandle.Alloc(uprightBuffer, GCHandleType.Pinned);
161 | Marshal.Copy(pin.AddrOfPinnedObject(), pixelBuffer, 0, pixelBuffer.Length);
162 | pin.Free();
163 | }
164 |
165 | public async Task SwitchCamera()
166 | {
167 | if (activeCamera == null)
168 | return;
169 |
170 | var _isRunning = activeCamera.isPlaying;
171 |
172 | Dispose();
173 |
174 | var devices = WebCamTexture.devices;
175 | cameraIndex = ++cameraIndex % devices.Length;
176 | cameraDevice = devices[cameraIndex];
177 |
178 | bool front = cameraDevice.isFrontFacing;
179 | int framerate = requestedFramerate;
180 | #if UNITY_ANDROID && !UNITY_EDITOR
181 | // Set the requestedFPS parameter to avoid the problem of the WebCamTexture image becoming low light on some Android devices. (Pixel, Pixel 2)
182 | // https://forum.unity.com/threads/released-opencv-for-unity.277080/page-33#post-3445178
183 | framerate = front ? 15 : framerate;
184 | #endif
185 |
186 | activeCamera = new WebCamTexture(cameraDevice.name, requestedWidth, requestedHeight, framerate);
187 | await StartRunning(startCallback, frameCallback);
188 |
189 | if (!_isRunning)
190 | StopRunning();
191 | }
192 |
193 | #endregion
194 |
195 |
196 | #region --Operations--
197 |
198 | private void OnFrame()
199 | {
200 | if (!activeCamera.isPlaying || !activeCamera.didUpdateThisFrame)
201 | return;
202 |
203 | // Check buffers
204 | sourceBuffer = sourceBuffer ?? activeCamera.GetPixels32();
205 | uprightBuffer = uprightBuffer ?? new Color32[sourceBuffer.Length];
206 | // Update buffers
207 | activeCamera.GetPixels32(sourceBuffer);
208 |
209 | if (firstFrame)
210 | {
211 | rotate90Degree = false;
212 |
213 | #if !UNITY_EDITOR && !(UNITY_STANDALONE || UNITY_WEBGL)
214 | switch (orientation)
215 | {
216 | case DeviceOrientation.LandscapeLeft:
217 | case DeviceOrientation.LandscapeRight:
218 | width = activeCamera.width;
219 | height = activeCamera.height;
220 | break;
221 | case DeviceOrientation.Portrait:
222 | case DeviceOrientation.PortraitUpsideDown:
223 | width = activeCamera.height;
224 | height = activeCamera.width;
225 | rotate90Degree = true;
226 | break;
227 | }
228 | #else
229 | width = activeCamera.width;
230 | height = activeCamera.height;
231 | #endif
232 | }
233 |
234 | int flipCode = int.MinValue;
235 | if (cameraDevice.isFrontFacing)
236 | {
237 | if (activeCamera.videoRotationAngle == 0 || activeCamera.videoRotationAngle == 90)
238 | {
239 | flipCode = 1;
240 | }
241 | else if (activeCamera.videoRotationAngle == 180 || activeCamera.videoRotationAngle == 270)
242 | {
243 | flipCode = 0;
244 | }
245 | }
246 | else
247 | {
248 | if (activeCamera.videoRotationAngle == 180 || activeCamera.videoRotationAngle == 270)
249 | {
250 | flipCode = -1;
251 | }
252 | }
253 |
254 | if (rotate90Degree && cameraDevice.isFrontFacing)
255 | {
256 | if (flipCode == int.MinValue)
257 | {
258 | flipCode = -1;
259 | }
260 | else if (flipCode == 0)
261 | {
262 | flipCode = 1;
263 | }
264 | else if (flipCode == 1)
265 | {
266 | flipCode = 0;
267 | }
268 | else if (flipCode == -1)
269 | {
270 | flipCode = int.MinValue;
271 | }
272 | }
273 |
274 | if (flipCode > int.MinValue)
275 | {
276 | if (flipCode == 0)
277 | {
278 | FlipVertical(sourceBuffer, activeCamera.width, activeCamera.height, sourceBuffer);
279 | }
280 | else if (flipCode == 1)
281 | {
282 | FlipHorizontal(sourceBuffer, activeCamera.width, activeCamera.height, sourceBuffer);
283 | }
284 | else if (flipCode == -1)
285 | {
286 | Rotate(sourceBuffer, activeCamera.width, activeCamera.height, sourceBuffer, 2);
287 | }
288 | }
289 |
290 | if (rotate90Degree)
291 | {
292 | Rotate(sourceBuffer, activeCamera.width, activeCamera.height, uprightBuffer, 1);
293 | }
294 | else
295 | {
296 | Array.Copy(sourceBuffer, uprightBuffer, sourceBuffer.Length);
297 | }
298 |
299 | // Invoke client callbacks
300 | if (firstFrame)
301 | {
302 | startCallback();
303 | firstFrame = false;
304 | }
305 |
306 | frameCallback();
307 | }
308 |
309 | #endregion
310 |
311 |
312 | #region --Utilities--
313 |
314 | private static void FlipVertical(Color32[] src, int width, int height, Color32[] dst)
315 | {
316 | for (var i = 0; i < height / 2; i++)
317 | {
318 | var y = i * width;
319 | var x = (height - i - 1) * width;
320 | for (var j = 0; j < width; j++)
321 | {
322 | int s = y + j;
323 | int t = x + j;
324 | Color32 c = src[s];
325 | dst[s] = src[t];
326 | dst[t] = c;
327 | }
328 | }
329 | }
330 |
331 | private static void FlipHorizontal(Color32[] src, int width, int height, Color32[] dst)
332 | {
333 | for (int i = 0; i < height; i++)
334 | {
335 | int y = i * width;
336 | int x = y + width - 1;
337 | for (var j = 0; j < width / 2; j++)
338 | {
339 | int s = y + j;
340 | int t = x - j;
341 | Color32 c = src[s];
342 | dst[s] = src[t];
343 | dst[t] = c;
344 | }
345 | }
346 | }
347 |
348 | private static void Rotate(Color32[] src, int srcWidth, int srcHeight, Color32[] dst, int rotation)
349 | {
350 | int i;
351 | switch (rotation)
352 | {
353 | case 0:
354 | Array.Copy(src, dst, src.Length);
355 | break;
356 | case 1:
357 | // Rotate 90 degrees (CLOCKWISE)
358 | i = 0;
359 | for (int x = srcWidth - 1; x >= 0; x--)
360 | {
361 | for (int y = 0; y < srcHeight; y++)
362 | {
363 | dst[i] = src[x + y * srcWidth];
364 | i++;
365 | }
366 | }
367 | break;
368 | case 2:
369 | // Rotate 180 degrees
370 | i = src.Length;
371 | for (int x = 0; x < i / 2; x++)
372 | {
373 | Color32 t = src[x];
374 | dst[x] = src[i - x - 1];
375 | dst[i - x - 1] = t;
376 | }
377 | break;
378 | case 3:
379 | // Rotate 90 degrees (COUNTERCLOCKWISE)
380 | i = 0;
381 | for (int x = 0; x < srcWidth; x++)
382 | {
383 | for (int y = srcHeight - 1; y >= 0; y--)
384 | {
385 | dst[i] = src[x + y * srcWidth];
386 | i++;
387 | }
388 | }
389 | break;
390 | }
391 | }
392 |
393 | #endregion
394 | }
395 | }
--------------------------------------------------------------------------------
/Assets/NatDeviceWithOpenCVForUnityExample/Scripts/WebCamSource.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 486b80aae3ddd4e14bb0406376991414
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Assets/NatDeviceWithOpenCVForUnityExample/ShowLicense.cs:
--------------------------------------------------------------------------------
1 | using UnityEngine;
2 | using UnityEngine.SceneManagement;
3 |
4 | namespace NatDeviceWithOpenCVForUnityExample
5 | {
6 |
7 | public class ShowLicense : MonoBehaviour
8 | {
9 |
10 | public void OnBackButtonClick()
11 | {
12 | SceneManager.LoadScene("NatDeviceWithOpenCVForUnityExample");
13 | }
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/Assets/NatDeviceWithOpenCVForUnityExample/ShowLicense.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 599febf5582a8084bbb793443573466c
3 | timeCreated: 1521862659
4 | licenseType: Free
5 | MonoImporter:
6 | serializedVersion: 2
7 | defaultReferences: []
8 | executionOrder: 0
9 | icon: {instanceID: 0}
10 | userData:
11 | assetBundleName:
12 | assetBundleVariant:
13 |
--------------------------------------------------------------------------------
/Assets/NatDeviceWithOpenCVForUnityExample/ShowLicense.unity.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 8d1000b636372dc4e8ce1be55a9f0e58
3 | timeCreated: 1521862659
4 | licenseType: Free
5 | DefaultImporter:
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/Assets/NatDeviceWithOpenCVForUnityExample/ShowSystemInfo.cs:
--------------------------------------------------------------------------------
1 | using OpenCVForUnity.CoreModule;
2 | using OpenCVForUnity.UnityUtils;
3 | using System;
4 | using System.Collections.Generic;
5 | using System.Reflection;
6 | using System.Text;
7 | using UnityEngine;
8 | using UnityEngine.SceneManagement;
9 | using UnityEngine.UI;
10 |
11 | namespace NatDeviceWithOpenCVForUnityExample
12 | {
13 | public class ShowSystemInfo : MonoBehaviour
14 | {
15 | public Text systemInfoText;
16 | public InputField systemInfoInputField;
17 |
18 | private const string ASSET_NAME = "OpenCVForUnity";
19 |
20 | // Use this for initialization
21 | void Start()
22 | {
23 |
24 | StringBuilder sb = new StringBuilder();
25 | sb.Append("###### Build Info ######\n");
26 | IDictionary buildInfo = GetBuildInfo();
27 | foreach (string key in buildInfo.Keys)
28 | {
29 | sb.Append(key).Append(" = ").Append(buildInfo[key]).Append("\n");
30 | }
31 | sb.Append("\n");
32 |
33 | #if UNITY_IOS || (UNITY_ANDROID && UNITY_2018_3_OR_NEWER)
34 | sb.Append("###### Device Info ######\n");
35 | IDictionary deviceInfo = GetDeviceInfo();
36 | foreach (string key in deviceInfo.Keys)
37 | {
38 | sb.Append(key).Append(" = ").Append(deviceInfo[key]).Append("\n");
39 | }
40 | sb.Append("\n");
41 | #endif
42 |
43 | sb.Append("###### System Info ######\n");
44 | IDictionary systemInfo = GetSystemInfo();
45 | foreach (string key in systemInfo.Keys)
46 | {
47 | sb.Append(key).Append(" = ").Append(systemInfo[key]).Append("\n");
48 | }
49 | sb.Append("#########################\n");
50 |
51 | systemInfoText.text = systemInfoInputField.text = sb.ToString();
52 | Debug.Log(sb.ToString());
53 | }
54 |
55 | // Update is called once per frame
56 | void Update()
57 | {
58 |
59 | }
60 |
61 | public Dictionary GetBuildInfo()
62 | {
63 | Dictionary dict = new Dictionary();
64 |
65 | dict.Add(ASSET_NAME + " version", Core.NATIVE_LIBRARY_NAME + " " + Utils.getVersion() + " (" + Core.VERSION + ")");
66 | dict.Add("Build Unity version", Application.unityVersion);
67 |
68 | #if UNITY_EDITOR
69 | dict.Add("Build target", "Editor");
70 | #elif UNITY_STANDALONE_WIN
71 | dict.Add("Build target", "Windows");
72 | #elif UNITY_STANDALONE_OSX
73 | dict.Add("Build target", "Mac OSX");
74 | #elif UNITY_STANDALONE_LINUX
75 | dict.Add("Build target", "Linux");
76 | #elif UNITY_ANDROID
77 | dict.Add("Build target", "Android");
78 | #elif UNITY_IOS
79 | dict.Add("Build target", "iOS");
80 | #elif UNITY_WSA
81 | dict.Add("Build target", "WSA");
82 | #elif UNITY_WEBGL
83 | dict.Add("Build target", "WebGL");
84 | #elif PLATFORM_LUMIN
85 | dict.Add("Build target", "LUMIN");
86 | #else
87 | dict.Add("Build target", "");
88 | #endif
89 |
90 | #if ENABLE_MONO
91 | dict.Add("Scripting backend", "Mono");
92 | #elif ENABLE_IL2CPP
93 | dict.Add("Scripting backend", "IL2CPP");
94 | #elif ENABLE_DOTNET
95 | dict.Add("Scripting backend", ".NET");
96 | #else
97 | dict.Add("Scripting backend", "");
98 | #endif
99 |
100 | #if OPENCV_USE_UNSAFE_CODE
101 | dict.Add("Allow 'unsafe' Code", "Enabled");
102 | #else
103 | dict.Add("Allow 'unsafe' Code", "Disabled");
104 | #endif
105 |
106 | return dict;
107 | }
108 |
109 | public Dictionary GetDeviceInfo()
110 | {
111 | Dictionary dict = new Dictionary();
112 |
113 | #if UNITY_IOS
114 | dict.Add("iOS.Device.generation", UnityEngine.iOS.Device.generation.ToString());
115 | dict.Add("iOS.Device.systemVersion", UnityEngine.iOS.Device.systemVersion.ToString());
116 | #endif
117 | #if UNITY_IOS && UNITY_2018_1_OR_NEWER
118 | dict.Add("UserAuthorization.WebCam", Application.HasUserAuthorization(UserAuthorization.WebCam).ToString());
119 | dict.Add("UserAuthorization.Microphone", Application.HasUserAuthorization(UserAuthorization.Microphone).ToString());
120 | #endif
121 | #if UNITY_ANDROID && UNITY_2018_3_OR_NEWER
122 | dict.Add("Android.Permission.Camera", UnityEngine.Android.Permission.HasUserAuthorizedPermission(UnityEngine.Android.Permission.Camera).ToString());
123 | dict.Add("Android.Permission.CoarseLocation", UnityEngine.Android.Permission.HasUserAuthorizedPermission(UnityEngine.Android.Permission.CoarseLocation).ToString());
124 | dict.Add("Android.Permission.ExternalStorageRead", UnityEngine.Android.Permission.HasUserAuthorizedPermission(UnityEngine.Android.Permission.ExternalStorageRead).ToString());
125 | dict.Add("Android.Permission.ExternalStorageWrite", UnityEngine.Android.Permission.HasUserAuthorizedPermission(UnityEngine.Android.Permission.ExternalStorageWrite).ToString());
126 | dict.Add("Android.Permission.FineLocation", UnityEngine.Android.Permission.HasUserAuthorizedPermission(UnityEngine.Android.Permission.FineLocation).ToString());
127 | dict.Add("Android.Permission.Microphone", UnityEngine.Android.Permission.HasUserAuthorizedPermission(UnityEngine.Android.Permission.Microphone).ToString());
128 | #endif
129 |
130 | return dict;
131 | }
132 |
133 | /// SystemInfo Class Propertys
134 | public SortedDictionary GetSystemInfo()
135 | {
136 | SortedDictionary dict = new SortedDictionary();
137 |
138 | Type type = typeof(SystemInfo);
139 | MemberInfo[] members = type.GetMembers(
140 | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static);
141 |
142 | foreach (MemberInfo mb in members)
143 | {
144 | try
145 | {
146 | if (mb.MemberType == MemberTypes.Property)
147 | {
148 | if (mb.Name == "deviceUniqueIdentifier")
149 | {
150 | dict.Add(mb.Name, "xxxxxxxxxxxxxxxxxxxxxxxx");
151 | continue;
152 | }
153 |
154 | PropertyInfo pr = type.GetProperty(mb.Name);
155 |
156 | if (pr != null)
157 | {
158 | object resobj = pr.GetValue(type, null);
159 | dict.Add(mb.Name, resobj.ToString());
160 | }
161 | else
162 | {
163 | dict.Add(mb.Name, "");
164 | }
165 | }
166 | }
167 | catch (Exception e)
168 | {
169 | Debug.Log("Exception: " + e);
170 | }
171 | }
172 |
173 | return dict;
174 | }
175 |
176 | public void OnBackButtonClick()
177 | {
178 | SceneManager.LoadScene("NatDeviceWithOpenCVForUnityExample");
179 | }
180 | }
181 | }
--------------------------------------------------------------------------------
/Assets/NatDeviceWithOpenCVForUnityExample/ShowSystemInfo.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: ebfaa02d802aac44399fcf98a93f24f0
3 | timeCreated: 1522792936
4 | licenseType: Free
5 | MonoImporter:
6 | serializedVersion: 2
7 | defaultReferences: []
8 | executionOrder: 0
9 | icon: {instanceID: 0}
10 | userData:
11 | assetBundleName:
12 | assetBundleVariant:
13 |
--------------------------------------------------------------------------------
/Assets/NatDeviceWithOpenCVForUnityExample/ShowSystemInfo.unity.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 9ce31c29464a23a4380beca317fc5b01
3 | timeCreated: 1522792936
4 | licenseType: Free
5 | DefaultImporter:
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/Assets/NatDeviceWithOpenCVForUnityExample/WebCamTextureOnlyExample.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 8522a0c763b132a49bbb1568e9f6fcae
3 | folderAsset: yes
4 | timeCreated: 1522155404
5 | licenseType: Free
6 | DefaultImporter:
7 | userData:
8 | assetBundleName:
9 | assetBundleVariant:
10 |
--------------------------------------------------------------------------------
/Assets/NatDeviceWithOpenCVForUnityExample/WebCamTextureOnlyExample/WebCamTextureOnlyExample.cs:
--------------------------------------------------------------------------------
1 | using UnityEngine;
2 |
3 | namespace NatDeviceWithOpenCVForUnityExample
4 | {
5 |
6 | ///
7 | /// WebCamTexture Only Example
8 | /// An example of displaying the preview frame of camera only using WebCamTexture API.
9 | ///
10 | public class WebCamTextureOnlyExample : ExampleBase
11 | {
12 |
13 | Texture2D texture;
14 | byte[] pixelBuffer;
15 |
16 | FpsMonitor fpsMonitor;
17 |
18 | #region --ExampleBase--
19 |
20 | protected override async void Start()
21 | {
22 | base.Start();
23 |
24 | fpsMonitor = GetComponent();
25 | if (fpsMonitor != null)
26 | {
27 | fpsMonitor.Add("Name", "WebCamTextureOnlyExample");
28 | fpsMonitor.Add("onFrameFPS", onFrameFPS.ToString("F1"));
29 | fpsMonitor.Add("drawFPS", drawFPS.ToString("F1"));
30 | fpsMonitor.Add("width", "");
31 | fpsMonitor.Add("height", "");
32 | fpsMonitor.Add("isFrontFacing", "");
33 | fpsMonitor.Add("orientation", "");
34 | }
35 |
36 | // Load global camera benchmark settings.
37 | int width, height, framerate;
38 | NatDeviceWithOpenCVForUnityExample.CameraConfiguration(out width, out height, out framerate);
39 | // Create camera source
40 | cameraSource = new WebCamSource(width, height, framerate, useFrontCamera);
41 | if (!cameraSource.activeCamera)
42 | cameraSource = new WebCamSource(width, height, framerate, !useFrontCamera);
43 | await cameraSource.StartRunning(OnStart, OnFrame);
44 | }
45 |
46 | protected override void OnStart()
47 | {
48 | base.OnStart();
49 |
50 | // Create pixel buffer
51 | pixelBuffer = new byte[cameraSource.width * cameraSource.height * 4];
52 | // Create texture
53 | if (texture != null)
54 | Texture2D.Destroy(texture);
55 | texture = new Texture2D(
56 | cameraSource.width,
57 | cameraSource.height,
58 | TextureFormat.RGBA32,
59 | false,
60 | false
61 | );
62 | // Display texture
63 | rawImage.texture = texture;
64 | aspectFitter.aspectRatio = cameraSource.width / (float)cameraSource.height;
65 | Debug.Log("WebCam camera source started with resolution: " + cameraSource.width + "x" + cameraSource.height + " isFrontFacing: " + cameraSource.isFrontFacing);
66 |
67 | if (fpsMonitor != null)
68 | {
69 | fpsMonitor.Add("width", cameraSource.width.ToString());
70 | fpsMonitor.Add("height", cameraSource.height.ToString());
71 | fpsMonitor.Add("isFrontFacing", cameraSource.isFrontFacing.ToString());
72 | fpsMonitor.Add("orientation", Screen.orientation.ToString());
73 | }
74 | }
75 |
76 | protected override void Update()
77 | {
78 | base.Update();
79 |
80 | if (updateCount == 0)
81 | {
82 | if (fpsMonitor != null)
83 | {
84 | fpsMonitor.Add("onFrameFPS", onFrameFPS.ToString("F1"));
85 | fpsMonitor.Add("drawFPS", drawFPS.ToString("F1"));
86 | fpsMonitor.Add("orientation", Screen.orientation.ToString());
87 | }
88 | }
89 | }
90 |
91 | protected override void UpdateTexture()
92 | {
93 | cameraSource.CaptureFrame(pixelBuffer);
94 | ProcessImage(pixelBuffer, texture.width, texture.height, imageProcessingType);
95 | texture.LoadRawTextureData(pixelBuffer);
96 | texture.Apply();
97 | }
98 |
99 | protected override void OnDestroy()
100 | {
101 | base.OnDestroy();
102 |
103 | Texture2D.Destroy(texture);
104 | texture = null;
105 | pixelBuffer = null;
106 | }
107 |
108 | #endregion
109 |
110 | }
111 | }
--------------------------------------------------------------------------------
/Assets/NatDeviceWithOpenCVForUnityExample/WebCamTextureOnlyExample/WebCamTextureOnlyExample.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 39f2790264240404281d4d8069864b53
3 | MonoImporter:
4 | serializedVersion: 2
5 | defaultReferences: []
6 | executionOrder: 0
7 | icon: {instanceID: 0}
8 | userData:
9 | assetBundleName:
10 | assetBundleVariant:
11 |
--------------------------------------------------------------------------------
/Assets/NatDeviceWithOpenCVForUnityExample/WebCamTextureOnlyExample/WebCamTextureOnlyExample.unity.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 247e68aaae4c3a4478a32b7849213734
3 | DefaultImporter:
4 | userData:
5 | assetBundleName:
6 | assetBundleVariant:
7 |
--------------------------------------------------------------------------------
/Assets/NatDeviceWithOpenCVForUnityExample/WebCamTextureToMatExample.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: fb415b3de5b7e55478861734060ef255
3 | folderAsset: yes
4 | timeCreated: 1522155404
5 | licenseType: Free
6 | DefaultImporter:
7 | userData:
8 | assetBundleName:
9 | assetBundleVariant:
10 |
--------------------------------------------------------------------------------
/Assets/NatDeviceWithOpenCVForUnityExample/WebCamTextureToMatExample/WebCamTextureToMatExample.cs:
--------------------------------------------------------------------------------
1 | using OpenCVForUnity.CoreModule;
2 | using OpenCVForUnity.UnityUtils;
3 | using UnityEngine;
4 |
5 | namespace NatDeviceWithOpenCVForUnityExample
6 | {
7 |
8 | ///
9 | /// WebCamTexture To Mat Example
10 | /// An example of converting a WebCamTexture image to OpenCV's Mat format.
11 | ///
12 | public class WebCamTextureToMatExample : ExampleBase
13 | {
14 |
15 | Mat frameMatrix, grayMatrix;
16 | Texture2D texture;
17 |
18 | FpsMonitor fpsMonitor;
19 |
20 | #region --ExampleBase--
21 |
22 | protected override async void Start()
23 | {
24 | base.Start();
25 |
26 | fpsMonitor = GetComponent();
27 | if (fpsMonitor != null)
28 | {
29 | fpsMonitor.Add("Name", "WebCamTextureToMatExample");
30 | fpsMonitor.Add("onFrameFPS", onFrameFPS.ToString("F1"));
31 | fpsMonitor.Add("drawFPS", drawFPS.ToString("F1"));
32 | fpsMonitor.Add("width", "");
33 | fpsMonitor.Add("height", "");
34 | fpsMonitor.Add("isFrontFacing", "");
35 | fpsMonitor.Add("orientation", "");
36 | }
37 |
38 | // Load global camera benchmark settings.
39 | int width, height, framerate;
40 | NatDeviceWithOpenCVForUnityExample.CameraConfiguration(out width, out height, out framerate);
41 | // Create camera source
42 | cameraSource = new WebCamMatSource(width, height, framerate, useFrontCamera);
43 | if (!cameraSource.activeCamera)
44 | cameraSource = new WebCamMatSource(width, height, framerate, !useFrontCamera);
45 | await cameraSource.StartRunning(OnStart, OnFrame);
46 | }
47 |
48 | protected override void OnStart()
49 | {
50 | base.OnStart();
51 |
52 | // Create matrices
53 | if (frameMatrix != null)
54 | frameMatrix.Dispose();
55 | frameMatrix = new Mat(cameraSource.height, cameraSource.width, CvType.CV_8UC4);
56 | if (grayMatrix != null)
57 | grayMatrix.Dispose();
58 | grayMatrix = new Mat(cameraSource.height, cameraSource.width, CvType.CV_8UC1);
59 | // Create texture
60 | if (texture != null)
61 | Texture2D.Destroy(texture);
62 | texture = new Texture2D(
63 | cameraSource.width,
64 | cameraSource.height,
65 | TextureFormat.RGBA32,
66 | false,
67 | false
68 | );
69 | // Display texture
70 | rawImage.texture = texture;
71 | aspectFitter.aspectRatio = cameraSource.width / (float)cameraSource.height;
72 | Debug.Log("WebCam camera source started with resolution: " + cameraSource.width + "x" + cameraSource.height + " isFrontFacing: " + cameraSource.isFrontFacing);
73 |
74 | if (fpsMonitor != null)
75 | {
76 | fpsMonitor.Add("width", cameraSource.width.ToString());
77 | fpsMonitor.Add("height", cameraSource.height.ToString());
78 | fpsMonitor.Add("isFrontFacing", cameraSource.isFrontFacing.ToString());
79 | fpsMonitor.Add("orientation", Screen.orientation.ToString());
80 | }
81 | }
82 |
83 | protected override void Update()
84 | {
85 | base.Update();
86 |
87 | if (updateCount == 0)
88 | {
89 | if (fpsMonitor != null)
90 | {
91 | fpsMonitor.Add("onFrameFPS", onFrameFPS.ToString("F1"));
92 | fpsMonitor.Add("drawFPS", drawFPS.ToString("F1"));
93 | fpsMonitor.Add("orientation", Screen.orientation.ToString());
94 | }
95 | }
96 | }
97 |
98 | protected override void UpdateTexture()
99 | {
100 | cameraSource.CaptureFrame(frameMatrix);
101 | ProcessImage(frameMatrix, grayMatrix, imageProcessingType);
102 | // Convert to Texture2D
103 | Utils.fastMatToTexture2D(frameMatrix, texture);
104 | }
105 |
106 | protected override void OnDestroy()
107 | {
108 | base.OnDestroy();
109 |
110 | grayMatrix.Dispose();
111 | frameMatrix.Dispose();
112 | Texture2D.Destroy(texture);
113 | texture = null;
114 | grayMatrix =
115 | frameMatrix = null;
116 | }
117 |
118 | #endregion
119 |
120 | }
121 | }
--------------------------------------------------------------------------------
/Assets/NatDeviceWithOpenCVForUnityExample/WebCamTextureToMatExample/WebCamTextureToMatExample.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: f2163b2acf1d92b4591f93c90a5e82f2
3 | MonoImporter:
4 | serializedVersion: 2
5 | defaultReferences: []
6 | executionOrder: 0
7 | icon: {instanceID: 0}
8 | userData:
9 | assetBundleName:
10 | assetBundleVariant:
11 |
--------------------------------------------------------------------------------
/Assets/NatDeviceWithOpenCVForUnityExample/WebCamTextureToMatExample/WebCamTextureToMatExample.unity.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: b90a2bbbb939a5a45aab414e3f5a7a56
3 | DefaultImporter:
4 | userData:
5 | assetBundleName:
6 | assetBundleVariant:
7 |
--------------------------------------------------------------------------------
/Assets/NatDeviceWithOpenCVForUnityExample/link.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/Assets/NatDeviceWithOpenCVForUnityExample/link.xml.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: d11dbcae93faacf48a73bef9bee50163
3 | TextScriptImporter:
4 | externalObjects: {}
5 | userData:
6 | assetBundleName:
7 | assetBundleVariant:
8 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # This example project has been deprecated.
2 | **The “NatDevice” and “NatShare” assets that the integration example depends on have been deprecated in the Unity Asset Store. These features appear to have been merged and evolved into a new asset called VideoKit (https://www.videokit.ai/).**
3 |
4 | ---
5 |
6 | # NatDevice With OpenCVForUnity Example
7 | - An example of a benchmark test integrating NatDevice and OpenCVForUnity. (Comparison between WebCamTexture and NatDevice API)
8 | - An example of replacing WebCamTextureToMatHelper with NatDeviceCamPreviewToMatHelper.
9 | - An example of native sharing and save to the camera roll using NatShare API.
10 |
11 |
12 | ## Environment
13 | - Anddroid (Pixel 3a) / iOS (iPhoneSE2)
14 | - Unity >= 2020.3.31f1+
15 | - Scripting backend MONO / IL2CPP
16 | - [NatDevice - Media Device API](https://assetstore.unity.com/packages/tools/integration/natdevice-media-device-api-162053?aid=1011l4ehR) 1.2.0+
17 | - [NatShare - Mobile Sharing API](https://github.com/natsuite/NatShare) 1.2.6+
18 | - [OpenCV for Unity](https://assetstore.unity.com/packages/tools/integration/opencv-for-unity-21088?aid=1011l4ehR) 2.4.7+
19 |
20 |
21 | ## Demo
22 | - Android [NatDeviceWithOpenCVForUnityExample.apk](https://github.com/EnoxSoftware/NatDeviceWithOpenCVForUnityExample/releases)
23 |
24 |
25 | ## Setup
26 | 1. Download the latest release unitypackage. [NatDeviceWithOpenCVForUnityExample.unitypackage](https://github.com/EnoxSoftware/NatDeviceWithOpenCVForUnityExample/releases)
27 | 1. Create a new project. (NatDeviceWithOpenCVForUnityExample)
28 | * Enable "Allow 'unsafe' Code" option in the "Player Settings > Other Settings" Inspector.
29 | 1. Import NatDevice.
30 | 1. Import NatShare.
31 | 1. Import OpenCVForUnity.
32 | * Setup the OpenCVForUnity. (Tools > OpenCV for Unity > Set Plugin Import Settings)
33 | * Select MenuItem[Tools/OpenCV for Unity/Use Unsafe Code].
34 | 
35 | 
36 | 1. Import the NatDeviceWithOpenCVForUnityExample.unitypackage.
37 | 1. Change the "Minimum API Level" to 24 or higher in the "Player Settings (Androd)" Inspector.
38 | 1. Change the "Target minimum iOS Version" to 13 or higher in the "Player Settings (iOS)" Inspector.
39 | * Set the reason for accessing the camera in "cameraUsageDescription".
40 | 1. Add the "Assets/NatDeviceWithOpenCVForUnityExample/*.unity" files to the "Scenes In Build" list in the "Build Settings" window.
41 | 1. Build and Deploy to Android and iOS.
42 |
43 |
44 | ## Android Instructions
45 | Build requires Android SDK Platform 29 or higher.
46 |
47 |
48 | ## iOS Instructions
49 | After building an Xcode project from Unity, add the following keys to the `Info.plist` file with a good description:
50 | - `NSPhotoLibraryUsageDescription`
51 | - `NSPhotoLibraryAddUsageDescription`
52 |
53 |
54 | ## ScreenShot
55 | 
56 | 
57 | 
58 |
--------------------------------------------------------------------------------
/Use_UnsafeCode.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EnoxSoftware/NatDeviceWithOpenCVForUnityExample/4bf5536abc1a2088686e63e375128af84d8454d9/Use_UnsafeCode.png
--------------------------------------------------------------------------------
/screenshot01.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EnoxSoftware/NatDeviceWithOpenCVForUnityExample/4bf5536abc1a2088686e63e375128af84d8454d9/screenshot01.jpg
--------------------------------------------------------------------------------
/screenshot02.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EnoxSoftware/NatDeviceWithOpenCVForUnityExample/4bf5536abc1a2088686e63e375128af84d8454d9/screenshot02.jpg
--------------------------------------------------------------------------------
/screenshot03.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EnoxSoftware/NatDeviceWithOpenCVForUnityExample/4bf5536abc1a2088686e63e375128af84d8454d9/screenshot03.jpg
--------------------------------------------------------------------------------