Pickle exception for cv2.Boost when using multiprocessing

青春壹個敷衍的年華 提交于 2019-12-01 13:17:15

Pickle is used by the multiprocessing module to communicate between the different parts, and in the programming guidelines it explains that you must ensure that all your data that you pass between processes must be compatible with pickling:

Picklability: Ensure that the arguments to the methods of proxies are picklable.

You are using data that is not picklable.

Specifically, what is going wrong is that the cv2.Boost class doesn't quite tell the truth on how you can create more copies of the class. pickle stores references to classes and functions, not their definition, because that's way more efficient. This means that instances only need to store the data for that instance, not also all of the class hierarchy and method definitions.

In order to do this, pickle takes the module a class or function is defined in, and the name of the object, and together that's the reference to the class or function. It then double-checks that it can use that name to load the same class or function back again.

That sanity check failed for the cv2.Boost class. You have instances of a class is named Boost and that claims to have come from the cv2 module, but when pickle then goes to the cv2 module and looks up the Boost attribute of that module it found a different object. This means your data could not be unpickled.

There are ways to correct this; you need to teach the pickle module to use a different function to load the same data again, using the copyreg.pickle() function; if such a registration exists for the cv2.Boost class then pickle will not make the above check:

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)

WARNING: I didn't actually test if the above will work, because I don't have a 2.4.x version of cv2 installed locally; I merely referred to the cv2.Boost() documentation to guess at what attributes such a class would have. You'll probably need to adjust it. The idea is that for the cv2.Boost().__class__ type, the _pickle_boost() function is called, returning a callable (cv2.Boost) to create a new instance, and the arguments that you want to pass to that callable.

If any of the above values are themselves more cv2 types that exhibit the same problem, then you need to register more functions.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!