解决方法参考:https://stackoverflow.com/questions/10045363/pickling-cv2-keypoint-causes-picklingerror
在使用SIFT将提取到的特征保存到pkl文件时,会出现如下错误:
_pickle.PicklingError: Can't pickle <class 'cv2.KeyPoint'>: it's not the same object as cv2.KeyPoint
这是由于cv2.KeyPoint的class类无法直接通过pickle.dump写入到pkl文件中。
代码如下:(出错代码)
self.sift = cv2.xfeatures2d.SIFT_create()
k, d = self.sift.detectAndCompute(im, mask=None)
self.key_tpls.append(k) #包含所有的关键点信息
self.desc_tpls.append(d)
with open(pkl_fn, 'wb') as f:
data = [self.key_tpls, self.desc_tpls]
pickle.dump(data, f)
此时需要对sift.detectAndCompute函数返回的k转换数据类型。
1.K得到的是关键点相关的信息(坐标、尺寸、角度等),将这些值保存到tuple(元组)或者dict(字典)中。
2.代码修改方式
1)例如:(写入元组tuple)
new_k = []
for i in range(len(k)):
temp = (k[i].pt , k[i].size , k[i].angle , k[i].response , k[i].octave , k[i].class_id)
#把这些信息写入到元组中
new_k.append(temp)
self.key_tpls.append(new_k) #包含所有的关键点信息
2)例如:(写入字典dict)
new_k = []
for i in range(len(k)):
temp = {'pt':k[i].pt , 'size':k[i].size , 'angle':k[i].angle ,'octave':k[i].octave ,
'class_id':k[i].class_id}#把这些信息写入到字典中
new_k.append(temp)
self.key_tpls.append(new_k) #包含所有的关键点信息
这样再pickle.dump(data,f)就不会出错了。个人建议用“字典”的形式,因为在下面调用的时候直接k[‘pt’]就可以了,如果是元组的话,还需要自己去看第几位保存的是‘pt’值。
不写入pickle.dump中可以直接用k.pt就可读取到‘pt’值,写入后要用k[‘pt’]。
分割线
补充,如出现:AttributeError: module 'cv2.cv2' has no attribute 'xfeatures2d'
原因:opencv-python版本太高
方法:
1) pip uninstall opencv-contrib-python
2)pip install opencv-contrib-python==3.3.0.10
(ps:据说opencv3.4以上写了专利了)