2012-04-06 8 views
16

Chcę wyszukiwać fale na wszystkich obrazach w danym katalogu i zapisać ich kluczowe i deskryptory do wykorzystania w przyszłości. Postanowiłem wykorzystać marynatę, jak pokazano poniżej:Wytrawianie cv2.KeyPoint powoduje 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() 

Kiedy próbuję wykonać, otrzymuję następujący błąd:

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 

Czy ktoś wie, co to znaczy i jak to naprawić? Używam Pythona 2.6 i OpenCV 2.3.1

Dziękuję dużo

Odpowiedz

14

Problem polega na tym, że nie można zrzucić cv2.KeyPoint do pliku marynaty. Miałem ten sam problem i udało mi się go obejść, zasadniczo serializując i deserializując osobiście punkty przed wyrzuceniem ich z marynatą.

więc reprezentować każdą KeyPoint i jego deskryptor z krotka:

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

Append wszystkie te punkty w pewnym liście, które następnie zrzucić z marynaty.

Potem, gdy chcesz ponownie pobrać dane, należy załadować wszystkie dane z marynacie:

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] 

Tworzenie cv2.KeyPoint z tych danych, wykorzystując powyższy kod, a następnie można użyć tych punktów do skonstruowania lista funkcji.

Podejrzewam, że jest to lepszy sposób, ale powyższe działa dobrze (i szybko) dla mnie. Być może będziesz musiał trochę pograć z formatem danych, ponieważ moje funkcje są przechowywane na listach specyficznych dla formatu. Próbowałem przedstawić powyższe, wykorzystując mój pomysł w jego ogólnej bazie. Mam nadzieję, że to może ci pomóc.

0

Część problemu to cv2.KeyPoint to funkcja w pythonie, która zwraca obiekt cv2.KeyPoint. Pickle staje się zdezorientowany, ponieważ, dosłownie, "<type 'cv2.KeyPoint'> [jest] not the same object as cv2.KeyPoint". Oznacza to, że cv2.KeyPoint jest obiektem funkcji, a typem jest cv2.KeyPoint. Dlaczego tak jest w OpenCV, mogę tylko zgadywać, chyba że zacznę kopać. Mam wrażenie, że ma to coś wspólnego z tym, że jest opakowaniem w bibliotece C/C++.

Python daje możliwość samodzielnego rozwiązania problemu. I found the inspiration on this post about pickling methods of classes.

I rzeczywiście wykorzystać ten klip kodu, silnie zmodyfikowane od oryginału w poście

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) 

Kluczowe punkty Uwaga:

  • W Pythonie 2, trzeba użyć copy_reg zamiast copyreg .
  • Z jakiegoś powodu nie można uzyskać bezpośredniego dostępu do klasy cv2.KeyPoint, więc tworzysz obiekt tymczasowy i używasz tego.
  • Na łatanie użyje się innej problematycznej funkcji: cv2.KeyPoint, która została podana na wyjściu z _pickle_keypoints, gdy zostanie rozpryskana, więc nie musimy implementować procedury rozpytywania.
  • I być kompletnie mylący, cv2::KeyPoint::KeyPoint jest przeciążoną funkcją w C++, ale w Pythonie to nie jest dokładnie rzecz. Podczas gdy w C++ istnieje funkcja, która przyjmuje punkt dla pierwszego argumentu, w Pythonie spróbuje to zinterpretować jako int. * rozwija punkt na dwa argumenty, x i y, aby dopasować jedyny konstruktor argumentów int.

Używałem casper's excellent solution, dopóki nie zdałem sobie sprawy, że to możliwe.

Powiązane problemy