I have a program with mainly OpenCV and NumPy, with some SciPy as well. The system needs to be a real-time system with a frame rate close to 30 fps but right now only about 10 fps. Will using Cython help speed this up? I ask because OpenCV is already written in C++ and should already be quite optimized, and NumPy, as far as I understand, is also quite optimized. So will the use of Cython help improve the processing time of my program?
-
2it depends what is taking the time. The calls inside opencv/numpy are as fast as they will be in 'c'. But looping in python, or waiting for camera frames in the python side is slow. Search SO for profiling python codeMartin Beckett– Martin Beckett2018-05-25 19:44:07 +00:00Commented May 25, 2018 at 19:44
-
@MartinBeckett it seems that some of the opencv functions are taking some time, including capturing frames. So in this case would cython provide any improvement?TanMath– TanMath2018-05-25 19:45:02 +00:00Commented May 25, 2018 at 19:45
-
1@downvoter what is the reason behind the downvote? Is there something I should improve?TanMath– TanMath2018-05-25 19:54:19 +00:00Commented May 25, 2018 at 19:54
-
4Profile your code, identify which parts takes the most time. Then you can post some working example of the critical part(s). Nobody can really say if there are possible improvements without seeing some code. (I am not the downvoter)max9111– max91112018-05-25 20:53:16 +00:00Commented May 25, 2018 at 20:53
-
1Your question is unanswerable unless you provide your code.Mark Setchell– Mark Setchell2018-06-02 09:44:50 +00:00Commented Jun 2, 2018 at 9:44
3 Answers
Hope this helps someone
Found this awesome post Use Cython to get more than 30X speedup on your Python code
Used the same factorial calculation inside video stream through the camera for two frames each
video_python.py
import numpy as np
import cv2
import time
def function(number):
cap = cv2.VideoCapture(0)
increment = 0
while(True):
# Capture frame-by-frame
ret, frame = cap.read()
# Our operations on the frame come here
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
# Display the resulting frame
cv2.imshow('frame',gray)
start_time = time.time()
y = 1
for i in range(1, number+1):
y *= i
increment+=1
if increment >2:
# print(time.time()-start_time)
print('Python increment ',increment)
break
if cv2.waitKey(1) & 0xFF == ord('q'):
break
cap.release()
cv2.destroyAllWindows()
return 0
video_cython.pyx
import numpy as np
import cv2
import time
cpdef int function(int number):
cdef bint video_true = True
cap = cv2.VideoCapture(0)
cdef int y = 1
cdef int i
cdef int increment = 0
cdef int increment_times = 0
while(video_true):
# Capture frame-by-frame
ret, frame = cap.read()
# Our operations on the frame come here
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
# Display the resulting frame
cv2.imshow('frame',gray)
start_time = time.time()
for i in range(1, number+1):
y *= i
increment_times+=1
if increment_times > 2:
# print(time.time()-start_time)
print('Cython increment ',increment_times)
break
if cv2.waitKey(1) & 0xFF == ord('q'):
break
cap.release()
cv2.destroyAllWindows()
return 0
setup.py
from distutils.core import setup
from Cython.Build import cythonize
setup(ext_modules = cythonize('video_cython.pyx',compiler_directives={'language_level' : "3"}))
then run
python setup.py build_ext --inplace
video_test.py
import video_python
import video_cython
import time
number = 100000
start = time.time()
video_python.function(number)
end = time.time()
py_time = end - start
print("Python time = {}".format(py_time))
start = time.time()
video_cython.function(number)
end = time.time()
cy_time = end - start
print("Cython time = {}".format(cy_time))
print("Speedup = {}".format(py_time / cy_time))
result:
Python increment 3
Python time = 6.602917671203613
Cython increment 3
Cython time = 0.4903101921081543
Speedup = 13.466817083311046
So doing any kind of python related stuff inside the loop can increase speed
2 Comments
Using Cython won't make a significant difference in this problem.
To get a profile/benchmark of your code the Pycharm IDE has a profiling tool, or you can use kernprof.
However, as a test, you can convert your code to the Cython code or C code with these instructions:
[NOTE]:
This approach is for Python3, but it can also be applied to Python2.7 with a few changes. I've tested it before.
[UPDATE]:
You can also use PyInstaller and Nuitka to test another way to convert your code as compiled executable.
2 Comments
time.time() you can figure out how many FPS you get. Start from the end of your code and comment out processing operations. For me, running very simple operations, I typically get 20-30 fps on a 640x480 camera running on a snappy workstation. If I'm getting into more heavy stuff like template matching or keypoint/feature matching it drops further to 10-15 fps.