Segmentation error when drawing a frame from a webcam to DrawableArea in pygtk3

As the title says, I am reading frames from my webcam (using openCV, I want to do some function tracking) and want to write the result in the pyGTK3 DrawableArea widget. After this answer, which I will give 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 more question remains: is this the preferred way to do something?

So now I use:

 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 is an array with several sizes (m,n,3) .

Unfortunately, I get a segmentation fault in the statement:

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

This was due to the large number of participants, as shown in the comments to the answer above, however no solution was provided, and a quick search on Google does not yield any results.

Update 1: Loading pixbuf from a file works as expected, i.e.

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

with the same call to _on_drawablearea_draw , except for changing to ._image2pixbuf , it renders some_test_image.jpg in DrawableArea widgets.

Update 2: Converting to bytes and creating 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โ€ (?) extra step to convert the frame data into bytes.

Questions

  • How to fix this segmentation error in case of GdkPixbuf.Pixbuf.new_from_data ? Now it seems to me that the arguments to the function are poorly selected.

  • Also, since the answer above also asks: is this the preferred way to record a frame from a webcam to a DrawableArea widget?

+1
source share
1 answer

To answer your first question, the problem 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 variable frame_in_bytes , which is local to the _frame2pixbuf function. Thus, the image data is likely to be released and will no longer be valid after you exit the _frame2pixbuf function _frame2pixbuf .

This is not the case when you use the new_from_file function, which itself allocates image memory; neither in the case of new_from_bytes , because you create a new Bytes object on the heap that is not freed when you exit the scope.

To use new_from_data() , you will need to make sure that your image data does not become invalid before calling Gdk.cairo_set_source_pixbuf() . I think one way to do this is to put the contents of your _frame2pixbuf function in your _on_drawablearea_draw function _on_drawablearea_draw that the frame_in_bytes var character frame_in_bytes valid in this context.

0
source

Source: https://habr.com/ru/post/913854/


All Articles