Camera preview face detection failed - c#

In my Xamarin.forms android app, I am using IFaceDetectionListener Doc, for detecting faces in custom camera preview. When I try to open my custom camera page I am getting error like this.
Java.Lang.RuntimeException: start face detection failed
My stack traces are
JniEnvironment+InstanceMethods.CallNonvirtualVoidMethod (Java.Interop.JniObjectReference instance, Java.Interop.JniObjectReference type, Java.Interop.JniMethodInfo method, Java.Interop.JniArgumentValue* args)
JniPeerMembers+JniInstanceMethods.InvokeNonvirtualVoidMethod (System.String encodedMember, Java.Interop.IJavaPeerable self, Java.Interop.JniArgumentValue* parameters)
Camera.StartFaceDetection ()
CameraPreviewRenderer+<>c__DisplayClass8_0.<OnElementChanged>b__1 ()
Thread+RunnableImplementor.Run ()
mono.java.lang.RunnableImplementor.run RunnableImplementor.java:30
android.os.Handler.handleCallback Handler.java:883
This error occurs on my OnElementChanged of CameraCustomRender.
CameraCustomRender
public class CameraPreviewRenderer : ViewRenderer<App.Views.Clocking.CustomCamera.CameraPreview, App.Droid.CustomRender.Clocking.CameraPreview>, Camera.IFaceDetectionListener, Camera.IPictureCallback, Camera.IShutterCallback
{
CameraPreview cameraPreview;
String Picture_Name = "";
private CameraFacing camerainfo = CameraFacing.Front;
int DetectedFaceCount = 0;
[get: Android.Runtime.Register("getMaxNumDetectedFaces", "()I", "GetGetMaxNumDetectedFacesHandler", ApiSince = 14)]
public virtual int MaxNumDetectedFaces { get; }
public CameraPreviewRenderer(Context context) : base(context)
{
}
[Obsolete]
protected override void OnElementChanged(ElementChangedEventArgs<Centraverse.Views.Clocking.CustomCamera.CameraPreview> e)
{
try
{
base.OnElementChanged(e);
if (Control == null)
{
try
{
cameraPreview = new CameraPreview(Context);
SetNativeControl(cameraPreview);
}
catch (Exception ex)
{
}
}
if (e.OldElement != null)
{
}
if (e.NewElement != null)
{
try
{
if (Control == null)
{
cameraPreview = new CameraPreview(Context);
SetNativeControl(cameraPreview);
}
Control.Preview = Camera.Open((int)e.NewElement.Camera);
Control.CameraID = 1;
var CameraParaMeters = cameraPreview.camera.GetParameters();
if (CameraParaMeters != null)
{
if (CameraParaMeters.MaxNumDetectedFaces > 0)
{
Device.BeginInvokeOnMainThread(() =>
{
>------------------// Getting crashed at here-------------------------------------<
Control.Preview.SetFaceDetectionListener(this);
Control.Preview.StartFaceDetection();
});
}
}
}
catch (Exception ex)
{
}
}
}
catch(Exception ex)
{
}
}
protected override void Dispose(bool disposing)
{
try
{
if (disposing)
{
Control.Preview.Release();
MessagingCenter.Unsubscribe<Object>(this, "CaptureClick");
MessagingCenter.Unsubscribe<Object>(this, "FlipClick");
}
Device.BeginInvokeOnMainThread(base.Dispose);
}
catch (Exception ex)
{
}
}
[Obsolete]
public void OnFaceDetection(Camera.Face[] faces, Camera camera)
{
try
{
DetectedFaceCount = faces.Length;
}
catch (Exception ex)
{
}
}
private void takepicture()
{
try
{
Control.Preview.TakePicture(this, this, this);
}
catch (Exception ex)
{
}
}
public void OnPictureTaken(byte[] data, Camera camera)
{
try
{
// Managing camera capture
}
catch (Exception ex)
{
}
}
public void OnShutter() { }
}
I am not able to isolate the issue. The app gets crash with error saying "start Face detection failed". Since I am using older camera API , will that cause this issue? Please help me to fix this issue. For the convenience I have the sample project here.sample Project
EDIT
I am able to catch the exception like this
try
{
Control.Preview.SetFaceDetectionListener(this);
Control.Preview.StartFaceDetection();
}
catch (Java.Lang.RuntimeException ex)
{
}

