Process Camera frames in background with IoT UWP and Raspberry pi - c#

I'm trying to capture frames from a camera(usb or raspberrp pi camera) and process them in various ways. I've tried using the MediaCapture Object but it seems like it needs to be tied to the UI. The frames are not being viewed on a UI or saved on any type of storage. They will just be processed and thrown out.
var cameraDevice = await FindCameraDevice();
if (cameraDevice == null)
{
IsInitialized = false;
return false;
}
var settings = new MediaCaptureInitializationSettings { VideoDeviceId = cameraDevice.Id };
mediaCapture = new MediaCapture();
try
{
await mediaCapture.InitializeAsync(settings);
IsInitialized = true;
return true;
}
catch{}
Any ideas how I can accomplish this?

Related

How to open and auto capture camera using MediaCapture class

we are trying to automatically capture an image from the webcam using MediaCapture class. We are trying to create an application which opens the camera, waits for a moment and captures the image in front of it without someone to tap the screen to capture. we tried using LowLagPhotoCapture class but does not work as desired. Sample code -
async private void InitMediaCapture()
{
MediaCapture _mediaCapture = new MediaCapture();
await _mediaCapture.InitializeAsync();
_displayRequest.RequestActive();
PreviewControlCheckIn.Source = _mediaCapture;
await _mediaCapture.StartPreviewAsync();
await Task.delay(500);
CaptureImage();
}
async private void CaptureImage()
{
storeFile = await ApplicationData.Current.TemporaryFolder.CreateFileAsync ("TestPhoto.jpg",CreationCollisionOption.GenerateUniqueName);
ImageEncodingProperties imgFormat = ImageEncodingProperties.CreateJpeg();
await _mediaCapture.CapturePhotoToStorageFileAsync(imgFormat, storeFile);
await _mediaCapture.StopPreviewAsync();
}
Any info would be great, thanks in advance for the help.
I have completed your provided code and achieved your requirement. Please refer to the following code. Please note that you should declare camera and the microphone capabilities in your Universal Windows Platform (UWP) app's package manifest to access certain API.
async private void InitMediaCapture()
{
_mediaCapture = new MediaCapture();
var cameraDevice = await FindCameraDeviceByPanelAsync(Windows.Devices.Enumeration.Panel.Back);
var settings = new MediaCaptureInitializationSettings { VideoDeviceId = cameraDevice.Id };
await _mediaCapture.InitializeAsync(settings);
_displayRequest.RequestActive();
PreviewControl.Source = _mediaCapture;
await _mediaCapture.StartPreviewAsync();
var picturesLibrary = await StorageLibrary.GetLibraryAsync(KnownLibraryId.Pictures);
_captureFolder = picturesLibrary.SaveFolder ?? ApplicationData.Current.LocalFolder;
await Task.Delay(500);
CaptureImage();
}
async private void CaptureImage()
{
var storeFile = await _captureFolder.CreateFileAsync("PreviewFrame.jpg", CreationCollisionOption.GenerateUniqueName);
ImageEncodingProperties imgFormat = ImageEncodingProperties.CreateJpeg();
await _mediaCapture.CapturePhotoToStorageFileAsync(imgFormat, storeFile);
await _mediaCapture.StopPreviewAsync();
}
private static async Task<DeviceInformation> FindCameraDeviceByPanelAsync(Windows.Devices.Enumeration.Panel desiredPanel)
{
// Get available devices for capturing pictures
var allVideoDevices = await DeviceInformation.FindAllAsync(DeviceClass.VideoCapture);
// Get the desired camera by panel
DeviceInformation desiredDevice = allVideoDevices.FirstOrDefault(x => x.EnclosureLocation != null && x.EnclosureLocation.Panel == desiredPanel);
// If there is no device mounted on the desired panel, return the first device found
return desiredDevice ?? allVideoDevices.FirstOrDefault();
}
The photo will be saved to Pictures library. And I have upload the code sample to github. Please check!

UWP Media Capture Not Recording Video through WebCam

