【问题标题】:Display numpy array cv2 image in wxpython correctly在 wxpython 中正确显示 numpy 数组 cv2 图像
【发布时间】:2021-03-24 18:31:47
【问题描述】:

我正在尝试将 numpy 数组(cv2 图像)转换为 wxpython 位图并正确显示。我已经研究了 SO 和其他地方的各种解决方案,但没有成功。您可以在下面的代码中看到我的两个尝试。

import wx
import cv2
import numpy as np


def create_wx_bitmap(cv2_image):
    # type: (np.ndarray) -> wx.Bitmap

    # My Attempt based on https://stackoverflow.com/questions/32995679/converting-wx-bitmap-to-numpy-using-bitmapbufferformat-rgba-python/32995940#32995940
    height, width = cv2_image.shape[:2]

    array = cv2_image # the OpenCV image
    image = wx.Image(width, height)
    image.SetData(array.tobytes())
    wxBitmap = image.ConvertToBitmap()   

    return wxBitmap

    # My other attempt:
    # height, width = cv2_image.shape[:2]
    # cv2_image_rgb = cv2.cvtColor(cv2_image, cv2.COLOR_BGR2RGB)
    # return wx.Bitmap.FromBuffer(width, height, cv2_image_rgb)

class MyFrame(wx.Frame):
    def __init__(self, parent, title):
        wx.Frame.__init__(self, parent, title=title)

        cv2_image = cv2.imread("test1.png", cv2.IMREAD_ANYDEPTH | cv2.IMREAD_COLOR)  # type: np.ndarray
        print(cv2_image.dtype)

        bitmap = create_wx_bitmap(cv2_image)  # type: wx.Bitmap

        wx.StaticBitmap(self, -1, bitmap, (0, 0), self.GetClientSize())
        self.SetSize(bitmap.GetSize())


if __name__ == "__main__":
    app = wx.App(False)
    frame = MyFrame(None, "wxPython with OpenCV")
    frame.Show()
    app.MainLoop()

上面的代码似乎适用于 16 位(24 位深度)以下的图像。但是,位深为 64 的图像会导致如下图所示的条带。(这是从 Blender 3D 导出​​的 16 位深设置的渲染):

我也尝试过转换数组数据类型,但似乎没有任何区别。

编辑(最终解决方案):

我的问题的解决方案是在规范化数据之后将数组转换为np.uint8,如this SO answer 中所述。感谢@PetrBlahos 在他的回答中提到数据需要是 8 位 RGB。

def create_wx_bitmap(cv2_image):
    # type: (np.ndarray) -> wx.Bitmap

    height, width = cv2_image.shape[:2]

    info = np.iinfo(cv2_image.dtype) # Get the information of the incoming image type
    data = cv2_image.astype(np.float64) / info.max # normalize the data to 0 - 1
    data = 255 * data # Now scale by 255
    cv2_image = data.astype(np.uint8)

    cv2_image_rgb = cv2.cvtColor(cv2_image, cv2.COLOR_BGR2RGB)
    return wx.Bitmap.FromBuffer(width, height, cv2_image_rgb)

【问题讨论】:

    标签: python numpy opencv wxpython


    【解决方案1】:

    我用

    dc.DrawBitmap(wx.Bitmap.FromBuffer(iw, ih, cv_image), 0, 0)
    

    但 cv_image 必须是 rgb 值的 numpy 字节数组。因此,无论您做什么,都必须将数据转换为 8 位 RGB(或者可能是 RGBA,使用 FromBufferRGBA)。 我不太明白您的数据是如何构造的。 64位意味着你有4个通道(RGBA),每个通道都是16b整数?

    我想你可能会使用 cv2.convertScaleAbs,或者可能是 convertTo。

    【讨论】:

      猜你喜欢
      • 2020-08-04
      • 1970-01-01
      • 1970-01-01
      • 2021-08-21
      • 2019-07-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-01-21
      相关资源
      最近更新 更多