Webcam wie kommt man an die Bilddaten



  • Hi ich habe mich in letzter Zeit damit beschäftigt meine Webcam in ein c++ Programm einzubinden. Hier im Forum habe ich einen quellcode von www.allanpetersen.com gefunden:

    //---------------------------------------------------------------------------
    
    #include <vcl.h>
    #pragma hdrstop
    
    #include <stdio.h>
    #include "c_cap.h"
    
    //---------------------------------------------------------------------------
    #pragma package(smart_init)
    
    __fastcall TCap::TCap (HWND Handle)
    {
    		// create video capture window
    		ParentHandle = Handle;
    		hwndVideo = capCreateCaptureWindow(
    					(LPSTR) "My Capture Window",
    					WS_CHILD | WS_VISIBLE,
    					0, 0, 300, 200,
    					(HWND) Handle,
    					(int) 1);
    
    		pStringCapDrivers = new TStringList;
    		SelectedDevice = -1;
    }
    
    __fastcall TCap::~TCap ()
    {
    
            delete pStringCapDrivers;
    
            capCaptureStop(hwndVideo);
            capPreview(hwndVideo, FALSE); // end preview
            capDriverConnect(hwndVideo, SelectedDevice);
            capDriverDisconnect(hwndVideo); // disconnect from driver
            capCaptureAbort(hwndVideo);
    }
    
    //---------------------------------------------------------------------------
    // enumerate the installed capture drivers
    //---------------------------------------------------------------------------
    int TCap::EnumCapDrv ()
    {
        char szDeviceName[80]; // driver name
        char szDeviceVersion[80]; // driver version
        char str[161]; // concatinated string
        int xcap; // counter
    
            xcap = 0;
            pStringCapDrivers->Clear ();
            do
            {
                    if (capGetDriverDescription(xcap, szDeviceName, sizeof(szDeviceName),
                    szDeviceVersion, sizeof(szDeviceVersion)))
                    {
                            sprintf (str, "%s, %s", szDeviceName, szDeviceVersion);
                            pStringCapDrivers->AddObject (str, (TObject *)xcap);
                    }
                    else
                    {
                            break;
                    }
                    xcap++;
            } while (true);
    
            return 0;
    }
    
    //---------------------------------------------------------------------------
    //  connecting to selected device and starts preview
    //---------------------------------------------------------------------------
    void TCap::Connect (int Selected)
    {
            CAPSTATUS CapStatus;
            int       hsize;
    
            // capDlgVideoDisplay(hwndVideo);
            // connect to the driver
            if (SelectedDevice != -1)
            {
            capPreview (hwndVideo, FALSE);
            capDriverConnect(hwndVideo, SelectedDevice);
            }
    
            if (!capDriverConnect(hwndVideo, Selected))
            {
            // ---- Unable to connect to driver
            return;
            }
    
            // update the driver capabilities
            capDriverGetCaps (hwndVideo, sizeof(CAPDRIVERCAPS), &CapDrvCaps);
    
            capDlgVideoFormat(ParentHandle);
    
    //-----------------------------------------------------------------------------
    
    //**********Eigene Veränderungen an dem Header*********************************
    //-----------------------------------------------------------------------------
            //Die Standarteinstellungen laden
    	DWORD dwSize;                                             // Länge der Formateigenschaften
    	BITMAPINFO pbiInfo;                                       // Bitmap-Eigenschaften der Datei
    
    	dwSize=capGetVideoFormatSize(hwndVideo);                  // Messen der Länge
    
    	capGetVideoFormat(hwndVideo, &pbiInfo, dwSize);           // Momentane Formatierung laden
    
        // Einstellen der neuen Werte
        DWORD dwWidth,dwHeight,dwBPP;
    
    		dwWidth=640;                                          // Horizontale Auflösung
    		dwHeight=480;                                         // Vertikale Auflösung
    		dwBPP=24;                                             // Farbtiefe
    
        pbiInfo.bmiHeader.biWidth = dwWidth;
        pbiInfo.bmiHeader.biHeight = dwHeight;
        pbiInfo.bmiHeader.biBitCount = (WORD) dwBPP;
    
    	pbiInfo.bmiHeader.biSizeImage = 0;                        // Größe der reservierten Bytes
    	pbiInfo.bmiHeader.biCompression = BI_RGB;                 // Komprimierung (BI_RGB=keine Kompr.)
    	pbiInfo.bmiHeader.biClrUsed = 0;                          // Maximale Anzahl der dargestellten
    	pbiInfo.bmiHeader.biClrImportant = 0;                     // Farben, 0=alle Farben
    	pbiInfo.bmiHeader.biPlanes = 1;                           // Einstellung der Treiberebenen. Muss 1 sein
    
    	pbiInfo.bmiColors->rgbBlue = 0;                           // Eingabe der Farbverstärkung der
    	pbiInfo.bmiColors->rgbGreen = 0;                          // Grundfarben. 0=keine Verstärkung
        pbiInfo.bmiColors->rgbRed = 0;
    	pbiInfo.bmiColors->rgbReserved = 0;                       // Muss auf 0 gesetzt sein
    
        //Zurückschreiben zur API
        capSetVideoFormat(hwndVideo, &pbiInfo, dwSize);
    //-----------------------------------------------------------------------------
    
            // Die neu eingestellte Bildgröße wird in den CapStatus geladen
            capGetStatus(hwndVideo, &CapStatus, sizeof(CAPSTATUS));
    
            hsize = GetSystemMetrics(SM_CYMENU);
            hsize += GetSystemMetrics(SM_CYCAPTION);
    
            // Das Anzeigefenster wird neu aufgebaut
            SetWindowPos(hwndVideo, NULL, 0, 0, CapStatus.uiImageWidth,
                    CapStatus.uiImageHeight, SWP_NOZORDER | SWP_NOMOVE);
            SetWindowPos(ParentHandle, NULL, 0, hsize, CapStatus.uiImageWidth,
                    CapStatus.uiImageHeight+hsize, SWP_NOZORDER | SWP_NOMOVE);
    
            // Stellt die Bildwiederholrate des Vorschaufensters ein
            capPreviewRate (hwndVideo, 33.3);
    
            // startet die Bildvorschau
            capPreview (hwndVideo, TRUE);
    
            // Das geöffnete Aufnahmegerät wird gespeichert
            SelectedDevice = Selected;
    
    }
    
    //---------------------------------------------------------------------------
    //  Get access to the video source format box
    //---------------------------------------------------------------------------
    void TCap::Format ()
    {
            int hsize;
    
            CAPSTATUS CapStatus;
    
            capDlgVideoFormat(hwndVideo);
            // Are there new image dimensions
            capGetStatus(hwndVideo, &CapStatus, sizeof(CAPSTATUS));
    
            hsize = GetSystemMetrics(SM_CYMENU);
            hsize += GetSystemMetrics(SM_CYCAPTION);
    
            SetWindowPos(ParentHandle, NULL, 0, hsize, CapStatus.uiImageWidth,
    				CapStatus.uiImageHeight+hsize, SWP_NOZORDER | SWP_NOMOVE);
            SetWindowPos(hwndVideo, NULL, 0, 0, CapStatus.uiImageWidth,
                    CapStatus.uiImageHeight, SWP_NOZORDER | SWP_NOMOVE);
    }
    //---------------------------------------------------------------------------
    //  Get access to the video source dialog box
    //---------------------------------------------------------------------------
    void TCap::Source ()
    {
            capDlgVideoSource(hwndVideo);
    }
    
    //---------------------------------------------------------------------------
    //  capture a frame and save it
    //---------------------------------------------------------------------------
    void TCap::CaptureFrame (char *FileName)
    {
            capFileSaveDIB (hwndVideo, FileName);
    }
    //---------------------------------------------------------------------------
    

    (dazu gehört noch die unit1.cpp datei)
    Ich habe das Programm zum laufen gebracht(ein Borland compiler bewirkt wunder), aber ich weiß immer noch nicht
    1. wie ich an die Bilddaten selber drankomme,
    2. wie ich ein Bild ohne speichern Dialog speichere und
    3. wie ich das alle x millisekunden machen kann.
    Wie ich ein Timer benutze ist mir schon klar nur ich habe noch nicht sowas wie ein Mainloop gefunden der kontinuirlich ausgeführt wird.

    Am Ich möchte aus diesem Program eine art bewegungsmelder basteln.
    Welches auf meinem Server laufen soll. dazu brauche ich von dem webcam stream alle x millisekunden nen grauwert array
    zb(3x3 Bild Dunkles kreuz):
    [ 246 20 230
    14 37 11
    250 40 255 ]
    die gui ist mir vollkommen egal die kann ruhig wegbleiben. Ich würde die daten am liebsten nicht erst auf die HD speichern sondern gleich benutzen.
    vielen Dank für eure Mühe
    Gruß KOR



  • Im Preview-Modus kannst du dir den DC vom capture-window holen und einfach via BitBlt() in eine von dir erzeugte Bitmap blitten.

    (Ich würde aber eher auf DirectShow umsteigen statt Vfw zu nutzen)



  • warum würdest du auf DirectShow umsteigen und hast du einen Funktionierenden code?
    das mit BitBlt() werde ich gleich mal ausprobieren.



  • BitBlt() nimmt sich die daten des Handles und kopiert sie in ein Bitmap file. Ich möchte aber nur an die Farbwerte und nicht erst nen bitmap machen und dann wieder einlesen.



  • Nimm eine DIBSection oder sowas, da kannst du direkt via Pointer auf die Pixeldaten zugreifen.

    Alternativ kannst du auch BitBlt() weglassen und direkt mit GetPixel() arbeiten.
    GetPixel() ist allerdings sau lahm wenn du mehrere Pixel angucken willst.

    Quellcode habe ich keinen (mehr) da 😉

    DirectShow meinte ich weil:
    - Vfw noch ein Überbleibsel aus Windows 3.x Zeiten ist und aktuelle Webcams teilweise nur noch DirectShow-Wrapper auf Vfw mitliefern.
    - Bei DirectShow kannst du dir einen DirectShow-Filter schreiben und kommst damit direkt an die Pixeldaten. Zudem ist DirectShow auch noch ziemlich schnell.
    - Nachteil: In DirectShow muss man sich erstmal einarbeiten 😉



  • hi ich benutze jetzt openCV das ist recht einfach und man kommt nach kurzer einarbeitungszeit auch an die pixeldaten. Wenns jemand mal braucht ich habe mal das minimal programm aus meinem Quelltext zusammenkopiert:

    #include <cv.h>
    #include <cxcore.h>
    #include <highgui.h>
    //nicht das linken der libs und header vergessen
    int _tmain(int argc, _TCHAR* argv[])
    {
    CvCapture* capture = cvCaptureFromCAM(0);// capture from video device #0
    if(!cvGrabFrame(capture)){               // capture a frame 
     printf("Could not grab a frame\n\7");   // if it fails print errormsg
     exit(0);				                // and exit
    }
    img=cvRetrieveFrame(capture);            // get image
    IplImage *gray_img;			          // creating empty grey image pointer	
    gray_img = cvCreateImage(imgSize, IPL_DEPTH_8U, 1);	// allocate Memory
    cvCvtColor(img, gray_img, CV_BGR2GRAY);  // converting from color to grayscale
    int step = gray_img->widthStep;
    int channels  = gray_img->nChannels;	 // channels RGB(3) grey(1) etc
    uchar *data   = (uchar *)gray_img->imageData;// pixeldata of image
    int r=0;
    int c=1;
    pixelrc=int(data[r*step+c]);             //pixel at pos (0,1)
    cout<<pixelrc<<endl;
    return 0;
    }
    

Anmelden zum Antworten