PDA

View Full Version : Long image sequence with timer



aaborkar
May 12, 2009, 18:59:57
Hi Stefan,
I would like to generate an image sequence using .NET component. The idea is to create functionality similar to the sequence timer based image capture in the IC Capture 2.0 app with the addition of a millisecond timestamp attached to the file name. This will be useful to synchronize images in multiple streams. I am getting the time stamp using the stop watch class elapsed property in the thread diagnostics namespace. I am currently doing

[C#]

++frameCounter;
TIS_Control1.MemorySnapImage();
TIS_Control1.MemorySaveImage(@"D:\Tmp\CAM_01_" +frameCounter.ToString() + ".bmp");

in the timer tick. I am using a high res timer (http://www.codeproject.com/KB/miscctrl/lescsmultimediatimer.aspx) that is giving me near 33ms ticks for a 30fps capture. My problem being the app is very unstable at 25 or 30 fps capture rate. I used the

Application.DoEvents()

to resolve the issue, but now the frame rate gets affected. I did not use ring buffers or image buffers as I plan to record 30-60min at a stretch and the buffers will run out by then. When I tried to capture 2 streams in parallel (both RGB24 VGA), I got a stack overflow exception in about 10 secs.

Any suggestions on how I can replicate the functionality of the timer capture in the IC Capture app? Adjustable framerate with the mm timer is useful but not neccesarry, seamless capture is more important (with the timestamp in the name). I am able to record 2 streams onto seperate hdd's with occasional frame drops in the IC Capture app.

I am using the PCIe 4Ch frame grabber.

Thanks

Amol

Stefan Geissler
May 13, 2009, 09:17:07
Hello Amol,

IC Capture uses the ImageAvailable event and the Stopwatch, not MemorySnapImage. MemorySnapImage is a blocking call, thus you will receive a lot of trouble using more than one IC Imaging Control for your streams.

However, the solution is using the ImageAvailable event and the stopwatch. The ImageAvaialble event will be implemented as follows:



private void icImagingControl1_ImageAvailable(object sender, TIS.Imaging.ICImagingControl.ImageAvailableEventAr gs e)
{
try
{
if (Clock.ElapsedMilliseconds > 500) //Write an image every 500ms
{
++frameCounter;
TIS.Imaging.ImageBuffer ImgBuffer;
ImgBuffer = icImagingControl1.ImageActiveBuffer;
ImgBuffer.Lock();
ImgBuffer.SaveAsBmp(@"D:\Tmp\CAM_01_" +frameCounter.ToString() + ".bmp"))
ImgBuffer.Unlock();
Console.WriteLine("Save image");
Clock = Stopwatch.StartNew();
}
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine(ex.Message);
}
}

You must call "icImagingControl1.LiveCaptureContinuous = true;", so the ImageAvailableEvent is called automatically for each incoming frame.

"Clock" is of type "Stopwatch". It is started first time after LiveStart() has been called:


frameCounter = 0;
icImagingControl1.LiveStart();
Clock = Stopwatch.StartNew();


For each stream you use one IC Imaging Control and one ImageAvailable event.

aaborkar
May 13, 2009, 15:39:57
Hi Stefan,
Your soln works great. Thanks. Although I am unable to display my framecounter into a label or textbox when called inside the imageAvailable event handler. I added the last line of code to the handler ...



++frameCounter;
TIS.Imaging.ImageBuffer ImgBuffer;
...
Clock = Stopwatch.StartNew();
this.text = frameCounter.toString()


the caption of the form does not update when called inside the event handler. It will show an update when called from another timer tick or similar event. Any idea why this would happen?

Thanks

Stefan Geissler
May 13, 2009, 16:00:33
Hi,

If you to show things from with in the ImageAvailable event, you must use Delegates, because the ImageAvaialable event is called from another thread. Please see this sample, that shows, how to make Delegates at the end of the text:
http://www.imagingcontrol.com/en_US/library/dotnet/iterating-an-image-sequence/

aaborkar
May 14, 2009, 04:51:30
Hi Stefan,
The solution you provided performs well for the most part. Now, after about 10s after initiating the grabbing of images, the video in the IC control gets choppy. This also leads to frame drops every couple of seconds. I tried disabling the instantiation of the stopwatch class with along with the use of smaller and less complicated file names but that did not provide any improvement. Similar to before, I have the code as follows



try
{
if (grabbing_enabled)
{
++frameCounter;
TIS.Imaging.ImageBuffer ImgBuffer;
ImgBuffer = IC1.ImageActiveBuffer;
ImgBuffer.Lock();
ImgBuffer.SaveImage(@"E:\Tmp\CAM_01_" +
frameCounter.ToString() + ".bmp");
ImgBuffer.Unlock();
}
}


The code lies in the imageAvailable handler. 'grabbing_enabled' is a bool that allows images to be written to the disk. Without using the lock/unlock buffer, I got slight performance gain but not significant. When testing the simultaneous capture of 2 streams in the IC capture app, the preview showed much smoother video along with far less frequent frame drops in both streams. Any suggestions on where I could improve my code?

Thanks

Stefan Geissler
May 14, 2009, 08:24:24
Hi,

First of all, you may write only one line of code:


IC1.ImageActiveBuffer.SaveImage(@"E:\Tmp\CAM_01_" + frameCounter.ToString() + ".bmp");

I am not sure, whether this advances your source code.
Then I suggest to defragment your target device.
The main problem is, the harddisc buffers are full after some time, depending how fast you save images. Then the harddisc needs to save the images. While this happens, other threads are stopped. I think this makes your video chopping and produces your dropps.

How many frames do you save per second?
Does the same happen, if you save less images per second?

aaborkar
May 14, 2009, 14:40:35
Hi,

How many frames do you save per second?
Does the same happen, if you save less images per second?

Hi Stefan,
I am able to save 26-30fps using my code with chopiness and frame drops. Using the IC capture tool, I am getting roughly the same images saved per second without issues above. If I use a control statement and clock



if (grabber && clock.ElapsedMilliseconds > 33) //for 30fps


to verify the elapsed time, I cannot exceed 15fps.

Stefan Geissler
May 14, 2009, 14:47:07
Same here with our fastest computer. This seems to be a hard disc limitation.

Well, in order to avoid this, you may write in AVI files? If you want to save 30 fps, then you can write directly into an AVI file.

aaborkar
May 14, 2009, 15:42:45
Same here with our fastest computer. This seems to be a hard disc limitation.

I am not sure if hdd is the case. To test, I am recording the input video into bitmaps using the sequence timer in the IC cap app. I capture ~30 images/sec and as before, the video is smooth in the preview window with minimal frame drops. I built a similar app in C# that saves an image to a hdd physically different from the OS drive connected via PCIe RAID controller everytime the imageAvailable event is fired. As before, the video gets choppy after sometime and the frame drops appear to be more frequent.

Since I am trying to build an app similar to what exists in the IC cap, I expect to be able to produce similar performance is my concern.


Well, in order to avoid this, you may write in AVI files? If you want to save 30 fps, then you can write directly into an AVI file.

With AVI's I wont be able to synchronize the frames which is needed for our project later on when dealing with multiple video inputs.

Thanks

Stefan Geissler
May 15, 2009, 08:27:45
First of all, the preview window has a low priority.
Secondly, "synchronizing" with AVI files is hard job. You are right.

Did you try your application out of Visual Studio, I mean, call it directly? Visual Studio slows applications down a little bit.

Also may by an active virus scanner can cause frame drops.

You may try to save 10 images per second and check for frame drops. May be you can approach to the limit where frame drops start.

As you can see, I am little bit clueless too.

aaborkar
May 15, 2009, 14:17:09
Hi Stefan,
Thanks for your replies. I actually found a solution that works really well.

I used to mmtimer (1ms period, not system.timer) to check the clock for the elapsed time between each tick. If its exceeds 33ms, I save the image to the disk and reset the clock. This way, even with 2 or 3 stream, the preview video is smooth and captures have very few frame drops.

It appears to me that the imageAvailable event takes up a lot of "cpu time" causing the lags and chopiness while the save image from the active buffer is very "light" in comparison.

Now frame drops occur usually after 50k frames i.e. gap between frames goes to 50-100ms. Might have to cache 100k files before capture to reduce this effect as windows might be spending time trying to modify the directory and file headers when files are created dynamically, will let you know how that goes.

P.S. If I stop my app using the "Stop" debugger in VS when a video display is available, the system crashes. If I close the app directly, there are no problems. Any suggestion?

Stefan Geissler
May 15, 2009, 14:21:42
Hello,

Thank you for the feedback.

What does "System crashes" mean? Blue screen?

aaborkar
May 15, 2009, 14:36:17
What does "System crashes" mean? Blue screen?

Hangs up, no response to keyboard or mouse. Have to hit the reset button and reboot pc. Occasionally, mouse/kb will be operational but debugger will take 2-3 mins to stop and show a popup saying "Debugger is trying to stop, processes are being stopped...." Thereafter, framegrabber is locked and will not operate until system is rebooted.

Stefan Geissler
May 15, 2009, 14:49:04
This sounds for a threading problem. I am afraid, I have no idea about this.