OpenCV + Gtk - Framegrabbing (Problem)



  • Hey leute!

    Ich bin derzeit daran, ein Programm zu schreiben, dass per Knopfdruck die (USB-)Kamera initialisiert und per weiterer Knopfdruck ein Bild von der Kamera holt, dieses anzeigt und abspeichert.

    Dank Opensourceprojekte (OpenCV + Gtk) lässt sich dies recht einfach realisieren. Quellcode siehe unten.

    Jetzt zu meinem Problem: Wenn ich die Kamera initialisiere, grabbt das Programm schon ein Frame. Zumindest vermute ich das. Denn wenn ich dann die Funktion aufrufe, die eigentlich genau zu diesem Zeitpunkt ein Frame grabben soll, zeigt mir das Programm das Bild an, bei der die Kamera bei der initialisierungsphase war.
    Und wenn ich nochmal ein Frame grabbe, dann zeigt es mir das Bild an dass ich zuvor aufgenommen habe....

    Ich hoffe ihr versteht mein Problem, und könnt mir vllt. noch den ein oder anderen Tipp geben (bin selber noch Neuling und es is das erste Projekt dieser Art). 😃

    #include <stdlib.h>
    #include <windows.h>
    #include <gtk/gtk.h>
    #include <gdk-pixbuf/gdk-pixbuf.h>
    
    #include <cv.h> // OpenCV
    #include <highgui.h> // OpenCV-Highgui
    
    /* Eventuelle Variablen deklarieren */
    GtkWidget *fenster;
    GtkWidget *button0, *button1, *button2;
    GtkWidget *hbox, *vbox;
    
    GtkWidget *aspect_frame;
    GtkWidget *drawing_area;
    
    CvCapture *capture = NULL;
    IplImage *frame;
    IplImage* rgbImage;
    
    GdkPixbuf *pix;
    
    void ocv_init_cam()
    {
        /* Kamera initialisieren */
        capture = cvCaptureFromCAM(0); //Kamera-Index: 0
    
        if(!capture)
        {
            g_print("Initialisierung der Kamera fehlgeschlagen!");
        }
    }
    
    void ocv_grab_frame()
    {
        g_print("Funktion aufgerufen!\n\n");
        if(capture) // Kamera initialisiert?
        {
            if(!cvGrabFrame(capture))
            {
                g_print("Kein Bild aufgenommen!\n");
            }
            else
            {
                g_print("Bild aufgenommen! \n");
                frame = cvRetrieveFrame(capture, 0);
                cvSaveImage("bild.jpg", frame,0);
                rgbImage = cvCloneImage(frame);
                cvCvtColor( frame, rgbImage, CV_BGR2RGB ); // Usually opencv image is BGR, so we need to change it to RGB
                pix = gdk_pixbuf_new_from_data ((guchar*)rgbImage->imageData,
                            GDK_COLORSPACE_RGB,
                            FALSE,
                           rgbImage->depth,
                           rgbImage->width,
                           rgbImage->height,
                            (rgbImage->widthStep),
                             NULL,
                             NULL);
            }
        }
    }
    
    void ende(GtkObject *object)
    {
        cvReleaseCapture(&capture);
        gtk_main_quit();
    }
    
    gboolean expose_event_callback (GtkWidget *widget, GdkEventExpose *event, gpointer data)
    {
    
    if(rgbImage != 0) // Frame aufgenommen?
    {
    
        gtk_widget_queue_draw(GTK_WIDGET(widget));
        gdk_draw_pixbuf (widget->window,
             widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
             pix,
             0, 0, 0, 0, 320, 240, GDK_RGB_DITHER_MAX, 0, 0 );
    }
    else // wenn nicht -> schwarzes Rechteck als Platzhalter
    {
        gtk_widget_queue_draw(GTK_WIDGET(widget));
        gdk_draw_rectangle(widget->window,widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
                           TRUE,
                           0,0,320,240);
    }
    return TRUE;
    }
    
    int WINAPI
    WinMain (HINSTANCE hThisInstance,
             HINSTANCE hPrevInstance,
             LPSTR lpszArgument,
             int nFunsterStil)
    {
    
        /*GTK initialisieren - Anfang */
        g_log_set_handler ("Gtk", G_LOG_LEVEL_WARNING,
                        (GLogFunc) gtk_false, NULL);
        gtk_init (&_argc, &_argv);
        g_log_set_handler ("Gtk", G_LOG_LEVEL_WARNING,
        g_log_default_handler, NULL);
        /*GTK initialisieren - Ende */
    
        // Ein neues Fenster erstellen
        fenster = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    
        // Horizontaler Container
        hbox = gtk_hbox_new(TRUE, 0);
        // Vertikaler Container
        vbox = gtk_vbox_new(TRUE, 0);
    
        //Buttons erstellen
        button0 = gtk_button_new_with_label("Kamera initialisieren!");
        button1 = gtk_button_new_with_label("Frame grabben");
        button2 = gtk_button_new_with_label("Exit");
    
        /* Create an aspect_frame*/
    
        aspect_frame = gtk_aspect_frame_new ("1x1", /* label */
                                         0.5, /* center x */
                                         0.5, /* center y */
                                         1, /* xsize/ysize = 2 */
                                         FALSE /* ignore child's aspect */);
    
        drawing_area = gtk_drawing_area_new ();
        gtk_widget_set_size_request (drawing_area, 320, 240);
    
        // Signale registrieren
        gtk_signal_connect(GTK_OBJECT(fenster), "destroy",
                        GTK_SIGNAL_FUNC(ende),NULL);
    
        gtk_signal_connect(GTK_OBJECT(button2), "clicked",
                           GTK_SIGNAL_FUNC(ende), GTK_OBJECT(fenster));
    
        gtk_signal_connect(GTK_OBJECT(button0), "clicked",
                           GTK_SIGNAL_FUNC(ocv_init_cam), NULL);
    
        gtk_signal_connect(GTK_OBJECT(button1), "clicked",
                           GTK_SIGNAL_FUNC(ocv_grab_frame), NULL);
    
        gtk_signal_connect (GTK_OBJECT (drawing_area), "expose_event",
                             G_CALLBACK (expose_event_callback), NULL);
    
        gtk_window_set_title(GTK_WINDOW(fenster), "GTK mit OpenCV!");
        gtk_window_set_default_size(GTK_WINDOW(fenster), 800, 400);
        gtk_window_set_position(GTK_WINDOW(fenster),GTK_WIN_POS_CENTER);
        gtk_container_set_border_width(GTK_CONTAINER(fenster),25);
    
        //Nun alles in die Box...
        gtk_box_pack_start(GTK_BOX(vbox), button0, FALSE, FALSE, 0);
        gtk_box_pack_start(GTK_BOX(vbox), button1, FALSE, FALSE, 0);
        gtk_box_pack_start(GTK_BOX(vbox), button2, FALSE, FALSE, 0);
        gtk_box_pack_start(GTK_BOX(hbox), vbox, FALSE, FALSE, 20);
        gtk_box_pack_start(GTK_BOX(hbox), drawing_area, FALSE, FALSE, 0);
        gtk_box_pack_start(GTK_BOX(drawing_area), aspect_frame, FALSE, FALSE, 0);
    
        //Container(-box) in das Fenster einfügen
        gtk_container_add(GTK_CONTAINER(fenster),hbox);
    
        //Zeig uns...
        gtk_widget_show_all(fenster);
    
        gtk_main();
        return 0;
    }
    

    PS: Ich habe dieses Thema schonmal gepostet. Allerdings in das Forum "ANSI C" und habe jetzt festgestellt, dass es hierher besser passt. Wäre ein Moderator so lieb den anderen Thread zu löschen? Danke. 🙂



  • Wenn es nur darum geht beim ersten Capturen zwei Bilder auszulesen:

    void ocv_grab_frame()
    {
        // snip
            if(!cvGrabFrame(capture))
            // snip
            else
            {
                // snip  
                static bool notFirstRun = false;
                if (! notFirstRun) // nur beim ersten Durchlauf erfüllt ....
                { 
                    // Bild auslesen und verwerfen ...
                    notFirstRun = true; 
                }
                // normal auslesen
            }
        }
    }
    

    Ich hatte soetwas ähnliches beim einem USB Video Grabber ... der hat immer ein Bild gepuffert und musste ähnlich "gelöscht" werden



  • Wie einfach doch die Lösung ist, wenn man mal genau weiß was das Problem ist 😉
    Ich stand diesbezüglich etwas aufem Schlauch 😉

    Tausend Dank!



  • Dann editier doch den Beitragstitel als "[gelöst] OpenCV + Gtk - Framegrabbing (Problem)" 😉



  • Würd ich ja gern 😉
    Aber ich hab mich nicht registriert, und kann deswegen meinen Post nichtmehr ändern....

    Sry 😉


Anmelden zum Antworten