2015-05-27 4 views
35

Ich habe versucht, sowohl die Python-Implementierung (opencv 2.4.11) und die Java-Implementierung (opencv 2.4.10) von OpenCV MSER-Algorithmus zu verwenden. Interessanterweise habe ich festgestellt, dass MSERs Erkennung verschiedene Ausgabearten in Python vs Java zurückgibt. In Python gibt detect eine Liste von Punktlisten zurück, wobei jede Liste von Punkten einen gefundenen Blob darstellt. In Java wird Mat zurückgegeben, wobei jede Zeile ein einzelner Punkt mit einem zugeordneten Durchmesser ist, der einen erkannten Blob darstellt. Ich möchte das Python-Verhalten in Java reproduzieren, wo Blobs durch eine Menge von Punkten definiert werden, nicht durch einen Punkt. Wer weiß was los ist?Warum erstellt Python-Implementierung und Java-Implementierung von OpenCV MSER unterschiedliche Ausgabe?

Python:

frame = cv2.imread('test.jpg') 
mser = cv2.MSER(**dict((k, kw[k]) for k in MSER_KEYS)) 
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) 
regions = mser.detect(gray, None) 
print("REGIONS ARE: " + str(regions)) 

where the dict given to cv2.MSER is 
{'_delta':7, '_min_area': 2000, '_max_area': 20000, '_max_variation': .25, '_min_diversity': .2, '_max_evolution': 200, '_area_threshold': 1.01, '_min_margin': .003, '_edge_blur_size': 5} 

Python Ausgabe:

REGIONS ARE: [array([[197, 58], 
    [197, 59], 
    [197, 60], 
    ..., 
    [143, 75], 
    [167, 86], 
    [172, 98]], dtype=int32), array([[114, 2], 
    [114, 1], 
    [114, 0], 
    ..., 
    [144, 56], 
    [ 84, 55], 
    [ 83, 55]], dtype=int32)] 

Java:

Mat mat = new Mat(bitmap.getWidth(), bitmap.getHeight(), CvType.CV_16S, new Scalar(4)); 
Mat gray = new Mat(bitmap.getWidth(), bitmap.getHeight(), CvType.CV_16S, new Scalar(4)); 
Imgproc.cvtColor(mat, gray, Imgproc.COLOR_RGB2GRAY, 4); 

FeatureDetector fd = FeatureDetector.create(FeatureDetector.MSER); 
MatOfKeyPoint regions = new MatOfKeyPoint(); 
fd.detect(gray, regions); 
System.out.println("REGIONS ARE: " + regions); 

Java Ausgabe:

REGIONS ARE: Mat [ 10*1*CV_32FC(7), isCont=true, isSubmat=false, nativeObj=0x6702c688, dataAddr=0x59add760 ] 

where each row of the Mat looks like 
KeyPoint [pt={365.3387451171875, 363.75640869140625}, size=10.680443, angle=-1.0, response=0.0, octave=0, class_id=-1] 

EDIT:

A mod auf dem answers.opencv.org Forum zur Verfügung gestellt ein wenig mehr Informationen (http://answers.opencv.org/question/63733/why-does-python-implementation-and-java-implementation-of-mser-create-different-output/):

leider sieht es aus, wie die Java-Version auf den features2d.FeatureDetector begrenzt ist Schnittstelle, die Sie nur Zugriff keypoints (nicht die tatsächlichen Regionen)

berak (10. Juni '15)

@berak läßt: Also, wenn ich das richtig verstanden, aus den Dokumenten, sowohl die Java-Version und die Python/C++ - Version hat die features2d.FeatureDetector-Schnittstelle, aber die Python/C++ - Version hat die zusätzliche MSER-Klasse, um Regionen zu finden, nicht nur Schlüsselpunkte? In diesem Fall, was machen die Leute? Ist es möglich, dem OpenCV-Manager die C++ MSER-Klasse hinzuzufügen, hier etwas wie den javaFeatureDetector zu bearbeiten und einen Java-Wrapper dafür zu erstellen? Danke für jeden Hinweis.

sloreti (11. Juni '15)

so ja, können Sie die Rechtecke in c bekommen ++ oder Python, aber nicht von Java. Das ist ein Fehler im Design. Der javaFeatureDetector wird immer noch benutzt, aber um die Rechtecke zu bekommen, müßtest du deine eigene jni-Schnittstelle schreiben, denke ich. (Und verteilen Sie Ihre eigenen .so zusammen mit Ihrem apk)

berak (12. Juni '15)

+1

Können Sie die Antwort einschließen, die Sie erhalten haben, um [Antworten.opencsv.org] (http://answers.opencv.org/question/63733/why-does-python-implementation-and-java-implementation-of- mser-create-different-output /)? –

+1

es ist nicht in meiner Erfahrung stabil. Haben Sie dieses versucht: das gleiche Bild, aber gedreht (90 oder 180 Grad), dann wenden Sie den Algorithmus mit genau den gleichen Parametern an. Es wird erwartet, dass die extrahierten Regionen das gleiche Recht haben werden? Aber sie sind nicht gleich (die Anzahl der Regionen und ihre Formen). Ich habe in Python getestet, Sie können sehen, wie es in Python und Java funktioniert. –

+0

Haben Sie das Problem gelöst? @sloret – mumu

Antwort

1

Sie verwenden zwei verschiedene Schnittstellen zur MSER Implementierung.

Python cv2.MSER gibt Ihnen einen umhüllten cv::MSER, die als detect seine operator() zu Python macht:

//! the operator that extracts the MSERs from the image or the specific part of it 
CV_WRAP_AS(detect) void operator()(const Mat& image, CV_OUT vector<vector<Point> >& msers, 
            const Mat& mask=Mat()) const; 

Dies Sie die schöne Liste von Konturen Schnittstelle gibt, die Sie suchen.

Im Gegensatz Java verwendet die javaFeatureDetector Wrapper, die FeatureDetector::detect Anrufe, die von MSER::detectImpl und nutzt den Standard-FeatureDetector Schnittstelle unterstützt wird: eine Liste von Schlüsselpunkten.

Wenn Sie auf die operator() in Java (in OpenCV 2.4) zugreifen möchten, müssen Sie es in JNI einpacken.

Verwandte Themen