【发布时间】:2021-12-21 11:12:20
【问题描述】:
我的任务是尽快显示来自相机的帧。相机是Basler Dart,每秒可以产生超过70帧。不幸的是它不支持流输出,但它会生成位图。
现在我们的解决方案类似于 Basler 示例中的解决方案,但它使用PictureBox 来显示帧。我在某处读到它很慢,应该使用更好的解决方案。我同意它很慢,因为在显示所有 70 fps 时它会占用 25% 的 CPU(仅相机,应用程序的其余部分仅占用 5%)。不幸的是,我还没有找到更好的解决方案。
private void OnImageGrabbed(Object sender, ImageGrabbedEventArgs e)
{
if (InvokeRequired)
{
// If called from a different thread, we must use the Invoke method to marshal the call to the proper GUI thread.
// The grab result will be disposed after the event call. Clone the event arguments for marshaling to the GUI thread.
BeginInvoke( new EventHandler<ImageGrabbedEventArgs>( OnImageGrabbed ), sender, e.Clone() );
return;
}
try
{
// Acquire the image from the camera. Only show the latest image. The camera may acquire images faster than the images can be displayed.
// Get the grab result.
IGrabResult grabResult = e.GrabResult;
// Check if the image can be displayed.
if (grabResult.IsValid)
{
// Reduce the number of displayed images to a reasonable amount if the camera is acquiring images very fast.
if (!stopWatch.IsRunning || stopWatch.ElapsedMilliseconds > 100)
{
stopWatch.Restart();
bool reqBitmapOldDispose=true;
if(grConvBitmap==null || grConvBitmap.Width!=grabResult.Width || grConvBitmap.Height!=grabResult.Height)
{
grConvBitmap = new Bitmap(grabResult.Width, grabResult.Height, PixelFormat.Format32bppRgb);
grConvRect=new Rectangle(0, 0, grConvBitmap.Width, grConvBitmap.Height);
}
else
reqBitmapOldDispose=false;
// Lock the bits of the bitmap.
BitmapData bmpData = grConvBitmap.LockBits(grConvRect, ImageLockMode.ReadWrite, grConvBitmap.PixelFormat);
// Place the pointer to the buffer of the bitmap.
converter.OutputPixelFormat = PixelType.BGRA8packed;
IntPtr ptrBmp = bmpData.Scan0;
converter.Convert( ptrBmp, bmpData.Stride * grConvBitmap.Height, grabResult );
grConvBitmap.UnlockBits( bmpData );
// Assign a temporary variable to dispose the bitmap after assigning the new bitmap to the display control.
Bitmap bitmapOld = pictureBox.Image as Bitmap;
// Provide the display control with the new bitmap. This action automatically updates the display.
pictureBox.Image = grConvBitmap;
if (bitmapOld != null && reqBitmapOldDispose)
{
// Dispose the bitmap.
bitmapOld.Dispose();
}
}
}
}
catch (Exception exception)
{
ShowException(exception, "OnImageGrabbed" );
}
finally
{
e.DisposeGrabResultIfClone();
}
}
我的想法是将负载转移到 GPU。我尝试过 SharpGL (OpenGL for C#),但它似乎不能每秒消耗 70 个纹理,但我想这是因为我在 60 分钟内完成了 OpenGL 学习基础的解决方案。
我的问题是:我应该使用什么来代替 PictureBox 来提高功率并减少 CPU 负载?我应该使用 OpenGL 还是只限制显示的帧(如示例所示)? PC 只有集成显卡(Intel i3 第 6 代)。
【问题讨论】: