Laden...

Bild aus Kamerabuffer erstellen und in Anwendung ausgeben

Erstellt von userid3554 vor 16 Jahren Letzter Beitrag vor 16 Jahren 3.671 Views
U
userid3554 Themenstarter:in
38 Beiträge seit 2006
vor 16 Jahren
Bild aus Kamerabuffer erstellen und in Anwendung ausgeben

Hallo Leute!

Ich habe eine Kamera der Firma Prosilica vor mir liegen, welche einen Ethernet Anschluss besitzt!

Was ich machen will, ist eine einfache C#-Anwendung die mir direkt in einer PictureBox oder einem Sonstigen Steuerelement(weis nicht was hier am besten ist, dachte aber mal PictureBox) die aktuellen Bilder die die Kamera erfasst ausgibt...
(z.B.: 5 Bilder/Sekunde... ist aber jetzt noch nicht weiter wichtig... ist ja später einstellbar)

Ich habe da einmal selbst ein wenig rum gebastelt, nur was ich habe ist nicht optimal!
Von dem Bild wird jedes einzelne Pixel in ein byte-Array(Buffer) gespeichert(1024x768 Werte) und anschließend wird in der PictureBox jedes einzelne Pixel gezeichnet und ausgegeben...
Natürlich wie man daran erkennen kann dauert dies schon einige Sekunden, bzw. einfach viiiel zu lange bis das Bild dann vorhanden ist!

Daher möchte ich gerne wissen ob es in C# eine geeignetere Funktion dafür gibt?

Anbei der gesamte Code bzw. weiter unten die Funktion die das Bild erstellt:


using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using PvNET;
using System.Threading;
using System.Runtime.InteropServices;
using System.IO;
using System.Drawing.Imaging;

