Real Time Image Processing
Real Time Image Processing
The Situation
Supports research and teaching in computer vision Rapid prototyping of algorithms Easy frame-grabbing with the pygame library Notoriously bad performance in tight loops Use Cython and Numpy
Why Python?
Solution
Goal
Use image sequences to guide robot behavior Acquire an image Transform it into a data structure Select a robot action based on data structure Rate of action selection is bounded by rate of image acquisition and transformation
Process
Performance consideration
Real-time systems
Correctness of code depends on whether deadlines are met Efficiency is helpful Only necessary for meeting a deadline Implies a soft deadline for the image computations Ideal is 10 frames/second Performance degrades below this point
Must visit every array element Need fast array access Need fast looping Image subtraction Edge detection Color matching Connected components
Typical operations
Pygame Library
pygame.display
pygame.surface
pygame.camera
Initialization
import pygame import pygame.camera from pygame.locals import * pygame.init() pygame.camera.init() size = (640, 480)
Setting up
d = pygame.display.set_mode(size, 0) s = pygame.surface.Surface(size, 0, d) c = pygame.camera.list_cameras() cam = pygame.camera.Camera(c[0], size) cam.start() going = True
Main Loop
while going: if cam.query_image(): s = cam.get_image(s) d.blit(s, (0, 0)) pygame.display.flip() for e in pygame.event.get(): if e.type == QUIT: cam.stop() going = False
Processing Images
Converts pygame surfaces to numpy arrays High-speed n-dimensional arrays (ndarray) All elements have the same data type Tight two-dimensional loop Each inner loop iteration involves a type check!
Numpy (1.3)
Convert image to an array Subtract the previous array Find the non-zero regions of nontrivial size
Add before the start of the loop: last_array = None diffs = None s = pygame.surface.Surface(size)
Problem
Hue: The type of a color Saturation: The strength of a color Value: The whiteness of a color
Bits 23-16 are Red (RGB) or Hue (HSV) Bits 15-8 are Green (RGB) or Saturation (HSV) Bits 7-0 are Blue (RGB) or Value (HSV)
Mask all but the lower 8 bits to get V NB: Display is still RGB
Code Alterations
Blob finding:
Useful variables to initialize at the start: b = (0, 0, 0xFF) r = (0xFF, 0, 0) t = (0x5A, 0xAA, 0xAA)
Additional Code
Image Shrinking
Often an effective technique to boost frame rate Into our original program, insert at the top: shrunken = (320, 240) Then replace the blit() call with: p = pygame.transform.scale(s, size) d.blit(p, (0, 0))
Numpy is very nice, but it doesn't do everything Basic threshold function: def threshold(img, value, hi, lo): for i in range(img.shape[0]) for j in range(img.shape[1]): if img[i,j] < value: img[i,j] = lo else: img[i,j] = hi
Cython
From C, compiles to binary object code Still very experimental Will compile any Python program For best results, augment with type declarations
Superset of Python
Cython Initialization
cimport numpy cimport cython @cython.boundscheck(False) @cython.wraparound(False)
Performance Difference
Interpreted Python
Generated C Code
Checks expected vs. actual arguments Creates lots of temporary variables Use cdef to minimize this cdef functions are not callable from Python
Code is otherwise a direct translation into C Numpy arrays are not C arrays
Generated C Code
for (__pyx_t_1 = 0; __pyx_t_1 < (__pyx_v_img->dimensions[0]); __pyx_t_1+=1) { __pyx_v_i = __pyx_t_1; for (__pyx_t_2 = 0; __pyx_t_2 < (__pyx_v_img->dimensions[1]); __pyx_t_2+=1) { __pyx_v_j = __pyx_t_2; __pyx_t_3 = __pyx_v_i; __pyx_t_4 = __pyx_v_j; if (((*__Pyx_BufPtrStrided2d(__pyx_t_5numpy_int32_t *, __pyx_bstruct_img.b uf, __pyx_t_3, __pyx_bstride_0_img, __pyx_t_4, __pyx_bstride_1_img)) < __pyx_v_v alue)) { __pyx_1 = __pyx_v_lo; } else { __pyx_1 = __pyx_v_hi; } __pyx_t_5 = __pyx_v_i; __pyx_t_6 = __pyx_v_j; *__Pyx_BufPtrStrided2d(__pyx_t_5numpy_int32_t *, __pyx_bstruct_img.buf, __ pyx_t_5, __pyx_bstride_0_img, __pyx_t_6, __pyx_bstride_1_img) = __pyx_1; } }
Conclusion
Frame grabbing Some image processing High-performance arrays Matrix arithmetic Compilation; high-performance object code
numpy
cython
Resources