如何在小 GUI 中修复“allow_pickle=False 时无法加载对象数组”

Posted

技术标签:

【中文标题】如何在小 GUI 中修复“allow_pickle=False 时无法加载对象数组”【英文标题】:How to fix 'Object arrays cannot be loaded when allow_pickle=False' in A little GUI 【发布时间】:2022-01-24 02:27:12 【问题描述】:

我正在运行一个允许加载和查看存储的 OCT 卷的小 GUI 作为 3D Numpy 数组,它返回错误“当 allow_pickle=False 时无法加载对象数组” 这是GitHub中开发者已经使用的代码

from __future__ import print_function
import sys
import os. path as op
import numpy as np
import matplotlib as mpl
import matplotlib.pyplot as plt
from glob import glob
from mpl_toolkits.mplot3d import Axes3D
from matplotlib. widgets import Button, Slider
datapath='E:/New folder\GlaucomaOCT'
class OCTViewer(object):
def __init__(self, datapath):
         self.cubepaths = self.read_cubepaths(datapath)
    self.cubeidx = 0
    self.cube_original = None
    self.cube = None
    self.name = None
    self.x = None
    self.y = None
    self.z = None
    self.threshold = 255
    self.init_gui()
def init_gui(self):
        mpl.rcParams['toolbar'] = 'None'
    bkg_color = (0.9, 0.9, 0.9)
    self.fig = plt.figure('OCT Viewer', figsize=(7, 7),facecolor=bkg_color)
    # scans and cube plots
    self.plt1 = self.fig.add_subplot(221)
    self.plt2 = self.fig.add_subplot(222)
    self.plt3 = self.fig.add_subplot(223)
    self.plt4 = self.fig.add_subplot(224, projection='3d')
    # Buttons
    self.fig.subplots_adjust(bottom=0.2)  # space for buttons
    axprev = self.fig.add_axes([0.4, 0.05, 0.1, 0.07])
    axnext = self.fig.add_axes([0.5, 0.05, 0.1, 0.07])
    self.bnext = Button(axnext, '>>', color='white')
    self.bnext.on_clicked(self.next_cube)
    self.bprev = Button(axprev, '<<', color='white')
    self.bprev.on_clicked(self.prev_cube)
    # Slider
    axthresh = self.fig.add_axes([0.1, 0.15, 0.8, 0.02])
    self.sthresh = Slider(axthresh, 'Thres', 0, 255, 255, '%3.0f',
                          color='lightgray')
    self.sthresh.on_changed(self.update_threshold)
    self.fig.canvas.mpl_connect('motion_notify_event', self.on_hover)
    self.fig.canvas.mpl_connect('key_press_event', self.on_key)

def read_cubepaths(self, datapath):
    inpath = op.join(datapath, '*.npy')
    return [fn for fn in glob(inpath)]
def load_cube(self):
    assert self. cubepaths, "No cubes found! Correct data path?"
    path = self.cubepaths[self.cubeidx]
    self.name = op.basename(path).replace('.npy', '')
    self.fig.suptitle(self.name)
    self.cube_original = np.load(path)
    self.update_threshold(self.threshold, False)
def init_cursor(self):
    if self.x is None:
        self.z, self.x, self.y = [s // 2 for s in self.cube.shape[:3]]
def show_cube(self, threshold=120):
    self.plt4.clear()
    self.plt4.set_axis_off()
    return  # disabled for speed
    # self.plt4.set_xticks([])
    # self.plt4.set_yticks([])
    # self.plt4.set_zticks([])
    # cube = self.cube.max(axis=3)  # max of RGB
    cube = self.cube[:, :, :, 2]  # only blue channel
    xs, ys, zs = np.where(cube > threshold)
    colors = self.cube[cube > threshold] / 255.0
    self.plt4.scatter(zs, ys, xs, c=colors,
                      marker='.', alpha=0.3, linewidth=0.0)
def show_scans(self):
    self.init_cursor()
    self.plt1.clear()
    self.plt2.clear()
    self.plt3.clear()
    self.plt1.axis('off')
    self.plt2.axis('off')
    self.plt3.axis('off')
    linecolor = (1, 1, 0, 0.2)
    self.plt1.imshow(self.cube[self.z, :, :], aspect='auto')
    self.plt1.axvline(x=self.x, color=linecolor)
    self.plt1.axhline(y=self.y, color=linecolor)
    self.plt2.imshow(self.cube[:, self.x, :], aspect='auto')
    self.plt2.axvline(x=self.x, color=linecolor)
    self.plt2.axhline(y=self.z, color=linecolor)
    self.plt3.imshow(self.cube[:, :, self.y], aspect='auto')
    self.plt3.axvline(x=self.y, color=linecolor)
    self.plt3.axhline(y=self.z, color=linecolor)
    self.fig.canvas.draw_idle()
def save_scan(self):
    filename = 'bscan-' + self.name + ".jpg"
    plt.imsave(filename, self.cube[:, :, self.y], dpi=600)
def next_cube(self, event=None):
    self.cubeidx = min(self.cubeidx + 1, len(self.cubepaths) - 1)
    self.load_cube()
    self.show_cube()
    self.show_scans()
def prev_cube(self, event=None):
    self.cubeidx = max(self.cubeidx - 1, 0)
    self.load_cube()
    self.show_cube()
    self.show_scans()
def on_key(self, event):
    if event.key == 'right':
        self.next_cube()
    if event.key == 'left':
        self.prev_cube()
    if event.key == 's':
        self.save_scan()
def on_hover(self, event):
    if event.button != 1:  # left mouse button
        return
    if event.inaxes == self.plt1.axes:
        self.x, self.y = int(event.xdata), int(event.ydata)
        self.show_scans()
    if event.inaxes == self.plt2.axes:
        self.x, self.z = int(event.xdata), int(event.ydata)
        self.show_scans()
    if event.inaxes == self.plt3.axes:
        self.y, self.z = int(event.xdata), int(event.ydata)
        self.show_scans()
def update_threshold(self, val, redraw=True):
    self.threshold = int(val)
    self.cube = self.cube_original.copy()
    if self.threshold < 255:
        self.cube[:, :, :, 0] = 0
        threshold = self.threshold / 255.0 * np.max(self.cube)
        self.cube[self.cube > threshold] = 255
    if redraw:
        self.show_scans()
def run(self):
    self.load_cube()
    self.show_cube()
    self.show_scans()
    plt.show()
if __name__ == '__main__':
datapath = '.' if len(sys.argv) < 2 else sys.argv[1]
viewer = OCTViewer(datapath)
viewer.run()

但它给了我 ValueError:allow_pickle=False 时无法加载对象数组

【问题讨论】:

np.save/load 可以保存包含objects 的数组,而不是数字(或字符串)元素。为此,它使用pickle。文档解释说,出于安全原因,用户必须明确允许这样做。根据文档,这在 1.16 版中已更改,因此您的开发人员可能在此之前创建了此代码。 请考虑正确格式化您的代码,这样每个人都会更清楚 【参考方案1】:

尝试在load_cube 函数中更改这一行:

self.cube_original = np.load(path)

到这里:

self.cube_original = np.load(path, allow_pickle=True)

【讨论】:

以上是关于如何在小 GUI 中修复“allow_pickle=False 时无法加载对象数组”的主要内容,如果未能解决你的问题,请参考以下文章

在 Keras 中加载数据集时如何修复错误?

如何使用 QMenuBar 在小部件之间切换?

如何修复 PyQt5 GUI 冻结

如何修复 Eclipse 中模糊的 Swing 元素

MFC:修复 GUI 上的控制台

如何将所有分类结果打印到 GUI 上的文本小部件?