pygtk3中将摄像头从网络摄像头绘制到DrawableArea时出现分段错误 [英] Segmentation fault while drawing frame from webcam to DrawableArea in pygtk3
问题描述
正如标题所示,我正在从网络摄像头读取帧(使用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.
问题:
-
在
GdkPixbuf.Pixbuf.new_from_data
的情况下如何解决此分段错误?在我看来,该函数的参数选择错误.
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屋!