web-dev-qa-db-de.com

Unterscheidet sich die Leistung zwischen der Python- oder C++ - Codierung von OpenCV?

Ich möchte OpenCV nach und nach starten, aber zuerst muss ich entscheiden, welche API von OpenCV nützlicher ist. Ich sage voraus, dass die Python-Implementierung kürzer ist, aber die Laufzeit wird im Vergleich zu den nativen C++ - Implementierungen dichter und langsamer sein. Gibt es irgendjemanden, der sich zu den Unterschieden zwischen Performance und Coding zwischen diesen beiden Perspektiven äußern kann?

51
erogol

Wie bereits in früheren Antworten erwähnt, ist Python im Vergleich zu C++ oder C langsamer. Python zeichnet sich durch seine Einfachheit, Portabilität und Kreativität aus, bei der sich die Benutzer nur um ihren Algorithmus kümmern müssen und nicht um Programmierprobleme.

Aber hier in OpenCV gibt es etwas anderes. Python-OpenCV ist nur ein Wrapper um den ursprünglichen C/C++ - Code. Es wird normalerweise verwendet, um die besten Funktionen der beiden Sprachen Leistung von C/C++ und Simplicity of Python zu kombinieren.

Wenn Sie also eine Funktion in OpenCV von Python aus aufrufen, wird die eigentliche C/C++ - Quelle ausgeführt. Es wird also keinen großen Unterschied in der Leistung geben. (Ich erinnere mich, dass ich irgendwo gelesen habe, dass die Leistungseinbußen <1% sind, nicht erinnern, wo.) Eine grobe Schätzung mit einigen grundlegenden Funktionen in OpenCV zeigt ein worst case Strafe von <4%, dh penalty = [maximum time taken in Python - minimum time taken in C++]/minimum time taken in C++).

Das Problem tritt auf, wenn Ihr Code viele native Python-Codes enthält. Wenn Sie z. B. eigene Funktionen erstellen, die in OpenCV nicht verfügbar sind, wird es noch schlimmer. Solche Codes werden nativ in Python ausgeführt, was die Leistung erheblich reduziert. 

Die neue OpenCV-Python-Schnittstelle unterstützt Numpy jedoch vollständig. Numpy ist ein Paket für Scientific Computing in Python. Es ist auch ein Wrapper um native C-Codes. Es ist eine hochoptimierte Bibliothek, die eine Vielzahl von Matrixoperationen unterstützt, die sich besonders für die Bildverarbeitung eignen. Wenn Sie also sowohl die OpenCV-Funktionen als auch die Numpy-Funktionen richtig kombinieren können, erhalten Sie einen sehr schnellen Code.

Denken Sie immer daran, Schleifen und Iterationen in Python zu vermeiden. Verwenden Sie stattdessen die in Numpy (und OpenCV) verfügbaren Array-Manipulationsfunktionen. Das Hinzufügen von zwei numpy-Arrays mit C = A+B ist viel schneller als die Verwendung von Doppelschleifen.

Zum Beispiel können Sie diese Artikel überprüfen: 

  1. Schnelle Array-Manipulation in Python
  2. Leistungsvergleich von OpenCV-Python-Schnittstellen, cv und cv2
121
Abid Rahman K

Alle Google-Ergebnisse für openCV sind identisch: Python ist nur etwas langsamer. Ich habe jedoch noch kein einziges Profil davon gesehen. Also entschied ich mich für einiges und entdeckte:

Python ist mit opencv sogar für triviale Programme deutlich langsamer als C++.

Das einfachste Beispiel, an das ich denken konnte, war, die Ausgabe einer Webcam auf dem Bildschirm und die Anzahl der Bilder pro Sekunde anzuzeigen. Mit Python habe ich 50FPS erreicht (auf einem Intel-Atom). Mit C++ erhielt ich 65 FPS, eine Steigerung von 25%. In beiden Fällen verwendete die CPU-Auslastung einen einzelnen Kern und war meines Wissens nach an die Leistung der CPU gebunden. Außerdem stimmt dieser Testfall mit dem überein, was ich in Projekten gesehen habe, die ich in der Vergangenheit von einem zum anderen portiert habe.

