Kamera Auslesen, Fragen zu DIB



  • Ich habe eine Kamera die ich mit C++ auslesen möchte. Leider habe ich als Beispielcode für die DLL nur Delphi Code und stehe vor dem Rätsel wie man das nun in MFC unsemtzen könnte.

    Da steht folgendes (delpi code, gekürzt):

    pBuf : pointer;
    DibPixels : pchar;
    FrameBuf : TRgbPixArray;
    FrameP : PChar;
    Status := CxGetSnapshot(H, 1, True, True, True, FrameP, RAME_WIDTH*FRAME_HEIGHT, RetLen);
    pBuf := FrameP;
    DibPixels:=pBuf;
    SetDIBitsToDevice(DC, dx, dy, ScW, ScH, 0, 0, 0, ScH, DibPixels, TBitMapInfo((@FDib)^), DIB_RGB_COLORS);
    

    SetDIBitsToDevice gibts ja auch in Win32
    aber wie setzte ich das ganze nun in MFC um?

    Konkret:
    - wie muss ich ein Array anlegen so dass die Daten als DIB darin gespeichert werden können?
    - gibt es eine andere/einfacherer Methode als SetDIBitsToDevice um dieses Array darzustellen?
    - was sollte ich sonst noch beachten?

    Matthias



  • Mal anders gefragt, hast du überhaupt schon ein Bild der Cam in einem IVideoWindow oder überhaupt etc., den so wie ich das sehe, sind wohl gesonderte Delphidateien dazu zuständig und solang du die Cam noch nicht in einem FilterGraph mit SampleGrabber hast, oder eine CaptureCallback für VfW, bringt dir das da reichlich wenig.



  • orr lol schrieb:

    Mal anders gefragt, hast du überhaupt schon ein Bild der Cam in einem IVideoWindow oder überhaupt etc., den so wie ich das sehe, sind wohl gesonderte Delphidateien dazu zuständig und solang du die Cam noch nicht in einem FilterGraph mit SampleGrabber hast, oder eine CaptureCallback für VfW, bringt dir das da reichlich wenig.

    Ich verstehe nicht wirklich was du meinst.
    Für die (Film)Kamera gibt es ein Programm mit dem ich die Bilder anschauen, die Einstellungen verändern und ein Video abspeichern kann.

    Um das ganze auch selber machen zu können gibt es eine dll mit einer Wrapperklasse die die DLL lädt und die Funktionen zur Verfügung stellt (Alles C++). CxGetSnapshot ist eine solche Funktion.

    In Delphi6 und VB5 gibt es Beispielprojekte die diese DLL nutzen. Mein Problem ist nur eine äquivalente C++ Ansteuerung zu schreiben, und dabei genauer die Daten auf den Bildschirm zu bringen.

    Matthias



  • das mit dem IVideoWindow kannst ignoriern
    er redet von directshow und das benutzt du hier garnich und brauchst du auch nich

    nun zu deinem problem
    prinzipiell gibt es imho nur eine SetDIBitsToDevice funktion, d.h. delphi ruft
    die c funktion auf

    du musst also eigentich nur den delphi code in c++ umschreiben

    SetDIBitsToDevice funktioniert an sich so, dass du einen HDC von deinem fenster
    brauchst auf das du zeichnen willst, dann gibst gibst du noch den bereich an
    den du zeichnen willst. an der adresse von lpvBits müssen sich die bilddaten
    befinden und dann musst du auch noch einen Bitmapinfoheader übergeben der das
    format der bilddaten enthält.

    is an sich nich so schwer aber beim ersten mal n bissi hakelig.

    http://msdn2.microsoft.com/en-us/library/ms532346.aspx



  • Ich habe jetzt folgendes probiert und wüsste gerne ob das vom Ansatz her richtig ist. Inbesondere ist mir unklar ob BYTE die richtige Initialisierung für ein Array von DIB Daten ist.

    BYTE* m_CameraFrameArray;
    
    CDlgCamera::CDlgCamera(CWnd* pParent /*=NULL*/)
    	: CDialog(CDlgCamera::IDD, pParent)
    {
    	m_camera.Initialize(); //loads Camera dll and does initialisation
    	m_HandleCamera = m_camera.CxOpenDevice(0); // open camera and save device
    	m_camera.CxGetScreenParams(m_HandleCamera, &m_CameraParameters);
    	m_CameraSize.x=m_CameraParameters.Width;
    	m_CameraSize.y=m_CameraParameters.Height;
    	m_CameraFrameArray = new BYTE[m_CameraSize.x * m_CameraSize.y];	
    }
    
    int BufSize = m_CameraSize.x*m_CameraSize.y;
    	int iTimeOut=1;
    	bool boolTriggerEnabled = false;
    	bool boolTriggerPosEnabled = false;
    	DWORD *retlength;
    	int result = m_camera.CxGetSnapshot(m_HandleCamera, 
    		iTimeOut, 
    		boolTriggerEnabled, 
    		boolTriggerPosEnabled, 
    		true, 
    		m_CameraFrameArray, 
    		BufSize, 
    		retlength);
    
    	m_WndGraphCamera.SetDIB(m_CameraFrameArray);
    
    void CGraphCtrl::SetDIB(BYTE* DIBArray)
    {	
    	if  ((PixelNumber.x>0) && (PixelNumber.y > 0))
    	{
    		DIBDataEnabled = true;
    		pDIBData = new BYTE[PixelNumber.x*PixelNumber.y];
    		memcpy(pDIBData, DIBArray, PixelNumber.x*PixelNumber.y*sizeof(BYTE));
    	}
    }
    
    void CGraphCtrl::OnPaint() 
    {
    	CPaintDC dc(this); // device context for painting	
    
    	if (PixelNumber.x == 0)
    		return;
    
    	if (DIBDataEnabled)
    	{
    
       //First step: Create BITMAP Header info:
      BITMAPINFOHEADER bitmapInfo;
      ::ZeroMemory(&bitmapInfo,sizeof(BITMAPINFOHEADER));
      bitmapInfo.biSize = sizeof(BITMAPINFOHEADER);
      bitmapInfo.biWidth = PixelNumber.x;/*enter Width*/
      bitmapInfo.biHeight = PixelNumber.y;/*enter Height*/
      bitmapInfo.biPlanes = 1;
      bitmapInfo.biBitCount = 32/*bit per pixel 24,32 */ ; //<-------LOOK HERE!!!
      bitmapInfo.biCompression = 0;  //RGB
      bitmapInfo.biSizeImage = bitmapInfo.biWidth*bitmapInfo.biHeight*bitmapInfo.biBitCount/8;
    
    SetDIBitsToDevice(dc, 0, 0, bitmapInfo.biWidth, bitmapInfo.biHeight, 0, 0, 0, bitmapInfo.biHeight, pDIBData, (LPBITMAPINFO)&bitmapInfo, DIB_RGB_COLORS);
    		DIBDataEnabled=false;
    		return;
    	}
    }
    

    In der jetzigen Form stürzt das Programm jedoch bei "CxGetSnapshot" ab.

    Matthias



  • welches bildformat hat die kamera, was sagt die kamera doku?
    in deinem code nimmst du ein graubild mit einem hpitch von einem byte und einem vpitch von m_CameraParameters.Width byte an.

    bist sicher, dass des stimmt?

    BYTE is als datentyp ok denk ich... kannst aber auch gleich unsigned char* nehmen

    was bedeuten die parameter von CxGetSnapshot?



  • Sovok schrieb:

    welches bildformat hat die kamera, was sagt die kamera doku?

    Das bekomme ich mit

    m_camera.CxGetScreenParams(m_HandleCamera, &m_CameraParameters);
        m_CameraSize.x=m_CameraParameters.Width;
        m_CameraSize.y=m_CameraParameters.Height;
    

    Kann ich aber auch einstellen mit

    m_camera.CxSetScreenParams(m_HandleCamera, &m_CameraParameters);
    

    Sovok schrieb:

    in deinem code nimmst du ein graubild mit einem hpitch von einem byte und einem vpitch von m_CameraParameters.Width byte an.

    Diese Daten sagen mir jetzt nichts. Ein Graybild ist es aber auf jeden Fall.

    Sovok schrieb:

    BYTE is als datentyp ok denk ich... kannst aber auch gleich unsigned char* nehmen

    Ich hatte an 8 Bit gedacht. Dann vermute ich das unsigned char* auch 8 Bit breit ist.

    Sovok schrieb:

    was bedeuten die parameter von CxGetSnapshot?

    Aus der Doku:

    CxGetSnapshot

    Grabs the hardware snapshot into the memory buffer.

    Parameters:
    DeviceHandle 32-bit integer value previously returned by CxOpenDevice function
    Timeout 32-bit integer value, wait timeout period, sec
    ExtTrgEnabled boolean, TRUE if wait external event
    ExtTrgPositive boolean, TRUE if wait positive level else negative
    SnapshotMode boolean, reserved, always True
    pBuf pointer to the frame buffer that receives the data
    BufSize 32-bit integer value specifying the buffer size, in bytes
    pRetLen pointer to 32-bit unsigned integer receiving the return snapshot size

    Return Value:
    Nonzero if successful

    Remarks:
    This function requires to turn the video stream OFF.

    Matthias



  • es geht im prinzip darum, dass manche kameras z.b. ein 640x480 bild haben
    aber z.b. 800x600 byte speicher für die bildaufnahme brauchen

    hpitch = horizontaler abstand zweier pixel im bild in bytes
    vpitch = vertikaler abstand zweier zeilen im bild in bytes

    der absturz deutet drauf hin, dass über den speicherbereich rausgelaufen wird
    kannst du noch posten welche exception auftritt?

    müsstest du im debugmodus im ausgabefenster sehn
    ich tipp auf access violation


Anmelden zum Antworten