Search code examples
c#wpfimagesequencewebcam

c# code for capturing image sequences from a web cam with button click


I'm a first timer with WPF and implementing a c# code for generating images captured from webcam in WPF. I have done it this far that currently it can get single image from the button click. But I want to take sequences of images captured (where each image has a slight difference from the previous one, depending on number of seconds/ms it is taken). The same functionality is achieved in javascript but I have come to know that javascript cannot be used in WPF applications.

Here is a code snippet so far that I have done

In XAML:

<Border  Grid.Column="1" Grid.Row="1" BorderThickness="3" CornerRadius="3" Margin="0,0,0,1">
    <Border.BorderBrush>
        <RadialGradientBrush>
            <GradientStop Color="Black" Offset="0.047"/>
            <GradientStop Color="#FF00907A" Offset="1"/>
        </RadialGradientBrush>
    </Border.BorderBrush>
    <Image x:Name="imgVideo" Stretch="Fill"  />
</Border>
<Border  Grid.Column="3" Grid.Row="1" BorderThickness="3" CornerRadius="3" Margin="0,0,0,1">
    <Border.BorderBrush>
        <RadialGradientBrush>
            <GradientStop Color="Black" Offset="0.047"/>
            <GradientStop Color="#FF00907A" Offset="1"/>
        </RadialGradientBrush>
    </Border.BorderBrush>
    <Image x:Name="imgCapture" Stretch="None" Width="200" Height="150" />
</Border>
<StackPanel Grid.Column="3" Grid.Row="5" Orientation="Horizontal" HorizontalAlignment="Left" Width="162">
    <Button x:Name="bntCapture" Content="Capture Image" Click="bntCapture_Click" />       
</StackPanel>

In C# event handler

private void bntCapture_Click(object sender, RoutedEventArgs e)
{
    for (int j = 1; j <=30;j++ )
    {
        string path = Directory.GetCurrentDirectory();              
        string em_cap_original_path=System.IO.Path.Combine(path, "Database");
        imgCapture.Source = imgVideo.Source;                
        Helper.SaveImageCapture((BitmapSource)imgCapture.Source, em_cap_original_path, j);
    }
    MessageBox.Show("Images created"); 
}

This is Helper class

class Helper
{
    //Block Memory Leak
    [System.Runtime.InteropServices.DllImport("gdi32.dll")]
    public static extern bool DeleteObject(IntPtr handle);
    public static BitmapSource bs;
    public static IntPtr ip;
    public static BitmapSource LoadBitmap(System.Drawing.Bitmap source)
    {

        ip = source.GetHbitmap();

        bs = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(ip, IntPtr.Zero, System.Windows.Int32Rect.Empty,

        System.Windows.Media.Imaging.BitmapSizeOptions.FromEmptyOptions());

        DeleteObject(ip);

        return bs;

    }
    public static void SaveImageCapture(BitmapSource bitmap, string em_cap_original_path, int counter)
    {            
        PngBitmapEncoder encoder = new PngBitmapEncoder();
        encoder.Interlace = PngInterlaceOption.On;
        encoder.Frames.Add(BitmapFrame.Create(bitmap));            
        string img_path = em_cap_original_path + "/" + "frame" + counter + ".png";
        FileStream fp;
        fp = System.IO.File.Create(img_path);
        encoder.Save(fp);
        fp.Close();                       
    }
}

This code can generate 10 images but they are shot of same image not from image sequence.

If anyone knows how I can do it. Any help will be appreciated.


Solution

  • If the loop in the even handler is how you take multiple pictures, you should wait a bit between taking the pictures, you could just do this:

    private async void bntCapture_Click(object sender, RoutedEventArgs e)
    {
        for (int j = 1; j <= 30; j++)
        {
            string path = Directory.GetCurrentDirectory();
            string em_cap_original_path = System.IO.Path.Combine(path, "Database");
            imgCapture.Source = imgVideo.Source;
            Helper.SaveImageCapture((BitmapSource)imgCapture.Source, em_cap_original_path, j);
            await Task.Delay(20);//Delay in ms
        }
        MessageBox.Show("Images created");
    }
    

    notice the async void and the await Task.Delay()