Browse Source

Allow choosing camera on Xamarin form using Android Camera2 API

pull/768/merge
Canming Huang 1 year ago
parent
commit
054e5da405
  1. 38
      Emgu.CV.Example/XamarinForms/Core/Android/AndroidCameraManager.cs
  2. 4
      Emgu.CV.Example/XamarinForms/Core/Android/AndroidCameraPage.cs
  3. 6
      Emgu.CV.Example/XamarinForms/Core/Android/OnYuvImageAvailableListener.cs
  4. 29
      Emgu.CV.Example/XamarinForms/Core/ButtonTextImagePage.cs
  5. 54
      Emgu.CV.Example/XamarinForms/Core/ProcessAndRenderPage.cs

38
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<Mat> 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
/// <summary>
/// ID of the current {@link CameraDevice}.
/// </summary>
string _cameraId;
private string _cameraId;
/// <summary>
/// Get the ID of the current {@link CameraDevice}.
/// </summary>
public String CurrentCameraId
{
get
{
return _cameraId;
}
}
/// <summary>
/// Return true if the given array contains the given integer.

4
Emgu.CV.Example/XamarinForms/Core/Android/AndroidCameraPage.cs

@ -38,7 +38,7 @@ namespace Emgu.CV.XamarinForms
}
public void StartCapture(EventHandler<Mat> matHandler, int preferredPreviewImageSize = -1)
public void StartCapture(EventHandler<Mat> 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();
}

6
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

29
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<Mat[]> 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<Mat>();
#if __ANDROID__ && __USE_ANDROID_CAMERA2__
String cameraIdCandidate = action.Replace("Camera ", "");
if (AndroidCameraManager.GetAvailableCameraIds().Contains(cameraIdCandidate))
{
_preferredCameraId = cameraIdCandidate;
}
else
{
_preferredCameraId = null;
}
#endif
}
}

54
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

Loading…
Cancel
Save