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