使用多处理时cv2.Boost的Pickle异常

问题描述 投票:1回答:1

我正在开发名为“Faciel Actions Units Detection”的项目我正在使用python2.7和opencv 2.4

错误:

pickle.PicklingError: Can't pickle <type 'cv2.Boost'>: it's not the same object as cv2.Boost

a screenshot转录的部分追溯:

Loading classifier for action unit 27
Traceback (most recent call last):
  File "C:\Python27\audetect-master\audetect-interactive.py", line 59, in <module>
    main()
  File "C:\Python27\audetect-master\audetect-interactive.py", line 18, in main
    active_aus = detector.detect()
  File "C:\Python27\audetect-master\detect.py", line 67, in detect
    initial_points = self.ffdetector.locate_features(first)
  File "C:\Python27\audetect-master\detect.py", line 183, in locate_features
    thread.start()
  File "C:\Python27\lib\multiprocessing\process.py", line 130, in start
    self._popen = Popen(self)
  File "C:\Python27\lib\multiprocessing\forking.py", line 227, in __init__
    dump(process_obj, to_child, HIGHEST_PROTOCOL)
  File "C:\Python27\lib\multiprocessing\forking.py", line 199, in dump
    ForkingPickler(file, protocol).dump(obj)
  File "C:\Python27\lib\pickle.py", line 224, in dump
    self.save(obj)
  File "C:\Python27\lib\pickle.py", line 331, in save
    self.save_reduce(obj=obj, *rv)
  File "C:\Python27\lib\pickle.py", line 425, in save_reduce
    save(state)
  File "C:\Python27\lib\pickle.py", line 286, in save
    f(self, obj) # Call unbound method with explicit self
  File "C:\Python27\lib\pickle.py", line 655, in save_dict
    self._batch_setitems(obj.iteritems())
  File "C:\Python27\lib\pickle.py", line 687, in _batch_setitems
    save(v)
  File "C:\Python27\lib\pickle.py", line 286, in save
    f(self, obj) # Call unbound method with explicit self
  File "C:\Python27\lib\multiprocessing\forking.py", line 67, in dispatcher
    self.save_reduce(obj=obj, *rv)
  File "C:\Python27\lib\pickle.py", line 401, in save_reduce
    save(args)
  File "C:\Python27\lib\pickle.py", line 286, in save
    f(self, obj) # Call unbound method with explicit self
  File "C:\Python27\lib\pickle.py", line 554, in save_tuple
    save(element)
python python-2.7 pickle python-multiprocessing cv2
1个回答
3
投票

multiprocessing模块使用Pickle在不同部分之间进行通信,在programming guidelines中,它解释了您必须确保在进程之间传递的所有数据必须与pickle兼容:

可选择性:确保代理方法的参数是可选择的。

您正在使用不可选择的数据。

具体来说,出现问题的是,cv2.Boost类并不能说明如何创建更多类的副本。 pickle存储对类和函数的引用,而不是它们的定义,因为这样更有效。这意味着实例只需要存储该实例的数据,而不是所有类层次结构和方法定义。

为了做到这一点,pickle将模块定义为一个类或函数,以及对象的名称,以及它们对类或函数的引用。然后再仔细检查它是否可以使用该名称再次加载相同的类或函数。

cv2.Boost班的理智检查失败了。你有一个类的实例名为Boost,并声称来自cv2模块,但当pickle然后转到cv2模块并查找该模块的Boost属性时,它发现了一个不同的对象。这意味着您的数据无法被打开。

有办法纠正这个问题;你需要教pickle模块使用不同的函数再次加载相同的数据,使用copyreg.pickle() function;如果cv2.Boost类有这样的注册,那么pickle将不会进行上述检查:

import copyreg
import cv2

def _pickle_boost(boost):
    return cv2.Boost, (
        boost.trainData,
        boost.tflag,
        boost.responses, 
        boost.varIdx,
        boost.sampleIdx,
        boost.varType,
        boost.missingDataMask,
        boost.paramsd,
    )

copyreg.pickle(cv2.Boost().__class__, _pickle_boost)

警告:我实际上没有测试上述是否有效,因为我没有在本地安装2.4.x版本的cv2;我只是提到cv2.Boost() documentation来猜测这样一个类会有什么属性。你可能需要调整它。这个想法是,对于cv2.Boost().__class__类型,调用_pickle_boost()函数,返回一个可调用的(cv2.Boost)来创建一个新实例,以及你想要传递给那个可调用的参数。

如果上述值中的任何一个本身是更多表现出相同问题的cv2类型,那么您需要注册更多函数。

© www.soinside.com 2019 - 2024. All rights reserved.