如何正确地将3d数组转换为连续的rgb字节

时间:2014-06-05 14:24:29

标签: python opencv gtk pygtk pygobject

我正在尝试将cv2.imread返回的3d数组转换为连续的rgb字节数组,以便在GTK中显示。以下是我的转换代码:

def ndarr2rgb(img):
    r_arr = img[:, :, 0].ravel()    # read channel
    g_arr = img[:, :, 1].ravel()    # green channel
    b_arr = img[:, :, 2].ravel()    # blue channel
    numItems = img.shape[0] * img.shape[1] * img.shape[2]   # number of entries in byte array
    z = img.shape[2]                # z dimension, always equal to 3
    arr = np.zeros((numItems, 1))
    # to fill the byte array with r,g,b channel
    for i in xrange(0, numItems):
        if i % z == 0:
            arr[i] = r_arr[i/z]
        if i % z == 1:
            arr[i] = g_arr[i/z]
        if i % z == 2:
            arr[i] = b_arr[i/z]
    return arr

所以,在我的代码中,我首先将三个维度分别放入r_arr,g_arr,b_arr,然后我将值或RGB中的值放入'arr'。所以在迭代之后,数组'arr'将像'r0,g0,b0,r1,g1,b1,...'

然后我使用“ GdkPixbuf.Pixbuf.new_from_data ”函数从上面的“ ndarr2rgb ”函数返回的arr中获取pixbuf。我使用“ image.set_from_pixbuf ”来显示图像。但我得到了以下结果:
enter image description here 这就像是有一些嘈杂的区域,所以请帮我解决我的问题,谢谢。

4 个答案:

答案 0 :(得分:3)

只是这样做:

all_in_one_row = np.reshape(img,(-1))

答案 1 :(得分:3)

问题可能是由于GdkPixbuf.Pixbuf.new_from_data无法正确管理内存,请参阅[1]。解决方法是将数据写入临时文件并使用GdkPixbuf.Pixbuf.new_from_file [2]。使用PIL的示例:

from PIL import Image

image = Image.frombytes('RGB', (width, height), data)
image.save(filename)
pixbuf = GdkPixbuf.Pixbuf.new_from_file(filename)
  1. https://bugzilla.gnome.org/show_bug.cgi?id=721497
  2. http://lazka.github.io/pgi-docs/api/GdkPixbuf-2.0/classes/Pixbuf.html#GdkPixbuf.Pixbuf.new_from_file

答案 2 :(得分:1)

由于io,PIL和/或GdkPixbuf的变化,即使在阅读了大量建议之后我也无法解决这个问题。最后,我采取了相当简单的解决方案:

import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk, GdkPixbuf

def array2pixbuf(width, height, arr):
    # pnm
    header = b"P6 %d %d 255 " % (width, height)
    # flatten and convert to an array of bytes (not a bytearray!)
    data = bytes(colour for pixel in arr for colour in pixel)

    loader = GdkPixbuf.PixbufLoader.new()
    loader.write(header)
    loader.write(data)
    pixbuf = loader.get_pixbuf()
    loader.close()

    return pixbuf

答案 3 :(得分:-1)

你不需要写一个临时文件,以便工作区 GdkPixbuf.Pixbuf.new_from_data无法正确管理内存, [1]你可以使用pnm图像格式[2]:

from gi.repository import GdkPixbuf
import cv2

filename = './file.png'
# read and convert image from BGR to RGB (pnm uses RGB)
im = cv2.cvtColor(cv2.imread(filename), cv2.COLOR_BGR2RGB)
# get image dimensions (depth is not used)
height, width, depth = im.shape
pixl = GdkPixbuf.PixbufLoader.new_with_type('pnm')
# P6 is the magic number of PNM format, 
# and 255 is the max color allowed, see [2]
pixl.write("P6 %d %d 255 " % (width, height) + im.tostring())
pix = pixl.get_pixbuf()
pixl.close()

在那次黑客攻击之后,你可以使用: image.set_from_pixbuf( pix

的参考文献:

  1. https://bugzilla.gnome.org/show_bug.cgi?id=732297
  2. http://en.wikipedia.org/wiki/Netpbm_format