我正在尝试从网络摄像头显示视频。我使用opencv从网络摄像头捕获图像,然后我尝试在GtkImage上显示它们。
这是我的代码,它以单独的线程运行。
gpointer View::updateView(gpointer v)
{
IplImage *image;
CvCapture *camera;
GMutex *mutex;
View *view;
view=(View*)v;
camera=view->camera;
mutex=view->cameraMutex;
while(1)
{
g_mutex_lock(view->cameraMutex);
image=cvQueryFrame(camera);
g_mutex_unlock(view->cameraMutex);
if(image==NULL) continue;
cvCvtColor(image,image,CV_BGR2RGB);
GDK_THREADS_ENTER();
g_object_unref(view->pixbuf);
view->pixbuf=gdk_pixbuf_new_from_data((guchar*)image->imageData,GDK_COLORSPACE_RGB,FALSE,image->depth,image->width,image->height,image->widthStep,NULL,NULL);
gtk_image_set_from_pixbuf(GTK_IMAGE(view->image),view->pixbuf);
gtk_widget_queue_draw(view->image);
GDK_THREADS_LEAVE();
usleep(10000);
}
}
会发生一个图像是从网络摄像头拍摄并显示,然后GtkImage停止更新。
另外,当我尝试使用cvReleaseImage时,我得到一个seg错误,表示free已经传递了无效的指针。
答案 0 :(得分:2)
GTK是一个事件驱动的工具包,与许多其他工具包一样。你正在做的是将新图像排队以无限循环绘制,但绝不让GTK有机会绘制它们。这不是message pump的工作原理。你需要回到GTK,这样它就可以绘制更新的图像。 gtk_events_pending文档中解释了执行此操作的方法。
此外,为每个图像分配/绘制/解除分配gdk-pixpuf是次优的。只需在循环中分配一次缓冲区,在循环中绘制它(它将覆盖以前的内容),然后显示它。如果图像大小发生变化,您只需要重新分配新的缓冲区。
答案 1 :(得分:0)
我不知道如何使用GtkImgae,但我的猜测是你没有将新图像传递到窗口。您需要在循环内部执行类似本机cvShowImage的操作。如果不是我不知道。
此外,您不应释放用于捕获的图像。 OpenCV自己分配和解除分配。
编辑:尝试使用OpenCV函数查看图像并查看问题是否仍然存在。