pygtk3中将摄像头从网络摄像头绘制到DrawableArea时出现分段错误 [英] Segmentation fault while drawing frame from webcam to DrawableArea in pygtk3

查看:137
本文介绍了pygtk3中将摄像头从网络摄像头绘制到DrawableArea时出现分段错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

正如标题所示,我正在从网络摄像头读取帧(使用openCV,我想对其进行一些后续功能检测),并希望将结果写入pyGTK3 DrawableArea小部件.遵循答案,为方便起见,我会引用该答案

As title suggests I am reading frames from my webcam (using openCV, i want to do some follow up feature detection with it) and want to write the result to a pyGTK3 DrawableArea widget. Following this answer, which i will quote for convenience:

以下似乎可以完成这项工作:

The following seems to do the job:

def draw(self, widget, context):
    Gdk.cairo_set_source_pixbuf(context, self.pixbuf, 0, 0)
    context.paint()

一个问题仍然存在:这是首选的做事方式吗?

One question still remains: Is this the preferred way of doing things?

所以我现在正在使用:

def _on_drawablearea_draw(self, canvas, context):
    frame = self.stream.read()
    self.pixbuf = self._frame2pixbuf(frame)
    Gdk.cairo_set_source_pixbuf(context, self.pixbuf, 0, 0)
    context.paint()

def _frame2pixbuf(self, frame):
    height, width, rgb_stride = frame.shape
    frame_to_list = frame.flatten() # must become list
    return GdkPixbuf.Pixbuf.new_from_data(frame_to_list,
                                          GdkPixbuf.Colorspace.RGB,
                                          False, 8, 
                                          width, height, rgb_stride * width)

frame是形状为(m,n,3)的numpy数组.

frame is a numpy array of shape (m,n,3).

不幸的是,我在声明中得到了segmentation fault:

Unfortunately, I get a segmentation fault at the statement:

Gdk.cairo_set_source_pixbuf(context, self.pixbuf, 0, 0)

从上面引用的答案的注释中可以看出,这似乎是更多成员遇到的,但是没有提供解决方案,并且快速的Google搜索没有结果.

This apparantly happened to more members as seen in the comments to the above quoted answer, however no solution was provided and a quick google search yields no results.

更新1:从文件中加载pixbuf符合预期,即

Update 1: Loading pixbuf from file is working as expected, i.e.

def _image2pixbuf(self):
    filename = 'some_test_image.jpg'
    return GdkPixbuf.Pixbuf.new_from_file(filename)

_on_drawablearea_draw的调用相同,但对._image2pixbuf的更改除外,在DrawableArea小部件中完美地呈现了some_test_image.jpg.

with the same call to _on_drawablearea_draw except for the change to ._image2pixbuf renders some_test_image.jpg perfectly in the DrawableArea widget.

更新2:转换为字节并从字节创建pixbuf对我来说是有效的,即

Update 2: Converting to bytes and creating the pixbuf from bytes works for me, i.e.

def _frame2pixbuf(self, frame):
    height, width, rgb_stride = frame.shape
    frame_in_bytes = GLib.Bytes.new(frame.tobytes())
    return GdkPixbuf.Pixbuf.new_from_bytes(frame_in_bytes,
                                          GdkPixbuf.Colorspace.RGB,
                                          False, 8, 
                                          width, height, rgb_stride * width)

但是它增加了一个不必要的"(?)附加步骤,将帧数据转换为字节.

but it adds an 'unnecessary' (?) additional step of converting the frame data to bytes.

问题:

  1. GdkPixbuf.Pixbuf.new_from_data的情况下如何解决此分段错误?在我看来,该函数的参数选择错误.

  1. How do i fix this segmentation fault in the case of GdkPixbuf.Pixbuf.new_from_data? It seems to me now that the arguments to the function are badly chosen.

此外,正如上面引用的答案还问到的那样:这是将帧从网络摄像头写入DrawableArea小部件的首选方法吗?

Furthermore, as the above quoted answer also asks: is this the preferred way of writing a frame from a webcam to a DrawableArea widget?

推荐答案

要回答您的第一个问题,问题是

To answer your first question, the issue is that new_from_data() does not make a copy of the image data that you pass to it, it uses it directly and in your case the image data is contained in the frame_in_bytes variable which is local to the _frame2pixbuf function. Thus that image data is likely freed and is no longer valid once you're out of the _frame2pixbuf function scope.

使用new_from_file函数分配图像存储器本身时,情况并非如此. new_from_bytes也不是,因为您在堆上创建了一个新的Bytes对象,当您离开函数作用域时该对象不会被释放.

This is not the case when you use the new_from_file function which allocates the image memory itself; nor in the case of new_from_bytes because you create a new Bytes object on the heap which does not get freed when you leave the function scope.

要使用new_from_data(),必须确保在调用Gdk.cairo_set_source_pixbuf()之前图像数据不会变得无效.我认为这样做的一种方法是将_frame2pixbuf函数的内容放入_on_drawablearea_draw函数中,以使frame_in_bytes var在那种情况下仍然有效.

To use new_from_data(), you would have to make sure that your image data does not become invalid before Gdk.cairo_set_source_pixbuf() is called. I think one way to do that would be to put the contents of your _frame2pixbuf function into your _on_drawablearea_draw function so that the frame_in_bytes var remains valid in that context.

这篇关于pygtk3中将摄像头从网络摄像头绘制到DrawableArea时出现分段错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