Woher kommt dieser Unterschied? In Python geben alle openCV-Funktionen neue Kopien der Bildmatrizen zurück. Immer, wenn Sie ein Bild aufnehmen oder dessen Größe ändern, können Sie in C++ vorhandenen Speicherplatz erneut verwenden. In Python kannst du nicht. Ich vermute, diese Zeit, die für die Speicherzuweisung aufgewendet wird, ist der Hauptunterschied, da, wie andere gesagt haben, der zugrunde liegende Code von openCV C++ ist.

Bevor Sie Python aus dem Fenster werfen: Python ist viel schneller zu entwickeln, und wenn Sie sich nicht an Hardware-Einschränkungen halten oder wenn die Entwicklungsgeschwindigkeit wichtiger ist als Leistung, verwenden Sie Python. In vielen Anwendungen, die ich mit openCV erstellt habe, habe ich mit Python begonnen und später nur die Computer-Vision-Komponenten nach C++ konvertiert (z. B. mit dem Ctype-Modul von Python und Kompilieren des CV-Codes in eine gemeinsam genutzte Bibliothek). 

Python-Code:

import cv2
import time

FPS_SMOOTHING = 0.9

cap = cv2.VideoCapture(2)
fps = 0.0
prev = time.time()
while True:
    now = time.time()
    fps = (fps*FPS_SMOOTHING + (1/(now - prev))*(1.0 - FPS_SMOOTHING))
    prev = now

    print("fps: {:.1f}".format(fps))

    got, frame = cap.read()
    if got:
        cv2.imshow("asdf", frame)
    if (cv2.waitKey(2) == 27):
        break

C++ - Code:

#include <opencv2/opencv.hpp>
#include <stdint.h>

using namespace std;
using namespace cv;

#define FPS_SMOOTHING 0.9

int main(int argc, char** argv){
    VideoCapture cap(2);
    Mat frame;

    float fps = 0.0;
    double prev = clock(); 
    while (true){
        double now = (clock()/(double)CLOCKS_PER_SEC);
        fps = (fps*FPS_SMOOTHING + (1/(now - prev))*(1.0 - FPS_SMOOTHING));
        prev = now;

        printf("fps: %.1f\n", fps);

        if (cap.isOpened()){
            cap.read(frame);
        }
        imshow("asdf", frame);
        if (waitKey(2) == 27){
            break;
        }
    }
}

Mögliche Benchmark-Einschränkungen:

  • Kamera-Framerate
  • Timer-Messgenauigkeit
  • Zeit für die Druckformatierung
6
sdfgeoff

Sie haben recht, Python ist fast immer deutlich langsamer als C++, da ein Interpreter erforderlich ist, was bei C++ nicht der Fall ist. Dies setzt jedoch voraus, dass C++ stark typisiert ist, was einen viel kleineren Spielraum für Fehler lässt. Einige Leute ziehen es vor, strikt zu programmieren, während andere die inhärente Nachgiebigkeit von Python genießen.

Wenn Sie einen vollständigen Diskurs über Python-Codierstile im Vergleich zu C++ - Codierstilen wünschen, ist dies nicht der beste Ort. Versuchen Sie, einen Artikel zu finden.

BEARBEITEN: Da Python eine interpretierte Sprache ist und C++ zu Maschinencode allgemein gesprochen kompiliert wird, können Sie mit C++ Leistungsvorteile erzielen. Im Hinblick auf die Verwendung von OpenCV sind die OpenCV-Kernbibliotheken jedoch bereits in Maschinencode kompiliert, sodass der Python-Wrapper um die OpenCV-Bibliothek kompilierten Code ausführt. Mit anderen Worten: Wenn Sie rechentechnisch aufwendige OpenCV-Algorithmen von Python ausführen, werden Sie keinen großen Performance-Erfolg erleben, da sie bereits für die spezifische Architektur kompiliert wurden, mit der Sie arbeiten.

3
Callum McLean

Der Antwort von sdfgeoff fehlt die Tatsache, dass Sie Can Arrays in Python wiederverwenden können. Ordne sie vor und gib sie weiter, und sie werden sich daran gewöhnen. So:

    image = numpy.zeros(shape=(height, width, 3), dtype=numpy.uint8)
    #....
    retval, _ = cv.VideoCapture.read(image)
1
Paul Rensing