namespace Kamera_Tests
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        //////////////////////////////////////////////////////
        //Kameradaten erfassen    Anfang                    
        //                                                 
        //Bei Klick auf den Button werden Details ausgegeben
        //////////////////////////////////////////////////////
        private void btnTest_Click(object sender, EventArgs e)
        {
            tErr err = 0;

            if ((err = Pv.Initialize()) == 0)
            {
                UInt32 Major, Minor, Count, Handle, UID = 14;
                tCameraInfo Info = new tCameraInfo();
                tCameraInfo[] List = new tCameraInfo[10];
                tIpSettings Settings = new tIpSettings();
                tIpSettings[] IPS = new tIpSettings[10];

                Major = 0;
                Minor = 0;
                Count = 0;

                Pv.Version(ref Major, ref Minor);
                Ausgabe("using API");
                Ausgabe("Major: ", Major.ToString());
                Ausgabe("Minor: ", Minor.ToString());

                Thread.Sleep(1500); //Zeit zum Suchen geben

                Ausgabe("Anzahl der Cams: ", Pv.CameraCount().ToString()); //Zeigt die Anzahl der angeschlossenen Cams an

                if ((Count = Pv.CameraList(List, 10, ref Count)) != 0)
                {
                    for (uint i = 0; i < Count; i++)
                    {
                        //Datenausgabe
                        Ausgabe("UniqueID: " + List[i].UniqueId.ToString()); 
                        Ausgabe("CAM-Name: " + List[i].DisplayName.ToString()); 
                        Ausgabe("InterfaceID: ", List[i].InterfaceId.ToString());
                        Ausgabe("PartVersion: ", List[i].PartVersion.ToString());
                        Ausgabe("Serialstring: ", List[i].SerialString.ToString());
                        Ausgabe("InterfaceType: ", List[i].InterfaceType.ToString());
                        Ausgabe("PartNumber: ", List[i].PartNumber.ToString());
                        Ausgabe("PermittedAccess: ", List[i].PermittedAccess.ToString());
                    }
                }
                else
                    Ausgabe("Keine Daten - no cam"); 
            }
            else
            {
                Ausgabe("failed to initialize the API : ");
                Ausgabe(err.ToString());
            }
        }


        private void Ausgabe(string bezeichnung, string ausgabewert)
        {
            lbxAusgabe.Items.Add(bezeichnung + ausgabewert);
        }
        private void Ausgabe(string bezeichnung)
        {
            lbxAusgabe.Items.Add(bezeichnung);
        }
        private void Ausgabe(string as1, string as2, string as3)
        {
            lbxAusgabe.Items.Add(as1 + as2 + as3);
        }

        /////////////////////////////////////////////////////
        //Kameradaten erfassen    Ende                     //
        /////////////////////////////////////////////////////




        /////////////////////////////////////////////////////
        //Bild erfassen    Anfange                         //
        ///////////////////////////////////////////////////// 

        static void LinkCB(IntPtr Context, tInterface Interface, tLinkEvent Event, UInt32 UniqueId)
        {
         
        }

        static void FrameCB(IntPtr pFrame)
        {
            // marshal the pointer into a frame structure
            tFrame Frame = (tFrame)Marshal.PtrToStructure(pFrame, typeof(tFrame));
        }

        void CaptureFrame()
        {
            tErr err = 0;

            // Initialisieren
            if ((err = Pv.Initialize()) == 0)
            {
                UInt32 Major, Minor, Count, Handle, UID = 40044; 
                tLinkCallback lLinkCB = new tLinkCallback(LinkCB);
                tFrameCallback lFrameCB = new tFrameCallback(FrameCB);
                tCameraInfo Info = new tCameraInfo();
                tCameraInfo[] List = new tCameraInfo[10];
                tIpSettings Settings = new tIpSettings();

                Major = 0;
                Minor = 0;
                Count = 0;

                //Version lesen
                Pv.Version(ref Major, ref Minor);

                // Warten
                Thread.Sleep(1500);

                // Lesen der Information
                if (Pv.CameraInfo(UID, ref Info) == tErr.eErrSuccess && Pv.CameraIpSettingsGet(UID, ref Settings) == tErr.eErrSuccess)
                {
                    // open the camera (in master mode)
                    if (Pv.CameraOpen(UID, tAccessFlags.eAccessMaster, out Handle) == 0)
                    {
                        tAttributeInfo Detail = new tAttributeInfo();
                        IntPtr Strings = IntPtr.Zero;
                        UInt32 FrameSize = 0;

                        if (Pv.AttrUint32Get(Handle, "TotalBytesPerFrame", ref FrameSize) == 0)
                        {
                            tFrame Frame = new tFrame();
                            byte[] Buffer = new byte[FrameSize];
                            GCHandle pBuffer = GCHandle.Alloc(Buffer, GCHandleType.Pinned);
                            Pv.AttrUint32Set(UID, "PacketSize", 1500);
                            

                            // Framefelder setzen
                            Frame.Context.Field0 = new IntPtr(Handle);			// Handle zum Öffnen der Kamera	
                            Frame.ImageBuffer = pBuffer.AddrOfPinnedObject();	// @ of the pinned buffer
                            Frame.ImageBufferSize = FrameSize;					// Buffergröße

                            // Start des CaptureModes
                            if (Pv.CaptureStart(Handle) == 0)
                            {
                                // set the camera in continuous acquisition mode
                                if (Pv.AttrEnumSet(Handle, "FrameStartTriggerMode", "FixedRate") == 0)
                                {
                                    // and set the acquisition mode into continuous
                                    if (Pv.CommandRun(Handle, "AcquisitionStart") != 0)
                                    {
                                        // if that fail, we reset the camera to non capture mode
                                        Pv.CaptureEnd(Handle);
                                    }
                                    else
                                    {
                                        UInt32 Completed = 0;
                                        UInt32 Received = 0;

                                        // pin down a copy of the frame structure
                                        GCHandle pFrame = GCHandle.Alloc(Frame, GCHandleType.Pinned);

                                        // .BMP ERSTELLEN
                                        if (Pv.CaptureQueueFrame(Handle, pFrame.AddrOfPinnedObject(), lFrameCB) == 0)
                                        {
                                            Bitmap bmp = new Bitmap(1024, 768);
                                            int color;
                                            
                                            for (int y = 0; y < 768; y++)
                                            {
                                                for (int x = 0; x < 1024; x++)
                                                {
                                                    color = Buffer[y * 1024 + x];
                                                    bmp.SetPixel(x, y, Color.FromArgb(color, color, color));

                                                }
                                            }

                                            picFrame.Image = bmp; //Ausgabe in der PictureBox

                                        }

                                        Pv.CommandRun(Handle, "AcquisitionStop");
                                        Pv.CaptureEnd(Handle);
                                        Pv.CaptureQueueClear(Handle); //Warteschlange löschen

                                        // Release the Frame
                                        pFrame.Free();
                                    }
                                }
                                else
                                   MessageBox.Show("failed to set trigger mode");
                            }
                            else
                                MessageBox.Show("failed to start capture");

                            // Release the Buffer
                            pBuffer.Free();
                        }

                        if (Pv.CameraClose(Handle) != 0)
                            MessageBox.Show("failed to close the camera");
                    }
                    else
                        MessageBox.Show("failed to open the camera");

                }

                //CB löschen
                if (Pv.LinkCallbackUnregister(lLinkCB, tLinkEvent.eLinkAdd) != 0)
                    MessageBox.Show("failed to unregister CB");
                if (Pv.LinkCallbackUnregister(lLinkCB, tLinkEvent.eLinkRemove) != 0)
                    MessageBox.Show("failed to unregister CB");

                Pv.UnInitialize();
            }
            else
            {
                MessageBox.Show("failed to initialize the API : ");
            }

            Thread.Sleep(2000);
        }

        private void picFrame_Click(object sender, EventArgs e)
        {
            CaptureFrame();
        }
    }
}

