从Vimba相机处理每个帧

时间:2018-04-12 13:59:33

标签: c# image image-processing camera

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

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

我并没有要求你帮助我完成整个过程,但我有一个不起作用的确切例子,我想理解。我正在使用Vimba .NET API,因此大多数人可能都不熟悉所调用的一些函数(对我来说它们并不是很多,真的),但我会尽力在代码中解释它们(API手册有点神秘)。

我的代码有一个部分,当我从相机中隔离一帧以对其进行处理时(通过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); } } 事件,绘制一个直方图,绘制垂直轴上的像素数和数字数值水平轴。这样我知道是否有些像素是饱和的(在255处),我可以降低曝光时间。这很好用,这里是按钮的代码,它隔离一帧并绘制直方图:

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 { }
}

现在我想要的是让这个工作生动,每一帧从相机传入。但它不起作用,我找不到原因。这是我试过的:

ERROR in src/app/rcyc-components/rcyc-channels/rcyc-channels.component.ts(53,44): error TS2339: Property '_urlSegment' does not exist on type 'ActivatedRouteSnapshot'.

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

让我发疯的事情是,随相机提供的VimbaViewer程序完全按照我想要的方式完成,但我无法访问它的源代码......

谢谢!

1 个答案:

答案 0 :(得分:0)

如果我正确关注,您的OnFrameReceived事件正在正确触发,但在处理完每个帧后WinForm应用程序UI没有更新。

看起来&#34; chartInit&#34;在你的OnFrameReceived中被引用而不是&#34; chartHist&#34;,那应该是这种情况吗?

无论您的图表控件是什么,请尝试&#34; chart.Refresh()&#34;或者&#34; chart.Update()&#34;。它可能不是从事件循环更新UI线程。

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