4

カメラ (30fps @ 640x480) からビデオ フレームをキャプチャして処理し、Windows フォームに表示するアプリケーションを構築しています。最初は DrawImage (以下のコードを参照) を使用していましたが、パフォーマンスはひどいものでした。処理ステップを無効にしても、2.8GHz Core 2 Duo マシンで 20fps が得られます。Windows フォームでダブル バッファリングが有効になっていると、ティアリングが発生します。

注: 使用されるイメージは、Format24bppRgb 形式のビットマップです。DrawImage は Format32bppArgb 形式の画像を使用すると高速になるはずですが、フレーム グラバーから出力される形式によって制限されます。

private void CameraViewForm_Paint(object sender, PaintEventArgs e)
{
    Graphics g = e.Graphics;

    // Maximize performance
    g.CompositingMode = CompositingMode.SourceOver;
    g.PixelOffsetMode = PixelOffsetMode.HighSpeed;
    g.CompositingQuality = CompositingQuality.HighSpeed;
    g.InterpolationMode = InterpolationMode.NearestNeighbor;
    g.SmoothingMode = SmoothingMode.None;

    g.DrawImage(currentFrame, displayRectangle);
}

Textures と Spites (以下を参照) で Managed DirectX 9 を使用してみましたが、パフォーマンスはさらに低下しました。私は DirectX プログラミングに非常に慣れていないため、これは最適な DirectX コードではない可能性があります。

private void CameraViewForm_Paint(object sender, PaintEventArgs e)
{
    device.Clear(ClearFlags.Target, Color.Black, 1.0f, 0);

    device.BeginScene();

    Texture texture = new Texture(device, currentFrame, Usage.None, Pool.Managed);
    Rectangle textureSize;

    using (Surface surface = texture.GetSurfaceLevel(0))
    {
        SurfaceDescription surfaceDescription = surface.Description;
        textureSize = new Rectangle(0, 0, surfaceDescription.Width, surfaceDescription.Height);
    }
    Sprite sprite = new Sprite(device);

    sprite.Begin(SpriteFlags.None);
    sprite.Draw(texture, textureSize, new Vector3(0, 0, 0), new Vector3(0, 0, 0), Color.White);
    sprite.End();

    device.EndScene();

    device.Present();

    sprite.Dispose();
    texture.Dispose();
}

XP、Vista、および Windows 7 で動作させるには、これが必要です。XNA または OpenGL を試す価値があるかどうかはわかりません。これは、達成するのが非常に簡単なことのように思えます。

4

2 に答える 2

3

答えは目の前にあります。これは古い質問に対する遅い回答ですが、誰かが回答を必要とするかもしれません...

描画ループ内で新しいテクスチャと四角形を宣言する代わりに (これはリソースに非常に負荷がかかります)、範囲外でテクスチャを作成してみませんか? たとえば、あなたのものの代わりに、これを試してください:

Texture texture;
Rectangle textureSize;
private void InitiateTexture()
{
    texture = new Texture(device, new Bitmap("CAR.jpg"), Usage.None, Pool.Managed);

    using (Surface surface = texture.GetSurfaceLevel(0))
    {
        SurfaceDescription surfaceDescription = surface.Description;
        textureSize = new Rectangle(0, 0, 
                          surfaceDescription.Width, 
                          surfaceDescription.Height);
    }
}
protected override void OnPaint(System.Windows.Forms.PaintEventArgs e)
{
    device.Clear(ClearFlags.Target, Color.DarkSlateBlue, 1.0f, 0);
    device.BeginScene();

    Sprite sprite = new Sprite(device);

    sprite.Begin(SpriteFlags.None);
    sprite.Draw(texture, textureSize, 
    new Vector3(0, 0, 0), 
    new Vector3(0, 0, 0), Color.White);
    sprite.End();
    device.EndScene();
    device.Present();
}

複数のテクスチャを開始する必要がある場合は、それをリストにしてから、そのリストからペイントします。リソースを使用してから各ペイントを解放する必要がなくなります。

于 2012-01-10T04:51:33.983 に答える
0

CameraViewFormはビューアウィンドウ全体ですか?その場合、ペイントでは、すべてのボタン、プログレスバーなどを含むウィンドウ全体が再描画されます。これは、フォーム上のコントロールの数、およびデスクトップ用に有効にした視覚的なお父さんに応じて、多かれ少なかれ高価になります。さまざまなOSの要素(ウィンドウバーの透明度など)。

フォーム全体をシングルバッファリングしてみてください。ただし、GreateGraphics()を呼び出すとき、またはPanelでInvalidate()を呼び出す前に、新しいものを宣言することにより、Panel(displayRectangleを取得すると想定します)に独自のBufferedGraphicsContextを与えます。これにより、パネルをフォームとは別にダブルバッファリングできます。

于 2010-10-01T18:21:17.540 に答える