I am trying to develop a UWP app where I need to record video via webcam. I have followed microsoft tutorial about it here but the problem is I am getting following error again and again and recording does not work.
Error
"This object needs to be initialized before the requested operation
can be carried out.\r\nThis object needs to be initialized before the
requested operation can be carried out."
Here is my code:
int counter = 1;
var myVideos = await Windows.Storage.StorageLibrary.GetLibraryAsync(Windows.Storage.KnownLibraryId.Videos);
StorageFile file = await myVideos.SaveFolder.CreateFileAsync("survillance "+DateTime.Now.ToString("dd-MM-yyyy")+"_"+counter+".wmv", CreationCollisionOption.GenerateUniqueName);
try
{
MediaEncodingProfile recordProfile = null;
recordProfile = MediaEncodingProfile.CreateWmv(VideoEncodingQuality.Auto);
_mediaRecording = await _mediaCapture.PrepareLowLagRecordToStorageFileAsync(recordProfile,file);
await _mediaRecording.StartAsync();
status.Text = "Video recording in progress...";
}
catch (Exception ex)
{
status.Text = "Failed to Capture...";
var msg = new MessageDialog(ex.Message, "Capturing Error").ShowAsync();
}
Please help me in figuring out the problem. Thanks
You forgot to call MediaCapture.InitializeAsync() before starting the capture.
MediaEncodingProfile recordProfile = MediaEncodingProfile.CreateMp4(VideoEncodingQuality.Auto);
_mediaCapture = new MediaCapture();
_mediaCapture.InitializeAsync();
_mediaRecording = await _mediaCapture.PrepareLowLagRecordToStorageFileAsync(recordProfile,file);
await _mediaRecording.StartAsync();

How to record and playback audio from default audio device

I can't seem to record the audio from default audio device, and play it on another audio device..
I don't want to record the microphone, but the audio device..
When I play a movie, I can hear sound, through my headphones, I want to copy that sound to any audio device I choose..
If you have any suggestions, it doesn't have to be with NAudio..
As far as I can tell, NAudio can't do this..
This is the code I use for the task at this time, but it only takes input from my Microphone: Code snippet with NAudio..
void playSoundCopy(int dv0)
{
disposeWave0();// stop previous sounds before starting
var waveOut0 = new WaveOut();
waveOut0.DeviceNumber = dv0;
wave0 = waveOut0;
Defaultwave0 = new WaveIn();
Defaultwave0.DeviceNumber = (int)GetDefaultDevice(Defaultdevice.FriendlyName);
var waveinReader0 = new WaveInProvider(Defaultwave0);
wave0.Init(waveinReader0);
play0 = false;
Thread.Sleep(1000);
play0 = true;
t0 = new Thread(() => { timeline0(); });
t0.IsBackground = true;
t0.Start();
Defaultwave0.StartRecording();
wave0.Play();
}
The real problem is actually that I can't record from a WaveOut device, only WaveIn..
Working Result:
void playSoundCopy(int dv0)
{
disposeWave0();// stop previous sounds before starting
var waveOut0 = new WaveOut();
waveOut0.DeviceNumber = dv0;
wave0 = waveOut0;
var format0 = Defaultdevice.AudioClient.MixFormat;
buffer0 = new BufferedWaveProvider(format0);
wave0.Init(buffer0);
capture = new WasapiLoopbackCapture(Defaultdevice);
capture.ShareMode = AudioClientShareMode.Shared;
capture.DataAvailable += CaptureOnDataAvailable;
play0 = false;
Thread.Sleep(1000);
play0 = true;
t0 = new Thread(() => { timeline0(); });
t0.IsBackground = true;
t0.Start();
capture.StartRecording();
wave0.Play();
}
void CaptureOnDataAvailable(object sender, WaveInEventArgs waveInEventArgs)
{
try
{
var itm = new byte[waveInEventArgs.BytesRecorded];
Array.Copy(waveInEventArgs.Buffer, itm, waveInEventArgs.BytesRecorded);
buffer0.AddSamples(itm, 0, itm.Length);
}
catch { }
}
You can capture audio being sent to a device using WasapiLoopbackCapture. Then you could pipe that into a BufferedWaveProvider and use that to feed another output device. There would be some latency introduced though, so don't expect the two devices to be in sync.

Try to add custom tile to Microsoft Band from UWP app