Hier die kleine selbstgebastelte Ausgabefunktion:


 // .BMP ERSTELLEN
                                        if (Pv.CaptureQueueFrame(Handle, pFrame.AddrOfPinnedObject(), lFrameCB) == 0)
                                        {
                                            Bitmap bmp = new Bitmap(1024, 768);
                                            int color;
                                            
                                            for (int y = 0; y < 768; y++)
                                            {
                                                for (int x = 0; x < 1024; x++)
                                                {
                                                    color = Buffer[y * 1024 + x];
                                                    bmp.SetPixel(x, y, Color.FromArgb(color, color, color));

                                                }
                                            }

                                            picFrame.Image = bmp; //Ausgabe in der PictureBox

                                        }

Danke für jede hilfreiche Antwort!!!

94 Beiträge seit 2006
vor 16 Jahren

Vielleicht solltest du zuerst noch den Code etwas leserlicher gestalten!
Einfach nicht so viel einrücken,dann müsste es besser sein...

www.mkellenberger.ch Was ich täglich (neu) entdecke...

U
userid3554 Themenstarter:in
38 Beiträge seit 2006
vor 16 Jahren

Besser so?


using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using PvNET;
using System.Threading;
using System.Runtime.InteropServices;
using System.IO;
using System.Drawing.Imaging;

namespace Kamera_Tests
{
  public partial class Form1 : Form
  {
    public Form1()
    {
      InitializeComponent();
    }

    //////////////////////////////////////////////////////
    //Kameradaten erfassen    Anfang                    //
    //                                                  //
    //Bei Klick auf den Button werden Details ausgegeben//
    //////////////////////////////////////////////////////
    private void btnTest_Click(object sender, EventArgs e)
    {
      tErr err = 0;

      if ((err = Pv.Initialize()) == 0)
      {
        UInt32 Major, Minor, Count, Handle, UID = 14;
        tCameraInfo Info = new tCameraInfo();
        tCameraInfo[] List = new tCameraInfo[10];
        tIpSettings Settings = new tIpSettings();
        tIpSettings[] IPS = new tIpSettings[10];

        Major = 0;
        Minor = 0;
        Count = 0;

        Pv.Version(ref Major, ref Minor);
        Ausgabe("using API");
        Ausgabe("Major: ", Major.ToString());
        Ausgabe("Minor: ", Minor.ToString());

        Thread.Sleep(1500); //Zeit zum Suchen geben

        Ausgabe("Anzahl der Cams: ", Pv.CameraCount().ToString()); //Zeigt die Anzahl der angeschlossenen Cams an

        if ((Count = Pv.CameraList(List, 10, ref Count)) != 0)
        {
          for (uint i = 0; i < Count; i++)
          {
            //Datenausgabe
            Ausgabe("UniqueID: " + List[i].UniqueId.ToString());
            Ausgabe("CAM-Name: " + List[i].DisplayName.ToString());
            Ausgabe("InterfaceID: ", List[i].InterfaceId.ToString());
            Ausgabe("PartVersion: ", List[i].PartVersion.ToString());
            Ausgabe("Serialstring: ", List[i].SerialString.ToString());
            Ausgabe("InterfaceType: ", List[i].InterfaceType.ToString());
            Ausgabe("PartNumber: ", List[i].PartNumber.ToString());
            Ausgabe("PermittedAccess: ", List[i].PermittedAccess.ToString());
          }
        }
        else
          Ausgabe("Keine Daten - no cam");
      }
      else
      {
        Ausgabe("failed to initialize the API : ");
        Ausgabe(err.ToString());
      }
    }


    private void Ausgabe(string bezeichnung, string ausgabewert)
    {
      lbxAusgabe.Items.Add(bezeichnung + ausgabewert);
    }
    private void Ausgabe(string bezeichnung)
    {
      lbxAusgabe.Items.Add(bezeichnung);
    }
    private void Ausgabe(string as1, string as2, string as3)
    {
      lbxAusgabe.Items.Add(as1 + as2 + as3);
    }

    /////////////////////////////////////////////////////
    //Kameradaten erfassen    Ende                     //
    /////////////////////////////////////////////////////




