added 4 warping functions. Added CvMat support.

Added cvGetRectSubPix, cvGetQuadrangleSubPix, cvWarpAffine, cvWarpPerspective.
As a byproduct added CvMat support.
This commit is contained in:
sccolbert
2009-10-16 21:25:20 +02:00
parent d26404969d
commit 1e1958b414
10 changed files with 3132 additions and 1115 deletions
+1 -1
View File
@@ -3,7 +3,7 @@ import sys
# try to open the opencv libs
# prints a warning if the libs are not found
from _libimport import cv
from _libimport import cv, cxcore
from opencv_constants import *
from opencv_cv import *
+1 -1
View File
@@ -59,4 +59,4 @@ def _tryload_macosx(which):
cv = _import_opencv_lib("cv")
cxcore = _import_opencv_lib("cxcore")
File diff suppressed because it is too large Load Diff
+1
View File
@@ -19,6 +19,7 @@ ctypedef np.float64_t FLOAT64_t
# Utility functions for IplImage creation, array validation, etc...
#-------------------------------------------------------------------------------
cdef void populate_iplimage(np.ndarray arr, IplImage* img)
cdef CvMat* cvmat_ptr_from_iplimage(IplImage* arr)
cdef int validate_array(np.ndarray arr) except -1
cdef int assert_dtype(np.ndarray arr, dtypes) except -1
cdef int assert_ndims(np.ndarray arr, dims) except -1
+20
View File
@@ -1,8 +1,10 @@
import ctypes
import numpy as np
cimport numpy as np
from python cimport *
from opencv_constants import *
from opencv_type cimport *
from _libimport import cxcore
np.import_array()
@@ -43,6 +45,13 @@ _ipltypes = {UINT8: IPL_DEPTH_8U, INT8: IPL_DEPTH_8S, INT16: IPL_DEPTH_16S,
cdef int IPLIMAGE_SIZE = sizeof(IplImage)
# a function to convert from IplImage to cvMat
# this eliminates the need for a second populate function
# for CvMat
ctypedef CvMat* (*cvGetMatPtr)(IplImage*, CvMat*, int*, int)
cdef cvGetMatPtr c_cvGetMat
c_cvGetMat = (<cvGetMatPtr*><size_t>ctypes.addressof(cxcore.cvGetMat))[0]
cdef void populate_iplimage(np.ndarray arr, IplImage* img):
# The numpy array should be validated with the validate_array
# function before using this function.
@@ -83,6 +92,17 @@ cdef void populate_iplimage(np.ndarray arr, IplImage* img):
# create ourselves.
img.imageDataOrigin = <char*>NULL
cdef CvMat* cvmat_ptr_from_iplimage(IplImage* arr):
# this functions takes an IplImage* and returns a CvMat*
# it is designed so that we dont need a separate populate_cvmat
# function, or deal with OpenCV magic values. However, it needs to create a
# CvMat header to pass to the opencv conversion routine.
# This means that you have to call PyMem_Free on the CvMat* when you're
# done with it.
cdef CvMat* mat_hdr = <CvMat*>PyMem_Malloc(sizeof(CvMat))
mat_hdr = c_cvGetMat(arr, mat_hdr, NULL, 0)
return mat_hdr
cdef int validate_array(np.ndarray arr) except -1:
if arr.ndim != 2 and arr.ndim != 3:
raise ValueError('Arrays must have either 2 or 3 dimensions')
+3
View File
@@ -19,6 +19,9 @@ CV_INTER_LINEAR = 1
CV_INTER_CUBIC = 2
CV_INTER_AREA = 3
CV_WARP_FILL_OUTLIERS = 8
CV_WARP_INVERSE_MAP = 16
#########################
# Calibration Constants #
#########################
File diff suppressed because it is too large Load Diff
+213 -1
View File
@@ -76,11 +76,37 @@ ctypedef void (*cvGoodFeaturesToTrackPtr)(IplImage*, IplImage*, IplImage*,
cdef cvGoodFeaturesToTrackPtr c_cvGoodFeaturesToTrack
c_cvGoodFeaturesToTrack = (<cvGoodFeaturesToTrackPtr*><size_t>
ctypes.addressof(cv.cvGoodFeaturesToTrack))[0]
# cvGetRectSubPix
ctypedef void (*cvGetRectSubPixPtr)(IplImage*, IplImage*, CvPoint2D32f)
cdef cvGetRectSubPixPtr c_cvGetRectSubPix
c_cvGetRectSubPix = (<cvGetRectSubPixPtr*><size_t>
ctypes.addressof(cv.cvGetRectSubPix))[0]
# cvGetQuadrangleSubPix
ctypedef void (*cvGetQuadrangleSubPixPtr)(IplImage*, IplImage*, CvMat*)
cdef cvGetQuadrangleSubPixPtr c_cvGetQuadrangleSubPix
c_cvGetQuadrangleSubPix = (<cvGetQuadrangleSubPixPtr*><size_t>
ctypes.addressof(cv.cvGetQuadrangleSubPix))[0]
# cvResize
ctypedef void (*cvResizePtr)(IplImage*, IplImage*, int)
cdef cvResizePtr c_cvResize
c_cvResize = (<cvResizePtr*><size_t>ctypes.addressof(cv.cvResize))[0]
# cvWarpAffine
ctypedef void (*cvWarpAffinePtr)(IplImage*, IplImage*, CvMat*, int, CvScalar)
cdef cvWarpAffinePtr c_cvWarpAffine
c_cvWarpAffine = (<cvWarpAffinePtr*><size_t>
ctypes.addressof(cv.cvWarpAffine))[0]
# cvWarpPerspective
ctypedef void (*cvWarpPerspectivePtr)(IplImage*, IplImage*, CvMat*, int,
CvScalar)
cdef cvWarpPerspectivePtr c_cvWarpPerspective
c_cvWarpPerspective = (<cvWarpPerspectivePtr*><size_t>
ctypes.addressof(cv.cvWarpPerspective))[0]
# cvFindChessboardCorners
ctypedef void (*cvFindChessboardCornersPtr)(IplImage*, CvSize, CvPoint2D32f*,
int*, int)
@@ -514,6 +540,94 @@ def cvGoodFeaturesToTrack(np.ndarray src, int corner_count,
return out[:ncorners_found]
def cvGetRectSubPix(np.ndarray src, size, center):
''' Retrieves the pixel rectangle from an image with
sub-pixel accuracy.
Paramters:
src - source image.
size - two tuple (height, width) of rectangle (ints)
center - two tuple (x, y) of rectangle center (floats)
the center must lie within the image, but the rectangle
may extend beyond the bounds of the image, at which point
the border is replicated.
Returns:
A new image of the extracted rectangle. The same dtype as the src image.
'''
validate_array(src)
cdef np.npy_intp* shape = clone_array_shape(src)
shape[0] = <np.npy_intp>size[0]
shape[1] = <np.npy_intp>size[1]
cdef CvPoint2D32f cvcenter
cvcenter.x = <float>center[0]
cvcenter.y = <float>center[1]
cdef np.ndarray out = new_array(src.ndim, shape, src.dtype)
cdef IplImage srcimg
cdef IplImage outimg
populate_iplimage(src, &srcimg)
populate_iplimage(out, &outimg)
c_cvGetRectSubPix(&srcimg, &outimg, cvcenter)
PyMem_Free(shape)
return out
def cvGetQuadrangleSubPix(np.ndarray src, np.ndarray warpmat, float_out=False):
''' Retrieves the pixel quandrangle from an image with
sub-pixel accuracy. In english: apply and affine transform to an image.
Parameters:
src - input image
warpmat - a 2x3 array which is an affine transform
float_out - return a float32 array. If true, input must be
uint8. If false, output is same type as input.
Return:
warped image of same size and dtype as src. Except when
float_out == True (see above)
'''
validate_array(src)
validate_array(warpmat)
assert_nchannels(src, [1, 3])
assert_nchannels(warpmat, [1])
assert warpmat.shape[0] == 2, 'warpmat must be 2x3'
assert warpmat.shape[1] == 3, 'warpmat must be 2x3'
cdef np.ndarray out
if float_out:
assert_dtype(src, [UINT8])
out = new_array_like_diff_dtype(src, FLOAT32)
else:
out = new_array_like(src)
cdef IplImage srcimg
cdef IplImage outimg
cdef IplImage cvmat
cdef CvMat* cvmatptr
populate_iplimage(src, &srcimg)
populate_iplimage(out, &outimg)
populate_iplimage(warpmat, &cvmat)
cvmatptr = cvmat_ptr_from_iplimage(&cvmat)
c_cvGetQuadrangleSubPix(&srcimg, &outimg, cvmatptr)
PyMem_Free(cvmatptr)
return out
def cvResize(np.ndarray src, height=None, width=None,
int method=CV_INTER_LINEAR):
"""
@@ -543,7 +657,105 @@ def cvResize(np.ndarray src, height=None, width=None,
c_cvResize(&srcimg, &outimg, method)
return out
return out
def cvWarpAffine(np.ndarray src, np.ndarray warpmat,
int flags=CV_INTER_LINEAR+CV_WARP_FILL_OUTLIERS,
fillval=(0., 0., 0., 0.)):
''' Applies an affine transformation to an image.
Parameters:
src - source image
warpmat - 2x3 affine transformation
flags - a combination of interpolation and method flags.
see opencv documentation for more details
fillval - a 4 tuple of a color to fill the background
defaults to black.
Returns:
a warped image the same size and dtype as src
'''
validate_array(src)
validate_array(warpmat)
assert len(fillval) == 4, 'fillval must be a 4-tuple'
assert_nchannels(src, [1, 3])
assert_nchannels(warpmat, [1])
assert warpmat.shape[0] == 2, 'warpmat must be 2x3'
assert warpmat.shape[1] == 3, 'warpmat must be 2x3'
cdef np.ndarray out
out = new_array_like(src)
cdef CvScalar cvfill
cdef int i
for i in range(4):
cvfill.val[i] = <double>fillval[i]
cdef IplImage srcimg
cdef IplImage outimg
cdef IplImage cvmat
cdef CvMat* cvmatptr
populate_iplimage(src, &srcimg)
populate_iplimage(out, &outimg)
populate_iplimage(warpmat, &cvmat)
cvmatptr = cvmat_ptr_from_iplimage(&cvmat)
c_cvWarpAffine(&srcimg, &outimg, cvmatptr, flags, cvfill)
PyMem_Free(cvmatptr)
return out
def cvWarpPerspective(np.ndarray src, np.ndarray warpmat,
int flags=CV_INTER_LINEAR+CV_WARP_FILL_OUTLIERS,
fillval=(0., 0., 0., 0.)):
''' Applies a perspective transformation to an image.
Parameters:
src - source image
warpmat - 3x3 perspective transformation
flags - a combination of interpolation and method flags.
see opencv documentation for more details
fillval - a 4 tuple of a color to fill the background
defaults to black.
Returns:
a warped image the same size and dtype as src
'''
validate_array(src)
validate_array(warpmat)
assert len(fillval) == 4, 'fillval must be a 4-tuple'
assert_nchannels(src, [1, 3])
assert_nchannels(warpmat, [1])
assert warpmat.shape[0] == 3, 'warpmat must be 3x3'
assert warpmat.shape[1] == 3, 'warpmat must be 3x3'
cdef np.ndarray out
out = new_array_like(src)
cdef CvScalar cvfill
cdef int i
for i in range(4):
cvfill.val[i] = <double>fillval[i]
cdef IplImage srcimg
cdef IplImage outimg
cdef IplImage cvmat
cdef CvMat* cvmatptr
populate_iplimage(src, &srcimg)
populate_iplimage(out, &outimg)
populate_iplimage(warpmat, &cvmat)
cvmatptr = cvmat_ptr_from_iplimage(&cvmat)
c_cvWarpPerspective(&srcimg, &outimg, cvmatptr, flags, cvfill)
PyMem_Free(cvmatptr)
return out
def cvFindChessboardCorners(np.ndarray src, pattern_size,
int flags = CV_CALIB_CB_ADAPTIVE_THRESH):
+20
View File
@@ -35,6 +35,23 @@ cdef struct _IplImage:
ctypedef _IplImage IplImage
# you will never directly populate a CvMat.
cdef union CvMat_uProxy:
unsigned char* ptr
short* s
int* i
float* fl
double* db
cdef struct CvMat:
int type
int step
int* refcount
CvMat_uProxy data
int rows
int cols
cdef struct CvPoint2D32f:
float x
float y
@@ -47,4 +64,7 @@ cdef struct CvTermCriteria:
int type
int max_iter
double epsilon
cdef struct CvScalar:
double val[4]
+32 -1
View File
@@ -94,13 +94,44 @@ class TestGoodFeaturesToTrack(OpenCVTest):
cvGoodFeaturesToTrack(self.lena_GRAY_U8, 100, 0.1, 3)
class TestGetRectSubPix(OpenCVTest):
@opencv_skip
def test_cvGetRectSubPix(self):
cvGetRectSubPix(self.lena_RGB_U8, (20, 20), (48.6, 48.6))
class TestGetQuadrangleSubPix(OpenCVTest):
@opencv_skip
def test_cvGetQuadrangleSubPix(self):
warpmat = np.array([[0.5, 0.3, 0.4],
[-.4, .23, 0.4]], dtype='float32')
cvGetQuadrangleSubPix(self.lena_RGB_U8, warpmat)
class TestResize(OpenCVTest):
@opencv_skip
def test_cvResize(self):
cvResize(self.lena_RGB_U8, height=50, width=50, method=CV_INTER_LINEAR)
cvResize(self.lena_RGB_U8, height=200, width=200, method=CV_INTER_CUBIC)
class TestWarpAffine(OpenCVTest):
@opencv_skip
def test_cvWarpAffine(self):
warpmat = np.array([[0.5, 0.3, 0.4],
[-.4, .23, 0.4]], dtype='float32')
cvWarpAffine(self.lena_RGB_U8, warpmat)
class TestWarpPerspective(OpenCVTest):
@opencv_skip
def test_cvWarpPerspective(self):
warpmat = np.array([[0.5, 0.3, 0.4],
[-.4, .23, 0.4],
[0.0, 1.0, 1.0]], dtype='float32')
cvWarpPerspective(self.lena_RGB_U8, warpmat)
class TestFindChessboardCorners:
@opencv_skip
def test_cvFindChessboardCorners(self):