Webcam Frames zu langsam mit vfw



  • Ich hatte vor, irgendwie an die Pixel meiner Webcam ranzukommen.
    WM_GRAB_FRAME benötigt pro Frame bei mir 140 ms was mir zu langsam ist (optimal wären volle 30 fps aber bisher ist das für mich utopisch).
    Also habe ich versucht, einen Stream zu starten und mir davon die Frames rauszusuchen.
    Immoment bin ich so weit, dass der Stream startet und sich sogar als AVI speichern lässt (brauch ich zwar nicht, ist aber auch schön), allerdings beträgt die Dauer zwischen den Frames anfangs 100 ms (zwar etwas lang, aber immerhin fast schon flüssig). Dann stellt sich irgend eine Art von Helligkeitsregulierung an, das Bild wird zwar wesentlich besser, aber pro Frame vergehen diesmal 200 ms. Einige Momente später springt die Farbkorrektur an und das ganze verzögert sich nochmals um 100 ms.
    Das Ganze lässt sich im Preview Window schön beobachten, ich muss mich also nicht nur auf clock() verlassen, um festzustellen, dass alles zu langsam ist.

    Andere Programme, wie z.B. ManyCam haben dieses Problem nicht und laufen weiterhin flüssig und bieten darüber hinaus noch die Möglichkeit, Sachen einzustellen die mit den WM_DLG_-Sachen als graue Kästchen angezeigt werden würden (z.B. ist es dort Möglich, den Weißabgleich an/aus zu schalten oder den Wert zu verändern, bei WM_DLG_blah ist das gleiche Feld grau, außerdem sieht das Layout des Einstellfensters anders aus [ist zwar egal, hilft aber vielleicht zur Lösung des Problems weiter]).

    Sonstiges:
    (Compiler: wxDevCpp [die portable Version, also nicht CodeBlocks vorschlagen 😉 ])
    OS: Windows 7
    USB2.0 UVC VGA WebCam von Sonix integriert in ein Asus A52J
    Hardware-Ids:
    USB\VID_13D3&PID_5130&REV_1211&MI_00
    USB\VID_13D3&PID_5130&MI_00

    Hier noch ein bisschen Code:

    #include <windows.h>
    #include <vfw.h>
    #include <time.h>
    
    int duration = 0;
    HWND hwnd, camhwnd;
    char szCaptureFile[] = "MYCAP.AVI", szName[] = "Webcam";
    
    LRESULT CALLBACK capVideoStreamCallback(HWND hWnd, LPVIDEOHDR lpVHdr){
    	printf("duration: %i\n", clock()-duration);
    	duration = clock();
    }
    
    LRESULT CALLBACK WindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam){
        switch (message){
    	    case WM_DESTROY: { capDriverDisconnect(camhwnd); PostQuitMessage(0); break; }
    	    default: return DefWindowProc(hwnd, message, wParam, lParam);
        } return 0;
    }
    
    int WINAPI WinMain ( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow ){
        WNDCLASS wc;
        wc.style = CS_HREDRAW|CS_VREDRAW;
        wc.lpfnWndProc = WindowProc;
        wc.cbClsExtra = 0;
        wc.cbWndExtra = 0;
        wc.hInstance = hInstance;
        wc.hIcon = LoadIcon(GetModuleHandle(NULL), IDI_APPLICATION);
        wc.hCursor = LoadCursor (NULL, IDC_ARROW);
        wc.hbrBackground = (HBRUSH) (COLOR_WINDOW+1);
        wc.lpszMenuName = NULL;
        wc.lpszClassName = szName;
        RegisterClass (&wc);
    
        hwnd = CreateWindow(szName,szName,WS_POPUPWINDOW | WS_VISIBLE,500,0,640,480,0,0,hInstance,0);
        camhwnd = capCreateCaptureWindow ("camera", WS_CHILD|WS_VISIBLE, 0, 0, 640, 480, hwnd, 0);
    
    	capDriverConnect(camhwnd, 0);
    	capPreviewRate(camhwnd, 66);
    	capPreview(camhwnd, TRUE);
    	capSetCallbackOnVideoStream(camhwnd, capVideoStreamCallback);
    	capFileSetCaptureFile(camhwnd, szCaptureFile);
    	//capFileAlloc(camhwnd, (1024L * 1024L * 100));
    	capCaptureSequence(camhwnd);
    	//capCaptureSequenceNoFile(camhwnd);
    	capFileSaveAs(camhwnd, szCaptureFile);
    
        MSG msg;
        while (GetMessage(&msg,0,0,0)) {
            if (!IsDialogMessage(hwnd, &msg)) {
                TranslateMessage (&msg);
                DispatchMessage (&msg);
            }
        }
        return msg.wParam;
    }
    

    Alternativ hätte ich hierzu noch den Code mit WM_GRAB_FRAME, der aufgrund von mehreren Threads und OpenGLeinbindung aber zu lang ist, als dass er hier rein passen würde.

    Ich hab zwar gelesen, dass dshow das Non plus ultra sein sollte, wenn es um dieses Thema geht, nur leider ist es für einen Neuling wie mich ein Ding der Unmöglichkeit, es vernünftig zu Compilen (selbst nach mehreren Stunden rumprobieren, mit CodeBlocks, DevCpp, MFC und watweißichnichalles). Wer aber einen "Ultimativen Tip" hat, wie ich es trotzdem zum laufen kriege bitte nicht zurückhalten.
    OpenCV macht genau das, was ich selber programmieren will, also kommt es nicht in Frage. Außerdem sind mir ein paar MB dlls zu viel des Guten.

    Zusammenfassung:
    Wie kriege ICH (also nicht irgendwer, der Ahnung von der Materie hat) es hin, 10 mal oder häufiger pro Sekunde die RGB-Daten des aktuellen Bilds meiner Webcam auszulesen?



  • Ich verstehe dein Problem nicht! Da ich mit deinem Code ein sehr flüssiges bild habe!



  • lowbyte_ schrieb:

    Ich verstehe dein Problem nicht! Da ich mit deinem Code ein sehr flüssiges bild habe!

    Welche Zahlen werden bei dir in der Konsole ausgegeben?
    Wenn sie sehr klein sind (<100) , dann liegt es wahrscheinlich irgendwie an meiner Webcam 😕
    Ich habe eben zufällig noch eine exe gefunden die mit Sicherheit dshow verwendet (videomanlib) und die lief flüssig.
    Also werde ich wahrscheinlich kaum eine Wahl haben.
    Entweder ich bastel mit dshow solange rum bis es sich compilen lässt oder ich finde einen Weg meine Webcam mit vfw zu optimieren.


Anmelden zum Antworten