Capturing a 3D Movie

This example illustrates how to capture a 3D movie using two synchronized cameras and the ImageAvailable events of IC Imaging Control.

Language:.NET C#/Visual Basic
Version:3.3
Released:20070411

Author:IC Imaging Control Support Department

Requirements:
Software:IC Imaging Control >3.0.3
Hardware: Two cameras, converters or grabbers with WDM Stream Class drivers.
Download C# sampleCapturing a 3D Movie - C#

For capture of 3-dimensional movies, two synchronised cameras are needed. The 3D image is composed by inserting both live video streams separatelly in the red and green color channel of the resulting images.

In order to recognize the 3D effect it is necessary to align the cameras exactly parallel in vertical and horizontal direction. Of course the viewer must carry red / green glasses. For fast image processing, this sample works only with monochrome cameras.

The application's window looks as follows:

3D Movie Creation with IC Imaging Control,

First of all, two variables for storing the references of the current image buffers of each camera must be created.

Additionally there are variables which save the recording and snap status, so that the program can respond in .ImageAvailable, in order to play safe that always the 3d images are saved.

C#
      
// Variables for storing the imagebuffers.
private TIS.Imaging.ImageBuffer Buffer1;
private TIS.Imaging.ImageBuffer Buffer2;

// Variables for Snap. If bSnap is true, the 3d-image will be saved
// to an Bitmap file.
private bool bSnap;
private String ImageFilename;

// Variables for Snap. If bRec is true, Avi-record is enabled
// and each 3d-frame will be added to the current avi.
private bool bRec;

        

Also the avifile.dll must be imported. This DLL contains functions for save IC Imaging Control ImageBuffers into an AVI file. Unfortunatelly only Video for Windows codecs are supported by this DLL, while all codecs are shown. By using an not supported codec, the resukting .avi file has a size of zero Bytes.

The dll functions are imported such as follows:

C#
      
[DllImport("avifile.dll")]
public static extern bool AVICreate(String FileName, int Width, int Height, short BitCount,
                                    int FrameRate, String CompressorOptionsFileName );
[DllImport("avifile.dll")]
public static extern byte AVIAddFrame( IntPtr Data );

[DllImport("avifile.dll")]
public static extern void AVIClose();

[DllImport("avifile.dll")]
public static extern byte SaveCompressorOptions( String CompressorOptionsFileName );

[DllImport("avifile.dll")]
public static extern byte LoadCompressorOptions( String CompressorOptionsFileName );

        

Also it is important to setup exactly the same property settings for each camera. For this task, both cameras are opened "manually" by passing the video capture device names directly to IC Imaging Control's property Device. The properties of one video capture device have been saved previously into an XML file. This file is reloaded call to .LoadDeviceStateFromFile. The second parameter of .LoadDeviceStateFromFile is set to false. This advises IC Imaging Control to load only an set the properties. Thus the XML can be used for both video capture devices and configure them with the same property values.

C#
      
private void SetupIC( TIS.Imaging.ICImagingControl ic )
{
    ic.LiveDisplayDefault = false;
    ic.LiveDisplayHeight = ic.Height ;
    ic.LiveDisplayWidth = ic.Width ;

    ic.LiveCaptureContinuous = true;
    ic.LiveDisplay = false;

    ic.MemorySnapTimeout = -1;
    ic.ImageRingBufferSize = 2;

    ic.MemoryCurrentGrabberColorformat =  TIS.Imaging.ICImagingControlColorformats.ICRGB32;

    // Set camera properties of each cam as the other.
    try
    {
        ic.LoadDeviceStateFromFile( "Devices.xml",false );
    }
    catch{}

}

        

This technique is also used to setup the properties with the integrated IC - Property - Dialog.

C#
      
private void btnProperties_Click(object sender, System.EventArgs e)
{
    // Setup camera1 properties and save to file.
    icImagingControl1.ShowPropertyDialog();
    icImagingControl1.SaveDeviceStateToFile("Devices.xml");

    // Set camera2 properties as same as camera1.
    icImagingControl2.LiveStop();
    try
    {
        icImagingControl2.LoadDeviceStateFromFile("Devices.xml",false );
    }
    catch {}

    icImagingControl2.LiveStart();
}

        

In the ImageAvailable events of each IC Imaging Control, the current ImageBuffers are locked and assigned to the form-global references. The color-channel mixing is done in the in the .ImageAvailable event of the second camera. This is done by putting the pixel brightness of the first camera in the red channel and the pixel brightness of the second camera 2 into the green channel of an extra .ImageBuffer. In this case an .ImageBuffer of the second camera is used to store and display the 3D-image.

C#
      
private void icImagingControl1_ImageAvailable(object sender, TIS.Imaging.ICImagingControl.ImageAvailableEventArgs e)
{
    Buffer1  = icImagingControl1.ImageBuffers[e.bufferIndex];
    Buffer1.Lock();

}

        

In order to create an AVI file from the 3D-images, the avifile.dll is used. This DLL provides the functionality for simple avi creation from ImageBuffers. Adding a frame to the AVI file is done by the static extern function AVIAddFrame(IntPtr Data) from the avifile.dll. The passed Data parameter is ImageBuffer.GetImageDataPtr() from the buffer of the second camera. This is done in .ImageAvailable event of the second camera, too.

C#
      
    private void icImagingControl2_ImageAvailable(object sender, TIS.Imaging.ICImagingControl.ImageAvailableEventArgs e)
    {
        Buffer2 = icImagingControl2.ImageBuffers[e.bufferIndex];
        Buffer2.Lock();

        int width = Buffer1.PixelPerLine*4;
        int height = Buffer1.Lines;

        // Generate a 3d image by putting the pixel brightness of camera 1 in the r channel and
        // the pixel brightness of camera 2 into the g channel of an imagebuffer.
        for ( int y=0;y<height ;++y)
        {
            for ( int x = 0; x <width  ; x+=4)
            {
                Buffer2[x,y] = 0;
                Buffer2[x+1,y] = Buffer1[x,y];
            }
        }

        // show current Imagebuffer
        icImagingControl2.DisplayImageBuffer( Buffer2 );

        // Save a bitmap if "Snap Image" was pressed.
        if ( bSnap )
        {
            bSnap = false;
            Buffer2.SaveAsBitmap(ImageFilename  );
        }

        // Add a frame to the .avi file, if recording is enabled.
        if ( bRec )
        {
            AVIAddFrame(Buffer2.GetImageDataPtr());
        }

        // Unlock the image buffers.
        Buffer1.Unlock();
        Buffer2.Unlock();

    }