Problem with getting frames in C#

jeff.will@valpo.edu
Posts: 8
Joined: Tue Sep 18, 2007 10:04 am

Problem with getting frames in C#

Post by jeff.will@valpo.edu »

Hi. I'm using a single flex c120 and trying to develop a very basic app in C# to snap and image (and record coordinates of a detected point), move the camera, and do this again.

I must be doing something conceptually wrong. If the object is in the camera view, my program will give me 4-5 good frames, then 4-6 null frames. It is pretty repeatable.

The full project, etc. is at:
diamond.gem.valpo.edu/~jwill/odis/CamerTest.zip

Here is my main C# code:

namespace CamerTest
{
public partial class Form1 : Form
{

bool cameraOpen = false;
OptiTrack.NPCameraCollection cameraCollection;
OptiTrack.NPCamera camera;
OptiTrack.NPCameraFrame frame;
OptiTrack.NPObject detectedObject;
int i = 0;


public Form1()
{
InitializeComponent();
}

private void label1_Click(object sender, EventArgs e)
{

}

private void StartButton_Click(object sender, EventArgs e)
{
if (!cameraOpen)
{

cameraCollection = new OptiTrack.NPCameraCollection();
cameraCollection.Enum();
int numCams = cameraCollection.Count;

if (numCams > 0)
{
camera = cameraCollection.Item(0);
camera.Open();
camera.Start();
camera.SetLED(1, true);
cameraOpen = true;
System.Console.WriteLine("Camera Opened Successfully");

}
}
}

private void StopButton_Click(object sender, EventArgs e)
{
if (camera != null)
{
camera.Stop();
camera.Close();
}
}

private void Snap_Click(object sender, EventArgs e)
{

if (!cameraOpen)
{
System.Console.WriteLine("Error: Camera Not Open");
return;
}
frame = camera.GetFrame(0);

if (frame == null)
{
System.Console.WriteLine("Error: No Frame " + i++ );
return;
}

detectedObject = frame.Item(0);

Xbox.Text = System.Convert.ToString(detectedObject.X);
YBox.Text = System.Convert.ToString(detectedObject.Y);
NumBox.Text = System.Convert.ToString(frame.Count);

System.Console.WriteLine("Successful frame grab: " + i++);

}

private void TimerButton_Click(object sender, EventArgs e)
{
if (timer1.Enabled == false)
timer1.Enabled = true;
else timer1.Enabled = false;
}

private void timer1_Tick(object sender, EventArgs e)
{
Snap_Click(null, null);
}
}
}
Birch
Posts: 1139
Joined: Thu Jan 30, 2003 5:00 am
Location: Corvallis, Oregon

Re: Problem with getting frames in C#

Post by Birch »

When polling for frames we recommend reading frames until there are no more available. This will flush the frame queue and should help you get better results. You can just discard the null ones.
jeff.will@valpo.edu
Posts: 8
Joined: Tue Sep 18, 2007 10:04 am

Re: Problem with getting frames in C#

Post by jeff.will@valpo.edu »

Birch,

Thanks so much for the help. I'll try this.

However, I'm a bit unclear how to determine that "there are no frames left." I'm sure this can easily be done in a while loop, but what would signal that there aren't any frames left? I already test to see if the frame returned is "null."

Would this mean that the buffer is flushed? And then I would subsequently read another frame and wait for a valid (non null) one?

I beg your forgiveness for asking for this, but if you could write a snippet to do this (maybe even a "flush buffer" function), it would help us out immensely.

Thanks,
Jim
beckdo
Posts: 520
Joined: Tue Jan 02, 2007 2:02 pm

Re: Problem with getting frames in C#

Post by beckdo »

Hey Jim,

The problem here is that when you call GetFrame() only once when the user clicks the button is that you'll get the oldest frame as compared to receiving the most recent frame. Once you call Start() on a camera it starts generating frames that need to be grabbed. In your case you're not 'servicing' GetFrame() at all, so once the camera queues up something like 5-10 frames it will stop storing new frames until the queue is flushed. So in your particular case, when the user clicks the button one possible solution is to flush the queue and then wait for a new frame to ensure the latest data. Perhaps something like this:

private void Snap_Click(object sender, EventArgs e)
{

if (!cameraOpen)
{
System.Console.WriteLine("Error: Camera Not Open");
return;
}

frame = camera.GetFrame(0);

if(frame!=NULL)
{
while(frame!=null)
{
frame.Release();
frame = camera.GetFrame(0);
}
}

//== the frames are flushed at this point, now wait for a fresh frame ==

frame=null;

while(frame==null)
{
// If the camera isn't Start()ed this will be an infinite loop
frame = camera.GetFrame(0);
}

detectedObject = frame.Item(0);

Xbox.Text = System.Convert.ToString(detectedObject.X);
YBox.Text = System.Convert.ToString(detectedObject.Y);
NumBox.Text = System.Convert.ToString(frame.Count);

frame.Release();
detectedObject.Release();

System.Console.WriteLine("Successful frame grab: " + i++);
}

Also, remember to always call .Release() on an object if it has been returned from the library. And make sure not to call Release() on null.

