我想在给定目录中的所有图像中搜索冲浪,并保存它们的关键点和描述符以备将来使用。我决定用泡菜,如下所示:
#!/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()
当我尝试执行时,出现以下错误:
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
有人知道,这是什么意思,怎么解决?我使用的是Python 2.6和opencv2.3.1
非常感谢
类似于Poik提供的解决方案。腌制前先打个电话。
除了代码,这里还有一个非常清晰的解释:https://stackoverflow.com/a/50394788/11094914
请注意,如果您想将这个想法扩展到openCV的其他“不可接受”类,只需要构建一个类似于“pickle”keypoint的函数。确保以与构造函数相同的顺序存储属性。您可以考虑复制C++构造函数,即使在Python中,也像我一样。大多数C++和Python构造函数似乎没有太大的区别。
我对“pt”元组有意见。然而,对于X和Y分离的坐标,存在C++构造函数,因此允许这种修复/处理。
部分问题是
cv2.KeyPoint
是python中返回cv2.KeyPoint
对象的函数。Pickle被搞糊涂了,因为字面意思是,“<type 'cv2.KeyPoint'>
[是]not the same object as cv2.KeyPoint
”。也就是说,cv2.KeyPoint
是一个函数对象,而类型是cv2.KeyPoint
。为什么OpenCV是这样的,我只能猜测,除非我去挖掘。我有一种感觉,它与一个围绕C/C++库的包装有关。Python确实让您能够自己解决这个问题。I found the inspiration on this post about pickling methods of classes。
实际上,我使用的是这段代码,经过高度修改后
注意要点:
copy_reg
而不是copyreg
,使用point.pt[0], point.pt[1]
而不是*point.pt
。cv2.KeyPoint
类,因此您需要创建一个临时对象并使用它。copyreg
修补将使用我在_pickle_keypoints
输出中指定的其他有问题的cv2.KeyPoint
函数,因此我们不需要实现取消锁定例程。*
将点展开为两个参数,x
和y
以匹配唯一的int
参数构造函数。我一直在使用casper's excellent solution直到我意识到这是可能的。
问题是不能将cv2.KeyPoint转储到pickle文件。我也遇到了同样的问题,在用Pickle处理关键点之前,我自己通过序列化和反序列化来解决这个问题。
所以用元组表示每个关键点及其描述符:
将所有这些点附加到一些列表中,然后用Pickle转储这些列表。
然后,如果要再次检索数据,请使用Pickle加载所有数据:
使用上面的代码从这些数据创建一个cv2.KeyPoint,然后您可以使用这些点构建一个特性列表。
我想有一个更整洁的方法来做这件事,但上面的工作很好(和快速)为我。由于我的功能存储在特定于格式的列表中,因此您可能需要稍微修改一下数据格式。我试图用我的想法在它的一般基础上提出上述观点。我希望这对你有帮助。
相关问题 更多 >
编程相关推荐