I want to add a custom tile to the Microsoft Band through Microsoft Band SDK in a UWP app for Windows Phone. Here is my sample code.
private async void ButtonBase_OnClick(object sender, RoutedEventArgs e)
{
try
{
// Get the list of Microsoft Bands paired to the phone.
var pairedBands = await BandClientManager.Instance.GetBandsAsync();
if (pairedBands.Length < 1)
{
Debug.WriteLine("This sample app requires a Microsoft Band paired to your device.Also make sure that you have the latest firmware installed on your Band, as provided by the latest Microsoft Health app.");
return;
}
// Connect to Microsoft Band.
using (var bandClient = await BandClientManager.Instance.ConnectAsync(pairedBands[0]))
{
// Create a Tile with a TextButton on it.
var myTileId = new Guid("12408A60-13EB-46C2-9D24-F14BF6A033C6");
var myTile = new BandTile(myTileId)
{
Name = "My Tile",
TileIcon = await LoadIcon("ms-appx:///Assets/SampleTileIconLarge.png"),
SmallIcon = await LoadIcon("ms-appx:///Assets/SampleTileIconSmall.png")
};
// Remove the Tile from the Band, if present. An application won't need to do this everytime it runs.
// But in case you modify this sample code and run it again, let's make sure to start fresh.
await bandClient.TileManager.RemoveTileAsync(myTileId);
// Create the Tile on the Band.
await bandClient.TileManager.AddTileAsync(myTile);
// Subscribe to Tile events.
}
}
catch (Exception ex)
{
Debug.WriteLine(ex);
}
}
private async Task<BandIcon> LoadIcon(string uri)
{
StorageFile imageFile = await StorageFile.GetFileFromApplicationUriAsync(new Uri(uri));
using (IRandomAccessStream fileStream = await imageFile.OpenAsync(FileAccessMode.Read))
{
WriteableBitmap bitmap = new WriteableBitmap(1, 1);
await bitmap.SetSourceAsync(fileStream);
return bitmap.ToBandIcon();
}
}
If I run this code nothing happend. The app connected to Microsoft Band, but is not able to add a tile. The method AddTileAsync(myTile); Returns false and doesn't add a tile to the Microsoft Band.
If I try this code in a Windows Phone 8.1 app it works, but not in the UWP app.
Any ideas?
Update
Here is the sample app as download. Maybe this can help.
maybe this would help, coming from the documentation of MS Band
using Microsoft.Band.Tiles;
...
try
{
IEnumerable<BandTile> tiles = await bandClient.TileManager.GetTilesAsync();
}
catch (BandException ex)
{
//handle exception
}
//determine if there is space for tile
try
{
int tileCapacity = await bandClient.TileManager.GetRemainingTileCapacityAsync();
}
catch (BandException ex)
{
//handle ex
}
//create tile
WriteAbleBitmap smallIconBit = new WriteAbleBitmap(24, 24);
BandIcon smallIcon = smallIconBit.ToBandIcon();
WriteAbleBitmap largeIconBit = new WriteAbleBitmap(48, 48);//46, 46 for MS band 1
BandIcon largeIcon = largeIconBit.ToBandIcon();
Guid guid = Guid.NewGuid();
BandTile tile = new BandTile(guid)
{
//enable Badging
IsBadgingEnabled = true,
Name = "MYNAME"
SmallIcon = smallIcon;
TileIcon = largeIcon;
};
try
{
if(await bandClient.TileManager.AddTileAsync(tile))
{
///console print something
}
}
catch(BandException ex)
{
//blabla handle
}
I think the issue may be you're setting the writeable bitmap size to (1,1)?
I have this method working:
public static class BandIconUtil
{
public static async Task<BandIcon> FromAssetAsync(string iconFileName, int size = 24)
{
string uri = "ms-appx:///" + iconFileName;
StorageFile imageFile = await StorageFile.GetFileFromApplicationUriAsync(new Uri(uri, UriKind.RelativeOrAbsolute));
using (IRandomAccessStream fileStream = await imageFile.OpenAsync(FileAccessMode.Read))
{
WriteableBitmap bitmap = new WriteableBitmap(size, size);
await bitmap.SetSourceAsync(fileStream);
return bitmap.ToBandIcon();
}
}
}

UnauthorizedAccessException on MediaElement in DatagramSocket.ReceivedMessage

I want start my mediaElement (instance of MediaElement class) at when first pack of data came. So I wrote it like that.
private void SocketOnMessageReceived(DatagramSocket sender, DatagramSocketMessageReceivedEventArgs args)
{
if (isPaused) return;
if (!isStarted)
{
mediaElement.Play();
isStarted = true;
}
var r = args.GetDataReader();
var l = r.UnconsumedBufferLength;
var buff = new byte[l];
r.ReadBytes(buff);
if (System.Text.Encoding.UTF8.GetString(buff, 0, buff.Length) != "stop")
{
AudioSteam.AddBytes(buff);
}
else
{
mediaElement.Pause();
isStarted = false;
Debug.WriteLine("stop");
}
buff = null;
}
Of course elier I set source for mediaElement (MediaStreamSource).
var socket = new DatagramSocket();
socket.MessageReceived += SocketOnMessageReceived;
await socket.BindServiceNameAsync("4444");
HostName multicast = new HostName("230.0.0.1");
socket.JoinMulticastGroup(multicast);
isPaused = true;
isStarted = false;
AudioSteam = new Sine440AudioStreamSource(44100);
mdiaElement.SetSource(AudioSteam);
At first I get System.IO.FileNotFoundException then System.UnauthorizedAccessException at mediaElement.Start(); I have no idea why.
Any suggestion will be appreciated.
It's turns out that DatagramSocket.ReceivedMessage method is running at other thread so If you want access variables out of method scope you need to use Dispatcher.BeginInvoke()
Dispatcher.BeginInvoke(() =>{
//Code
});
All in all I resign for that approach.

Categories