Исключение Pickle для cv2. Boost при использовании многопроцессорной обработки - PullRequest
0 голосов
/ 14 мая 2018

Я работаю над проектом под названием «Обнаружение единиц действия Faciel». Я использую python2.7 и opencv 2.4

Ошибка:

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

Частичная обратная запись, транскрибированная с скриншот :

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)

1 Ответ

0 голосов
/ 17 мая 2018

Pickle используется модулем multiprocessing для связи между различными частями, и в Руководстве по программированию объясняется, что вы должны убедиться, что все ваши данные, которые вы передаете между процессами, должны быть совместимы с травлением:

Возможность выбора : убедитесь, что аргументы методов прокси можно выбрать.

Вы используете данные, которые нельзя выбрать.

В частности, что происходит неправильно, так это то, что класс cv2.Boost не совсем говорит правду о том, как вы можете создать больше копий класса.pickle хранит ссылки на классы и функции, а не на их определения, потому что это намного эффективнее.Это означает, что экземплярам нужно хранить данные только для этого экземпляра, а не все иерархии классов и определения методов.

Для этого pickle принимает модуль, в котором определен класс или функция.и имя объекта, и вместе это ссылка на класс или функцию.Затем перепроверяет , что он может использовать это имя для повторной загрузки того же класса или функции.

Эта проверка работоспособности не удалась для класса cv2.Boost.У вас есть экземпляры класса с именем Boost, который утверждает, что он поступил из модуля cv2, но когда pickle затем переходит к модулю cv2 и ищет атрибут Boost того модуля, который он обнаружил другой объект .Это означает, что ваши данные не могут быть выбраны.

Есть способы исправить это;вам нужно научить модуль pickle использовать другую функцию для повторной загрузки тех же данных, используя функцию copyreg.pickle() ;если такая регистрация существует для класса 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() документацию , чтобы догадаться, какими атрибутами будет обладать такой класс.Вы, вероятно, должны будете настроить это.Идея состоит в том, что для типа cv2.Boost().__class__ вызывается функция _pickle_boost(), возвращающая вызываемый объект (cv2.Boost) для создания нового экземпляра и аргументы, которые вы хотите передать этому вызываемому элементу.

Если какое-либо из приведенных выше значений сами по себе являются более cv2 типами, которые представляют такую ​​же проблему, то вам нужно зарегистрировать больше функций.

...