Hello fellow programmer,
I’m having trouble trying to figure out how to film with two identical cameras with different settings at the same time.
So far the two cameras only film in the same settings but there is some weird things happening:
- The displayed fps is twice what I put in the configuration settings.
- When i look up the camera’s with Stemmer app, the fps is set to the same value I set in my application so it “should work”.
Here is some samples of my application:
Grab event:
{
// turn grab on or off
if (m_cbGrab.Checked)
{
if (IsRecordingInitialized)
{
StartRecording();
}
else
{
InitializeRecording();
m_cvImage.Grab = true;
m_cvImage2.Grab = true;
if (!m_bTimerStarted)
{
m_cvDisplay.StatusUserText = string.Empty;
m_cvDisplay2.StatusUserText = string.Empty;
m_framecounter = 0;
m_FramesToNextMeasurement = 1;
}
}
}
else
{
if (IsRecordingInitialized)
StopRecording();
m_cvImage.Grab = false;
m_cvImage2.Grab = false;
}
UpdateUI();
}
start recording method:
{
System.IO.File.WriteAllText(startFile, DateTime.Now.ToString("o"));
//m_Recorder.StartRecording();
//m_Recorder2.StartRecording();
if (!(m_Recorder.StartRecording() && m_Recorder2.StartRecording()))
{
MessageBox.Show("Error while Start Recording. Check if target video is open and writable");
StopRecording();
return;
}
if (timerRecord.Interval != 0)
timerRecord.Start();
if (m_Recorder.AcquisitionMode == Movie2Recorder.AcquisitionModeType.AddFrame)
m_cvImage.Grab = true;
else
m_cvImage.Grab = false;
if (m_Recorder2.AcquisitionMode == Movie2Recorder.AcquisitionModeType.AddFrame)
m_cvImage2.Grab = true;
else
m_cvImage2.Grab = false;
m_RecordButton.Text = "recording...(Click to stop)";
}
loading driver method:
{
// if grab is currently running, stop it first
if (m_cvImage.Grab)
{
m_cbGrab.Checked = false;
this.m_cbGrab_CheckedChanged(sender, e);
}
// Open LoadImage Dialog
String filename = "";
if (m_cvImage2.LoadImageByDialog())
{
// store filename as it will be overwritten with axCVimage2.Image = ...
filename = m_cvImage2.Filename;
// check if opened driver supports the ICameraSelect2 interface
if (Driver.ICameraSelect2.CanCameraSelect2(m_cvImage2.Image))
{
// change camera
SharedImg imgNew = null;
try
{
int result = Driver.ICameraSelect2.CS2SetCamPort(m_cvImage2.Image, 1, 0, out imgNew);
if (result == 0 && imgNew.Handle != IntPtr.Zero)
{
m_cvImage2.Image = imgNew;
m_cvDisplay2.Image = (int)m_cvImage2.Image;
m_cvDisplay2.Refresh();
}
}
finally
{
// ActiveX controls share the assigned image (shared ownership)
if (imgNew != null)
imgNew.Dispose();
}
}
else
{
MessageBox.Show("Image does not support the ICameraSelect2 interface.");
return;
}
}
else
{
MessageBox.Show("Error while loading the driver");
return;
}
if (m_cvImage.LoadImage(filename))
{
m_cvDisplay.Image = (int)m_cvImage.Image;
}
this.ReadGenICamInfos();
this.ReadGenICamInfos2();
// Register all Callbacks
this.RegisterCallbacks();
}
If you need more information, dont hesitate! I only put these sample because i think they are the most relevant.
I had a quick look at your code, it looks ok so far.
I would like to see the “InitializeRecording” method, and the part where you create your recorder objects.
Maybe you can zip your project and upload so I can debug it.
I don’t have yet the authorization to share all the code but here are the bits of code you asked for:
Loading Method:
{
// set LeftButtonMode of the Display to create AOIs with the mouse
this.m_cvDisplay.LeftButtonMode = CVDISPLAYLib.LeftButtonMode.LB_FRAME;
// show image size in the Display status line
this.m_cvDisplay.StatusImageSize = true;
// set DirectDraw property of the Display
this.m_cvDisplay.DirectDrawEnabled = true;
m_Recorder = new Movie2Recorder(Movie2Recorder.RecordingEngineType.DirectShow, m_cvImage.Image);
// Register Recorder Image Snaped Event
m_Recorder.ImageSnapped += m_Recorder_ImageSnaped;
// set LeftButtonMode of the Display to create AOIs with the mouse
this.m_cvDisplay2.LeftButtonMode = CVDISPLAYLib.LeftButtonMode.LB_FRAME;
// show image size in the Display status line
this.m_cvDisplay2.StatusImageSize = true;
// set DirectDraw property of the Display
this.m_cvDisplay2.DirectDrawEnabled = true;
m_Recorder2 = new Movie2Recorder(Movie2Recorder.RecordingEngineType.DirectShow, m_cvImage2.Image);
// Register Recorder Image Snaped Event
m_Recorder2.ImageSnapped += m_Recorder2_ImageSnaped;
// Register Recorder Image Snaped Event
foreach (string codec in m_Recorder.AvailableCodecs)
{
m_CodecsList.Items.Add(codec);
}
m_CodecsList.SelectedIndex = 0;
// Connect ProvideMetaData Event with Event function
m_Recorder.ProvideMetaData += recorderReadyForNewMetaData;
m_Recorder2.ProvideMetaData += recorderReadyForNewMetaData;
// Set initial FileName
string fileName = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + @"\Movie2Video.avi";
m_FileNameTextBox.Text = fileName.Replace(@"\\", @"\");
_radioButtonSynchronizeAfterCopy.Checked = true;
_radioButtonAddFrame.Checked = true;
}
InitializeRecording:
{
Int64 result = (Int64)DateTime.UtcNow.Subtract(DateTime.MinValue).TotalSeconds;
String path = @"D:\" + result.ToString();
startFile = path + @"\start_recording.txt";
endFile = path + @"\end_recording.txt";
dirName = result.ToString();
DirectoryInfo di = Directory.CreateDirectory(path);
string fileName = path + @"\Movie2Video.avi";
m_FileNameTextBox.Text = fileName.Replace(@"\\", @"\");
IsRecordingInitialized = true;
m_Recorder.TargetFileName = m_FileNameTextBox.Text;
m_Recorder.FrameRate = m_LastPlaybackFPS;
m_Recorder.CompressionCodecIndex = m_CodecsList.SelectedIndex;
m_Recorder.UseMetaData = _saveMetadataToolStripMenuItem.Checked;
String filename_cam2 = m_FileNameTextBox.Text;
filename_cam2 = filename_cam2.Remove(filename_cam2.Length - 4);
filename_cam2 += "_camera2.avi";
m_Recorder2.TargetFileName = filename_cam2;
m_Recorder2.FrameRate = m_LastPlaybackFPS;
m_Recorder2.CompressionCodecIndex = m_CodecsList.SelectedIndex;
m_Recorder2.UseMetaData = _saveMetadataToolStripMenuItem.Checked;
if (m_Recorder2.Image == 0)
{
m_Recorder2.Image = m_cvImage2.Image;
}
if (!m_Recorder.PreStartRecording())
{
MessageBox.Show("Error while Initialize Recording. Check if target video is open and writable for camera 1");
IsRecordingInitialized = false;
return;
}
else if (!m_Recorder2.PreStartRecording())
{
MessageBox.Show("Error while Initialize Recording. Check if target video is open and writable for camera 2");
IsRecordingInitialized = false;
return;
}
try
{
maxFPSrequested = (double.Parse(timerText.Text) / 1000) * double.Parse(_FPSTextBox.Text);
}
catch
{
maxFPSrequested = 0;
}
m_RecordButton.Text = "Record";
}
I only see frameCounter member.
Could it be, that you increment the framecounter in BOTH ImageSnapped events (of camera 1 and camera 2)?
This would explain why the display is twice the framerate you configured.
Clearly, that’s why it was displaying the double of the fps, i managed to correct it, but not to target the fps of the second camera though.
Calculate fps for 1st camera:
{
// Calculate FPS
m_framecounter++;
if (m_framecounter == 0)
{
Utilities.TWStartStopWatch(m_Timer, 0);
}
else if (m_framecounter >= m_FramesToNextMeasurement)
{
// read the time since the last ImageSnaped event
double dTimeMS;
Utilities.TWReadStopWatch(m_Timer, 0, out dTimeMS);
// Measure every second and use the last MeasuredFPS to
// now how many frames have to be counted
double measuredFPS = (m_framecounter * 1.0 / dTimeMS * 1000.0);
if ((int)m_LastMeasuredFPS > 1)
m_FramesToNextMeasurement = (int)measuredFPS;
else
m_FramesToNextMeasurement = 1;
if (!m_FPSRecommended && measuredFPS > 0.1 && Math.Abs(measuredFPS - m_LastMeasuredFPS) < 0.2)
{
m_LastPlaybackFPS = measuredFPS;
_FPSTextBox.Text = m_LastPlaybackFPS.ToString();
}
m_framecounter = 0;
m_LastMeasuredFPS = measuredFPS;
Utilities.TWStartStopWatch(m_Timer, 0);
}
return m_LastMeasuredFPS;
}
calculate fps for second camera:
{
// Calculate FPS
m_framecounter_2++;
if (m_framecounter_2 == 0)
{
Utilities.TWStartStopWatch(m_Timer_2, 0);
}
else if (m_framecounter_2 >= m_FramesToNextMeasurement_2)
{
// read the time since the last ImageSnaped event
double dTimeMS;
Utilities.TWReadStopWatch(m_Timer_2, 0, out dTimeMS);
// Measure every second and use the last MeasuredFPS to
// now how many frames have to be counted
double measuredFPS_2 = (m_framecounter_2 * 1.0 / dTimeMS * 1000.0);
if ((int)m_LastMeasuredFPS_2 > 1)
m_FramesToNextMeasurement_2 = (int)measuredFPS_2;
else
m_FramesToNextMeasurement_2 = 1;
if (!m_FPSRecommended && measuredFPS_2 > 0.1 && Math.Abs(measuredFPS_2 - m_LastMeasuredFPS_2) < 0.2)
{
m_LastPlaybackFPS = measuredFPS_2;
_FPSTextBox.Text = m_LastPlaybackFPS.ToString();
}
m_framecounter_2 = 0;
m_LastMeasuredFPS_2 = measuredFPS_2;
Utilities.TWStartStopWatch(m_Timer_2, 0);
}
return m_LastMeasuredFPS_2;
}
Yes, both methods calculate the FPS of the first camera, I want the second method to calculate the FPS of the second camera but I don’t know what to change to target the camera.
Oh I found the problem, i didn’t link any imagesnapped method to my second camera, now i made another method for the second one and linked it and it works! thanks a lot for your help and your time!