2012-04-06 8 views
16

特定のディレクトリ内のすべての画像でサーフィンを検索し、将来の使用のためにキーポイントとディスクリプタを保存したい。私は、以下に示すように漬物を使用することにしました:pickling cv2.KeyPointによりPicklingErrorが発生する

#!/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とOpenCVの2.3.1

問題はあなたがピクルスファイルにcv2.KeyPointをダンプすることができないということであるあなたにたくさん

答えて

14

ありがとうござい使用しています。私は同じ問題を抱えていましたが、キーポイントを自分でシリアル化してデシリアライズしてからPickleでそれらを破棄していました。

だから、タプルを持つすべてのキーポイントとその記述子を表します。

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

あなたはその後、ピクルスにダンプいくつかのリストにすべてのこれらの点を追加します。その後

再度データを取得したい、ピクルスを持つすべてのデータをロード:

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] 

上記のコードを使用してこのデータからcv2.KeyPointを作成し、あなたが構築するために、これらのポイントを使用することができます機能のリスト

私はこれを行うためのより良い方法があると思うが、上記はうまくいく(そして速い)。私の機能はフォーマット固有のリストに保存されているので、データフォーマットを少しでも使いこなす必要があるかもしれません。私は、私の考えをその一般的な基盤に使って上記を提示しようとしました。これがあなたに役立つことを願っています。

0

cv2.KeyPointは、cv2.KeyPointオブジェクトを返すPythonの関数です。文字通り "<type 'cv2.KeyPoint'> [is] not the same object as cv2.KeyPoint"という理由で、Pickleは混乱しています。つまり、cv2.KeyPointは関数オブジェクトですが、タイプはcv2.KeyPointです。なぜOpenCVがそうであるのか、私が掘る限り私は推測することができます。私はそれがC/C++ライブラリのラッパーであることとは何か関係があると感じています。

Pythonでは、これを自分で修正することができます。 I found the inspiration on this post about pickling methods of classes

私は実際にノートの

キーポイント

import copyreg 
import cv2 

def _pickle_keypoints(point): 
    return cv2.KeyPoint, (*point.pt, point.size, point.angle, 
          point.response, point.octave, point.class_id) 

copyreg.pickle(cv2.KeyPoint().__class__, _pickle_keypoints) 

ポストにオリジナリティから変更され、コードのこのクリップを使用

:Pythonの2で

  • 、あなたがcopy_reg代わりのcopyregを使用する必要があります。
  • 何らかの理由でcv2.KeyPointクラスに直接アクセスすることはできないため、一時オブジェクトを作成して使用します。
  • copyregパッチを適用すると、unpickling時に_pickle_keypointsの出力に指定したように、他の点で問題のあるcv2.KeyPoint関数が使用されるため、unpicklingルーチンを実装する必要はありません。
  • そして、吐き気のために完了するためには、cv2::KeyPoint::KeyPointはC++でオーバーロードされた関数ですが、Pythonではこれはまさに問題ではありません。 C++では、最初の引数のポイントを取る関数がありますが、Pythonでは、代わりにintと解釈しようとします。 *は、ポイントを2つの引数xyに展開し、唯一のint引数コンストラクタと一致させます。

私はこれが可能であることを認識するまでcasper's excellent solutionを使っていました。

関連する問題