在wxpython中正确显示numpy数组cv2图像

在wxpython中正确显示numpy数组cv2图像

本文介绍了在wxpython中正确显示numpy数组cv2图像的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am trying to convert a numpy array (cv2 image) to a wxpython Bitmap and display it properly. I have looked into various solutions on SO and elsewhere, but without success. You can see two of my attempts in the code below.

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 的图像会产生如下图所示的条带.(这是使用 16 位深度设置导出的 Blender 3D 渲染):

The code above seems to work for images under 16-bit (24 bit depth). However, an image that has a bit depth of 64 results in banding like the below screenshot. (which was a render from Blender 3D exported with 16 bit depth setting):

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

I have also tried converting the array datatype, but it didn't seem to make any difference.

编辑(最终解决方案):

我的问题的解决方案是在.感谢@PetrBlahos 在他的回答中提到数据需要是 8 位 RGB.

The solution to my problem was to convert the array to np.uint8 after normalizing the data as mentioned in this SO answer. Thanks to @PetrBlahos for mentioning that the data needs to be 8bit RGB in his answer.

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)

推荐答案

我用

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

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

but cv_image must be a numpy byte array of rgb values. So, whatever you do, you must convert your data to 8bit RGB (or possibly RGBA, the use FromBufferRGBA).I do not quite see how your data is structured. 64bits means you have 4 channels (RGBA) each one is 16b integer?

我认为您可能会使用 cv2.convertScaleAbs,或者可能使用 convertTo.

I think you might use cv2.convertScaleAbs, or perhaps convertTo.

这篇关于在wxpython中正确显示numpy数组cv2图像的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-05 20:13