Fix TypeError: can’t pickle cv2.KeyPoint objects Error in Python OpenCV

By | August 11, 2022

When we are using opencv SIFT algorithm to compute the similarity between two images, we will get two objects: keypoint, descriptor. In order to save processing time, we may save them to a file using python pickle. However, we may get this error: TypeError: can’t pickle cv2.KeyPoint objects. In this tutorial, we will introduce you how t fix it.

For example:

keypoint1, descriptor1 = computeSIFT(image_1_data)
print(type(keypoint1))
for k in keypoint1:
    print(type(k))

with open("test.txt", "wb") as f:
    pickle.dump(keypoint1, f)

Here keypoint1 is python list, it contains some <class ‘cv2.KeyPoint’>

Run this code, we will get this error:

TypeError: can’t pickle cv2.KeyPoint objects

Fix TypeError can't pickle cv2.KeyPoint objects Error in Python OpenCV

How to fix this error?

In order to save KeyPoint object using pickle, we can wrap it by using a python dictionary.

For example:

    #-------------------------------------------------------------
    new_k = []
    k = keypoint1
    for i in range(len(k)):
        temp = {'pt': k[i].pt,
                'size': k[i].size,
                'angle': k[i].angle,
                'octave': k[i].octave,
                "response":k[i].response,
                "octave":k[i].octave,
                'class_id': k[i].class_id
                }  # 把这些信息写入到字典中
        new_k.append(temp)
    data = [new_k, descriptor1]

    with open("key.txt", 'wb') as fp:
        pickle.dump(data, fp)

Run this code, we will save keypoint1 and descriptor1 to a key.txt

How to load keypoint1 and descriptor1and from key.txt file?

We should rebuild keypoint1 from points saved in key.txt

For example:

    with open("key.txt", 'rb') as fp:
        data = pickle.load(fp)
        descriptor1 = data[1]
        new_k = data[0]
        keypoint1 = []
        for temp in new_k:
            point = cv2.KeyPoint(x=temp['pt'][0], y=temp['pt'][1],
                                 _size=temp['size'], _angle=temp['angle'],
                                 _response=temp['size'],
                                 _octave=temp['octave'], _class_id=temp['class_id'])
            keypoint1.append(point)
    #------------------------

Run this code, we can find keypoint1 and descriptor1 are restored.