2010-10-01 22 views
3

Je suis en train de créer une application qui capture les images vidéo d'une caméra (30fps @ 640x480), les traite et les affiche ensuite sur un Windows Form. J'utilisais initialement DrawImage (voir le code ci-dessous) mais la performance était terrible. Même avec l'étape de traitement désactivée, le meilleur que je peux obtenir est de 20fps sur une machine Core 2 Duo à 2,8 GHz. La double mise en mémoire tampon est activée sur le formulaire Windows sinon je me déchire.Le moyen le plus rapide de dessiner une série de bitmaps avec C#

Remarque: L'image utilisée est une image bitmap au format Format24bppRgb. Je sais que DrawImage est censé être plus rapide avec une image formatée Format32bppArgb mais je suis limité par le format qui sort de la capture d'image. J'ai essayé d'utiliser Managed DirectX 9 avec Textures and Spites (voir ci-dessous), mais les performances étaient encore plus mauvaises. Je suis très nouveau à la programmation DirectX donc ce n'est peut-être pas le meilleur code 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(); 
} 

J'ai besoin que cela fonctionne sur XP, Vista et Windows 7. Je ne sais pas si cela vaut la peine d'essayer XNA ou OpenGL. Cela semble être une chose très simple à accomplir.

+0

La plupart des interfaces de capture disposent d'une fonction de prévisualisation qui s'attache directement à la poignée de la fenêtre, puis peint sans aucun problème. Si vous n'avez pas cette option, êtes-vous capable de plonger dans DirectShow? Si oui, je pourrais avoir une réponse pour vous. –

Répondre

0

CameraViewForm est-il entièrement votre fenêtre de visionneuse? Si c'est le cas, puis sur Paint, toute la fenêtre est redessinée, y compris tous les boutons, barres de progression, etc. Cela sera plus ou moins cher selon le nombre de contrôles sur votre formulaire, et les doo-papads visuels que vous avez activés pour le bureau éléments dans divers OS (par exemple, la transparence de la barre de fenêtre). Essayez de mettre en tampon unique tout le formulaire, mais en donnant au Panel (dont je suppose que vous obtenez displayRectangle) son propre BufferedGraphicsContext, en en déclarant un nouveau lorsque vous appelez GreateGraphics() ou avant d'appeler Invalidate() sur le Panel. Cela permet au panneau d'être à double tampon séparément du formulaire.

3

La réponse est juste en face de vous. C'est une réponse tardive à une vieille question, mais quelqu'un pourrait avoir besoin de la réponse ...

Au lieu de déclarer de nouvelles textures et rectangles dans votre boucle de dessin (ce qui est assez intense sur les ressources) pourquoi ne pas créer une texture à l'extérieur Le viseur? Au lieu de votre un, par exemple, essayez ceci:

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(); 
} 

et si vous avez besoin d'initier plusieurs textures, faites-le dans une liste, puis la peinture de cette liste. Cela évite d'avoir à utiliser des ressources puis de les libérer de chaque peinture.