    /////////////////////////////////////////////////////
    //Bild erfassen    Anfange                         //
    ///////////////////////////////////////////////////// 

    static void LinkCB(IntPtr Context, tInterface Interface, tLinkEvent Event, UInt32 UniqueId)
    {

    }

    static void FrameCB(IntPtr pFrame)
    {
      // marshal the pointer into a frame structure
      tFrame Frame = (tFrame)Marshal.PtrToStructure(pFrame, typeof(tFrame));
    }

    void CaptureFrame()
    {
      tErr err = 0;

      // Initialisieren
      if ((err = Pv.Initialize()) == 0)
      {
        UInt32 Major, Minor, Count, Handle, UID = 40044;
        tLinkCallback lLinkCB = new tLinkCallback(LinkCB);
        tFrameCallback lFrameCB = new tFrameCallback(FrameCB);
        tCameraInfo Info = new tCameraInfo();
        tCameraInfo[] List = new tCameraInfo[10];
        tIpSettings Settings = new tIpSettings();

        Major = 0;
        Minor = 0;
        Count = 0;

        //Version lesen
        Pv.Version(ref Major, ref Minor);

        // Warten
        Thread.Sleep(1500);

        // Lesen der Information
        if (Pv.CameraInfo(UID, ref Info) == tErr.eErrSuccess && Pv.CameraIpSettingsGet(UID, ref Settings) == tErr.eErrSuccess)
        {
          // open the camera (in master mode)
          if (Pv.CameraOpen(UID, tAccessFlags.eAccessMaster, out Handle) == 0)
          {
            tAttributeInfo Detail = new tAttributeInfo();
            IntPtr Strings = IntPtr.Zero;
            UInt32 FrameSize = 0;

            if (Pv.AttrUint32Get(Handle, "TotalBytesPerFrame", ref FrameSize) == 0)
            {
              tFrame Frame = new tFrame();
              byte[] Buffer = new byte[FrameSize];
              GCHandle pBuffer = GCHandle.Alloc(Buffer, GCHandleType.Pinned);
              Pv.AttrUint32Set(UID, "PacketSize", 1500);


              // Framefelder setzen
              Frame.Context.Field0 = new IntPtr(Handle);			// Handle zum Öffnen der Kamera	
              Frame.ImageBuffer = pBuffer.AddrOfPinnedObject();	// @ of the pinned buffer
              Frame.ImageBufferSize = FrameSize;					// Buffergröße

              // Start des CaptureModes
              if (Pv.CaptureStart(Handle) == 0)
              {
                // set the camera in continuous acquisition mode
                if (Pv.AttrEnumSet(Handle, "FrameStartTriggerMode", "FixedRate") == 0)
                {
                  // and set the acquisition mode into continuous
                  if (Pv.CommandRun(Handle, "AcquisitionStart") != 0)
                  {
                    // if that fail, we reset the camera to non capture mode
                    Pv.CaptureEnd(Handle);
                  }
                  else
                  {
                    UInt32 Completed = 0;
                    UInt32 Received = 0;

                    // pin down a copy of the frame structure
                    GCHandle pFrame = GCHandle.Alloc(Frame, GCHandleType.Pinned);

                    // .BMP ERSTELLEN
                    if (Pv.CaptureQueueFrame(Handle, pFrame.AddrOfPinnedObject(), lFrameCB) == 0)
                    {
                      Bitmap bmp = new Bitmap(1024, 768);
                      int color;

                      for (int y = 0; y < 768; y++)
                      {
                        for (int x = 0; x < 1024; x++)
                        {
                          color = Buffer[y * 1024 + x];
                          bmp.SetPixel(x, y, Color.FromArgb(color, color, color));

                        }
                      }

                      picFrame.Image = bmp; //Ausgabe in der PictureBox

                    }

                    Pv.CommandRun(Handle, "AcquisitionStop");
                    Pv.CaptureEnd(Handle);
                    Pv.CaptureQueueClear(Handle); //Warteschlange löschen

                    // Release the Frame
                    pFrame.Free();
                  }
                }
                else
                  MessageBox.Show("failed to set trigger mode");
              }
              else
                MessageBox.Show("failed to start capture");

              // Release the Buffer
              pBuffer.Free();
            }

            if (Pv.CameraClose(Handle) != 0)
              MessageBox.Show("failed to close the camera");
          }
          else
            MessageBox.Show("failed to open the camera");

        }

        //CB löschen
        if (Pv.LinkCallbackUnregister(lLinkCB, tLinkEvent.eLinkAdd) != 0)
          MessageBox.Show("failed to unregister CB");
        if (Pv.LinkCallbackUnregister(lLinkCB, tLinkEvent.eLinkRemove) != 0)
          MessageBox.Show("failed to unregister CB");

        Pv.UnInitialize();
      }
      else
      {
        MessageBox.Show("failed to initialize the API : ");
      }

      Thread.Sleep(2000);
    }

