Pickling cv2.KeyPoint causes PicklingError

I want to search surfs in all images in a given directory and save their keypoints and descriptors for future use. I decided to use pickle as shown below:

#!/usr/bin/env python
import os
import pickle
import cv2

class Frame:
  def __init__(self, filename):
    surf = cv2.SURF(500, 4, 2, True)
    self.filename = filename
    self.keypoints, self.descriptors = surf.detect(cv2.imread(filename, cv2.CV_LOAD_IMAGE_GRAYSCALE), None, False)

if __name__ == '__main__':

  Fdb = open('db.dat', 'wb')
  base_path = "img/"
  frame_base = []

  for filename in os.listdir(base_path):
    frame_base.append(Frame(base_path+filename))
    print filename

  pickle.dump(frame_base,Fdb,-1)

  Fdb.close()

When I try to execute, I get a following error:

File "src/pickle_test.py", line 23, in <module>
    pickle.dump(frame_base,Fdb,-1)
...
pickle.PicklingError: Can't pickle <type 'cv2.KeyPoint'>: it's not the same object as cv2.KeyPoint

Does anybody know, what does it mean and how to fix it? I am using Python 2.6 and Opencv 2.3.1

Thank you a lot

The problem is that you cannot dump cv2.KeyPoint to a pickle file. I had the same issue, and managed to work around it by essentially serializing and deserializing the keypoints myself before dumping them with Pickle.

So represent every keypoint and its descriptor with a tuple:

temp = (point.pt, point.size, point.angle, point.response, point.octave, 
        point.class_id, desc)       

Append all these points to some list that you then dump with Pickle.

Then when you want to retrieve the data again, load all the data with Pickle:

temp_feature = cv2.KeyPoint(x=point[0][0],y=point[0][1],_size=point[1], _angle=point[2], 
                            _response=point[3], _octave=point[4], _class_id=point[5]) 
temp_descriptor = point[6]

Create a cv2.KeyPoint from this data using the above code, and you can then use these points to construct a list of features.

I suspect there is a neater way to do this, but the above works fine (and fast) for me. You might have to play around with your data format a bit, as my features are stored in format-specific lists. I tried to present the above using my idea at its generic base. I hope that this may help you.

Pickling cv2.KeyPoint causes PicklingError, Pickling cv2.KeyPoint causes PicklingError. I want to search surfs in all images in a given directory and save their keypoints and descriptors for future use. pickle is somehow finding a different definition of Nation than you used when creating your dictionary, and this seems like a possible cause - an imported class will never be identical to one defined directly in your code, even if the definitions are character-for-character identical. – jasonharper Jun 22 at 1:38

pickle.PicklingError: Can't pickle (class 'cv2.KeyPoint'), Remedy Reference:https://stackoverflow.com/questions/10045363/pickling-cv2- keypoint-causes-picklingerror. When you save a file to pkl using the extracted� Проблема в том, что вы не можете сбрасывать cv2.KeyPoint в файл pickle. У меня была такая же проблема, и мне удалось обойти это, по сути, сериализовать и десериализовать ключевые точки, прежде чем сбросить их с помощью Pickle.

A similar solution to the one provided by Poik. Just call this once before pickling.

def patch_Keypoint_pickiling(self):
    # Create the bundling between class and arguments to save for Keypoint class
    # See : https://stackoverflow.com/questions/50337569/pickle-exception-for-cv2-boost-when-using-multiprocessing/50394788#50394788
    def _pickle_keypoint(keypoint): #  : cv2.KeyPoint
        return cv2.KeyPoint, (
            keypoint.pt[0],
            keypoint.pt[1],
            keypoint.size,
            keypoint.angle,
            keypoint.response,
            keypoint.octave,
            keypoint.class_id,
        )
    # C++ Constructor, notice order of arguments : 
    # KeyPoint (float x, float y, float _size, float _angle=-1, float _response=0, int _octave=0, int _class_id=-1)

    # Apply the bundling to pickle
    copyreg.pickle(cv2.KeyPoint().__class__, _pickle_keypoint)

More than for the code, this is for the incredibly clear explanation available there : https://stackoverflow.com/a/50394788/11094914

Please note that if you want to expand this idea to other "unpickable" class of openCV, you only need to build a similar function to "_pickle_keypoint". Be sure that you store attributes in the same order as the constructor. You can consider copying the C++ constructor, even in Python, as I did. Mostly C++ and Python constructors seems not to differ too much.

I has issue with the "pt" tuple. However, a C++ constructor exists for X and Y separated coordinates, and thus, allow this fix/workaround.

serialization � Issue #4251 � opencv/opencv � GitHub, Transferred from http://code.opencv.org/issues/379 || James Bowman on 2010-06 -11 00:47 PicklingError: Can't pickle <type 'cv2.KeyPoint'>: it's not the same object as cv2.KeyPoint The underlying cause is that the __name__ attribute on the class of instances returned by functions such as cv2.Boost()� uhfband@59faee3#diff-0d1ba4e35115631664436b13944953fd This one worked for me. Replace all the 'import caffe_pb2' with 'import caffe.proto.caffe_pb2 as caffe_pb2'.

Saving and Loading Keypoints in File using OpenCV and Python, pickle.PicklingError: Can't pickle <type 'cv2.KeyPoint'>: it's not the same object as cv2.KeyPoint. So, we need to serialize and deserialize the� Dismiss Join GitHub today. GitHub is home to over 50 million developers working together to host and review code, manage projects, and build software together.

_pickle.PicklingError: Cant pickle (class cv2.KeyPoint): its not the , pickling is recursive, not sequential. Thus, to pickle a list, pickle will start to pickle the containing list, then pickle the first element… diving into the first element and pickling dependencies and sub-elements until the first element is serialized. Then moves on to the next element of the list, and so on, until it finally finishes the

_pickle.PicklingError: Can't pickle <class 'ctypes.CDLL.__init__.<locals>._FuncPtr'>: it's not found as ctypes.CDLL.__init__.<locals>._FuncPtr. I am unsure which line of inputs code causes it, but there is a following piece of code relevant to the problem in the CDLL class inside ctypes built-in library:

Comments
  • Answer heavily link to this post's answer : stackoverflow.com/questions/50337569/…
  • Shouldn't *point.pt be point.pt? Also, I am getting a TypeError: a float is required in the load_reduce function of pickle. Is there any way to fix this?
  • @sha1 It should be *point.pt to seperate it into x and y. The constructor of cv2.Keypoint requires that, hence the TypeError you encounter. Alternatively, use point.pt[0], point.pt[1] at the cost of a small amount of speed per point, and to be able to use it in legacy code that still requires python 2.