Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/71.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 如何将网络摄像头馈送到GTK窗口?_C_Opencv_Gtk_Cairo_Webcam Capture - Fatal编程技术网

C 如何将网络摄像头馈送到GTK窗口?

C 如何将网络摄像头馈送到GTK窗口?,c,opencv,gtk,cairo,webcam-capture,C,Opencv,Gtk,Cairo,Webcam Capture,我需要使用C,GTK2/3,Cairo获取网络摄像头视频源。 但是我找不到任何关于它的参考资料 下面显示了我是如何尝试使用opencv的。它不成功。我需要知道其他一些使用gstreamer的方法,开罗 我期待着简单的代码得到视频到GTK窗口。如果有人能提供示例代码,我将不胜感激 /* gcc -o weby3 att3.c `pkg-config --libs --cflags gtk+-2.0 opencv` */ #include "highgui.h" #include <

我需要使用C,GTK2/3,Cairo获取网络摄像头视频源。 但是我找不到任何关于它的参考资料

下面显示了我是如何尝试使用opencv的。它不成功。我需要知道其他一些使用gstreamer的方法,开罗

我期待着简单的代码得到视频到GTK窗口。如果有人能提供示例代码,我将不胜感激

    /*
gcc -o weby3 att3.c `pkg-config --libs --cflags gtk+-2.0 opencv`
*/

#include "highgui.h"
#include <gtk/gtk.h>
#include <opencv/cv.h>
#include <opencv/cxcore.h>

GdkPixbuf* pix;
IplImage* frame;
CvCapture* capture;

