Czy wydajność różni się między Pythonem A C++ kodowaniem OpenCV?

Chcę zacząć OpenCV stopniowo, ale najpierw muszę zdecydować, które API OpenCV jest bardziej przydatne. Przewiduję, że implementacja Pythona jest krótsza, ale czas pracy będzie bardziej gęsty i powolny w porównaniu do natywnych implementacji C++. Czy jest ktoś, kto może skomentować różnice w wydajności i kodowaniu między tymi dwoma perspektywami?

Author: splatte, 2012-11-17

4 answers

Jak wspomniano we wcześniejszych odpowiedziach, Python jest wolniejszy w porównaniu do C++ lub C. Python jest zbudowany ze względu na swoją prostotę, przenośność, a ponadto kreatywność, w której użytkownicy muszą martwić się tylko o swój algorytm, a nie problemy z programowaniem.

Ale tutaj w OpenCV jest coś innego. Python-OpenCV jest tylko owijką wokół oryginalnego kodu C / C++. Jest zwykle używany do łączenia najlepszych cech obu języków, wydajność C / C++ i prostota Pythona .

Więc kiedy wywołujesz funkcję w OpenCV z Pythona, to co faktycznie jest uruchamiane jest podstawą C / C++ source. Więc nie będzie dużej różnicy w wydajności.(Pamiętam, że gdzieś czytałem, że kara za wykonanie wynosi najgorszy przypadek kary <4%. ie penalty = [maximum time taken in Python - minimum time taken in C++]/minimum time taken in C++).

Problem pojawia się, gdy twój kod ma wiele natywnych kodów Pythona.Na przykład, jeśli tworzysz własne funkcje, które nie są dostępne w OpenCV, sprawy się pogarszają. Takie kody są uruchamiane natywnie w Pythonie, co znacznie zmniejsza wydajność.

Ale nowy interfejs OpenCV-Python ma pełne wsparcie dla Numpy. Numpy jest pakietem do obliczeń naukowych w języku Python. Jest to również owijarka wokół natywnego kodu C. Jest to wysoce zoptymalizowana biblioteka, która obsługuje szeroką gamę operacji matrycowych, doskonale nadających się do przetwarzania obrazu. Jeśli więc poprawnie połączysz obie funkcje OpenCV i Numpy, uzyskasz bardzo dużą prędkość kod.

Należy pamiętać, że zawsze staraj się unikać pętli i iteracji w Pythonie. Zamiast tego użyj funkcji manipulacji tablicami dostępnych w Numpy (i OpenCV). Po prostu dodanie dwóch tablic numpy za pomocą C = A+B jest dużo razy szybsze niż użycie podwójnych pętli.

Na przykład możesz sprawdzić te artykuły:

  1. szybkie manipulowanie tablicami w Pythonie
  2. porównanie wydajności interfejsów OpenCV-Python, cv i CV2
 162
Author: Abid Rahman K,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:34:08

Wszystkie wyniki google dla openCV mówią to samo: python będzie tylko nieco wolniejszy. Ale ani razu nie widziałem żadnego profilowania na ten temat. Więc postanowiłem zrobić trochę i odkryłem:

Python jest znacznie wolniejszy niż C++ z opencv, nawet dla trywialnych programów.

Najprostszym przykładem, jaki mogłem wymyślić, było wyświetlenie na ekranie wyjścia kamery internetowej i wyświetlenie liczby klatek na sekundę. W Pythonie osiągnąłem 50FPS (na Intel atomie). Z C++ mam 65FPS, wzrost o 25%. W obu przypadkach użycie procesora wykorzystywało pojedynczy rdzeń i według mojej najlepszej wiedzy było związane z wydajnością procesora. Dodatkowo ten przypadek testowy jest zgodny z tym, co widziałem w projektach, które przeportowałem z jednego do drugiego w przeszłości.

Skąd ta różnica? W Pythonie wszystkie funkcje openCV zwracają nowe kopie macierzy obrazu. Za każdym razem, gdy przechwytywasz obraz lub zmieniasz jego rozmiar - w C++ możesz ponownie użyć istniejącej pamięci. W Pythonie nie możesz. Podejrzewam, że ten czas spędzony na Przydzielaniu pamięci jest główną różnicą, ponieważ jak mówili inni: podstawowym kodem openCV jest C++.

Zanim wyrzucisz Pythona przez okno: python jest znacznie szybszy w rozwoju, a jeśli nie masz ograniczeń sprzętowych lub jeśli rozwój jest ważniejszy niż wydajność, użyj Pythona. W wielu aplikacjach, które zrobiłem z openCV, zacząłem w Pythonie, a później przekonwertowałem tylko wizję komputera komponenty do C++ (np. korzystanie z modułu ctype Pythona i kompilacja kodu CV do biblioteki współdzielonej).

Kod Pythona:

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

Kod C++:

#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;
        }
    }
}

Możliwe ograniczenia benchmarku:

  • Liczba klatek na sekundę w aparacie
  • Timer precyzja pomiaru
  • Czas spędzony na formatowaniu druku
 16
Author: sdfgeoff,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-07-08 18:46:28

W odpowiedzi z sdfgeoff brakuje faktu, że Można ponownie używać tablic w Pythonie. Przydziel je i przekaż, A się przyzwyczają. Więc:

    image = numpy.zeros(shape=(height, width, 3), dtype=numpy.uint8)
    #....
    retval, _ = cv.VideoCapture.read(image)
 6
Author: Paul Rensing,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-11-29 14:21:02

Masz rację, Python jest prawie zawsze znacznie wolniejszy od C++ , ponieważ wymaga interpretera, którego C++ nie ma. Wymaga to jednak silnego pisania C++, co pozostawia znacznie mniejszy margines błędu. Niektórzy ludzie wolą być zmuszeni do ścisłego kodowania, podczas gdy inni cieszą się nieodłączną pobłażliwością Pythona.

Jeśli chcesz mieć pełny dyskurs na temat stylów kodowania Pythona a stylów kodowania C++, to nie jest najlepsze miejsce, spróbuj znaleźć artykuł.

Edytuj: Ponieważ Python jest język interpretowany, natomiast C++ jest kompilowany do kodu maszynowego, ogólnie rzecz biorąc, możesz uzyskać korzyści z wydajności za pomocą C++. Jednak w odniesieniu do korzystania z OpenCV, podstawowe biblioteki OpenCV są już skompilowane do kodu maszynowego, więc owijarka Pythona wokół biblioteki OpenCV wykonuje skompilowany kod. Innymi słowy, jeśli chodzi o wykonywanie obliczeniowo drogich algorytmów OpenCV z Pythona, nie zobaczysz dużego hitu wydajności, ponieważ zostały już skompilowane pod kątem konkretnej architektury, z którą pracujesz.

 5
Author: Callum McLean,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-06-09 18:09:04