I test your sample,and when i don't use a mode page to open the CameraPage,it will work.
You could try to change which in your MainPage.xaml.cs :
await Navigation.PushModalAsync(new CameraPage());
to
await Navigation.PushAsync(new CameraPage());
like:
private async void Open_Camera(object sender, EventArgs e)
{
try
{
var PhotoRequeststatus = await Permissions.RequestAsync<Permissions.Camera>();
var StorageRequStatus = await Permissions.RequestAsync<Permissions.StorageWrite>();
if (PhotoRequeststatus != Xamarin.Essentials.PermissionStatus.Granted || StorageRequStatus != Xamarin.Essentials.PermissionStatus.Granted)
{
await DisplayAlert("Enable Permission", "Please allow camera permission", "Close");
}
else
{
await Navigation.PushAsync(new CameraPage());
}
}
catch(Exception ex)
{
}
}

Related

Is there a way to make something like a function template using C#?

I have this code here:
private void brandAnalytics_Click(object sender, EventArgs e)
{
try
{
string fileTARGET = System.IO.Path.GetFullPath(openFileDialogTARGET.FileName);
if (fileTARGET == null)
{
MessageBox.Show("Please select a valid document.");
}
else if (driver == null)
{
MessageBox.Show("Please start the Edge Driver.");
}
else
{
doStuff();
}
}
catch (Exception ex)
{
brandAnalytics.BackColor = Color.White;
button3.Text = "Error occured - check message box";
MessageBox.Show(ex.Message);
}
}
This is how I start pretty much every function, using try and catch. How do I save the repeatance, so that if I modify something, it changes in all functions? I can't think of anything, maybe someone has an idea? - is there such a thing as function templates?
I would apply the Template Method pattern here:
https://refactoring.guru/design-patterns/template-method
Basically your class
class Test
{
private void brandAnalytics_Click(object sender, EventArgs e)
{
try
{
string fileTARGET = System.IO.Path.GetFullPath(openFileDialogTARGET.FileName);
if (fileTARGET == null)
{
MessageBox.Show("Please select a valid document.");
}
else if (driver == null)
{
MessageBox.Show("Please start the Edge Driver.");
}
else
{
doStuff();
}
}
catch (Exception ex)
{
brandAnalytics.BackColor = Color.White;
button3.Text = "Error occured - check message box";
MessageBox.Show(ex.Message);
}
}
}
will be split into 2 classes.
An abstract class:
// defines the template
abstract class Template
{
private void brandAnalytics_Click(object sender, EventArgs e)
{
try
{
if (EnsurePreconditions())
{
DoStuff();
}
}
catch (Exception ex)
{
HandleException(ex);
}
}
private abstract bool EnsurePreconditions();
private abstract void DoStuff();
private abstract void HandleException(Exception ex);
}
And a concrete class:
// concrete test based on the template
class TestV2 : Template
{
private override bool EnsurePreconditions()
{
string fileTARGET = System.IO.Path.GetFullPath(openFileDialogTARGET.FileName);
if (fileTARGET == null)
{
MessageBox.Show("Please select a valid document.");
return false;
}
else if (driver == null)
{
MessageBox.Show("Please start the Edge Driver.");
return false;
}
return true;
}
private override void DoStuff()
{
// ommitted
}
private override void HandleException(Exception)
{
brandAnalytics.BackColor = Color.White;
button3.Text = "Error occured - check message box";
MessageBox.Show(ex.Message);
}
}
and you can have as many concrete classes which are based on the template as you wish.
(I did not compile the code so there might be some syntax errors.)

Grabbing GPU Utilization using openhardwaremonitor

