实时移动GTK +窗口

我正在创build一个移动窗口,使用人脸检测坐标作为input来分配窗口的新位置。 目前,人脸检测function正常,但直到捕捉循环的最后才显示窗口。

我的问题是:
– 如何在整个拍照和人脸检测过程中保持窗口?
– 是否需要“gtk_main”循环,在这种情况下是否正确使用?
– 即使当“gtk_widget_show(window)”被放置在捕获循环中时,为什么窗口不能打开?
– 更详细的GTK +问题有更好的论坛吗?

我想在OpenCV的“moveWindow”函数之后进行build模。 这个function对于我所需要的是完美的,使用这个function的唯一问题是我无法自定义窗口。

OpenCV“moveWindow”函数的源代码:查看window.cpp和window_gtk.cpp https://github.com/opencv/opencv/tree/master/modules/highgui/src

#include "FlyCapture2.h" #include <opencv2/core/core.hpp> #include <opencv2/highgui/highgui.hpp> #include <opencv2/objdetect/objdetect.hpp> #include <opencv2/core/cuda.hpp> #include <opencv2/cudalegacy/NCVHaarObjectDetection.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; int x,y; void detect_faces(cv::Mat img, cv::cuda::GpuMat buf) { std::vector<cv::Rect>faces; //Detect faces ... if (faces.size() > 0) { float x_f = faces[0].x; float y_f = faces[0].y; x = roundf(x_f*40/51); y = roundf(y_f*135/256); } } int main( int argc, char *argv[]) { //Camera initialization ... //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; gtk_init (&argc, &argv); 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_show (window); // capture loop double t = (double)cv::getTickCount(); for (int i=0;i<100;i++) { // Get the image ... // convert to OpenCV Mat ... //Detect Faces detect_faces(image,objbuf); std::cout<<"x: "<<x<<" "<<"y: "<<y<<std::endl; gtk_window_move(GTK_WINDOW (window),x,y); while (gtk_events_pending()) gtk_main_iteration (); } //Record Time t = ((double)cv::getTickCount() - t)/cv::getTickFrequency(); std::cout << "Time: " << (t/100)*1000 << std::endl; //Disconnect Camera camera.StopCapture(); camera.Disconnect(); gtk_main(); return 0; } 

最好的方法是在两个不同的线程中分离面部识别过程和GUI操作,GUI应该总是运行在主线程中(或者是首先创建窗口的那个,这在X11上不是必须的,但它例如在Win32和Cocoa GTK后端)。

然后,识别线程可以根据需要忙于循环,并使用空闲回调将窗口更新“发送”给主线程。 这是常用的多线程GTK方法。

下面是一些解释方法的代码(一个支持函数和另一个捕获循环):

 /// support function struct WindowData { GtkWindow win; int x, y; }; int move_window(WindowData *p) { gtk_move_window(p->win, p->x, p->y); delete p; return FALSE; } [...] // updated capture loop inside main (capture the variables you need, or this if you are working in a class environment std::thread t([window, image, objectbuf]{ for (int i=0;i<100;i++) { // Get the image ... // convert to OpenCV Mat ... //Detect Faces detect_faces(image,objbuf); WindowData *p = new WindowData(); p.win = window; px = x; py = y; g_idle_add((GFunction)move_window, p); } }); gtk_main(); t.join(); [...] 

请注意,您也可以将“window”设置为全局变量(或类成员),并使x和y std :: atomic以避免为每个窗口移动分配/取消分配WindowData。