从 Vimba 相机处理每一帧



我正在使用Allied Vision Vimba相机来监控涉及激光的实验。

我编写了一个代码,允许我从摄像机实时成像中获取一帧(以pictureBoxLiveCamera显示,黑白),将其放入另一个PictureBox(pictureBoxFixe1)中并对其进行处理。代码在大多数情况下工作正常,即使它没有完成。 我的问题是,最终,我需要连续工作,这意味着相机的每一帧(大约每秒15-20帧),我开始觉得这会很复杂。

我不是要求你帮助我完成整个过程,但我有一个行不通的精确示例,我想了解。我正在使用 Vimba .NET API,所以你们大多数人可能不熟悉调用的一些函数(对我来说它们真的不多),但我会尽力在代码中解释它们(API 手册有点神秘)。

我的代码有一个部分,当我从相机中分离出一帧以对其进行处理时(通过button-click事件),绘制一个直方图,该直方图绘制垂直轴上的像素数和水平轴上的数字数字值。这样我就可以知道某些像素是否饱和(255),并且可以降低曝光时间。这工作正常,这是隔离一帧并绘制直方图的按钮的代码:

private void fixButton_Click(object sender, EventArgs e)
{
if (m_Acquiring == true) //mm_Acquiring being true indicates that the camera is sending images continuously, and that they are toggled in pictureBoxLiveCamera
{
pictureBoxFixe1.Image = SaveBitmap; //SaveBitmap is the bitmap isolated from the live camera in an earlier code portion
Array.Clear(PixelColorCount, 0, 256);
foreach (var Series in chartHist.Series)
{
Series.Points.Clear();
}
//Creating a bitmap from pictureBoxFixe1 to draw the histogram from
Bitmap Couleur = new Bitmap(pictureBoxFixe1.Image);
//Collecting data from pictureBoxFixe1
for (int i = 0; i < 1023; i++)
{
for (int j = 157; j < 288; j++)
{
PixelColorCount[Couleur.GetPixel(i + 1, j).B] += 1;
}
for (int j = 484; j < 615; j++)
{
PixelColorCount[Couleur.GetPixel(i + 1, j).B] += 1;
}
}
//Plotting the pixel counter, to detect saturation
for (int i = 0; i < 256; i++)
{
chartHist.Series["Pixel count"].Points.AddXY(i, PixelColorCount[i]);
}
//If there are saturated pixels : toggle a title on chart 1 to warn the user
if (PixelColorCount[255] > 1)
{
chartHist.Titles["Title1"].Visible = false;
chartHist.Titles["Title2"].Visible = true;
}
else
{
chartHist.Titles["Title1"].Visible = true;
chartHist.Titles["Title2"].Visible = false;
}
}
else
{
MessageBox.Show("Acquisition is not running.", "Something went wrong !", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
}

现在我想要的是让这项工作变得生动起来,每一帧都来自相机。但它不起作用,我找不到为什么。这是我尝试过的:

private void BtAcquisitionLiveCam_Click(object sender, EventArgs e)
{
//Here is the part of the code that starts the live acquisition when I click the button, I don't copy it completely because I don't think this is relevant.
this.m_Acquiring = true;
mycamera.OnFrameReceived += new Camera.OnFrameReceivedHandler(this.OnFrameReceived); //This is the event handler for the reception of a frame for the camera, it is part of the Vimba API
mycamera.StartContinuousImageAcquisition(1); //According to the manual, this "Starts streaming and allocates the needed frames", with the argument being "count of Frame(s) which should be used for this method"
}
private void OnFrameReceived(Frame frame) //Frame is the class in which the code puts the data from the camera, frame is the last pack of data received from the camera
{
Bitmap myBitmap = null;
if (true == m_Acquiring)
{
try
{
mycamera.QueueFrame(frame);
}
catch (Exception)
{
MessageBox.Show("Frame queuing failed.", "Something went wrong !", MessageBoxButtons.OK, MessageBoxIcon.Warning);
}
}
else
{
MessageBox.Show("Acquisition is not running.", "Something went wrong !", MessageBoxButtons.OK, MessageBoxIcon.Warning);
}
featureExposureTime.FloatValue = (double)hScrollBarLiveExposureTime.Value;
frame.Fill(ref myBitmap);
pictureBoxLiveCamera.Image = myBitmap;
SaveBitmap = myBitmap; //Up until here the code works perfectly, because I can use SaveBitmap without problem later in the code (not shown here)
Array.Clear(PixelColorCount, 0, 256);
foreach (var Series in chartHist.Series)
{
Series.Points.Clear();
}
//Collecting data from pictureBoxFixe1
for (int i = 1; i < 1023; i++)
{
for (int j = 1; j < 767; j++)
{
PixelColorCount[SaveBitmap.GetPixel(i, j).B] += 1;
}
}
//Plotting the pixel counter, to detect saturation
for (int i = 0; i < 256; i++)
{
chartHist.Series["Pixel count"].Points.AddXY(i, PixelColorCount[i]);
}
//If there are saturated pixels : toggle a title on chart 1 to warn the user
if (PixelColorCount[255] > 1)
{
chartInit.Titles["Title1"].Visible = true;
}
else { }
}

很抱歉代码量,但我认为我不能这样做。我的问题是直方图根本没有显示(好吧,它被设置为可见,我看到了标题,但没有绘制任何内容)。有人知道吗?

让我发疯的是,相机随附的 VimbaViewer 程序以完美的方式完全完成了我想要的,但我无法访问它的源代码......

谢谢!

如果我正确遵循,您的 OnFrameReceived 事件将正确触发,但在处理每个帧后,WinForm 应用程序 UI 不会更新。

看起来"chartInit"在你的OnFrameReceived而不是"chartHist"中被引用,应该是这样吗?

无论您的图表控件是什么,请尝试"图表。刷新()"或"图表。更新()"。它可能不会从事件循环更新 UI 线程。

您需要考虑的另一件事是这些图像的传入速度。它会每秒绘制和重绘图表 15-20 次吗?这合理吗?可能需要某种队列/平均机制来仅每x秒更新一次图表,或者如果超过图像更改的某个阈值。只是一个想法。

最新更新