9

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?

TanMath
  • 598
  • 1
  • 9
  • 27
  • 2
    it 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 code – Martin Beckett May 25 '18 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 May 25 '18 at 19:45
  • Most likely cython will provide a speedup, but if it's going to be 10% or 1000% is impossible to tell from such a distance. – user7138814 May 25 '18 at 19:52
  • 1
    @downvoter what is the reason behind the downvote? Is there something I should improve? – TanMath May 25 '18 at 19:54
  • 4
    Profile 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 May 25 '18 at 20:53
  • @TanMath I am not the down voter I also up vote. I update my answer. – Benyamin Jafari Jun 01 '18 at 20:33
  • 1
    Your question is unanswerable unless you provide your code. – Mark Setchell Jun 02 '18 at 09:44

3 Answers3

10

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

Community
  • 1
  • 1
  • Looks like the only thing you are optimizing with cyhton here is that extra loop for 100000 iterations, that has nothing to do with opencv here. – Pawel Jun 17 '23 at 19:33
2

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.

Benyamin Jafari
  • 27,880
  • 26
  • 135
  • 150
  • I agree with the overall sentiment here. As long as you're not doing pixel by pixel operations, OpenCV and Numpy should be pretty fast. Also, when it comes to profiling, using `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. – bfris May 26 '18 at 01:32
  • @bfris yes, I have done this before and I get pretty much 10 fps with the signal processing... Simple collection of frames is usually around 30 fps... – TanMath May 26 '18 at 03:04
0

It all depends on what your program is doing.

If you program is just stringing together large operations that are implemented in C++ then cython isn't going to help you much if at all.

If you are writing code that works directly on individual pixels then cython could be a big help.

plugwash
  • 9,724
  • 2
  • 38
  • 51