OpenCV Python

Starting with release 2.0, OpenCV has a new Python interface. (The previous Python interface is described in SwigPythonInterface.) Some highlights of the new bindings:

Cookbook

Convert an image

import cv
cv.SaveImage("foo.png", cv.LoadImage("foo.jpg"))

Compute the Laplacian

im = cv.LoadImage("foo.png", 1)
dst = cv.CreateImage(cv.GetSize(im), cv.IPL_DEPTH_16S, 3);
laplace = cv.Laplace(im, dst)
cv.SaveImage("foo-laplace.png", dst)

Using cvGoodFeaturesToTrack

img = cv.LoadImage("foo.jpg")
eig_image = cv.CreateImage(cv.GetSize(img), cv.IPL_DEPTH_32F, 1)
temp_image = cv.CreateImage(cv.GetSize(img), cv.IPL_DEPTH_32F, 1)
# Find up to 300 corners using Harris
for (x,y) in cv.GoodFeaturesToTrack(img, eig_image, temp_image, 300, None, 1.0, use_harris = True):
  print "good feature at", x,y

Using GetSubRect

img = cv.LoadImage("foo.jpg")
sub = cv.CreateImageHeader((10,10), cv.IPL_DEPTH_8U, 1)  # Parameters overwritten anyway...
cv.GetSubRect(img, sub, (0, 0, 32, 32))  # sub is 32x32 patch from image top-left

Using CreateMat, and accessing an element

mat = cv.CreateMat(5, 5, cv.CV_32FC1)
mat[3,2] += 0.787

ROS image message -> OpenCV

See this tutorial: http://www.ros.org/wiki/opencv_latest/Tutorials/UsingCvBridgeToConvertBetweenROSImagesAndOpenCVImages

PIL Image -> OpenCV

See PIL Image.

import Image
import cv
pi = Image.open('foo.png')       # PIL image
cv_im = cv.CreateImageHeader(pi.size, cv.IPL_DEPTH_8U, 1)
cv.SetData(cv_im, pi.tostring())

OpenCV -> PIL Image

cv_im = cv.CreateImage((320,200), cv.IPL_DEPTH_8U, 1)
pi = Image.fromstring("L", cv.GetSize(cv_im), cv_im.tostring())

numpy <-> OpenCV

Numpy and OpenCV have different orderings for dimensions, hence the tuple reversals here.

def cv2array(im):
  depth2dtype = {
        cv.IPL_DEPTH_8U: 'uint8',
        cv.IPL_DEPTH_8S: 'int8',
        cv.IPL_DEPTH_16U: 'uint16',
        cv.IPL_DEPTH_16S: 'int16',
        cv.IPL_DEPTH_32S: 'int32',
        cv.IPL_DEPTH_32F: 'float32',
        cv.IPL_DEPTH_64F: 'float64',
    }
  
  arrdtype=im.depth
  a = np.fromstring(
         im.tostring(),
         dtype=depth2dtype[im.depth],
         count=im.width*im.height*im.nChannels)
  a.shape = (im.height,im.width,im.nChannels)
  return a
    
def array2cv(a):
  dtype2depth = {
        'uint8':   cv.IPL_DEPTH_8U,
        'int8':    cv.IPL_DEPTH_8S,
        'uint16':  cv.IPL_DEPTH_16U,
        'int16':   cv.IPL_DEPTH_16S,
        'int32':   cv.IPL_DEPTH_32S,
        'float32': cv.IPL_DEPTH_32F,
        'float64': cv.IPL_DEPTH_64F,
    }
  try:
    nChannels = a.shape[2]
  except:
    nChannels = 1
  cv_im = cv.CreateImageHeader((a.shape[1],a.shape[0]), 
          dtype2depth[str(a.dtype)],
          nChannels)
  cv.SetData(cv_im, a.tostring(), 
             a.dtype.itemsize*nChannels*a.shape[1])
  return cv_im

Notes

Under the covers

CvSeq

CvSeq does two jobs in OpenCV:

OpenCV creates CvSeq objects in CvMemStorage, so in Python every CvSeq object refers to its containing CvMemStorage obect. By doing this, it automatically manages the lifetime of the CvMemStorage object: when the last CvSeq is deleted, the CvMemStorage is deleted, and CvMemStorage's delete method calls CvReleaseMemStorage. For this reason, the Python API does not expose CvReleaseMemStorage.

A CvSeq is a Python sequence:

seq = cv.FindContours(scribble, storage, cv.CV_RETR_CCOMP, cv.CV_CHAIN_APPROX_SIMPLE)
# Seq is a sequence of point pairs
print len(seq)
for (x,y) in seq:
  print (x,y)
print seq[10]
print seq[::-1]
print sorted(list(seq))

h_prev, h_next, v_prev, v_next are methods that yield other CvSeq objects:

>>> print seq.v_next()
<opencv.cvseq object at 0x2b4460>

For example to traverse a tree depth-first:

def traverse(seq):
  while seq:
    traverse(seq.v_next())    # Recurse on children
    seq = seq.h_next()        # Next sibling

CvSet

A CvSet is a special type of CvSeq where some elements in the CvSeq are marked as "empty".

The Python API only allows iteration over the CvSet.

Slice Access

The Python API lets you use slice operators to extract rows, columns, or subregions of an OpenCV array. These operators work in a similar way to the explicit OpenCV functions in http://opencv.willowgarage.com/documentation/python/operations_on_arrays.html - they return a new CvMat that shares data with the original array. Because of this, there are some restrictions on the allowed slice operators. Briefly:

Some examples.

Get a row

   1 row = x[i]

Get a column

   1 col = x[:, i]

Get the top-left 10x10 subrectangle

   1 slice = x[0:10, 0:10]

Get every other row:

   1 slice = x[::2, :]

Get an element

   1 elem = x[i, j]
   2 # or if x is a vector
   3 elem = x[i]

OpenCVWiki: PythonInterface (last edited 2009-12-29 17:58:21 by NathanielFairfield)