【问题标题】:How to turn Gdk pixbuf object into numpy array如何将 Gdk pixbuf 对象转换为 numpy 数组
【发布时间】:2016-10-08 19:53:45
【问题描述】:

所以,我正在尝试截取屏幕截图并将其用作 numpy 数组。但是,我能找到的只是先将其转换为 PIL Image,然后再转换为 numpy 数组。所以,我想知道是否有一种方法可以在不使用 PIL 库的情况下将其直接转换为 numpy 数组

from gi.repository import Gdk

window = Gdk.get_default_root_window()
x, y, width, height = window.get_geometry()
pb = Gdk.pixbuf_get_from_window(window, x, y, width, height)

谢谢

【问题讨论】:

    标签: python arrays image


    【解决方案1】:

    如果你不介意使用 Gtk2 和 PyGtk,那么下面的就可以了

    import gtk, numpy
    image="yourimage.jpg"
    t=gtk.gdk.pixbuf_new_from_file(image)
    n=t.get_pixels_array()
    print n.shape
    

    最好的部分是 n 是对 t 中数据的引用,因此您可以使用 numpy 更改 pixbuf

    如果你想使用 Gtk3,这两个调用就可以了

    from gi.repository import GdkPixbuf
    import numpy
    def array_from_pixbuf(p):
        " convert from GdkPixbuf to numpy array"
        w,h,c,r=(p.get_width(), p.get_height(), p.get_n_channels(), p.get_rowstride())
        assert p.get_colorspace() == GdkPixbuf.Colorspace.RGB
        assert p.get_bits_per_sample() == 8
        if  p.get_has_alpha():
            assert c == 4
        else:
            assert c == 3
        assert r >= w * c
        a=numpy.frombuffer(p.get_pixels(),dtype=numpy.uint8)
        if a.shape[0] == w*c*h:
            return a.reshape( (h, w, c) )
        else:
            b=numpy.zeros((h,w*c),'uint8')
            for j in range(h):
                b[j,:]=a[r*j:r*j+w*c]
            return b.reshape( (h, w, c) )
    
    def pixbuf_from_array(z):
        " convert from numpy array to GdkPixbuf "
        z=z.astype('uint8')
        h,w,c=z.shape
        assert c == 3 or c == 4
        if hasattr(GdkPixbuf.Pixbuf,'new_from_bytes'):
            Z = GLib.Bytes.new(z.tobytes())
            return GdkPixbuf.Pixbuf.new_from_bytes(Z, GdkPixbuf.Colorspace.RGB, c==4, 8, w, h, w*c)
        return GdkPixbuf.Pixbuf.new_from_data(z.tobytes(),  GdkPixbuf.Colorspace.RGB, c==4, 8, w, h, w*c, None, None)
    

    【讨论】:

    • array_from_pixbuf 函数运行良好,但 pixbuf_from_array 函数显示垃圾或导致分段错误。经过大量搜索,我找到了这个答案,描述了保存图像的内存在使用前被释放:stackoverflow.com/a/36634145/5613485。解决方法是使用 Pixbuf.new_from_data 并在 z.tobytes() 周围放置一个 GLib.Bytes.new()。
    • 亲爱的 Zoltan,我最近尝试了您的版本,实际上随着您的更改代码崩溃,而我上面的版本运行良好。我不知道为什么。
    • 有趣。对我来说,这两种变体的行为是完全相反的。
    猜你喜欢
    • 1970-01-01
    • 2021-07-06
    • 2013-04-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-18
    相关资源
    最近更新 更多