diff --git a/Emgu.CV.Example/XamarinForms/Core/Android/AndroidCameraManager.cs b/Emgu.CV.Example/XamarinForms/Core/Android/AndroidCameraManager.cs index ae9dcc39f..f321b876f 100644 --- a/Emgu.CV.Example/XamarinForms/Core/Android/AndroidCameraManager.cs +++ b/Emgu.CV.Example/XamarinForms/Core/Android/AndroidCameraManager.cs @@ -21,6 +21,7 @@ using Android.Runtime; using Android.Util; using Android.Views; using Android.Widget; +using Java.Security; using Paint = Android.Graphics.Paint; using Java.Util.Concurrent; using Xamarin.Forms.Platform.Android; @@ -32,9 +33,16 @@ namespace Emgu.CV.XamarinForms { public class AndroidCameraManager { + public static String[] GetAvailableCameraIds() + { + CameraManager manager = + (CameraManager)Android.App.Application.Context.GetSystemService(Context.CameraService); + return manager.GetCameraIdList(); + } + public EventHandler OnImageCaptured; - public AndroidCameraManager(int? preferredPreviewSize = null) + public AndroidCameraManager(int? preferredPreviewSize = null, String preferedCameraId = null) { if (!SetUpCameraOutputs(preferredPreviewSize)) return; @@ -54,11 +62,26 @@ namespace Emgu.CV.XamarinForms var list = manager.GetCameraIdList(); var cameraId = list[0]; + if (preferedCameraId != null) + { + if (list.Contains(preferedCameraId)) + { + cameraId = preferedCameraId; + } + else + { + throw new InvalidParameterException( + String.Format("Camera ID '{0}' is not one of the available camera ids.", preferedCameraId)); + } + } + backgroundHandler = _backgroundHandler; // Attempt to open the camera. mStateCallback will be called on the background handler's // thread when this succeeds or fails. manager.OpenCamera(cameraId, _stateCallback, backgroundHandler); + + _cameraId = cameraId; } catch (CameraAccessException e) { @@ -133,7 +156,18 @@ namespace Emgu.CV.XamarinForms /// /// ID of the current {@link CameraDevice}. /// - string _cameraId; + private string _cameraId; + + /// + /// Get the ID of the current {@link CameraDevice}. + /// + public String CurrentCameraId + { + get + { + return _cameraId; + } + } /// /// Return true if the given array contains the given integer. diff --git a/Emgu.CV.Example/XamarinForms/Core/Android/AndroidCameraPage.cs b/Emgu.CV.Example/XamarinForms/Core/Android/AndroidCameraPage.cs index 26100b1ca..9349fe3a2 100644 --- a/Emgu.CV.Example/XamarinForms/Core/Android/AndroidCameraPage.cs +++ b/Emgu.CV.Example/XamarinForms/Core/Android/AndroidCameraPage.cs @@ -38,7 +38,7 @@ namespace Emgu.CV.XamarinForms } - public void StartCapture(EventHandler matHandler, int preferredPreviewImageSize = -1) + public void StartCapture(EventHandler matHandler, int preferredPreviewImageSize = -1, String preferedCameraId = null) { if (_cameraManager == null) { @@ -49,7 +49,7 @@ namespace Emgu.CV.XamarinForms preferredPreviewImageSize = Math.Max(preferredPreviewImageSize, 480 * 600); } - _cameraManager = new AndroidCameraManager( preferredPreviewImageSize ); + _cameraManager = new AndroidCameraManager( preferredPreviewImageSize, preferedCameraId ); _cameraManager.OnImageCaptured += matHandler; _cameraManager.StartBackgroundThread(); } diff --git a/Emgu.CV.Example/XamarinForms/Core/Android/OnYuvImageAvailableListener.cs b/Emgu.CV.Example/XamarinForms/Core/Android/OnYuvImageAvailableListener.cs index b4f5078ea..b73b67699 100644 --- a/Emgu.CV.Example/XamarinForms/Core/Android/OnYuvImageAvailableListener.cs +++ b/Emgu.CV.Example/XamarinForms/Core/Android/OnYuvImageAvailableListener.cs @@ -45,10 +45,10 @@ namespace Emgu.CV.XamarinForms using (GMat inYuvMat = new GMat()) using (GMat rgbMat = GapiInvoke.I4202BGR(inYuvMat)) //The following two step will rotate the image 90 degrees - using (GMat transposeMat = GapiInvoke.Transpose(rgbMat)) - using (GMat rotatedMat = GapiInvoke.Flip(transposeMat, FlipType.Horizontal)) + using (GMat tMat = GapiInvoke.Transpose(rgbMat)) + using (GMat rMat = GapiInvoke.Flip(tMat, FlipType.Horizontal)) { - _gComputation = new GComputation(inYuvMat, rotatedMat); + _gComputation = new GComputation(inYuvMat, rMat); } } else diff --git a/Emgu.CV.Example/XamarinForms/Core/ButtonTextImagePage.cs b/Emgu.CV.Example/XamarinForms/Core/ButtonTextImagePage.cs index 1d6f054b4..80043f94b 100644 --- a/Emgu.CV.Example/XamarinForms/Core/ButtonTextImagePage.cs +++ b/Emgu.CV.Example/XamarinForms/Core/ButtonTextImagePage.cs @@ -177,6 +177,10 @@ namespace Emgu.CV.XamarinForms public bool HasCameraOption { get; set; } +#if __ANDROID__ && __USE_ANDROID_CAMERA2__ + protected String _preferredCameraId = null; +#endif + public virtual async Task LoadImages(String[] imageNames, String[] labels = null) { Mat[] mats = new Mat[imageNames.Length]; @@ -216,7 +220,16 @@ namespace Emgu.CV.XamarinForms || Device.RuntimePlatform == Device.UWP) { if (captureSupported) + { +#if __ANDROID__ && __USE_ANDROID_CAMERA2__ + foreach (String cameraId in AndroidCameraManager.GetAvailableCameraIds()) + { + options.Add(String.Format("Camera {0}", cameraId)); + } +#else options.Add("Camera"); +#endif + } } else if (Device.RuntimePlatform == Device.WPF || Device.RuntimePlatform == Device.macOS) @@ -224,7 +237,9 @@ namespace Emgu.CV.XamarinForms var openCVConfigDict = CvInvoke.ConfigDict; bool haveVideoio = (openCVConfigDict["HAVE_OPENCV_VIDEOIO"] != 0); if (haveVideoio) + { options.Add("Camera"); + } } } @@ -287,9 +302,21 @@ namespace Emgu.CV.XamarinForms using (Stream stream = await takePhotoResult.OpenReadAsync()) mats[i] = await ReadStream(stream); } - else if (action.Equals("Camera")) + else if (action.StartsWith("Camera")) { mats = Array.Empty(); + +#if __ANDROID__ && __USE_ANDROID_CAMERA2__ + String cameraIdCandidate = action.Replace("Camera ", ""); + if (AndroidCameraManager.GetAvailableCameraIds().Contains(cameraIdCandidate)) + { + _preferredCameraId = cameraIdCandidate; + } + else + { + _preferredCameraId = null; + } +#endif } } diff --git a/Emgu.CV.Example/XamarinForms/Core/ProcessAndRenderPage.cs b/Emgu.CV.Example/XamarinForms/Core/ProcessAndRenderPage.cs index aee7ba655..a32a16045 100644 --- a/Emgu.CV.Example/XamarinForms/Core/ProcessAndRenderPage.cs +++ b/Emgu.CV.Example/XamarinForms/Core/ProcessAndRenderPage.cs @@ -291,36 +291,40 @@ namespace Emgu.CV.XamarinForms { #if __ANDROID__ && __USE_ANDROID_CAMERA2__ - StartCapture(async delegate (Object captureSender, Mat m) - { - //Skip the frame if busy, - //Otherwise too many frames arriving and will eventually saturated the memory. - if (!_isBusy) + StartCapture( + async delegate (Object captureSender, Mat m) { - _isBusy = true; - try + //Skip the frame if busy, + //Otherwise too many frames arriving and will eventually saturated the memory. + if (!_isBusy) { - String message = String.Empty; - await Task.Run(() => + _isBusy = true; + try { - if (_renderMat == null) - _renderMat = new Mat(); - using (InputArray iaImage = m.GetInputArray()) + String message = String.Empty; + await Task.Run(() => { - iaImage.CopyTo(_renderMat); - } - message = _model.ProcessAndRender(m, _renderMat); - }); - SetImage(_renderMat); - SetMessage(message); - - } - finally - { - _isBusy = false; + if (_renderMat == null) + _renderMat = new Mat(); + using (InputArray iaImage = m.GetInputArray()) + { + iaImage.CopyTo(_renderMat); + } + message = _model.ProcessAndRender(m, _renderMat); + }); + SetImage(_renderMat); + SetMessage(message); + + } + finally + { + _isBusy = false; + } } - } - }); + }, + -1, + this._preferredCameraId + ); #elif __IOS__ CheckVideoPermissionAndStart (); #else