Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cython + OpenCV and NumPy

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?

like image 216
TanMath Avatar asked May 25 '18 19:05

TanMath


People also ask

Does Cython support NumPy?

You can use NumPy from Cython exactly the same as in regular Python, but by doing so you are losing potentially high speedups because Cython has support for fast access to NumPy arrays.

Can I use Cython with Python?

To make your Python into Cython, first you need to create a file with the . pyx extension rather than the . py extension. Inside this file, you can start by writing regular Python code (note that there are some limitations in the Python code accepted by Cython, as clarified in the Cython docs).

What Cython used for?

Besides web and software development, Python is used for data analytics, machine learning, and even design. We take a closer look at some of the uses of Python, as well as why it's such a popular and versatile programming language.

How do you use Cython in Jupyter notebook?

You can launch a notebook session by typing jupyter notebook in the command line and you can load the Cython magic by typing %load_ext cython in a cell. As already mentioned earlier, the %%cython magic can be used to compile and load the Cython code inside the current session.


2 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

like image 156
Santhosh Dhaipule Chandrakanth Avatar answered Oct 02 '22 19:10

Santhosh Dhaipule Chandrakanth


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:

  • Compile main Python program using Cython.
  • Specifically, convert python code to C code.

[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.

like image 24
Benyamin Jafari Avatar answered Oct 02 '22 19:10

Benyamin Jafari