Browse Source

Enable AndroidCameraManager to open a preferred camera.

pull/768/merge
Canming Huang 1 year ago
parent
commit
4efc19bbf9
  1. 40
      Emgu.CV.Platform/Maui/UI/ButtonTextImagePage.cs
  2. 41
      Emgu.CV.Platform/Maui/UI/Platforms/Android/AndroidCameraManager.cs
  3. 43
      Emgu.CV.Platform/Maui/UI/Platforms/Android/AndroidCameraPage.cs
  4. 6
      Emgu.CV.Platform/Maui/UI/Platforms/Android/OnYuvImageAvailableListener.cs
  5. 74
      Emgu.CV.Platform/Maui/UI/ProcessAndRenderPage.cs

40
Emgu.CV.Platform/Maui/UI/ButtonTextImagePage.cs

@ -234,6 +234,9 @@ namespace Emgu.CV.Platform.Maui.UI
}
}
/// <summary>
/// Load the images and return them asynchronously
/// </summary>
@ -279,8 +282,30 @@ namespace Emgu.CV.Platform.Maui.UI
if (this.HasCameraOption)
{
if (Microsoft.Maui.Devices.DeviceInfo.Platform == DevicePlatform.Android
|| Microsoft.Maui.Devices.DeviceInfo.Platform == DevicePlatform.iOS)
if (Microsoft.Maui.Devices.DeviceInfo.Platform == DevicePlatform.Android)
{
if (captureSupported)
{
options.Add("Camera");
/*
#if __ANDROID__
if (this.CameraBackend == AndroidCameraBackend.AndroidCamera2)
{
foreach (String cameraId in AndroidCameraManager.GetAvailableCameraIds())
{
options.Add(String.Format("Camera {0}", cameraId));
}
}
else
{
options.Add("Camera");
}
#else
options.Add("Camera");
#endif
*/
}
} else if (Microsoft.Maui.Devices.DeviceInfo.Platform == DevicePlatform.iOS)
{
if (captureSupported)
options.Add("Camera");
@ -368,6 +393,17 @@ namespace Emgu.CV.Platform.Maui.UI
else if (action.Equals("Camera"))
{
mats = new Mat[0];
#if __ANDROID__
String cameraIdCandidate = action.Replace("Camera ", "");
if (AndroidCameraManager.GetAvailableCameraIds().Contains(cameraIdCandidate))
{
_preferredCameraId = cameraIdCandidate;
}
else
{
_preferredCameraId = null;
}
#endif
}
}

41
Emgu.CV.Platform/Maui/UI/Platforms/Android/AndroidCameraManager.cs

@ -23,9 +23,11 @@ using Android.Views;
using Android.Widget;
using Paint = Android.Graphics.Paint;
using Java.Security;
using Java.Util.Concurrent;
using Application = Android.App.Application;
//using Xamarin.Forms.Platform.Android;
using Camera = Android.Hardware.Camera;
using Type = System.Type;
@ -34,9 +36,16 @@ namespace Emgu.CV.Platform.Maui.UI
{
public class AndroidCameraManager
{
public static String[] GetAvailableCameraIds()
{
CameraManager manager =
(CameraManager)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;
@ -56,11 +65,26 @@ namespace Emgu.CV.Platform.Maui.UI
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)
{
@ -135,7 +159,18 @@ namespace Emgu.CV.Platform.Maui.UI
/// <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.

43
Emgu.CV.Platform/Maui/UI/Platforms/Android/AndroidCameraPage.cs

@ -19,7 +19,46 @@ namespace Emgu.CV.Platform.Maui.UI
private EventHandler<Mat> _onImageCapturedHandler = null;
public void StartCapture(EventHandler<Mat> matHandler, int preferredPreviewImageSize = -1)
protected String _preferredCameraId = null;
public enum AndroidCameraBackend
{
AndroidCamera2,
OpenCV
}
private AndroidCameraBackend _androidCameraBackend = AndroidCameraBackend.AndroidCamera2;
//private AndroidCameraBackend _androidCameraBackend = AndroidCameraBackend.OpenCV;
public AndroidCameraBackend CameraBackend
{
get
{
return _androidCameraBackend;
}
set
{
_androidCameraBackend = value;
}
}
private bool _isAndroidCamera2Busy = false;
public bool IsAndroidCamera2Busy
{
get
{
return _isAndroidCamera2Busy;
}
set
{
_isAndroidCamera2Busy = value;
}
}
public void StartCapture(EventHandler<Mat> matHandler, int preferredPreviewImageSize = -1, String preferedCameraId = null)
{
if (_cameraManager == null)
{
@ -30,7 +69,7 @@ namespace Emgu.CV.Platform.Maui.UI
preferredPreviewImageSize = Math.Max(preferredPreviewImageSize, 480 * 600);
}
_cameraManager = new AndroidCameraManager( preferredPreviewImageSize );
_cameraManager = new AndroidCameraManager( preferredPreviewImageSize, preferedCameraId);
_onImageCapturedHandler = matHandler;
_cameraManager.OnImageCaptured += _onImageCapturedHandler;
_cameraManager.StartBackgroundThread();

6
Emgu.CV.Platform/Maui/UI/Platforms/Android/OnYuvImageAvailableListener.cs

@ -41,10 +41,10 @@ namespace Emgu.CV.Platform.Maui.UI
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

74
Emgu.CV.Platform/Maui/UI/ProcessAndRenderPage.cs

@ -60,30 +60,6 @@ namespace Emgu.CV.Platform.Maui.UI
protected String _StopCameraButtonText = "Stop Camera";
private String _deaultImage;
#if __ANDROID__
public enum AndroidCameraBackend
{
AndroidCamera2,
OpenCV
}
private AndroidCameraBackend _androidCameraBackend = AndroidCameraBackend.AndroidCamera2;
//private AndroidCameraBackend _androidCameraBackend = AndroidCameraBackend.OpenCV;
public AndroidCameraBackend CameraBackend
{
get
{
return _androidCameraBackend;
}
set
{
_androidCameraBackend = value;
}
}
private bool _isAndroidCamera2Busy = false;
#endif
/// <summary>
/// Get the model associated with this page
@ -110,7 +86,7 @@ namespace Emgu.CV.Platform.Maui.UI
|| Microsoft.Maui.Devices.DeviceInfo.Platform == DevicePlatform.WinUI))
{
#if __ANDROID__
if (_androidCameraBackend == AndroidCameraBackend.AndroidCamera2)
if (CameraBackend == AndroidCameraBackend.AndroidCamera2)
return true;
#endif
@ -297,7 +273,7 @@ namespace Emgu.CV.Platform.Maui.UI
if (button.Text.Equals(_StopCameraButtonText))
{
#if __ANDROID__
if (_androidCameraBackend == AndroidCameraBackend.AndroidCamera2)
if (CameraBackend == AndroidCameraBackend.AndroidCamera2)
StopCapture();
else
{
@ -374,31 +350,35 @@ namespace Emgu.CV.Platform.Maui.UI
}
}
if (_androidCameraBackend == AndroidCameraBackend.AndroidCamera2)
if (CameraBackend == AndroidCameraBackend.AndroidCamera2)
{
StartCapture(async delegate (Object captureSender, Mat m)
{
//Skip the frame if busy,
//Otherwise too many frames arriving and will eventually saturated the memory.
if (!_isAndroidCamera2Busy)
StartCapture(
async delegate (Object captureSender, Mat m)
{
_isAndroidCamera2Busy = true;
try
{
//This run on the main thread, using the async pattern with the ProcessFrame is required,
//otherwise it will freeze up the main thread/app.
await Task.Run(
() =>
{
ProcessFrame(m);
});
}
finally
//Skip the frame if busy,
//Otherwise too many frames arriving and will eventually saturated the memory.
if (!IsAndroidCamera2Busy)
{
_isAndroidCamera2Busy = false;
IsAndroidCamera2Busy = true;
try
{
//This run on the main thread, using the async pattern with the ProcessFrame is required,
//otherwise it will freeze up the main thread/app.
await Task.Run(
() =>
{
ProcessFrame(m);
});
}
finally
{
IsAndroidCamera2Busy = false;
}
}
}
});
},
-1,
_preferredCameraId
);
} else
{
//Handle video

Loading…
Cancel
Save