1
+ // Make sure to uncomment '#define OPENCV_API' in NatCam (Assets>NatCam>Pro>Plugins>Managed>NatCam.cs) and in OpenCVBehaviour
2
+ //#define OPENCV_API // Uncomment this to run this example properly
3
+
4
+ using UnityEngine ;
5
+ using NatCamU . Core ;
6
+ using NatCamU . Pro ;
7
+ using System . Collections . Generic ;
8
+ using System ;
9
+ using UnityEngine . UI ;
10
+ using System . Runtime . InteropServices ;
11
+
12
+ #if UNITY_5_3 || UNITY_5_3_OR_NEWER
13
+ using UnityEngine . SceneManagement ;
14
+ #endif
15
+
16
+ namespace NatCamWithOpenCVForUnityExample
17
+ {
18
+ /// <summary>
19
+ /// NatCamPreview Only Example
20
+ /// An example of displaying the preview frame of camera only using NatCam.
21
+ /// </summary>
22
+ public class NatCamPreviewOnlyExample : NatCamBehaviour
23
+ {
24
+ public enum ImageProcessingType
25
+ {
26
+ None ,
27
+ DrawLine ,
28
+ ConvertToGray ,
29
+ }
30
+
31
+ [ Header ( "ImageProcessing" ) ]
32
+ public ImageProcessingType imageProcessingType = ImageProcessingType . None ;
33
+ public Dropdown imageProcessingTypeDropdown ;
34
+
35
+ [ Header ( "Preview" ) ]
36
+ public int requestedFPS = 30 ;
37
+ public AspectRatioFitter aspectFitter ;
38
+
39
+ bool didUpdateThisFrame = false ;
40
+ private Texture2D texture ;
41
+ private byte [ ] buffer ;
42
+ const TextureFormat textureFormat =
43
+ #if UNITY_IOS && ! UNITY_EDITOR
44
+ TextureFormat . BGRA32 ;
45
+ #else
46
+ TextureFormat . RGBA32 ;
47
+ #endif
48
+
49
+ int updateCount = 0 ;
50
+ int onFrameCount = 0 ;
51
+ int drawCount = 0 ;
52
+
53
+ float elapsed = 0 ;
54
+ float updateFPS = 0 ;
55
+ float onFrameFPS = 0 ;
56
+ float drawFPS = 0 ;
57
+
58
+ FpsMonitor fpsMonitor ;
59
+
60
+ public override void Start ( )
61
+ {
62
+ base . Start ( ) ;
63
+
64
+ NatCam . Camera . SetFramerate ( requestedFPS ) ;
65
+
66
+ fpsMonitor = GetComponent < FpsMonitor > ( ) ;
67
+ if ( fpsMonitor != null ) {
68
+ fpsMonitor . Add ( "Name" , "NatCamPreviewOnlyExample" ) ;
69
+ fpsMonitor . Add ( "onFrameFPS" , onFrameFPS . ToString ( "F1" ) ) ;
70
+ fpsMonitor . Add ( "drawFPS" , drawFPS . ToString ( "F1" ) ) ;
71
+ fpsMonitor . Add ( "width" , "" ) ;
72
+ fpsMonitor . Add ( "height" , "" ) ;
73
+ fpsMonitor . Add ( "orientation" , "" ) ;
74
+ }
75
+
76
+ imageProcessingTypeDropdown . value = ( int ) imageProcessingType ;
77
+ }
78
+
79
+ public override void OnStart ( ) {
80
+
81
+ base . OnStart ( ) ;
82
+
83
+ // Scale the panel to match aspect ratios
84
+ aspectFitter . aspectRatio = NatCam . Preview . width / ( float ) NatCam . Preview . height ;
85
+
86
+ Debug . Log ( "# Active Camera Properties #####################" ) ;
87
+
88
+ try
89
+ {
90
+ Dictionary < string , string > cameraProps = new Dictionary < string , string > ( ) ;
91
+
92
+ cameraProps . Add ( "IsFrontFacing" , NatCam . Camera . IsFrontFacing . ToString ( ) ) ;
93
+
94
+ cameraProps . Add ( "Framerate" , NatCam . Camera . Framerate . ToString ( ) ) ;
95
+
96
+ cameraProps . Add ( "PreviewResolution" , NatCam . Camera . PreviewResolution . width + "x" + NatCam . Camera . PreviewResolution . height ) ;
97
+ cameraProps . Add ( "PhotoResolution" , NatCam . Camera . PhotoResolution . width + "x" + NatCam . Camera . PhotoResolution . height ) ;
98
+
99
+ cameraProps . Add ( "ExposureMode" , NatCam . Camera . ExposureMode . ToString ( ) ) ;
100
+ cameraProps . Add ( "ExposureBias" , NatCam . Camera . ExposureBias . ToString ( ) ) ;
101
+ cameraProps . Add ( "MinExposureBias" , NatCam . Camera . MinExposureBias . ToString ( ) ) ;
102
+ cameraProps . Add ( "MaxExposureBias" , NatCam . Camera . MaxExposureBias . ToString ( ) ) ;
103
+
104
+ cameraProps . Add ( "IsFlashSupported" , NatCam . Camera . IsFlashSupported . ToString ( ) ) ;
105
+ cameraProps . Add ( "FlashMode" , NatCam . Camera . FlashMode . ToString ( ) ) ;
106
+
107
+ cameraProps . Add ( "FocusMode" , NatCam . Camera . FocusMode . ToString ( ) ) ;
108
+
109
+ cameraProps . Add ( "HorizontalFOV" , NatCam . Camera . HorizontalFOV . ToString ( ) ) ;
110
+ cameraProps . Add ( "VerticalFOV" , NatCam . Camera . VerticalFOV . ToString ( ) ) ;
111
+
112
+ cameraProps . Add ( "IsTorchSupported" , NatCam . Camera . IsTorchSupported . ToString ( ) ) ;
113
+ cameraProps . Add ( "TorchEnabled" , NatCam . Camera . TorchEnabled . ToString ( ) ) ;
114
+
115
+ cameraProps . Add ( "MaxZoomRatio" , NatCam . Camera . MaxZoomRatio . ToString ( ) ) ;
116
+ cameraProps . Add ( "ZoomRatio" , NatCam . Camera . ZoomRatio . ToString ( ) ) ;
117
+
118
+ foreach ( string key in cameraProps . Keys )
119
+ {
120
+ Debug . Log ( key + ": " + cameraProps [ key ] ) ;
121
+ }
122
+
123
+ if ( fpsMonitor != null && verbose ) {
124
+ fpsMonitor . boxWidth = 200 ;
125
+ fpsMonitor . boxHeight = 620 ;
126
+ fpsMonitor . LocateGUI ( ) ;
127
+
128
+ foreach ( string key in cameraProps . Keys )
129
+ {
130
+ fpsMonitor . Add ( key , cameraProps [ key ] ) ;
131
+ }
132
+ }
133
+ }
134
+ catch ( Exception e )
135
+ {
136
+ Debug . Log ( "Exception: " + e ) ;
137
+ if ( fpsMonitor != null && verbose ) {
138
+ fpsMonitor . consoleText = "Exception: " + e ;
139
+ }
140
+ }
141
+ Debug . Log ( "#######################################" ) ;
142
+
143
+
144
+ Debug . Log ( "OnStart (): " + NatCam . Preview . width + " " + NatCam . Preview . height ) ;
145
+ }
146
+
147
+ public override void OnFrame ( ) {
148
+
149
+ onFrameCount ++ ;
150
+
151
+ if ( imageProcessingType == ImageProcessingType . None ) {
152
+ didUpdateThisFrame = true ;
153
+ preview . texture = NatCam . Preview ;
154
+ } else {
155
+ // Declare buffer properties
156
+ IntPtr handle ;
157
+ int width , height , size ;
158
+ // Read the preview buffer
159
+ if ( ! NatCam . PreviewBuffer ( out handle , out width , out height , out size ) )
160
+ return ;
161
+
162
+ didUpdateThisFrame = true ;
163
+
164
+ // Size checking
165
+ if ( buffer != null && buffer . Length != size ) {
166
+ buffer = null ;
167
+ }
168
+ // Create the managed buffer
169
+ buffer = buffer ?? new byte [ size ] ;
170
+
171
+ // Copy the pixel data from the native buffer into our managed bufffer
172
+ // This is faster than accessing each byte using Marshal.ReadByte
173
+ Marshal . Copy ( handle , buffer , 0 , size ) ;
174
+
175
+ // Size checking
176
+ if ( texture && ( texture . width != width || texture . height != height ) ) {
177
+ Texture2D . Destroy ( texture ) ;
178
+ texture = null ;
179
+ }
180
+ // Create the texture
181
+ texture = texture ?? new Texture2D ( width , height , textureFormat , false , false ) ;
182
+ }
183
+ }
184
+
185
+ void Update ( ) {
186
+
187
+ updateCount ++ ;
188
+ elapsed += Time . deltaTime ;
189
+ if ( elapsed >= 1f ) {
190
+ updateFPS = updateCount / elapsed ;
191
+ onFrameFPS = onFrameCount / elapsed ;
192
+ drawFPS = drawCount / elapsed ;
193
+ updateCount = 0 ;
194
+ onFrameCount = 0 ;
195
+ drawCount = 0 ;
196
+ elapsed = 0 ;
197
+
198
+ Debug . Log ( "didUpdateThisFrame: " + didUpdateThisFrame + " updateFPS: " + updateFPS + " onFrameFPS: " + onFrameFPS + " drawFPS: " + drawFPS ) ;
199
+ if ( fpsMonitor != null ) {
200
+ fpsMonitor . Add ( "onFrameFPS" , onFrameFPS . ToString ( "F1" ) ) ;
201
+ fpsMonitor . Add ( "drawFPS" , drawFPS . ToString ( "F1" ) ) ;
202
+
203
+ if ( NatCam . Preview != null ) {
204
+ fpsMonitor . Add ( "width" , NatCam . Preview . width . ToString ( ) ) ;
205
+ fpsMonitor . Add ( "height" , NatCam . Preview . height . ToString ( ) ) ;
206
+ }
207
+ fpsMonitor . Add ( "orientation" , Screen . orientation . ToString ( ) ) ;
208
+ }
209
+ }
210
+
211
+ if ( NatCam . IsPlaying && didUpdateThisFrame ) {
212
+ drawCount ++ ;
213
+
214
+ if ( imageProcessingType == ImageProcessingType . None ) {
215
+
216
+ } else {
217
+
218
+ if ( texture . width * texture . height * 4 != buffer . Length )
219
+ return ;
220
+
221
+ // Process
222
+ ProcessImage ( buffer , texture . width , texture . height , buffer . Length , imageProcessingType ) ;
223
+
224
+ // Load texture data
225
+ texture . LoadRawTextureData ( buffer ) ;
226
+ // Upload to GPU
227
+ texture . Apply ( ) ;
228
+ // Set RawImage texture
229
+ preview . texture = texture ;
230
+ }
231
+ }
232
+ }
233
+
234
+ void LateUpdate ( )
235
+ {
236
+ didUpdateThisFrame = false ;
237
+ }
238
+
239
+ private void ProcessImage ( Byte [ ] buffer , int width , int height , int size , ImageProcessingType imageProcessingType = ImageProcessingType . None )
240
+ {
241
+ switch ( imageProcessingType ) {
242
+ case ImageProcessingType . DrawLine :
243
+ // Draw a diagonal line on our image
244
+ float inclination = height / ( float ) width ;
245
+ for ( int i = 0 ; i < 4 ; i ++ ) {
246
+ for ( int x = 0 ; x < width ; x ++ ) {
247
+ int y = ( int ) ( - inclination * x ) + height - 2 + i ;
248
+ if ( y < 0 )
249
+ y = 0 ;
250
+ if ( y > height - 1 )
251
+ y = height - 1 ;
252
+ int p = ( x * 4 ) + ( y * width * 4 ) ;
253
+ // Set pixels in the buffer
254
+ #if UNITY_IOS && ! UNITY_EDITOR
255
+ buffer [ p ] = 0 ; buffer [ p + 1 ] = 0 ; buffer [ p + 2 ] = 255 ; buffer [ p + 3 ] = 255 ;
256
+ #else
257
+ buffer [ p ] = 255 ; buffer [ p + 1 ] = 0 ; buffer [ p + 2 ] = 0 ; buffer [ p + 3 ] = 255 ;
258
+ #endif
259
+ }
260
+ }
261
+
262
+ break ;
263
+ case ImageProcessingType . ConvertToGray :
264
+ // Convert a four-channel pixel buffer to greyscale
265
+ // Iterate over the buffer
266
+ for ( int i = 0 ; i < size ; i += 4 ) {
267
+ // Get channel intensities
268
+ byte
269
+ r = buffer [ i + 0 ] , g = buffer [ i + 1 ] ,
270
+ b = buffer [ i + 2 ] , a = buffer [ i + 3 ] ,
271
+ // Use quick luminance approximation to save time and memory
272
+ l = ( byte ) ( ( r + r + r + b + g + g + g + g ) >> 3 ) ;
273
+ // Set pixels in the buffer
274
+ buffer [ i ] = buffer [ i + 1 ] = buffer [ i + 2 ] = l ; buffer [ i + 3 ] = a ;
275
+ }
276
+
277
+ break ;
278
+ }
279
+ }
280
+
281
+ /// <summary>
282
+ /// Releases all resource.
283
+ /// </summary>
284
+ private void Dispose ( )
285
+ {
286
+ NatCam . Release ( ) ;
287
+
288
+ if ( texture != null ) {
289
+ Texture2D . Destroy ( texture ) ;
290
+ texture = null ;
291
+ }
292
+
293
+ didUpdateThisFrame = false ;
294
+ }
295
+
296
+ /// <summary>
297
+ /// Raises the destroy event.
298
+ /// </summary>
299
+ void OnDestroy ( )
300
+ {
301
+ Dispose ( ) ;
302
+ }
303
+
304
+ /// <summary>
305
+ /// Raises the back button click event.
306
+ /// </summary>
307
+ public void OnBackButtonClick ( )
308
+ {
309
+ #if UNITY_5_3 || UNITY_5_3_OR_NEWER
310
+ SceneManager . LoadScene ( "NatCamWithOpenCVForUnityExample" ) ;
311
+ #else
312
+ Application . LoadLevel ( "NatCamWithOpenCVForUnityExample" ) ;
313
+ #endif
314
+ }
315
+
316
+ /// <summary>
317
+ /// Raises the play button click event.
318
+ /// </summary>
319
+ public void OnPlayButtonClick ( )
320
+ {
321
+ NatCam . Play ( ) ;
322
+ }
323
+
324
+ /// <summary>
325
+ /// Raises the pause button click event.
326
+ /// </summary>
327
+ public void OnPauseButtonClick ( )
328
+ {
329
+ NatCam . Pause ( ) ;
330
+ }
331
+
332
+ /// <summary>
333
+ /// Raises the stop button click event.
334
+ /// </summary>
335
+ public void OnStopButtonClick ( )
336
+ {
337
+ NatCam . Pause ( ) ;
338
+ }
339
+
340
+ /// <summary>
341
+ /// Raises the change camera button click event.
342
+ /// </summary>
343
+ public void OnChangeCameraButtonClick ( )
344
+ {
345
+ SwitchCamera ( ) ;
346
+ }
347
+
348
+ /// <summary>
349
+ /// Raises the image processing type dropdown value changed event.
350
+ /// </summary>
351
+ public void OnImageProcessingTypeDropdownValueChanged ( int result )
352
+ {
353
+ if ( ( int ) imageProcessingType != result ) {
354
+ imageProcessingType = ( ImageProcessingType ) result ;
355
+ }
356
+ }
357
+ }
358
+ }
0 commit comments