Implementing a "Continuous Capture" with single image snaps

Viewed 17

I have some code below that can take the current Image and displaying it whenever I click a PushSnap Button. How can I go about having it continuously capturing and displaying the updated image in an interval (say 100 ms)

    private void PushSnap_Click(object sender, EventArgs e)
    
    {

        if (mycam == null) 
        {
            MessageBox.Show("Internal Error: mycam is null");
            return;                                  // internal error
        }
        string text = "";
        if (IsMyFormStatus_Opened())
        {
            if (!mydcam.buf_alloc(3))
            {
                MessageBox.Show("Frame allocation failed");
                    return;
            }          
        }

        // start acquisition
        mycam.m_capmode = CAMCAP_START.SNAP; //one time capturing where Acquisition will start after m_nFrameCount frames
        if (!mycam.cap_start())
        { 
            return;
        }
        MyFormStatus_Acquiring();
        MyThreadCapture_Start();
    }

The Following MyThreadCapture_Start()

        private void MyThreadCapture_Start()
    {
        m_threadCapture = new Thread(new ThreadStart(OnThreadCapture));

        m_threadCapture.IsBackground = true;
        m_threadCapture.Start();
    }

and the following OnThreadCapture()

        private void OnThreadCapture()
    {

        using (mycamwait = new MycamWait()) 
        {
            while (True)
            {
                CAMWAIT eventmask = CAMWAIT.CAPEVENT.FRAMEREADY | CAMWAIT.CAPEVENT.STOPPED;
                DCAMWAIT eventhappened = DCAMWAIT.NONE;
                if (mycamwait.start(eventmask, ref eventhappened))
                {
                    if (eventhappened & CAMWAIT.CAPEVENT.FRAMEREADY)
                    {
                        int NewestFrame = 0;
                        int FrameCount = 0;

                        if (mycam.cap_transferinfo(ref NewestFrame, ref FrameCount))
                        {
                            MyUpdateImage(iNewestFrame);
                        }
                    }

                    if (eventhappened & CAMWAIT.CAPEVENT.STOPPED)
                    {
                        bContinue = false;
                        if (m_cap_stopping == false && mycam.m_capmode == CAMCAP_START.SNAP)
                        {
                            //cap_stop() happens automatically, therefore update the main dialog
                            //MySnapCaptureFinished();
                        }
                    }
                }

            }
        }

Afterwards the Display is updated in the following way

        private void UpdateDisplay()
    {
        Image oldImg = PicDisplay.Image;
        if (m_bitmap != null)
        {
            // Show center of image
            Int32 y0 = (m_image.height - PicDisplay.Height) / 2;
            Int32 x0 = (m_image.width - PicDisplay.Width) / 2;

            Rectangle rc = new Rectangle(x0, y0, PicDisplay.Width, PicDisplay.Height);
            Bitmap bmp = new Bitmap(PicDisplay.Width, PicDisplay.Height, PixelFormat.Format24bppRgb);
            using (var gr = Graphics.FromImage(bmp))
            {
                gr.DrawImage(m_bitmap, 0, 0, rc, GraphicsUnit.Pixel);
            }

            PicDisplay.Image = bmp;
            PicDisplay.Refresh();

        }
        else
        {
            PicDisplay.Image = null;
        }

        if (oldImg != null)
            oldImg.Dispose();

    }
1 Answers

I would really recommend using Tasks instead of Threads. That should let you update your methods to take parameters and return results:

Image CaptureImage(); // I.e. similar code to OnThreadCapture
UpdateDisplay(Image);

And capture an image like:

public async void PushSnap_Click(){

...
try{
   var image = await Task.Run(CaptureImage);
   DisplayImage(image);
}
catch{
 // Handle exceptions
}

That should let you simply rewrite your capture code to use a loop if you want live capture:

while(showLiveImagesBool){
   var image = await Task.Run(CaptureImage);
   DisplayImage(image);
}

The await-part should ensure the UI thread is not blocked while waiting for an image to be captured. If you do not want to show every image you might use a timer instead of a loop, just pick a timer that runs on the UI thread.

Keep in mind that showing live images will require a bit more performance, so you might need to optimize display and/or capture code. Ideally you should reuse image buffers when doing the capturing and displaying, otherwise you will allocate a fair amount of large objects that require a 2 gen GC to clean up.

Related