    private void picFrame_Click(object sender, EventArgs e)
    {
      CaptureFrame();
    }
  }
}



if (Pv.CaptureQueueFrame(Handle, pFrame.AddrOfPinnedObject(), lFrameCB) == 0)
{
     Bitmap bmp = new Bitmap(1024, 768);
     int color;

     for (int y = 0; y < 768; y++)
     {
          for (int x = 0; x < 1024; x++)
          {
               color = Buffer[y * 1024 + x];
               bmp.SetPixel(x, y, Color.FromArgb(color, color, color));
          }
      }
    
      picFrame.Image = bmp; //Ausgabe in der PictureBox
}

49.485 Beiträge seit 2005
vor 16 Jahren

Hallo suam111,

Besser so?

ich glaube, es war nicht nur Anzahl der Zeichen, um die pro Einrückungsebene eingerückt wird, gemeint, sondern eher die Anzahl der Einrückungsebenen. Viele Einrückungsebenen machen den Code schwerer zu verstehen und somit anfälliger für Fehler.

Daher möchte ich gerne wissen ob es in C# eine geeignetere Funktion dafür gibt? GetPixel und SetPixel um Längen geschlagen. 800 mal schneller

herbivore

U
userid3554 Themenstarter:in
38 Beiträge seit 2006
vor 16 Jahren

Original von herbivore


>

Habe das jetzt eingebaut...
tolle Sache hat es weit beschleunigt!
Doch das Problem ist jetzt, dass der ganz "Stream" noch ziemlich ruckelt...
Jedes Bild dauert beim erstellen ca. 0,3-0,6 Sekunden!
(Größe: 640x480)

Ich habe folgendes gebastelt...
Bei klick auf einen Button sollten 10 Bilder geschossen werden dies wird folgender Weise realisiert:


private void button1_Click(object sender, EventArgs e)
    {
      for (int i = 0; i < 10; i++)
      {
        CaptureFrame();
 
      }
    }

Danach durchläuft es die Funktion:

Hier der wichtigste Ausschnitt der Funktion


                      Bitmap test = new Bitmap(640, 480); // Bitmap neu laden
                      FastBitmap rob = new FastBitmap(test); // FastBitmap davon erzeugen
                      // leere Bitmap gleicher Größe erstellen
                      Bitmap test2 = new Bitmap(640, 480, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
                      FastBitmap rob2 = new FastBitmap(test2); // FastBitmap davon erzeugen
                     // test2 = new Bitmap(test.Width, test.Height, System.Drawing.Imaging.PixelFormat.Format24bppRgb);

                      int color;
                      //Zeit bestimmen,die das Bildumwandeln benötigt
                      DateTime now1 = DateTime.Now;

                      for (int x = 0; x < rob.Width; x++)
                        for (int y = 0; y < rob.Height; y++)
                        {
                          color = Buffer[y * 640 + x];
                          rob2.SetPixel(x, y, Color.FromArgb(color, color, color));
                        }
                    
                      
                      picFrame.Image = rob2.ToBitmap();// kommt das Richtige Bild heraus?

Wo oder/und wie kann ich noch mehr Zeit einsparen, bzw einen Echtzeit-Stream erzeugen?
Der Buffer wird von der Kamera geliefert, in dem Buffer stehen 640x480 Color-Werte mit denen dann jedes einzelne Bild gezeichnet wird

Bin über jede Hilfe dankbar!!!!

2.760 Beiträge seit 2006
vor 16 Jahren

Du könntest die Qualität einstellbar machen und dann Interlacing benutzen.

U
userid3554 Themenstarter:in
38 Beiträge seit 2006
vor 16 Jahren

Qualität sollte gleich bleiben...
jetzt ist es ja so, dass jedes mal bei klick 10mal die funktion durchlaufen wird...
das heisst, der Buffer wird immer weider neu gefüllt das dauert ja schon ne weile meiner meinung nach...
könnte man da nicht einsparen indem man irgendwie sagt, dass nur die Pixel die einen neuen wert besitzen überschrieben werden, oder macht das keinen sinn?

2.760 Beiträge seit 2006
vor 16 Jahren

Das wäre dann evtl. sowas in der Richtung:
http://www.codeproject.com/cs/media/Motion_Detection.asp