I'm trying to get the current utilization of my GPU using openhardwaremonitor
I've used SensorType.Load to get the utilization of the CPU but for the GPU it is instead returning the memory usage. I'm not sure exactly what to do
if (hardware.HardwareType == HardwareType.GpuNvidia)
{
hardware.Update();
foreach (var sensors in hardware.Sensors)
{
if (sensors.SensorType == SensorType.Load)
{
tester.Text = sensors.Name + ": " + sensors.Value.GetValueOrDefault();
int gpuLoadInt = Convert.ToInt32(sensors.Value.GetValueOrDefault());
string gpuLoadString = Convert.ToString(Decimal.Round(gpuLoadInt));
gpuLoadGuage.Value = gpuLoadInt;
gpuLoadLabel.Text = gpuLoadString + "%";
}
}
}
The library is a little tricky but once you know a little about it the rest will come out little by little. I did something like this...
using OpenHardwareMonitor.Hardware; // Don't forget this
public partial class MainWindow : Window, IVisitor // Don't forget to include the interface
{
// we need to call the method every X seconds to get data
readonly System.Windows.Threading.DispatcherTimer dispatcherTimer = new
System.Windows.Threading.DispatcherTimer();
}
public MainWindow()
{
dispatcherTimer.Tick += new EventHandler(dispatcherTimer_Tick);
dispatcherTimer.Interval = new TimeSpan(0, 0, 2); // <= two seconds
}
public void VisitComputer(IComputer computer) => computer.Traverse(this);
public void VisitHardware(IHardware hardware)
{
hardware.Update();
foreach (IHardware subHardware in hardware.SubHardware) subHardware.Accept(this);
}
public void VisitSensor(ISensor sensor) { }
public void VisitParameter(IParameter parameter) { }
private void dispatcherTimer_Tick(object sender, EventArgs e)
{
Thread ThreadGpu = new Thread(() => GetGpuInfo());
ThreadGpu.Start();
}
GetGpuInfo()
{
Computer computer = new Computer();
UpdateVisitor updateVisitor = new UpdateVisitor();
try
{
computer.Open(); // You must initialize what you are going to use
computer.GPUEnabled = true; // You must initialize what you are going to use
computer.Accept(updateVisitor); // You NEED this line to update
if (computer.Hardware.Length > 0)
{
foreach (var item in computer.Hardware)
{
foreach (ISensor gpu in item.Sensors)
{
if (gpu.Name == "GPU Memory" && gpu.Index == 1)
Console.WriteLine("Memory:" + Math.Round((float)gpu.Value) + "Mhz");
if (gpu.SensorType == SensorType.Temperature)
Console.WriteLine("Temperature:" + Math.Round((float)gpu.Value) + "°C");
if (gpu.SensorType == SensorType.Load && gpu.Name == "GPU Core")
Console.WriteLine("GPU Core:" + gpu.Value);
if (gpu.SensorType == SensorType.Clock && gpu.Name == "GPU Core")
Console.WriteLine(gpu.Value + "Mhz");
}
}
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
computer.Close(); // Close resources
}
You must use this OpenHardwareMonitor class as well, otherwise the data is not updated. You can use it in the same namespace or in another classes file
public class UpdateVisitor : IVisitor
{
public void VisitComputer(IComputer computer)
{
try
{
computer.Traverse(this);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
public void VisitHardware(IHardware hardware)
{
try
{
hardware.Update();
foreach (IHardware subHardware in hardware.SubHardware)
subHardware.Accept(this);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
public void VisitSensor(ISensor sensor) { }
public void VisitParameter(IParameter parameter) { }
}
}
I'm still learning C# but hope this help

Aggregating Event Exceptions

I'm following on with a tutorial detailing handling events thrown in multiple subscribers to an event. However when the code is run, the TargetInvocationException catch block isn't catching the exceptions thrown in the method body of the subscribers: throw new Exception("Hello") and throw new Exception("World") respectively.
Instead I get an unhandled exception error in the first listener, predictably at throw new Exception("Hello") in private static void AlarmListener.
What is it that I'm doing incorrectly when attempting to catch the invoked method's exceptions?
class AggregatingExceptions
{
public void Main()
{
//create the alarm
AlarmAndLocation alarm = new AlarmAndLocation();
//subscribe the listeners
alarm.OnAlarmRaised += AlarmListener;
alarm.OnAlarmRaised += AlarmListener2;
try
{
alarm.RaiseAlarm("Kitchen");
}
catch (AggregateException agg)
{
foreach (Exception ex in agg.InnerExceptions)
{
Console.WriteLine(ex.Message);
}
}
}
private static void AlarmListener(object sender, AlarmEventArgs e)
{
Console.WriteLine("Alarm listener 1 called.");
throw new Exception("Hello");
}
private static void AlarmListener2(object sender, AlarmEventArgs e)
{
Console.WriteLine("Alarm listener 2 called.");
throw new Exception("World");
}
}
public class AlarmAndLocation
{
public event EventHandler<AlarmEventArgs> OnAlarmRaised = delegate { };
public List<Exception> exceptionList = new List<Exception>();
public void RaiseAlarm(string location)
{
foreach (Delegate handler in OnAlarmRaised.GetInvocationList())
{
try
{
handler.DynamicInvoke(this, new AlarmEventArgs(location));
}
catch (TargetInvocationException ex)
{
exceptionList.Add(ex.InnerException);
}
}
if(exceptionList.Count > 0)
{
throw new AggregateException(exceptionList);
}
}
}
public class AlarmEventArgs : EventArgs
{
public string Location { get; set; }
public AlarmEventArgs(string location)
{
Location = location;
}
}

Android Video Streaming Using DatagramSocket setPreviewCallback

I've made an application that obeys UDP using Datagram Socket in android. I'm trying to use Camera's setPreviewCallback function to send bytes to a (c#) client, using Datagram Socket;
But,
The problem is : it throws an exception "The datagram was too big to fit the specified buffer,so truncated" and no bytes are received on client.
I've changed the size of buffer to different values but none work. Now :
Is Datagram approach is right?
What alternatives/approach I'd use to achieve the task?
What's the ideal solution for this?
Android Server :
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
videoView = (VideoView) findViewById(R.id.videoView1);
start = (Button)findViewById(R.id.start);
stop = (Button)findViewById(R.id.stop);
setTitle(GetCurrentIP());
mainList = new LinkedList<byte[]>();
secondaryList = new LinkedList<byte[]>();
mCam = null;
mCam = Camera.open();
if (mCam == null) {
Msg("Camera is null");
} else {
if (!Bind()) {
Msg("Bind Error.");
} else {
Msg("Bound Success.");
start.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
try {
mCam.setPreviewDisplay(videoView.getHolder());
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
Msg(e1.getMessage());
}
mCam.setPreviewCallback(new PreviewCallback() {
#Override
public void onPreviewFrame(byte[] data, Camera camera) {
// TODO Auto-generated method stub
DatagramPacket pack;
try {
pack = new DatagramPacket(data, data.length, InetAddress.getByName(clientIP), clientPort);
me.send(pack);
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
Msg(e.getMessage());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
Msg(e.getMessage());
}
}
});
mCam.startPreview();
}
});
}
}
}
private boolean Bind(){
try {
me = new DatagramSocket(MY_PORT);
return true;
} catch (SocketException e) {
// TODO Auto-generated catch block
e.printStackTrace();
Msg(e.getMessage());
}
return false;
}
private String GetCurrentIP(){
WifiManager wifiMgr = (WifiManager) getSystemService(WIFI_SERVICE);
return Formatter.formatIpAddress(wifiMgr.getConnectionInfo().getIpAddress());
}
public void Msg(String msg){
Toast.makeText(getApplicationContext(), msg, Toast.LENGTH_SHORT).show();
Log.v(">>>>>", msg);
}
}
C# client :
public partial class Form1 : Form
{
const int MY_PORT = 55566;
IPAddress MY_IP;
Thread Receiver;
Socket me;
EndPoint myEndPoint;
EndPoint serverEndPoint;
byte[] buffer;
public Form1()
{
InitializeComponent();
}
private IPAddress GetCurrentIPAddress()
{
IPAddress[] ips = Dns.GetHostAddresses(Dns.GetHostName());
var selectedIPs = from ip in ips
where ip.AddressFamily == AddressFamily.InterNetwork
select ip;
return selectedIPs.First();
}
private bool Bind()
{
try
{
myEndPoint = new IPEndPoint(MY_IP, MY_PORT);
me.Bind(myEndPoint);
return true;
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
return false;
}
private void Form1_Load(object sender, EventArgs e)
{
try
{
MY_IP = GetCurrentIPAddress();
this.Text = MY_IP.ToString()+":"+MY_PORT;
me = new Socket
(
AddressFamily.InterNetwork,
SocketType.Dgram,
ProtocolType.Udp
);
if (!Bind())
Task.Run(()=> MessageBox.Show("Bind() error."));
else
Task.Run(() => MessageBox.Show("Bind success."));
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
//private void AddToListBox(String msg)
//{
// this.Invoke((Action)delegate() { this.listBox1.Items.Add((this.listBox1.Items.Count+1)+" : "+msg); });
//}
private void buttonStart_Click(object sender, EventArgs e)
{
serverEndPoint = new IPEndPoint(IPAddress.Parse(textBoxmyIP.Text), int.Parse(textBoxmyPort.Text));
Receiver = new Thread(new ThreadStart(Receive));
Receiver.Start();
}
private Image ByteToImage(byte[] bytes)
{
MemoryStream ms = new MemoryStream(bytes);
return Image.FromStream(ms);
}
private void Receive()
{
while (true)
{
buffer = new byte[100];
int nobs = me.ReceiveFrom(buffer, ref serverEndPoint);
if (nobs>0)
{
Task.Run(() => MessageBox.Show("Bytes received"));
//AddToListBox(Encoding.Default.GetString(buffer));
//AddToPictureBox(buffer);
}
Thread.Sleep(100);
}
}
private void AddToPictureBox(byte[] buffer)
{
this.BeginInvoke
(
(Action)
delegate()
{
pictureBox1.Image = ByteToImage(buffer);
}
);
}
}

Why doesn't my Windows Store (Metro) app appear in the Share Pane?

I have made my app a Share Target (and Source), and I can successfully Share my app's content with other apps, but when I am in another app, like Mail or IE for example, I cannot share their content with my app because it doesn't appear in the Share Pane as an available Share Target app.
I have read and followed the MSDN documentation, checked out the samples, and have also setup the Share Target Declaration in the Package.AppXManifest file.
Why, and how can I fix this?
C# Code-behind:
ShareOperation shareOperation;
private string sharedDataTitle;
private string sharedDataDescription;
private string shareQuickLinkId;
private string sharedText;
private Uri sharedUri;
private IReadOnlyList<IStorageItem> sharedStorageItems;
private string sharedCustomData;
private string sharedHtmlFormat;
private IReadOnlyDictionary<string, RandomAccessStreamReference> sharedResourceMap;
private IRandomAccessStreamReference sharedBitmapStreamRef;
private IRandomAccessStreamReference sharedThumbnailStreamRef;
private void ReportStarted()
{
this.shareOperation.ReportStarted();
}
private void ReportCompleted()
{
this.shareOperation.ReportCompleted();
}
protected override async void OnNavigatedTo(NavigationEventArgs e)
{
RegisterForShare();
try
{
this.shareOperation = (ShareOperation)e.Parameter;
await Task.Factory.StartNew(async () =>
{
ReportStarted();
// Retrieve data package properties.
this.sharedDataTitle = this.shareOperation.Data.Properties.Title;
this.sharedDataDescription = this.shareOperation.Data.Properties.Description;
this.shareQuickLinkId = this.shareOperation.QuickLinkId;
// Retrieve data package content.
if (this.shareOperation.Data.Contains(StandardDataFormats.Text))
{
try
{
this.sharedText = await this.shareOperation.Data.GetTextAsync();
}
catch (Exception exception)
{
// NotifyUser of error.
}
}
else if(this.shareOperation.Data.Contains(StandardDataFormats.Html))
{
try
{
this.sharedHtmlFormat = await this.shareOperation.Data.GetHtmlFormatAsync();
}
catch (Exception exception)
{
}
}
else if (this.shareOperation.Data.Contains(StandardDataFormats.Uri))
{
try
{
this.sharedUri = await this.shareOperation.Data.GetUriAsync();
}
catch (Exception exception)
{
}
}
// Get back to the UI thread.
await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, async () =>
{
if (this.sharedText != null)
{
// Create a Note out of shared data.
CreateNote(this.sharedDataTitle, this.sharedText, null);
this.shareOperation.ReportDataRetrieved();
}
if (this.sharedUri != null)
{
CreateNote(this.sharedDataTitle, this.sharedUri.OriginalString, null);
this.shareOperation.ReportDataRetrieved();
}
if (this.sharedHtmlFormat != null)
{
CreateNote(this.sharedDataTitle, this.sharedHtmlFormat.ToString(), null);
this.shareOperation.ReportDataRetrieved();
}
});
});
}
catch (Exception exception)
{
Debug.WriteLine(exception.Message);
}
if (e.NavigationMode == NavigationMode.Back)
{
navigatedBack = true;
}
base.OnNavigatedTo(e);
}
App.xaml.cs:
protected override void OnShareTargetActivated(ShareTargetActivatedEventArgs args)
{
var rootFrame = new Frame();
rootFrame.Navigate(typeof(MainPage), args.ShareOperation);
Window.Current.Content = rootFrame;
Window.Current.Activate();
}
Any help will be greatly appreciated.
In your package manifest, make sure you add the declaration for "share target"

Categories