OpenCV Python
Information on this page is deprecated, check the latest always-up-to-date documentation at http://opencv.willowgarage.com/documentation/python/cookbook.html .
Starting with OpenCV release 2.2, OpenCV will have completed it's new Python interface to cover all the C and C++ functions directly using numpy arrays. (The previous Python interface is described in SwigPythonInterface.)
See notes on new developments at OpenCV Meeting Notes 2010-09-28 under "Vadim" subsection.
Some highlights of the new bindings:
- single import of all of OpenCV using "import cv"
- OpenCV functions no longer have the "cv" prefix
Simple types like CvRect and CvScalar use Python tuples
- Sharing of Image storage, so image transport between OpenCV and other systems (e.g. numpy and ROS) is very efficient
Full documentation for the Python functions in http://opencv.willowgarage.com/documentation/python/index.html
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
Some types are so simple we just use tuples. E.g. CvSize (ii), CvPoint (ii), CvPoint2D32f (ff)
- OpenCV API functions start with a capital letter.
IplImage and CvMat objects has a member data that is a Python string object. CreateImageHeader sets it to NULL. SetData sets it to an arbitrary string. Hence Python reference counting takes care of buffer management, and we minimize copying.
SetData's third 'step' argument defaulted to image width, for convenience
We think that SetData must have a step that is a multiple of 4
- cvArr objects have a method tostring() that returns its data in order.
Under the covers
CvSeq
CvSeq does two jobs in OpenCV:
- it holds a list of objects (2d points, for example)
it has references to other CvSeq objects via four pointers: h_prev, h_next, v_prev, v_next
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:
- negative steps illegal
- zero length step illegal
- column step can only be 1
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