2017-07-14 2 views
0

J'ai ici un programme qui effectue une détection de visage et j'aimerais utiliser ces coordonnées pour déplacer une fenêtre créée avec GTK + 3.22 en utilisant la fonction GTK gtk_window_move. Je voudrais que la fenêtre reste ouverte tout le temps pendant qu'elle se déplace comme la fonction moveWindow d'OpenCV.GTK + fenêtre mobile basée sur les coordonnées de détection de visage

Je viens de télécharger les paquets GTK + hier, donc je ne suis pas très familier. Le programme exécutera une boucle 100 fois, en suivant un visage tout le temps. Actuellement, le suivi du visage fonctionne, mais la fenêtre n'apparaît que lorsque la boucle est terminée. Pourquoi est-ce? Je crois que la fonction gtk_move_window fonctionne, mais la fenêtre ne reste pas ouverte. J'ai essayé de rouvrir la fenêtre chaque fois dans la boucle, ou juste en ouvrant une fois avant la boucle. Si vous connaissez la fonction moveWindow d'OpenCV, c'est exactement ce que je recherche. Voici l exemple de code. Par ailleurs, si vous savez comment une fonction GTK + qui amènera la fenêtre à la toute première couche au-dessus de toutes les autres fenêtres ouvertes à l'appel, c'est aussi une information utile pour moi.

#include "FlyCapture2.h" 
#include <opencv2/core/core.hpp> 
#include <opencv2/objdetect/objdetect.hpp> 
#include <opencv2/imgproc/imgproc.hpp> 
#include <opencv2/core/cuda.hpp> 
#include <opencv2/cudaobjdetect.hpp> 
#include <math.h> 
#include <thread> 
#include <iostream> 
#include <vector> 
#include <gtk-3.0/gtk/gtk.h> 

using namespace FlyCapture2; 


cv::Ptr<cv::cuda::CascadeClassifier> face_detect; 

void detect_faces(cv::Mat img, cv::cuda::GpuMat buf,GtkWidget *win) 
{ 
    std::vector<cv::Rect>faces; 
    cv::cuda::GpuMat image_gpu(img); 

    //Face detection here 
    ... 

    if (faces.size() > 0) 
    { 
     float x = faces[0].x; 
     float y = faces[0].y; 
     int new_x = roundf(x*40/51); 
     int new_y = roundf(y*135/256); 

     gtk_window_move(GTK_WINDOW (win),new_x,new_y); 
     gtk_widget_show (win); //Should this go here? 
     std::cout<<faces[0]<<std::endl; 
    } 
} 

int main(int argc, char *argv[]) 
{ 

    //Camera connect here 
    ... 

    //face detect variables 
    face_detect = cv::cuda::CascadeClassifier::create("/home/nvidia/opencv/data/haarcascades_cuda/haarcascade_frontalface_default.xml"); 
cv::cuda::GpuMat objbuf; 

    //GTK+ Params 
    GtkWidget *window; 
    GdkRGBA *color; 
    gtk_init (&argc, &argv); 
    gdk_rgba_parse(color,"(0,0,0)"); 
    window = gtk_window_new (GTK_WINDOW_TOPLEVEL); 
    gtk_window_set_decorated(GTK_WINDOW (window),FALSE); 
    gtk_window_set_position(GTK_WINDOW (window), GTK_WIN_POS_CENTER); 
    gtk_widget_override_background_color(window, GTK_STATE_FLAG_NORMAL, color); 
    gtk_widget_show (win); //Should this go here? 


    // capture loop 
    for (int i=0;i<100;i++) 
    { 
     // Get the image 
     Image rawImage; 
     camera.RetrieveBuffer(&rawImage); 

     // convert to rgb 
     Image rgbImage; 
     rawImage.Convert(FlyCapture2::PIXEL_FORMAT_MONO8, &rgbImage); 

     // convert to OpenCV Mat 
     unsigned int rowBytes = (double)rgbImage.GetReceivedDataSize()/(double)rgbImage.GetRows();  
     cv::Mat image = cv::Mat(rgbImage.GetRows(), rgbImage.GetCols(), CV_8UC1, rgbImage.GetData(),rowBytes); 

     //Detect Faces 
     detect_faces(image,objbuf,window); 
    } 

    //Disconnect Camera 
    camera.StopCapture(); 
    camera.Disconnect(); 

    gtk_main(); 

    return 0; 
} 
+0

Je ne suis pas familier avec Gtk +, mais généralement les frameworks GUI sont basés sur des messages, et ont besoin de code pour "pomper des messages" afin que l'interface utilisateur soit réactive. Dans ce cas, il semble que 'gtk_main' soit la seule fonction qui le fasse. Ma conjecture serait que vous devez appeler quelque chose comme ['gtk_main_iteration_do()'] (https://developer.gnome.org/gtk3/stable/gtk3-General.html#gtk-main-iteration-do) dans votre capture boucle pour que l'interface graphique se mette à jour. –

Répondre

0

Le code de votre boucle de capture doit être dans un rappel de gestionnaire d'événements. Vous devez d'abord appeler g_timeout_add ou g_idle_add pour enregistrer votre rappel.

Le rappel que vous avez enregistré est un GSourceFunc qui sera appelé après l'exécution de gtk_main. La valeur de retour (G_SOURCE_CONTINUE ou G_SOURCE_REMOVE) contrôle si vous souhaitez que le rappel soit appelé à nouveau.