gboolean
expose_event_callback(GtkWidget *widget, GdkEventExpose *event, gpointer data)
{
  while(1) {
         frame = cvQueryFrame( capture );
          if(!frame) break;  

         pix = gdk_pixbuf_new_from_data((guchar*) frame->imageData,
         GDK_COLORSPACE_RGB, FALSE, frame->depth, frame->width,
         frame->height, (frame->widthStep), NULL, NULL);


         gdk_draw_pixbuf(widget->window,
   widget->style->fg_gc[GTK_WIDGET_STATE (widget)], pix, 0, 0, 0, 0,
   -1, -1, GDK_RGB_DITHER_NONE, 0, 0); /* Other possible values are  GDK_RGB_DITHER_MAX,  GDK_RGB_DITHER_NORMAL */

         char c = cvWaitKey(33);
         if( c == 27 ) break;
   }

   cvReleaseCapture( &capture );   
   return TRUE;
}

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

   /* GtkWidget is the storage type for widgets */
   GtkWidget *window;
   GtkWidget *drawing_area;

   gtk_init (&argc, &argv);

   CvCapture* capture = cvCreateCameraCapture(0); 
   /* create a new window */
   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
   gtk_window_set_title (GTK_WINDOW (window), "Hello WebCam and OpenCV!");
   g_signal_connect (G_OBJECT (window), "destroy",
    G_CALLBACK (gtk_main_quit), NULL);

   /* Sets the border width of the window. */
   gtk_container_set_border_width (GTK_CONTAINER (window), 10);

   /* Now add a child widget to the aspect frame */
   drawing_area = gtk_drawing_area_new();


   /* window since we are forcing a aspect ratio */
   gtk_widget_set_size_request(drawing_area, 600, 400);
   gtk_container_add(GTK_CONTAINER (window), drawing_area);
   gtk_widget_show(drawing_area);

   g_signal_connect (G_OBJECT (drawing_area), "expose_event",
      G_CALLBACK (expose_event_callback), NULL);

   /* and the window */
   gtk_widget_show (window);

   /* All GTK applications must have a gtk_main(). Control ends here
    * and waits for an event to occur (like a key press or
    * mouse event). */
   gtk_main ();

   return 0;
}
/*
gcc-o weby3 att3.c`pkg config--libs--cflags gtk+-2.0 opencv`
*/
#包括“highgui.h”
#包括
#包括
#包括
GdkPixbuf*pix;
IplImage*框架;
捕获*捕获;
gboolean
expose_event_回调(GtkWidget*小部件、GdkEventExpose*事件、gpointer数据)
{
而(1){
帧=cvQueryFrame(捕获);
如果(!帧)中断;
pix=gdk_pixbuf_new_from_data((guchar*)frame->imageData,
GDK_COLORSPACE_RGB,FALSE,帧->深度,帧->宽度,
帧->高度,(帧->宽度步长),空,空;
gdk_draw_pixbuf(小部件->窗口,
widget->style->fg_gc[GTK_widget_STATE(widget)],pix,0,0,0,
-1,-1,GDK_RGB_DITHER_NONE,0,0);/*其他可能的值为GDK_RGB_DITHER_MAX,GDK_RGB_DITHER_NORMAL*/
char c=cvWaitKey(33);
如果(c==27)断开;
}
cvReleaseCapture(&capture);
返回TRUE;
}
int main(int argc,字符**argv){
/*GtkWidget是小部件的存储类型*/
GtkWidget*窗口;
GtkWidget*绘图区域;
gtk_init(&argc,&argv);
CvCapture*capture=cvCreateCameraCapture(0);
/*创建一个新窗口*/
窗口=gtk_窗口_新建(gtk_窗口_顶层);
gtk_window_set_标题(gtk_window(window),“Hello WebCam and OpenCV!”);
g_信号连接(g_对象(窗口),“销毁”,
G_回调(gtk_main_quit),NULL);
/*设置窗口的边框宽度*/
gtk_容器_设置_边框_宽度(gtk_容器(窗口),10);
/*现在将一个子小部件添加到aspect框架中*/
图纸面积=gtk图纸面积新();
/*窗口,因为我们强制使用纵横比*/
gtk_小部件_设置_大小_请求(绘图区域,600400);
gtk_容器添加(gtk_容器(窗口),绘图区域);
gtk_小部件_显示(绘图区域);
g_信号连接(g_对象(绘图区域),“暴露事件”,
G_回调(expose_event_CALLBACK),NULL);
/*窗户呢*/
gtk_widget_show(窗口);
/*所有GTK应用程序必须有一个GTK_main()。控制在此结束
*并等待事件发生(如按键或
*鼠标事件)*/
gtk_main();
返回0;
}

我在这里看到的主要问题是,您没有正确地将opencv代码集成到GTK事件模型中

GTK基本上与消息泵一起工作。消息在队列中发送,GTK读取并取消队列以对这些消息作出反应。在GTK 2中,
expose event
事件在需要绘制小部件或其一部分时发出(在GTK 3中,使用
draw
事件)。您可以将回调连接到该事件以捕获该事件。然后在回调中,绘制单个帧,然后将控件返回给GTK。它将在需要下一帧时再次调用回调

这里的问题是,您永远不会将手交还给GTK,因为您的opencv代码被封装在无限
while(1)
循环中。您应该只绘制一个帧,然后返回

键事件逻辑也应该使用GTK处理,而不是在
expose event
回调中处理。看到等待的按键后,只需调用
gtk\u main\u quit

编辑:

一旦可以显示一个帧,就必须显示所有帧。打电话告诉GTK小部件需要重新绘制

完成后,您将看到需要某种方式定期调用
gtk\u widget\u queue\u draw
。这很容易通过GLib函数完成,如
g\u timeout\u add
g\u idle\u add
。这些函数告诉主事件循环(我在上面称之为“消息泵”)在确定的时间后(对于
g\u timeout\u add
)或在没有其他事件要处理时(对于
g\u idle\u add
)调用回调。在该回调中调用
gtk\u widget\u queue\u draw


请注意,g_timeout_add不允许有完美的计时,因此每个帧之间的时间可能因帧而异。您可以通过增加传递给g_timeout_add的优先级来避免这种情况。您还可以使用GTimer在超时回调中计算上一帧和当前时间之间经过的时间,以及推断到下一帧的剩余时间。然后用更准确的时间调用g_timeout_add。如果使用
GTimer
技巧,不要忘记在超时回调结束时返回FALSE而不是TRUE,否则将在帧
n
上运行
n
超时回调t您没有正确地将opencv代码集成到GTK事件模型中

GTK基本上与消息泵一起工作。消息在队列中发送,GTK读取并取消队列以对这些消息作出反应。在GTK 2中,当需要绘制小部件或其一部分时,会发出
expose event
事件(在GTK 3中,使用
draw
事件)。您可以将回调连接到该事件以捕获该事件。然后在回调中,绘制一个帧,然后将控件返回给GTK。当需要下一帧时,GTK将再次调用您的回调

这里的问题是,您永远不会将手交还给GTK,因为您的opencv代码包含在无限
while(1)
循环中。您应该只绘制一个帧,然后返回

键事件逻辑也应该使用GTK来处理,而不是在
expose event
回调中。只要在看到等待的击键后调用
GTK\u main\u quit

编辑:

一旦可以显示一个帧,就必须