-Doug
jeff.will@valpo.edu
Posts: 8
Joined: Tue Sep 18, 2007 10:04 am

Re: Problem with getting frames in C#

Post by jeff.will@valpo.edu »

Doug,

Thank you so much. This has been a huge stoppage to my group.

I had tried messing around with .Release() before, but couldn't get it to work.

When I run the code above, I get a
'OptiTrack.NPCameraFrame' does not contain a definition for 'Release'

error and it fails to compile. Am I missing an include or something?

Thanks so much.

Jeff
leith
Posts: 194
Joined: Tue Jan 02, 2007 2:17 pm

Re: Problem with getting frames in C#

Post by leith »

I am also running into some odd behavior. Perhaps I'm doing someting wrong. below is my c# handler which is called by OptiTrack's FrameAvailable event:

Code: Select all

public void FrameAvailable(OptiTrack.NPCamera cam){                        
    
    OptiTrack.NPCameraFrame frame = cam.GetFrame(0);
    while (frame != null){
        if (!frame.IsCorrupt){
            if (!frame.IsEmpty){                        
                if (this.CameraSelectionListView.SelectedItems.Count > 0){
                    int serial = (int) this.CameraSelectionListView.SelectedItems[0].Tag;
                    if (cam.SerialNumber == serial){
                        this.label1.Text = "Objects: " + frame.Count.ToString();
                        if (this.DrawFramesToggle.Checked){
                            cam.DrawFrame(frame, viewer.Handle.ToInt32());                            
                        }
                            
                    }                    
                    
                }
            } else {
                System.Windows.Forms.MessageBox.Show("empty frame");
            }
        } else {
            System.Windows.Forms.MessageBox.Show("corrupt frame");
        }
        frame.Free();
        frame = cam.GetFrame(0);
    }
}
The behavior I'm seeing, is that the system gets frames for a good 10 seconds or so, and then stops one camera at a time. When a camera seizes, its LEDs change from the state I've specified upon connection. My program keeps running. However, the event is no longer triggered, it appears. There are no other handlers registered to this event. I think I'm Freeing all frames, no matter what. Yet the behavior suggests that the frame queue is seized. Also, in the past, when I've messed up and forgotten to free frames, it usually took half a second to seize up. This is taking much longer. Any thoughts as to why its seizing? Oh, and these cameras work find in Arena. So its not hardware afaik.

I may change over to a threaded execution rather than a event driven execution. It seems like thats what most people are using ?
beckdo
Posts: 520
Joined: Tue Jan 02, 2007 2:02 pm

Re: Problem with getting frames in C#

Post by beckdo »

Hey Brad,

That does seem a little unusual. Your code looks well formed and appears at first glance that it should work properly.

I peeked into the GetFrame() code a bit and it's unclear to me under all circumstances the GetFrame() call will properly set itself to NULL. Perhaps you could start with NULL before calling GetFrame(). My hunch is that this will fix it:




public void FrameAvailable(OptiTrack.NPCamera cam){

OptiTrack.NPCameraFrame frame = null;
frame = cam.GetFrame(0);

while (frame != null){
if (!frame.IsCorrupt){
if (!frame.IsEmpty){
if (this.CameraSelectionListView.SelectedItems.Count > 0){
int serial = (int) this.CameraSelectionListView.SelectedItems[0].Tag;
if (cam.SerialNumber == serial){
this.label1.Text = "Objects: " + frame.Count.ToString();
if (this.DrawFramesToggle.Checked){
cam.DrawFrame(frame, viewer.Handle.ToInt32());
}

}

}
} else {
System.Windows.Forms.MessageBox.Show("empty frame");
}
} else {
System.Windows.Forms.MessageBox.Show("corrupt frame");
}
frame.Free();
frame = null;
frame = cam.GetFrame(0);
}
}
leith
Posts: 194
Joined: Tue Jan 02, 2007 2:17 pm

Re: Problem with getting frames in C#

Post by leith »

good thought, but no luck.

It still seizes.

I had added some code to toggle the LEDs on the cameras when I select them in my UI. I just noticed that this code still works after the frames seize. So at the very least, the cameras are still responding to LED commands after they've stopped sending frames.

Is it possible there's a .net/COMinterop garbage collection issue here? Perhaps the frames are not really being freed when I call the Free method?

The "DrawFrame" part of the loop is off be default in my app, as I thought perhaps something inside DrawFrame might be causing the issue. However, that does not appear to be the case.

I can send more code or the whole project if you wish. I just don't quite know where to go from here except to put the whole thing inside a "while (true)" loop in another thread, and ditch the event model.
beckdo
Posts: 520
Joined: Tue Jan 02, 2007 2:02 pm

Re: Problem with getting frames in C#

Post by beckdo »

Jim,

In managed land it's .Free() I believe.

D
beckdo
Posts: 520
Joined: Tue Jan 02, 2007 2:02 pm

Re: Problem with getting frames in C#

Post by beckdo »

Have you tried the C# samples on the site? They don't have this problem. Perhaps you could compare the camera code. I recomment the .NET 3.0 sample.
Post Reply