# -*- python -*- import ctypes cimport numpy as np import numpy as np from cpython cimport * from libc.stdlib cimport * from opencv_type cimport * from opencv_backend import * from opencv_backend cimport * from opencv_constants import * from opencv_constants import * from opencv_cv import * from _libimport import cv from _utilities import cvdoc if cv is None: raise RuntimeError("Could not load libcv") # setup numpy tables for this module np.import_array() #------------------------------------------------------------------------------- # Useful global stuff #------------------------------------------------------------------------------- # a dict for cvCvtColor to get the appropriate types and shapes without # if statements all over the place (this way is faster, cause the dict is # created at import time) # the order of list arguments is: # [in_channels, out_channels, [input_dtypes]] # out type is always the same as in type _cvtcolor_dict = {CV_BGR2BGRA: [3, 4, [UINT8, UINT16, FLOAT32]], CV_RGB2RGBA: [3, 4, [UINT8, UINT16, FLOAT32]], CV_BGRA2BGR: [4, 3, [UINT8, UINT16, FLOAT32]], CV_RGBA2RGB: [4, 3, [UINT8, UINT16, FLOAT32]], CV_BGR2RGBA: [3, 4, [UINT8, UINT16, FLOAT32]], CV_RGB2BGRA: [3, 4, [UINT8, UINT16, FLOAT32]], CV_RGBA2BGR: [4, 3, [UINT8, UINT16, FLOAT32]], CV_BGRA2RGB: [4, 3, [UINT8, UINT16, FLOAT32]], CV_BGR2RGB: [3, 3, [UINT8, UINT16, FLOAT32]], CV_RGB2BGR: [3, 3, [UINT8, UINT16, FLOAT32]], CV_BGRA2RGBA: [4, 4, [UINT8, UINT16, FLOAT32]], CV_RGBA2BGRA: [4, 4, [UINT8, UINT16, FLOAT32]], CV_BGR2GRAY: [3, 1, [UINT8, UINT16, FLOAT32]], CV_RGB2GRAY: [3, 1, [UINT8, UINT16, FLOAT32]], CV_GRAY2BGR: [1, 3, [UINT8, UINT16, FLOAT32]], CV_GRAY2RGB: [1, 3, [UINT8, UINT16, FLOAT32]], CV_GRAY2BGRA: [1, 4, [UINT8, UINT16, FLOAT32]], CV_GRAY2RGBA: [1, 4, [UINT8, UINT16, FLOAT32]], CV_BGRA2GRAY: [4, 1, [UINT8, UINT16, FLOAT32]], CV_RGBA2GRAY: [4, 1, [UINT8, UINT16, FLOAT32]], CV_BGR2BGR565: [3, 2, [UINT8]], CV_RGB2BGR565: [3, 2, [UINT8]], CV_BGR5652BGR: [2, 3, [UINT8]], CV_BGR5652RGB: [2, 3, [UINT8]], CV_BGRA2BGR565: [4, 2, [UINT8]], CV_RGBA2BGR565: [4, 2, [UINT8]], CV_BGR5652BGRA: [2, 4, [UINT8]], CV_BGR5652RGBA: [2, 4, [UINT8]], CV_GRAY2BGR565: [1, 2, [UINT8]], CV_BGR5652GRAY: [2, 1, [UINT8]], CV_BGR2BGR555: [3, 2, [UINT8]], CV_RGB2BGR555: [3, 2, [UINT8]], CV_BGR5552BGR: [2, 3, [UINT8]], CV_BGR5552RGB: [2, 3, [UINT8]], CV_BGRA2BGR555: [4, 2, [UINT8]], CV_RGBA2BGR555: [4, 2, [UINT8]], CV_BGR5552BGRA: [2, 4, [UINT8]], CV_BGR5552RGBA: [2, 4, [UINT8]], CV_GRAY2BGR555: [1, 2, [UINT8]], CV_BGR5552GRAY: [2, 1, [UINT8]], CV_BGR2XYZ: [3, 3, [UINT8, UINT16, FLOAT32]], CV_RGB2XYZ: [3, 3, [UINT8, UINT16, FLOAT32]], CV_XYZ2BGR: [3, 3, [UINT8, UINT16, FLOAT32]], CV_XYZ2RGB: [3, 3, [UINT8, UINT16, FLOAT32]], CV_BGR2YCrCb: [3, 3, [UINT8, UINT16, FLOAT32]], CV_RGB2YCrCb: [3, 3, [UINT8, UINT16, FLOAT32]], CV_YCrCb2BGR: [3, 3, [UINT8, UINT16, FLOAT32]], CV_YCrCb2RGB: [3, 3, [UINT8, UINT16, FLOAT32]], CV_BGR2HSV: [3, 3, [UINT8, FLOAT32]], CV_RGB2HSV: [3, 3, [UINT8, FLOAT32]], CV_BGR2Lab: [3, 3, [UINT8, FLOAT32]], CV_RGB2Lab: [3, 3, [UINT8, FLOAT32]], CV_BayerBG2BGR: [1, 3, [UINT8]], CV_BayerGB2BGR: [1, 3, [UINT8]], CV_BayerRG2BGR: [1, 3, [UINT8]], CV_BayerGR2BGR: [1, 3, [UINT8]], CV_BayerBG2RGB: [1, 3, [UINT8]], CV_BayerGB2RGB: [1, 3, [UINT8]], CV_BayerRG2RGB: [1, 3, [UINT8]], CV_BayerGR2RGB: [1, 3, [UINT8]], CV_BGR2Luv: [3, 3, [UINT8, FLOAT32]], CV_RGB2Luv: [3, 3, [UINT8, FLOAT32]], CV_BGR2HLS: [3, 3, [UINT8, FLOAT32]], CV_RGB2HLS: [3, 3, [UINT8, FLOAT32]], CV_HSV2BGR: [3, 3, [UINT8, FLOAT32]], CV_HSV2RGB: [3, 3, [UINT8, FLOAT32]], CV_Lab2BGR: [3, 3, [UINT8, FLOAT32]], CV_Lab2RGB: [3, 3, [UINT8, FLOAT32]], CV_Luv2BGR: [3, 3, [UINT8, FLOAT32]], CV_Luv2RGB: [3, 3, [UINT8, FLOAT32]], CV_HLS2BGR: [3, 3, [UINT8, FLOAT32]], CV_HLS2RGB: [3, 3, [UINT8, FLOAT32]]} ################################### # opencv function declarations ################################### # cvSobel ctypedef void (*cvSobelPtr)(IplImage*, IplImage*, int, int, int) cdef cvSobelPtr c_cvSobel c_cvSobel = (ctypes.addressof(cv.cvSobel))[0] # cvLaplace ctypedef void (*cvLaplacePtr)(IplImage*, IplImage*, int) cdef cvLaplacePtr c_cvLaplace c_cvLaplace = (ctypes.addressof(cv.cvLaplace))[0] # cvCanny ctypedef void (*cvCannyPtr)(IplImage*, IplImage*, double, double, int) cdef cvCannyPtr c_cvCanny c_cvCanny = (ctypes.addressof(cv.cvCanny))[0] # cvPreCornerDetect ctypedef void (*cvPreCorneDetectPtr)(IplImage*, IplImage*, int) cdef cvPreCorneDetectPtr c_cvPreCornerDetect c_cvPreCornerDetect = ( ctypes.addressof(cv.cvPreCornerDetect))[0] # cvCornerEigenValsAndVecs ctypedef void (*cvCornerEigenValsAndVecsPtr)(IplImage*, IplImage*, int, int) cdef cvCornerEigenValsAndVecsPtr c_cvCornerEigenValsAndVecs c_cvCornerEigenValsAndVecs = ( ctypes.addressof(cv.cvCornerEigenValsAndVecs))[0] # cvCornerMinEigenVal ctypedef void (*cvCornerMinEigenValPtr)(IplImage*, IplImage*, int, int) cdef cvCornerMinEigenValPtr c_cvCornerMinEigenVal c_cvCornerMinEigenVal = ( ctypes.addressof(cv.cvCornerMinEigenVal))[0] # cvCornerHarris ctypedef void (*cvCornerHarrisPtr)(IplImage*, IplImage*, int, int, double) cdef cvCornerHarrisPtr c_cvCornerHarris c_cvCornerHarris = ( ctypes.addressof(cv.cvCornerHarris))[0] # cvFindCornerSubPix ctypedef void (*cvFindCornerSubPixPtr)(IplImage*, CvPoint2D32f*, int, CvSize, CvSize, CvTermCriteria) cdef cvFindCornerSubPixPtr c_cvFindCornerSubPix c_cvFindCornerSubPix = ( ctypes.addressof(cv.cvFindCornerSubPix))[0] # cvGoodFeaturesToTrack ctypedef void (*cvGoodFeaturesToTrackPtr)(IplImage*, IplImage*, IplImage*, CvPoint2D32f*, int*, double, double, IplImage*, int, int, double) cdef cvGoodFeaturesToTrackPtr c_cvGoodFeaturesToTrack c_cvGoodFeaturesToTrack = ( ctypes.addressof(cv.cvGoodFeaturesToTrack))[0] # cvGetRectSubPix ctypedef void (*cvGetRectSubPixPtr)(IplImage*, IplImage*, CvPoint2D32f) cdef cvGetRectSubPixPtr c_cvGetRectSubPix c_cvGetRectSubPix = ( ctypes.addressof(cv.cvGetRectSubPix))[0] # cvGetQuadrangleSubPix ctypedef void (*cvGetQuadrangleSubPixPtr)(IplImage*, IplImage*, CvMat*) cdef cvGetQuadrangleSubPixPtr c_cvGetQuadrangleSubPix c_cvGetQuadrangleSubPix = ( ctypes.addressof(cv.cvGetQuadrangleSubPix))[0] # cvResize ctypedef void (*cvResizePtr)(IplImage*, IplImage*, int) cdef cvResizePtr c_cvResize c_cvResize = (ctypes.addressof(cv.cvResize))[0] # cvWarpAffine ctypedef void (*cvWarpAffinePtr)(IplImage*, IplImage*, CvMat*, int, CvScalar) cdef cvWarpAffinePtr c_cvWarpAffine c_cvWarpAffine = ( ctypes.addressof(cv.cvWarpAffine))[0] # cvWarpPerspective ctypedef void (*cvWarpPerspectivePtr)(IplImage*, IplImage*, CvMat*, int, CvScalar) cdef cvWarpPerspectivePtr c_cvWarpPerspective c_cvWarpPerspective = ( ctypes.addressof(cv.cvWarpPerspective))[0] # cvLogPolar ctypedef void (*cvLogPolarPtr)(IplImage*, IplImage*, CvPoint2D32f, double, int) cdef cvLogPolarPtr c_cvLogPolar c_cvLogPolar = (ctypes.addressof(cv.cvLogPolar))[0] # cvErode ctypedef void (*cvErodePtr)(IplImage*, IplImage*, IplConvKernel*, int) cdef cvErodePtr c_cvErode c_cvErode = (ctypes.addressof(cv.cvErode))[0] # cvDilate ctypedef void (*cvDilatePtr)(IplImage*, IplImage*, IplConvKernel*, int) cdef cvDilatePtr c_cvDilate c_cvDilate = (ctypes.addressof(cv.cvDilate))[0] # cvMorphologyEx ctypedef void (*cvMorphologyExPtr)(IplImage*, IplImage*, IplImage*, IplConvKernel*, int, int) cdef cvMorphologyExPtr c_cvMorphologyEx c_cvMorphologyEx = ( ctypes.addressof(cv.cvMorphologyEx))[0] # cvSmooth ctypedef void (*cvSmoothPtr)(IplImage*, IplImage*, int, int, int, double, double) cdef cvSmoothPtr c_cvSmooth c_cvSmooth = (ctypes.addressof(cv.cvSmooth))[0] # cvFilter2D ctypedef void (*cvFilter2DPtr)(IplImage*, IplImage*, CvMat*, CvPoint) cdef cvFilter2DPtr c_cvFilter2D c_cvFilter2D = (ctypes.addressof(cv.cvFilter2D))[0] # cvIntegral ctypedef void (*cvIntegralPtr)(IplImage*, IplImage*, IplImage*, IplImage*) cdef cvIntegralPtr c_cvIntegral c_cvIntegral = (ctypes.addressof(cv.cvIntegral))[0] # cvCvtColor ctypedef void (*cvCvtColorPtr)(IplImage*, IplImage*, int) cdef cvCvtColorPtr c_cvCvtColor c_cvCvtColor = (ctypes.addressof(cv.cvCvtColor))[0] # cvThreshold ctypedef double (*cvThresholdPtr)(IplImage*, IplImage*, double, double, int) cdef cvThresholdPtr c_cvThreshold c_cvThreshold = (ctypes.addressof(cv.cvThreshold))[0] # cvAdaptiveThreshold ctypedef void (*cvAdaptiveThresholdPtr)(IplImage*, IplImage*, double, int, int, int, double) cdef cvAdaptiveThresholdPtr c_cvAdaptiveThreshold c_cvAdaptiveThreshold = ( ctypes.addressof(cv.cvAdaptiveThreshold))[0] # cvPyrDown ctypedef void (*cvPyrDownPtr)(IplImage*, IplImage*, int) cdef cvPyrDownPtr c_cvPyrDown c_cvPyrDown = (ctypes.addressof(cv.cvPyrDown))[0] # cvPyrUp ctypedef void (*cvPyrUpPtr)(IplImage*, IplImage*, int) cdef cvPyrUpPtr c_cvPyrUp c_cvPyrUp = (ctypes.addressof(cv.cvPyrUp))[0] # cvWatershed ctypedef void (*cvWatershedPtr)(IplImage*, IplImage*) cdef cvWatershedPtr c_cvWatershed c_cvWatershed = (ctypes.addressof(cv.cvWatershed))[0] # cvCalibrateCamera2 ctypedef void (*cvCalibrateCamera2Ptr)(CvMat*, CvMat*, CvMat*, CvSize, CvMat*, CvMat*, CvMat*, CvMat*, int) cdef cvCalibrateCamera2Ptr c_cvCalibrateCamera2 c_cvCalibrateCamera2 = ( ctypes.addressof(cv.cvCalibrateCamera2))[0] # cvUndistort2 ctypedef void (*cvUndistort2Ptr)(IplImage*, IplImage*, CvMat*, CvMat*, CvMat*) cdef cvUndistort2Ptr c_cvUndistort2 c_cvUndistort2 = (ctypes.addressof(cv.cvUndistort2))[0] # cvFindChessboardCorners ctypedef void (*cvFindChessboardCornersPtr)(IplImage*, CvSize, CvPoint2D32f*, int*, int) cdef cvFindChessboardCornersPtr c_cvFindChessboardCorners c_cvFindChessboardCorners = ( ctypes.addressof(cv.cvFindChessboardCorners))[0] # cvFindExtrinsicCameraParams2 ctypedef void (*cvFindExtrinsicCameraParams2Ptr)(CvMat*, CvMat*, CvMat*, CvMat*, CvMat*, CvMat*, int) cdef cvFindExtrinsicCameraParams2Ptr c_cvFindExtrinsicCameraParams2 c_cvFindExtrinsicCameraParams2 = \ ( ctypes.addressof(cv.cvFindExtrinsicCameraParams2))[0] # cvFindFundamentalMat ctypedef int (*cvFindFundamentalMatPtr)(CvMat*, CvMat*, CvMat*, int, double, double, CvMat*) cdef cvFindFundamentalMatPtr c_cvFindFundamentalMat c_cvFindFundamentalMat = \ ( ctypes.addressof(cv.cvFindFundamentalMat))[0] # cvDrawChessboardCorners ctypedef void (*cvDrawChessboardCornersPtr)(IplImage*, CvSize, CvPoint2D32f*, int, int) cdef cvDrawChessboardCornersPtr c_cvDrawChessboardCorners c_cvDrawChessboardCorners = ( ctypes.addressof(cv.cvDrawChessboardCorners))[0] # cvFloodFill ctypedef void (*cvFloodFillPtr)(IplImage*, CvPoint, CvScalar, CvScalar, CvScalar, void*, int, IplImage*) cdef cvFloodFillPtr c_cvFloodFill c_cvFloodFill = (ctypes.addressof(cv.cvFloodFill))[0] # cvMatchTemplate ctypedef void (*cvMatchTemplatePtr)(IplImage*, IplImage*, IplImage*, int) cdef cvMatchTemplatePtr c_cvMatchTemplate c_cvMatchTemplate = ( ctypes.addressof(cv.cvMatchTemplate))[0] #------------------------------------------------------------------------------- # Function Implementations #------------------------------------------------------------------------------- #-------- # cvSobel #-------- @cvdoc(package='cv', group='filter', doc=\ '''cvSobel(src, xorder=1, yorder=0, aperture_size=3) Apply the Sobel operator to the input image. Parameters ---------- src : ndarray, 2D, dtype=[uint8, int8, float32] The source image. xorder : integer The x order of the Sobel operator. yorder : integer The y order of the Sobel operator. aperture_size : integer=[3, 5, 7] The size of the Sobel kernel. Returns ------- out : ndarray A new which is the result of applying the Sobel operator to src.''') def cvSobel(np.ndarray src, int xorder=1, int yorder=0, int aperture_size=3): validate_array(src) assert_dtype(src, [UINT8, INT8, FLOAT32]) assert_nchannels(src, [1]) if (aperture_size != 3 and aperture_size != 5 and aperture_size != 7): raise ValueError('aperture_size must be 3, 5, or 7') cdef np.ndarray out if src.dtype == UINT8 or src.dtype == INT8: out = new_array_like_diff_dtype(src, INT16) else: out = new_array_like(src) cdef IplImage srcimg cdef IplImage outimg populate_iplimage(src, &srcimg) populate_iplimage(out, &outimg) c_cvSobel(&srcimg, &outimg, xorder, yorder, aperture_size) return out #---------- # cvLaplace #---------- @cvdoc(package='cv', group='filter', doc=\ '''cvLaplace(src, aperture_size=3) Apply the Laplace operator to the input image. Parameters ---------- src : ndarray, 2D, dtype=[uint8, int8, float32] The source image. aperture_size : integer=[3, 5, 7] The size of the Sobel kernel. Returns ------- out : ndarray A new which is the result of applying the Laplace operator to src.''') def cvLaplace(np.ndarray src, int aperture_size=3): validate_array(src) assert_dtype(src, [UINT8, INT8, FLOAT32]) assert_nchannels(src, [1]) if (aperture_size != 3 and aperture_size != 5 and aperture_size != 7): raise ValueError('aperture_size must be 3, 5, or 7') cdef np.ndarray out if src.dtype == UINT8 or src.dtype == INT8: out = new_array_like_diff_dtype(src, INT16) else: out = new_array_like(src) cdef IplImage srcimg cdef IplImage outimg populate_iplimage(src, &srcimg) populate_iplimage(out, &outimg) c_cvLaplace(&srcimg, &outimg, aperture_size) return out #-------- # cvCanny #-------- @cvdoc(package='cv', group='feature', doc=\ '''cvCanny(src, threshold1=10, threshold2=50, aperture_size=3) Apply Canny edge detection to the input image. Parameters ---------- src : ndarray, 2D, dtype=[uint8] The source image. threshold1 : float The lower threshold used for edge linking. threshold2 : float The upper threshold used to find strong edges. aperture_size : integer=[3, 5, 7] The size of the Sobel kernel. Returns ------- out : ndarray A new which is the result of applying Canny edge detection to src.''') def cvCanny(np.ndarray src, double threshold1=10, double threshold2=50, int aperture_size=3): validate_array(src) assert_dtype(src, [UINT8]) assert_nchannels(src, [1]) if (aperture_size != 3 and aperture_size != 5 and aperture_size != 7): raise ValueError('aperture_size must be 3, 5, or 7') cdef np.ndarray out out = new_array_like(src) cdef IplImage srcimg cdef IplImage outimg populate_iplimage(src, &srcimg) populate_iplimage(out, &outimg) c_cvCanny(&srcimg, &outimg, threshold1, threshold2, aperture_size) return out #------------------ # cvPreCornerDetect #------------------ @cvdoc(package='cv', group='feature', doc=\ '''cvPreCornerDetect(src, aperture_size=3) Calculate the feature map for corner detection. Parameters ---------- src : ndarray, 2D, dtype=[uint8, float32] The source image. aperture_size : integer=[3, 5, 7] The size of the Sobel kernel. Returns ------- out : ndarray A new array of the corner candidates.''') def cvPreCornerDetect(np.ndarray src, int aperture_size=3): validate_array(src) assert_dtype(src, [UINT8, FLOAT32]) assert_nchannels(src, [1]) if (aperture_size != 3 and aperture_size != 5 and aperture_size != 7): raise ValueError('aperture_size must be 3, 5, or 7') cdef np.ndarray out out = new_array_like_diff_dtype(src, FLOAT32) cdef IplImage srcimg cdef IplImage outimg populate_iplimage(src, &srcimg) populate_iplimage(out, &outimg) c_cvPreCornerDetect(&srcimg, &outimg, aperture_size) return out #------------------------- # cvCornerEigenValsAndVecs #------------------------- @cvdoc(package='cv', group='feature', doc=\ '''cvCornerEigenValsAndVecs(src, block_size=3, aperture_size=3) Calculates the eigenvalues and eigenvectors of image blocks for corner detection. Parameters ---------- src : ndarray, 2D, dtype=[uint8, float32] The source image. block_size : integer The size of the neighborhood in which to calculate the eigenvalues and eigenvectors. aperture_size : integer=[3, 5, 7] The size of the Sobel kernel. Returns ------- out : ndarray A new array of the eigenvalues and eigenvectors. The shape of this array is (height, width, 6), Where height and width are the same as that of src.''') def cvCornerEigenValsAndVecs(np.ndarray src, int block_size=3, int aperture_size=3): validate_array(src) assert_nchannels(src, [1]) assert_dtype(src, [UINT8, FLOAT32]) if (aperture_size != 3 and aperture_size != 5 and aperture_size != 7): raise ValueError('aperture_size must be 3, 5, or 7') cdef np.ndarray out cdef np.npy_intp outshape[2] outshape[0] = src.shape[0] outshape[1] = src.shape[1] * 6 out = new_array(2, outshape, FLOAT32) cdef IplImage srcimg cdef IplImage outimg populate_iplimage(src, &srcimg) populate_iplimage(out, &outimg) c_cvCornerEigenValsAndVecs(&srcimg, &outimg, block_size, aperture_size) return out.reshape(out.shape[0], -1, 6) #-------------------- # cvCornerMinEigenVal #-------------------- @cvdoc(package='cv', group='feature', doc=\ '''cvCornerMinEigenVal(src, block_size=3, aperture_size=3) Calculates the minimum eigenvalues of gradient matrices for corner detection. Parameters ---------- src : ndarray, 2D, dtype=[uint8, float32] The source image. block_size : integer The size of the neighborhood in which to calculate the eigenvalues. aperture_size : integer=[3, 5, 7] The size of the Sobel kernel. Returns ------- out : ndarray A new array of the eigenvalues.''') def cvCornerMinEigenVal(np.ndarray src, int block_size=3, int aperture_size=3): validate_array(src) assert_nchannels(src, [1]) assert_dtype(src, [UINT8, FLOAT32]) if (aperture_size != 3 and aperture_size != 5 and aperture_size != 7): raise ValueError('aperture_size must be 3, 5, or 7') cdef np.ndarray out out = new_array_like_diff_dtype(src, FLOAT32) cdef IplImage srcimg cdef IplImage outimg populate_iplimage(src, &srcimg) populate_iplimage(out, &outimg) c_cvCornerMinEigenVal(&srcimg, &outimg, block_size, aperture_size) return out #--------------- # cvCornerHarris #--------------- @cvdoc(package='cv', group='feature', doc=\ '''cvCornerHarris(src, block_size=3, aperture_size=3, k=0.04) Applies the Harris edge detector to the input image. Parameters ---------- src : ndarray, 2D, dtype=[uint8, float32] The source image. block_size : integer The size of the neighborhood in which to apply the detector. aperture_size : integer=[3, 5, 7] The size of the Sobel kernel. k : float Harris detector free parameter. See Notes. Returns ------- out : ndarray A new array of the Harris corners. Notes ----- The function cvCornerHarris() runs the Harris edge detector on the image. Similarly to cvCornerMinEigenVal() and cvCornerEigenValsAndVecs(), for each pixel it calculates a gradient covariation matrix M over a block_size X block_size neighborhood. Then, it stores det(M) - k * trace(M)**2 to the output image. Corners in the image can be found as the local maxima of the output image.''') def cvCornerHarris(np.ndarray src, int block_size=3, int aperture_size=3, double k=0.04): validate_array(src) assert_nchannels(src, [1]) assert_dtype(src, [UINT8, FLOAT32]) if (aperture_size != 3 and aperture_size != 5 and aperture_size != 7): raise ValueError('aperture_size must be 3, 5, or 7') cdef np.ndarray out out = new_array_like_diff_dtype(src, FLOAT32) cdef IplImage srcimg cdef IplImage outimg populate_iplimage(src, &srcimg) populate_iplimage(out, &outimg) c_cvCornerHarris(&srcimg, &outimg, block_size, aperture_size, k) return out #------------------- # cvFindCornerSubPix #------------------- @cvdoc(package='cv', group='feature', doc=\ '''cvFindCornerSubPix(src, corners, win, zero_zone=(-1, -1), iterations=0, epsilon=1e-5) Refines corner locations to sub-pixel accuracy. Parameters ---------- src : ndarray, 2D, dtype=[uint8] The source image. corners : ndarray, shape=(N x 2) An initial approximation of the corners in the image. The corners will be refined in-place in this array. win : tuple, (height, width) The window within which the function iterates until it converges on the real corner. The actual window is twice the size of what is declared here. (an OpenCV peculiarity). zero_zone : Half of the size of the dead region in the middle of the search zone over which the calculations are not performed. It is used sometimes to avoid possible singularities of the autocorrelation matrix. The value of (-1,-1) indicates that there is no such size. iterations : integer The maximum number of iterations to perform. If 0, the function iterates until the error is less than epsilon. epsilon : float The epsilon error, below which the function terminates. Can be used in combination with iterations. Returns ------- None. The array 'corners' is modified in place.''') def cvFindCornerSubPix(np.ndarray src, np.ndarray corners, win, zero_zone=(-1, -1), int iterations=0, double epsilon=1e-5): validate_array(src) assert_nchannels(src, [1]) assert_dtype(src, [UINT8]) validate_array(corners) assert_ndims(corners, [2]) assert_dtype(corners, [FLOAT32]) cdef int count = (corners.shape[0] * corners.shape[1] / 2.) cdef CvPoint2D32f* cvcorners = array_as_cvPoint2D32f_ptr(corners) if len(win) != 2: raise ValueError('win must be a 2-tuple') cdef CvSize cvwin cvwin.height = win[0] cvwin.width = win[1] cdef int imgheight = src.shape[0] cdef int imgwidth = src.shape[1] if imgwidth < (cvwin.width * 2 + 5) or imgheight < (cvwin.height * 2 + 5): raise ValueError('The window is too large.') cdef CvSize cvzerozone cvzerozone.height = zero_zone[0] cvzerozone.width = zero_zone[1] cdef IplImage srcimg populate_iplimage(src, &srcimg) cdef CvTermCriteria crit crit = get_cvTermCriteria(iterations, epsilon) c_cvFindCornerSubPix(&srcimg, cvcorners, count, cvwin, cvzerozone, crit) return None #---------------------- # cvGoodFeaturesToTrack #---------------------- @cvdoc(package='cv', group='feature', doc=\ '''cvGoodFeaturesToTrack(src, corner_count, quality_level, min_distance, block_size=3, use_harris=0, k=0.04) Determines strong corners in an image. Parameters ---------- src : ndarray, 2D, dtype=[uint8, float32] The source image. corner_count : int The maximum number of corners to find. Only found corners are returned. quality_level : float Multiplier for the max/min eigenvalue; specifies the minimal accepted quality of image corners. min_distance : float Limit, specifying the minimum possible distance between the returned corners; Euclidian distance is used. block_size : integer The size of the neighborhood in which to apply the detector. use_harris : integer If nonzero, Harris operator (cvCornerHarris()) is used instead of default cvCornerMinEigenVal() k : float Harris detector free parameter. Used only if use_harris != 0. Returns ------- out : ndarray The locations of the found corners in the image. Notes ----- This function finds distinct and strong corners in an image which can be used as features in a tracking algorithm. It also insures that features are distanced from one another by at least min_distance.''') def cvGoodFeaturesToTrack(np.ndarray src, int corner_count, double quality_level, double min_distance, int block_size=3, int use_harris=0, double k=0.04): validate_array(src) assert_dtype(src, [UINT8, FLOAT32]) assert_nchannels(src, [1]) cdef np.ndarray eig = new_array_like_diff_dtype(src, FLOAT32) cdef np.ndarray temp = new_array_like(eig) cdef np.npy_intp cornershape[2] cornershape[0] = corner_count cornershape[1] = 2 cdef np.ndarray out = new_array(2, cornershape, FLOAT32) cdef CvPoint2D32f* cvcorners = array_as_cvPoint2D32f_ptr(out) cdef int ncorners_found ncorners_found = corner_count cdef IplImage srcimg cdef IplImage eigimg cdef IplImage tempimg cdef IplImage *maskimg populate_iplimage(src, &srcimg) populate_iplimage(eig, &eigimg) populate_iplimage(temp, &tempimg) # don't need to support ROI. The user can just pass a slice. maskimg = NULL c_cvGoodFeaturesToTrack(&srcimg, &eigimg, &tempimg, cvcorners, &ncorners_found, quality_level, min_distance, maskimg, block_size, use_harris, k) return out[:ncorners_found] #---------------- # cvGetRectSubPix #---------------- @cvdoc(package='cv', group='geometry', doc=\ '''cvGetRectSubPix(src, size, center) Retrieves the pixel rectangle from an image with sub-pixel accuracy. Parameters ---------- src : ndarray The source image. size : two tuple, integers, (height, width) The size of the rectangle to extract. center : two tuple, floats, (x, y) The center location of the rectangle. The center must lie within the image, but the rectangle may extend beyond the bounds of the image. Returns ------- out : ndarray The extracted rectangle of the image. Notes ----- The center of the specified rectangle must lie within the image, but the bounds of the rectangle may extend beyond the image. Border replication is used to fill in missing pixels.''') def cvGetRectSubPix(np.ndarray src, size, center): validate_array(src) cdef np.npy_intp* shape = clone_array_shape(src) shape[0] = size[0] shape[1] = size[1] cdef CvPoint2D32f cvcenter cvcenter.x = center[0] cvcenter.y = 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 #---------------------- # cvGetQuadrangleSubPix #---------------------- @cvdoc(package='cv', group='geometry', doc=\ '''cvGetQuadrangleSubPix(src, warpmat, float_out=False) Retrieves the pixel quandrangle from an image with sub-pixel accuracy. In english: apply an affine transform to an image. Parameters ---------- src : ndarray The source image. warpmat : ndarray, 2x3 The affine transformation to apply to the src image. float_out : bool If True, the return array will have dtype np.float32. Otherwise, the return array will have the same dtype as the src array. If True, the src array MUST have dtype np.uint8 Returns ------- out : ndarray Warped image of same size as src. Notes ----- The values of pixels at non-integer coordinates are retrieved using bilinear interpolation. When the function needs pixels outside of the image, it uses replication border mode to reconstruct the values. Every channel of multiple-channel images is processed independently. This function has less overhead than cvWarpAffine and should be used unless specific feature of that function are required.''') def cvGetQuadrangleSubPix(np.ndarray src, np.ndarray warpmat, float_out=False): validate_array(src) validate_array(warpmat) assert_nchannels(src, [1, 3]) assert_nchannels(warpmat, [1]) if warpmat.shape[0] != 2 or warpmat.shape[1] != 3: raise ValueError('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 #--------- # cvResize #--------- @cvdoc(package='cv', group='geometry', doc=\ '''cvResize(src, size, method=CV_INTER_LINEAR) Resize an to the given size. Parameters ---------- src : ndarray The source image. size : tuple, (height, width) The target resize size. method : integer The interpolation method used for resizing. Supported methods are: CV_INTER_NN CV_INTER_LINEAR CV_INTER_AREA CV_INTER_CUBIC Returns ------- out : ndarray The resized image.''') def cvResize(np.ndarray src, size, int method=CV_INTER_LINEAR): validate_array(src) if len(size) != 2: raise ValueError('size must be a 2-tuple (height, width)') if method not in [CV_INTER_NN, CV_INTER_LINEAR, CV_INTER_AREA, CV_INTER_CUBIC]: raise ValueError('unsupported interpolation type') cdef int ndim = src.ndim cdef np.npy_intp* shape = clone_array_shape(src) shape[0] = size[0] shape[1] = size[1] cdef np.ndarray out = new_array(ndim, shape, src.dtype) validate_array(out) PyMem_Free(shape) cdef IplImage srcimg cdef IplImage outimg populate_iplimage(src, &srcimg) populate_iplimage(out, &outimg) c_cvResize(&srcimg, &outimg, method) return out #------------- # cvWarpAffine #------------- @cvdoc(package='cv', group='geometry', doc=\ '''cvWarpAffine(src, warpmat, flag=CV_INTER_LINEAR+CV_WARP_FILL_OUTLIERS, fillval=(0., 0., 0., 0.)) Applies an affine transformation to the image. Parameters ---------- src : ndarray The source image. warpmat : ndarray, 2x3 The affine transformation to apply to the src image. flag : integer A combination of interpolation and method flags. Supported flags are: (see notes) Interpolation: CV_INTER_NN CV_INTER_LINEAR CV_INTER_AREA CV_INTER_CUBIC Method: CV_WARP_FILL_OUTLIERS CV_WARP_INVERSE_MAP fillval : 4-tuple, (R, G, B, A) The color to fill in missing pixels. Defaults to black. For < 4 channel images, use 0.'s for the value. Returns ------- out : ndarray The warped image of same size and dtype as src. Notes ----- CV_WARP_FILL_OUTLIERS - fills all of the destination image pixels; if some of them correspond to outliers in the source image, they are set to fillval. CV_WARP_INVERSE_MAP - indicates that warpmat is inversely transformed from the destination image to the source and, thus, can be used directly for pixel interpolation. Otherwise, the function finds the inverse transform from warpmat. This function has a larger overhead than cvGetQuadrangleSubPix, and that function should be used instead, unless specific features of this function are needed.''') def cvWarpAffine(np.ndarray src, np.ndarray warpmat, int flag=CV_INTER_LINEAR+CV_WARP_FILL_OUTLIERS, fillval=(0., 0., 0., 0.)): validate_array(src) validate_array(warpmat) if len(fillval) != 4: raise ValueError('fillval must be a 4-tuple') assert_nchannels(src, [1, 3]) assert_nchannels(warpmat, [1]) if warpmat.shape[0] != 2 or warpmat.shape[1] != 3: raise ValueError('warpmat must be 2x3') valid_flags = [0, 1, 2, 3, 8, 16, 9, 17, 11, 19, 10, 18] if flag not in valid_flags: raise ValueError('unsupported flag combination') cdef np.ndarray out out = new_array_like(src) cdef CvScalar cvfill cdef int i for i in range(4): cvfill.val[i] = 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, flag, cvfill) PyMem_Free(cvmatptr) return out #------------------ # cvWarpPerspective #------------------ @cvdoc(package='cv', group='geometry', doc=\ '''cvWarpPerspective(src, warpmat, flag=CV_INTER_LINEAR+CV_WARP_FILL_OUTLIERS, fillval=(0., 0., 0., 0.)) Applies a perspective transformation to an image. Parameters ---------- src : ndarray The source image. warpmat : ndarray, 3x3 The affine transformation to apply to the src image. flag : integer A combination of interpolation and method flags. Supported flags are: (see notes) Interpolation: CV_INTER_NN CV_INTER_LINEAR CV_INTER_AREA CV_INTER_CUBIC Method: CV_WARP_FILL_OUTLIERS CV_WARP_INVERSE_MAP fillval : 4-tuple, (R, G, B, A) The color to fill in missing pixels. Defaults to black. For < 4 channel images, use 0.'s for the value. Returns ------- out : ndarray The warped image of same size and dtype as src. Notes ----- CV_WARP_FILL_OUTLIERS - fills all of the destination image pixels; if some of them correspond to outliers in the source image, they are set to fillval. CV_WARP_INVERSE_MAP - indicates that warpmat is inversely transformed from the destination image to the source and, thus, can be used directly for pixel interpolation. Otherwise, the function finds the inverse transform from warpmat.''') def cvWarpPerspective(np.ndarray src, np.ndarray warpmat, int flag=CV_INTER_LINEAR+CV_WARP_FILL_OUTLIERS, fillval=(0., 0., 0., 0.)): validate_array(src) validate_array(warpmat) if len(fillval) != 4: raise ValueError('fillval must be a 4-tuple') assert_nchannels(src, [1, 3]) assert_nchannels(warpmat, [1]) if warpmat.shape[0] != 3 or warpmat.shape[1] != 3: raise ValueError('warpmat must be 3x3') valid_flags = [0, 1, 2, 3, 8, 16, 9, 17, 11, 19, 10, 18] if flag not in valid_flags: raise ValueError('unsupported flag combination') cdef np.ndarray out out = new_array_like(src) cdef CvScalar cvfill cdef int i for i in range(4): cvfill.val[i] = fillval[i] cdef IplImage srcimg cdef IplImage outimg cdef IplImage cvmat cdef CvMat* cvmatptr = NULL populate_iplimage(src, &srcimg) populate_iplimage(out, &outimg) populate_iplimage(warpmat, &cvmat) cvmatptr = cvmat_ptr_from_iplimage(&cvmat) c_cvWarpPerspective(&srcimg, &outimg, cvmatptr, flag, cvfill) PyMem_Free(cvmatptr) return out #----------- # cvLogPolar #----------- @cvdoc(package='cv', group='geometry', doc=\ '''cvLogPolar(src, center, M, flag=CV_INTER_LINEAR+CV_WARP_FILL_OUTLIERS) Remaps and image to Log-Polar space. Parameters ---------- src : ndarray The source image. center : tuple, (x, y) The keypoint for the log polar transform. M : float The scale factor for the transform. (40 is a good starting point for a 256x256 image) flag : integer A combination of interpolation and method flags. Supported flags are: (see notes) Interpolation: CV_INTER_NN CV_INTER_LINEAR CV_INTER_AREA CV_INTER_CUBIC Method: CV_WARP_FILL_OUTLIERS CV_WARP_INVERSE_MAP Returns ------- out : ndarray A transformed image the same size and dtype as src. Notes ----- CV_WARP_FILL_OUTLIERS - fills all of the destination image pixels; if some of them correspond to outliers in the source image, they are set to zero. CV_WARP_INVERSE_MAP - assume that the source image is already in Log-Polar space, and transform back to cartesian space. The function emulates the human “foveal” vision and can be used for fast scale and rotation-invariant template matching, for object tracking and so forth.''') def cvLogPolar(np.ndarray src, center, double M, int flag=CV_INTER_LINEAR+CV_WARP_FILL_OUTLIERS): validate_array(src) if len(center) != 2: raise ValueError('center must be a 2-tuple') valid_flags = [0, 16, 8, 24, 1, 17, 9, 25, 2, 18, 10, 26, 3, 19, 11, 27] if flag not in valid_flags: raise ValueError('unsupported flag combination') cdef np.ndarray out = new_array_like(src) cdef CvPoint2D32f cv_center cv_center.x = center[0] cv_center.y = center[1] cdef IplImage srcimg cdef IplImage outimg populate_iplimage(src, &srcimg) populate_iplimage(out, &outimg) c_cvLogPolar(&srcimg, &outimg, cv_center, M, flag) return out #-------- # cvErode #-------- @cvdoc(package='cv', group='filter', doc=\ '''cvErode(src, element=None, iterations=1, anchor=None, in_place=False) Erode the source image with the given element. Parameters ---------- src : ndarray The source image. element : ndarray, 2D The structuring element. Must be 2D. Non-zero elements indicate which pixels of the underlying image to include in the operation as the element is slid over the image. If None, a 3x3 block element is used. iterations : integer The number of times to perform the operation. anchor: 2-tuple, (x, y) The anchor of the structuring element. Must be FULLY inside the element. If None, the center of the element is used. in_place: bool If True, perform the operation in place. Otherwise, store the results in a new image. Returns ------- out/None : ndarray or None An new array is returned only if in_place=False. Otherwise, this function returns None.''') def cvErode(np.ndarray src, np.ndarray element=None, int iterations=1, anchor=None, in_place=False): validate_array(src) cdef np.ndarray out cdef IplConvKernel* iplkernel if element == None: iplkernel = NULL else: iplkernel = get_IplConvKernel_ptr_from_array(element, anchor) if in_place: out = src else: out = new_array_like(src) cdef IplImage srcimg cdef IplImage outimg populate_iplimage(src, &srcimg) populate_iplimage(out, &outimg) c_cvErode(&srcimg, &outimg, iplkernel, iterations) free_IplConvKernel(iplkernel) if in_place: return None else: return out #--------- # cvDilate #--------- @cvdoc(package='cv', group='filter', doc=\ '''cvDilate(src, element=None, iterations=1, anchor=None, in_place=False) Dilate the source image with the given element. Parameters ---------- src : ndarray The source image. element : ndarray, 2D The structuring element. Must be 2D. Non-zero elements indicate which pixels of the underlying image to include in the operation as the element is slid over the image. If None, a 3x3 block element is used. iterations : integer The number of times to perform the operation. anchor: 2-tuple, (x, y) The anchor of the structuring element. Must be FULLY inside the element. If None, the center of the element is used. in_place: bool If True, perform the operation in place. Otherwise, store the results in a new image. Returns ------- out/None : ndarray or None An new array is returned only if in_place=False. Otherwise, this function returns None.''') def cvDilate(np.ndarray src, np.ndarray element=None, int iterations=1, anchor=None, in_place=False): validate_array(src) cdef np.ndarray out cdef IplConvKernel* iplkernel if element == None: iplkernel = NULL else: iplkernel = get_IplConvKernel_ptr_from_array(element, anchor) if in_place: out = src else: out = new_array_like(src) cdef IplImage srcimg cdef IplImage outimg populate_iplimage(src, &srcimg) populate_iplimage(out, &outimg) c_cvDilate(&srcimg, &outimg, iplkernel, iterations) free_IplConvKernel(iplkernel) if in_place: return None else: return out #--------------- # cvMorphologyEx #--------------- @cvdoc(package='cv', group='filter', doc=\ '''cvMorphologyEx(src, element, operation, iterations=1, anchor=None, in_place=False) Apply a morphological operation to the image. Parameters ---------- src : ndarray The source image. element : ndarray, 2D The structuring element. Must be 2D. Non-zero elements indicate which pixels of the underlying image to include in the operation as the element is slid over the image. Cannot be None. operation : flag The morphology operation to perform. Must be one of: CV_MOP_OPEN CV_MOP_CLOSE CV_MOP_GRADIENT CV_MOP_TOPHAT CV_MOP_BLACKHAT iterations : integer The number of times to perform the operation. anchor: 2-tuple, (x, y) The anchor of the structuring element. Must be FULLY inside the element. If None, the center of the element is used. in_place: bool If True, perform the operation in place. Otherwise, store the results in a new image. Returns ------- out/None : ndarray or None An new array is returned only if in_place=False. Otherwise, this function returns None.''') def cvMorphologyEx(np.ndarray src, np.ndarray element, int operation, int iterations=1, anchor=None, in_place=False): validate_array(src) cdef np.ndarray out cdef np.ndarray temp cdef IplConvKernel* iplkernel iplkernel = get_IplConvKernel_ptr_from_array(element, anchor) if in_place: out = src else: out = new_array_like(src) cdef IplImage srcimg cdef IplImage outimg cdef IplImage tempimg cdef IplImage* tempimgptr = &tempimg populate_iplimage(src, &srcimg) populate_iplimage(out, &outimg) # determine if we need the tempimg if operation == CV_MOP_OPEN or operation == CV_MOP_CLOSE: tempimgptr = NULL elif operation == CV_MOP_GRADIENT: temp = new_array_like(src) populate_iplimage(temp, &tempimg) elif operation == CV_MOP_TOPHAT or operation == CV_MOP_BLACKHAT: if in_place: temp = new_array_like(src) populate_iplimage(temp, &tempimg) else: tempimgptr = NULL else: raise RuntimeError('operation type not understood') c_cvMorphologyEx(&srcimg, &outimg, tempimgptr, iplkernel, operation, iterations) free_IplConvKernel(iplkernel) if in_place: return None else: return out #--------- # cvSmooth #--------- @cvdoc(package='cv', group='filter', doc=\ '''cvSmooth(src, smoothtype=CV_GAUSSIAN, param1=3, param2=0, param3=0., param4=0., in_place=False) Smooth an image with the specified filter. Parameters ---------- src : ndarray The source image. smoothtype : integer The flag representing which smoothing operation to perfom. See notes on restrictions. Must be one of: CV_BLUR_NO_SCALE CV_BLUR CV_GAUSSIAN CV_MEDIAN CV_BILATERAL param1 : integer See notes. param2 : integer See notes. param3 : float See notes. param4 : float See notes. in_place : bool If True, perform the operation in place. This is not supported for every combination of arguments. See notes. Returns ------- out/None : ndarray or None If in_place == True the function operates in place and returns None. Otherwise, the operation returns a new array that is the result of the smoothing operation. Notes ----- The following details the restrictions and argument interpretaions for each of the smoothing operations. CV_BLUR_NO_SCALE: Source image must be 2D and have dtype uint8, int8, or float32. param1 x param2 define the neighborhood over which the pixels are summed. If param2 is zero it is set equal to param1. param3 and param4 are ignored. in_place operation is not supported. CV_BLUR: Source image must have dtype uint8, int8, or float32. param1 x param2 define the neighborhood over which the pixels are summed. If param2 is zero it is set equal to param1. param3 and param4 are ignored. CV_GAUSSIAN: Source image must have dtype uint8, int8, or float32. param1 x param2 defines the size of the gaussian kernel. If param2 is zero it is set equal to param1. param3 is the standard deviation of the kernel. If param3 is zero, an optimum stddev is calculated based on the kernel size. If both param1 and param2 or zero, then an optimum kernel size is calculated based on param3. in_place operation is supported. CV_MEDIAN: Source image must have dtype uint8, or int8. param1 x param1 define the neigborhood over which to find the median. param2, param3, and param4 are ignored. in_place operation is not supported. CV_BILATERAL: Source image must have dtype uint8, or int8. param1 x param2 define the neighborhood. param3 defines the color stddev. param4 defines the space stddev. in_place operation is not supported. Using standard sigma for small kernels (3x3 to 7x7) gives better speed.''') def cvSmooth(np.ndarray src, int smoothtype=CV_GAUSSIAN, int param1=3, int param2=0, double param3=0, double param4=0, bint in_place=False): validate_array(src) cdef np.ndarray out # there are restrictions that must be placed on the data depending on # the smoothing operation requested # CV_BLUR_NO_SCALE if smoothtype == CV_BLUR_NO_SCALE: if in_place: raise RuntimeError('In place operation not supported with this ' 'filter') assert_dtype(src, [UINT8, INT8, FLOAT32]) assert_ndims(src, [2]) if src.dtype == FLOAT32: out = new_array_like(src) else: out = new_array_like_diff_dtype(src, INT16) # CV_BLUR and CV_GAUSSIAN elif smoothtype == CV_BLUR or smoothtype == CV_GAUSSIAN: assert_dtype(src, [UINT8, INT8, FLOAT32]) assert_nchannels(src, [1, 3]) if in_place: out = src else: out = new_array_like(src) # CV_MEDIAN and CV_BILATERAL else: assert_dtype(src, [UINT8, INT8]) assert_nchannels(src, [1, 3]) if in_place: raise RuntimeError('In place operation not supported with this ' 'filter') out = new_array_like(src) cdef IplImage srcimg cdef IplImage outimg populate_iplimage(src, &srcimg) populate_iplimage(out, &outimg) c_cvSmooth(&srcimg, &outimg, smoothtype, param1, param2, param3, param4) if in_place: return None else: return out #----------- # cvFilter2D #----------- @cvdoc(package='cv', group='filter', doc=\ '''cvFilter2D(src, kernel, anchor=None, in_place=False) Convolve an image with the given kernel. Parameters ---------- src : ndarray The source image. kernel : ndarray, 2D, dtype=float32 The kernel with which to convolve the image. anchor : 2-tuple, (x, y) The kernel anchor. in_place : bool If True, perform the operation in_place. Returns ------- out/None : ndarray or None If in_place is True, returns None. Otherwise a new array is returned which is the result of the convolution. Notes ----- This is a high performance function. OpenCV automatically determines, based on the size of the image and the kernel, whether it will faster to do the convolution in the spatial or the frequency domain, and behaves accordingly.''') def cvFilter2D(np.ndarray src, np.ndarray kernel, anchor=None, in_place=False): validate_array(src) validate_array(kernel) assert_ndims(kernel, [2]) assert_dtype(kernel, [FLOAT32]) cdef CvPoint cv_anchor if anchor is not None: assert len(anchor) == 2, 'anchor must be (x, y) tuple' cv_anchor.x = anchor[0] cv_anchor.y = anchor[1] assert (cv_anchor.x < kernel.shape[1]) and (cv_anchor.x >= 0) \ and (cv_anchor.y < kernel.shape[0]) and (cv_anchor.y >= 0), \ 'anchor point must be inside kernel' else: cv_anchor.x = (kernel.shape[1] / 2.) cv_anchor.y = (kernel.shape[0] / 2.) cdef np.ndarray out if in_place: out = src else: out = new_array_like(src) cdef IplImage srcimg cdef IplImage outimg cdef IplImage kernelimg populate_iplimage(src, &srcimg) populate_iplimage(out, &outimg) populate_iplimage(kernel, &kernelimg) cdef CvMat* cv_kernel cv_kernel = cvmat_ptr_from_iplimage(&kernelimg) c_cvFilter2D(&srcimg, &outimg, cv_kernel, cv_anchor) PyMem_Free(cv_kernel) if in_place: return None else: return out #----------- # cvIntegral #----------- @cvdoc(package='cv', group='transforms', doc=\ '''cvIntegral(src, square_sum=False, titled_sum=False) Calculate the integral of an image. Parameters ---------- src : ndarray, dtyp=[uint8, float32, float64] The source image. square_sum : bool If True, also returns the square sum. tilted_sum : bool If True, also returns the titled sum (45 degree tilt) Returns ------- [out1, out2, out3] : list of ndarray's Returns a list consisting at least of: out1: the integral image, and optionally: out2: the square sum image out3: the titled sum image, or any combination of these two.''') def cvIntegral(np.ndarray src, square_sum=False, tilted_sum=False): validate_array(src) assert_dtype(src, [UINT8, FLOAT32, FLOAT64]) out = [] cdef np.ndarray outsum cdef np.ndarray outsqsum cdef np.ndarray outtiltsum cdef IplImage srcimg cdef IplImage outsumimg cdef IplImage outsqsumimg cdef IplImage outtiltsumimg cdef IplImage* outsqsumimgptr = &outsqsumimg cdef IplImage* outtiltsumimgptr = &outtiltsumimg populate_iplimage(src, &srcimg) # out arrays need to be (H + 1) x (W + 1) cdef np.npy_intp* out_shape = clone_array_shape(src) out_shape[0] = src.shape[0] + 1 out_shape[1] = src.shape[1] + 1 cdef int out_dims = src.ndim if src.dtype == UINT8: outsum = new_array(out_dims, out_shape, INT32) else: outsum = new_array(out_dims, out_shape, FLOAT64) populate_iplimage(outsum, &outsumimg) out.append(outsum) if square_sum: outsqsum = new_array(out_dims, out_shape, FLOAT64) populate_iplimage(outsqsum, &outsqsumimg) out.append(outsqsum) else: outsqsumimgptr = NULL if tilted_sum: outtiltsum = new_array(out_dims, out_shape, outsum.dtype) populate_iplimage(outtiltsum, &outtiltsumimg) out.append(outtiltsum) else: outtiltsumimgptr = NULL c_cvIntegral(&srcimg, &outsumimg, outsqsumimgptr, outtiltsumimgptr) PyMem_Free(out_shape) return out #----------- # cvCvtColor #----------- @cvdoc(package='cv', group='transforms', doc=\ '''cvCvtColor(src, code) Convert an image to another color space. Parameters ---------- src : ndarray, dtype=[uint8, uint16, float32] The source image. code : integer A flag representing which color conversion to perform. Valid flags are the following: CV_BGR2BGRA, CV_RGB2RGBA, CV_BGRA2BGR, CV_RGBA2RGB, CV_BGR2RGBA, CV_RGB2BGRA, CV_RGBA2BGR, CV_BGRA2RGB, CV_BGR2RGB, CV_RGB2BGR, CV_BGRA2RGBA, CV_RGBA2BGRA, CV_BGR2GRAY, CV_RGB2GRAY, CV_GRAY2BGR, CV_GRAY2RGB, CV_GRAY2BGRA, CV_GRAY2RGBA, CV_BGRA2GRAY, CV_RGBA2GRAY, CV_BGR2BGR565, CV_RGB2BGR565, CV_BGR5652BGR, CV_BGR5652RGB, CV_BGRA2BGR565, CV_RGBA2BGR565, CV_BGR5652BGRA, CV_BGR5652RGBA, CV_GRAY2BGR565, CV_BGR5652GRAY, CV_BGR2BGR555, CV_RGB2BGR555, CV_BGR5552BGR, CV_BGR5552RGB, CV_BGRA2BGR555, CV_RGBA2BGR555, CV_BGR5552BGRA, CV_BGR5552RGBA, CV_GRAY2BGR555, CV_BGR5552GRAY, CV_BGR2XYZ, CV_RGB2XYZ, CV_XYZ2BGR, CV_XYZ2RGB, CV_BGR2YCrCb, CV_RGB2YCrCb, CV_YCrCb2BGR, CV_YCrCb2RGB, CV_BGR2HSV, CV_RGB2HSV, CV_BGR2Lab, CV_RGB2Lab, CV_BayerBG2BGR, CV_BayerGB2BGR, CV_BayerRG2BGR, CV_BayerGR2BGR, CV_BayerBG2RGB, CV_BayerGB2RGB, CV_BayerRG2RGB, CV_BayerGR2RGB, CV_BGR2Luv, CV_RGB2Luv, CV_BGR2HLS, CV_RGB2HLS, CV_HSV2BGR, CV_HSV2RGB, CV_Lab2BGR, CV_Lab2RGB, CV_Luv2BGR, CV_Luv2RGB, CV_HLS2BGR, CV_HLS2RGB Returns ------- out : ndarray A new image in the requested color-space, with an appropriate dtype. Notes ----- Not all conversion types support all dtypes. An exception will be raise if the dtype is not supported. See the OpenCV documentation for more details about the specific color conversions.''') def cvCvtColor(np.ndarray src, int code): validate_array(src) assert_dtype(src, [UINT8, UINT16, FLOAT32]) try: conversion_params = _cvtcolor_dict[code] except KeyError: print 'unknown conversion code' raise cdef int src_channels = conversion_params[0] cdef int out_channels = conversion_params[1] src_dtypes = conversion_params[2] assert_nchannels(src, [src_channels]) assert_dtype(src, src_dtypes) cdef np.ndarray out # the out array can be 2, 3, or 4 channels so we need shapes that # can handle either cdef np.npy_intp out_shape2[2] cdef np.npy_intp out_shape3[3] out_shape2[0] = src.shape[0] out_shape2[1] = src.shape[1] out_shape3[0] = src.shape[0] out_shape3[1] = src.shape[1] if out_channels == 1: out = new_array(2, out_shape2, src.dtype) else: out_shape3[2] = out_channels out = new_array(3, out_shape3, src.dtype) cdef IplImage srcimg cdef IplImage outimg populate_iplimage(src, &srcimg) populate_iplimage(out, &outimg) c_cvCvtColor(&srcimg, &outimg, code) return out #------------ # cvThreshold #------------ @cvdoc(package='cv', group='transforms', doc=\ '''cvThreshold(src, threshold, max_value=255, threshold_type=CV_THRESH_BINARY, use_otsu=False) Threshold an image. Parameters ---------- src : ndarray, 2D, dtype=[uint8, float32] threshold : float The threshold value. (decision value) max_value : float The maximum value. threshold_type : integer The flag representing which type of thresholding to apply. Valid flags are: CV_THRESH_BINARY (max_value if src(x,y) > threshold else 0) CV_THRESH_BINARY_INV (0 if src(x,y) > threshold else max_value) CV_THRESH_TRUNC (threshold if src(x,y) > threshold else src(x,y)) CV_THRESH_TOZERO (src(x,y) if src(x,y) > threshold else 0) CV_THRESH_TOZERO_INV (0 if src(x,y) > threshold else src(x,y)) use_otsu : bool If true, the optimum threshold is automatically computed and the passed in threshold value is ignored. Only implemented for uint8 source images. Returns ------- out/(out, threshold) : ndarray or (ndarray, float) If use_otsu is True, then the computed threshold value is returned in addition to the thresholded image. Otherwise just the thresholded image is returned.''') def cvThreshold(np.ndarray src, double threshold, double max_value=255, int threshold_type=CV_THRESH_BINARY, use_otsu=False): validate_array(src) assert_nchannels(src, [1]) assert_dtype(src, [UINT8, FLOAT32]) if use_otsu: assert_dtype(src, [UINT8]) threshold_type += 8 cdef np.ndarray out = new_array_like(src) cdef IplImage srcimg cdef IplImage outimg populate_iplimage(src, &srcimg) populate_iplimage(out, &outimg) threshold = c_cvThreshold(&srcimg, &outimg, threshold, max_value, threshold_type) if use_otsu: return (out, threshold) else: return out #-------------------- # cvAdaptiveThreshold #-------------------- @cvdoc(package='cv', group='transforms', doc=\ '''cvAdaptiveThreshold(src, max_value, adaptive_method=CV_ADAPTIVE_THRESH_MEAN_C, threshold_type=CV_THRESH_BINARY, block_size=3, param1=5) Apply an adaptive threshold to an image. Parameters ---------- src : ndarray, 2D, dtype=uint8 max_value : float The maximum value. adaptive_method : integer The flag representing the adaptive method. Valid flags are: CV_ADAPTIVE_THRESH_MEAN_C (uses mean of the neighborhood) CV_ADAPTIVE_THRESH_GAUSSIAN_C (uses gaussian of the neighborhood) threshold_type : integer The flag representing which type of thresholding to apply. Valid flags are: CV_THRESH_BINARY (max_value if src(x,y) > threshold else 0) CV_THRESH_BINARY_INV (0 if src(x,y) > threshold else max_value) block_size : integer Defines a block_size x block_size neighborhood param1 : float The weight to be subtracted from the neighborhood computation. Returns ------- out : ndarray The thresholded image.''') def cvAdaptiveThreshold(np.ndarray src, double max_value, int adaptive_method=CV_ADAPTIVE_THRESH_MEAN_C, int threshold_type=CV_THRESH_BINARY, int block_size=3, double param1=5): validate_array(src) assert_nchannels(src, [1]) assert_dtype(src, [UINT8]) if (adaptive_method!=CV_ADAPTIVE_THRESH_MEAN_C and adaptive_method!=CV_ADAPTIVE_THRESH_GAUSSIAN_C): raise ValueError('Invalid adaptive method') if (threshold_type!=CV_THRESH_BINARY and threshold_type!=CV_THRESH_BINARY_INV): raise ValueError('Invalid threshold type') if (block_size % 2 != 1 or block_size <= 1): raise ValueError('block size must be and odd number and greater than 1') cdef np.ndarray out = new_array_like(src) cdef IplImage srcimg cdef IplImage outimg populate_iplimage(src, &srcimg) populate_iplimage(out, &outimg) c_cvAdaptiveThreshold(&srcimg, &outimg, max_value, adaptive_method, threshold_type, block_size, param1) return out #---------- # cvPyrDown #---------- @cvdoc(package='cv', group='filter', doc=\ '''cvPyrDown(src) Downsample an image. Parameters ---------- src : ndarray, dtype=[uint8, uint16, float32, float64] Returns ------- out : ndarray Downsampled image half the size of the original in each dimension.''') def cvPyrDown(np.ndarray src): validate_array(src) assert_dtype(src, [UINT8, UINT16, FLOAT32, FLOAT64]) cdef int outdim = src.ndim cdef np.npy_intp* outshape = clone_array_shape(src) outshape[0] = (src.shape[0] + 1) / 2 outshape[1] = (src.shape[1] + 1) / 2 cdef np.ndarray out = new_array(outdim, outshape, src.dtype) cdef IplImage srcimg cdef IplImage outimg populate_iplimage(src, &srcimg) populate_iplimage(out, &outimg) c_cvPyrDown(&srcimg, &outimg, 7) PyMem_Free(outshape) return out #-------- # cvPyrUp #-------- @cvdoc(package='cv', group='filter', doc=\ '''cvPyrUp(src) Upsample an image. Parameters ---------- src : ndarray, dtype=[uint8, uint16, float32, float64] Returns ------- out : ndarray Upsampled image twice the size of the original in each dimension.''') def cvPyrUp(np.ndarray src): validate_array(src) assert_dtype(src, [UINT8, UINT16, FLOAT32, FLOAT64]) cdef int outdim = src.ndim cdef np.npy_intp* outshape = clone_array_shape(src) outshape[0] = (src.shape[0] * 2) outshape[1] = (src.shape[1] * 2) cdef np.ndarray out = new_array(outdim, outshape, src.dtype) cdef IplImage srcimg cdef IplImage outimg populate_iplimage(src, &srcimg) populate_iplimage(out, &outimg) c_cvPyrUp(&srcimg, &outimg, 7) PyMem_Free(outshape) return out #------------ # cvWatershed #------------ @cvdoc(package='cv', group='image', doc=\ '''cvWatershed(src, markers) Performs watershed segmentation. Parameters ---------- src : ndarray, 3D, dtype=uint8 The source image. markers : ndarray, 2D, dtype=int32 The markers identifying the regions of interest. Marker values should be non-zero. This array should have the same width and height as src. Returns ------- None : None The markers array is modified in place. The results of which identify the segmented regions of the image.''') def cvWatershed(src, markers): validate_array(src) validate_array(markers) assert_ndims(src, [3]) assert_dtype(src, [UINT8]) assert_ndims(markers, [2]) assert_dtype(markers, [INT32]) #assert src.shape[:2] == markers.shape[:2], \ # 'The src and markers array must have same width and height' cdef IplImage srcimg cdef IplImage markersimg populate_iplimage(src, &srcimg) populate_iplimage(markers, &markersimg) c_cvWatershed(&srcimg, &markersimg) return None #------------------- # cvCalibrateCamera2 #------------------- @cvdoc(package='cv', group='calibration', doc=\ '''cvCalibrateCamera2(object_points, image_points, point_counts, image_size) Finds the intrinsic and extrinsic camera parameters using a calibration pattern. Parameters ---------- object_points : ndarray, Nx3 An array representing the (X, Y, Z) known coordinates of the calibration object. image_points : ndarry, Nx2 An array representing the pixel image coordinate of the points in object_points. point_counts : ndarry, 1D, dtype=int32 Vector containing the number of points in each particular view. image_size : 2-tuple, (height, width) The height and width of the images used. Returns ------- (intrinsics, distortion) : ndarray 3x3, ndarray 5-vector Intrinsics is the 3x3 camera instrinsics matrix. Distortion is the 5-vector of distortion coefficients.''') def cvCalibrateCamera2(np.ndarray object_points, np.ndarray image_points, np.ndarray point_counts, image_size): # Validate input validate_array(object_points) assert_ndims(object_points, [2]) validate_array(image_points) assert_ndims(image_points, [2]) assert_dtype(point_counts, [INT32]) assert_ndims(point_counts, [1]) if not object_points.shape[1] == 3: raise ValueError("Object points must be Nx3") if not image_points.shape[1] == 2: raise ValueError("Image points must be Nx2") if not len(image_points) == len(object_points): raise ValueError("Must provide same number of image and object points.") if np.sum(point_counts) != len(image_points): raise ValueError("Point counts must sum to length of image_points " "(is %d must be %d)." % (np.sum(point_counts), len(image_points))) # Allocate a new intrinsics array cdef np.npy_intp intrinsics_shape[2] intrinsics_shape[0] = 3 intrinsics_shape[1] = 3 cdef np.ndarray intrinsics = new_array(2, intrinsics_shape, FLOAT64) cdef IplImage ipl_intrinsics populate_iplimage(intrinsics, &ipl_intrinsics) cdef CvMat* cvmat_intrinsics = cvmat_ptr_from_iplimage(&ipl_intrinsics) # Allocate a new distortion array cdef np.npy_intp distortion_shape[2] distortion_shape[0] = 1 distortion_shape[1] = 5 cdef np.ndarray distortion = new_array(2, distortion_shape, FLOAT64) cdef IplImage ipl_distortion populate_iplimage(distortion, &ipl_distortion) cdef CvMat* cvmat_distortion = cvmat_ptr_from_iplimage(&ipl_distortion) # Make the object & image points & npoints accessible for OpenCV cdef IplImage ipl_object_points, ipl_image_points, ipl_point_counts cdef CvMat* cvmat_object_points, *cvmat_image_points, *cvmat_point_counts populate_iplimage(object_points, &ipl_object_points) populate_iplimage(image_points, &ipl_image_points) populate_iplimage(point_counts, &ipl_point_counts) cvmat_object_points = cvmat_ptr_from_iplimage(&ipl_object_points) cvmat_image_points = cvmat_ptr_from_iplimage(&ipl_image_points) cvmat_point_counts = cvmat_ptr_from_iplimage(&ipl_point_counts) # Set image size cdef CvSize cv_image_size cv_image_size.height = image_size[0] cv_image_size.width = image_size[1] # Call the function c_cvCalibrateCamera2(cvmat_object_points, cvmat_image_points, cvmat_point_counts, cv_image_size, cvmat_intrinsics, cvmat_distortion, NULL, NULL, 0) # Convert distortion back into a vector distortion = np.PyArray_Squeeze(distortion) PyMem_Free(cvmat_intrinsics) PyMem_Free(cvmat_distortion) PyMem_Free(cvmat_object_points) PyMem_Free(cvmat_image_points) PyMem_Free(cvmat_point_counts) return intrinsics, distortion #------------- # cvUndistort2 #------------- @cvdoc(package='cv', group='calibration', doc=\ '''cvUndistort2(src, intrinsics, distortions, new_intrinsics=None) Undistorts an image given the camera intrinsics matrix and distortions vector. These values can be calculated using cvCalibrateCamera2. Parameters ---------- src : ndarray The image to undistort intrinsics : ndarray, 3x3, dtype=float64 The camera intrinsics matrix. distortions : ndarray, 5-vector, dtype=float64 The camera distortion coefficients. new_intrinsics : ndarray, 3x3, dtype=float64, optional Determine the subset of the source image that is visible after correction. Returns ------- out : ndarray The undistorted image the same size and dtype as the source image.''') def cvUndistort2(src, intrinsics, distortions, new_intrinsics=None): validate_array(src) assert_dtype(intrinsics, [FLOAT64]) assert_dtype(distortions, [FLOAT64]) assert_ndims(intrinsics, [2]) assert_ndims(distortions, [1]) if intrinsics.shape[0] != 3 or intrinsics.shape[1] != 3: raise ValueError('intrinsics must be 3x3') if distortions.shape[0] != 5: raise ValueError('distortions must be a 5-vector') cdef np.ndarray out = new_array_like(src) cdef IplImage srcimg cdef IplImage outimg cdef IplImage intrimg cdef IplImage distimg cdef IplImage new_intrinsics_img populate_iplimage(src, &srcimg) populate_iplimage(out, &outimg) populate_iplimage(intrinsics, &intrimg) populate_iplimage(distortions, &distimg) cdef CvMat* cvnew_intrinsics = NULL cdef CvMat* cvintr = cvmat_ptr_from_iplimage(&intrimg) cdef CvMat* cvdist = cvmat_ptr_from_iplimage(&distimg) if new_intrinsics is not None: populate_iplimage(new_intrinsics, &new_intrinsics_img) cvnew_intrinsics = cvmat_ptr_from_iplimage(&new_intrinsics_img) c_cvUndistort2(&srcimg, &outimg, cvintr, cvdist, cvnew_intrinsics) PyMem_Free(cvintr) PyMem_Free(cvdist) PyMem_Free(cvnew_intrinsics) return out #------------------------ # cvFindChessboardCorners #------------------------ @cvdoc(package='cv', group='calibration', doc=\ '''cvFindChessboardCorners(src, pattern_size, flag=CV_CALIB_CB_ADAPTIVE_THRESH) Finds the position of the internal corners of a chessboard. Parameters ---------- src : ndarray, dtype=uint8 Image to search for chessboard corners. pattern_size : 2-tuple of inner corners (h,w) flag : integer CV_CALIB_CB_ADAPTIVE_THRESH - use adaptive thresholding to convert the image to black and white, rather than a fixed threshold level (computed from the average image brightness). CV_CALIB_CB_NORMALIZE_IMAGE - normalize the image using cvNormalizeHist() before applying fixed or adaptive thresholding. CV_CALIB_CB_FILTER_QUADS - use additional criteria (like contour area, perimeter, square-like shape) to filter out false quads that are extracted at the contour retrieval stage. Returns ------- out : ndarray Nx2 An nx2 array of the corners found.''') def cvFindChessboardCorners(np.ndarray src, pattern_size, int flag=CV_CALIB_CB_ADAPTIVE_THRESH): validate_array(src) assert_nchannels(src, [1, 3]) assert_dtype(src, [UINT8]) cdef np.npy_intp outshape[2] outshape[0] = pattern_size[0] * pattern_size[1] outshape[1] = 2 cdef np.ndarray out out = new_array(2, outshape, FLOAT32) cdef CvPoint2D32f* cvpoints = array_as_cvPoint2D32f_ptr(out) cdef CvSize cvpattern_size cvpattern_size.height = pattern_size[0] cvpattern_size.width = pattern_size[1] cdef IplImage srcimg populate_iplimage(src, &srcimg) cdef int ncorners_found c_cvFindChessboardCorners(&srcimg, cvpattern_size, cvpoints, &ncorners_found, flag) return out[:ncorners_found] #----------------------------- # cvFindExtrinsicCameraParams2 #----------------------------- @cvdoc(package='cv', group='calibration', doc=\ '''cvFindExtrinsicCameraParams2(object_points, image_points, intrinsic_matrix, distortion_coeffs) Calculates the extrinsic camera parameters given a set of 3D points, their 2D locations in the image, and the camera instrinsics matrix and distortion coefficients. i.e. given this information, it calculates the offset and rotation of the camera from the chessboard origin. Parameters ---------- object_points: ndarray, nx3 The 3D coordinates of the chessboard corners. image_points: ndarray, nx2 The 2D image coordinates of the object_points intrinsic_matrix: ndarray, 3x3, dtype=float64 The 2D camera intrinsics matrix that is the result of camera calibration distortion_coeffs: ndarray, 5-vector, dtype=float64 The 5 distortion coefficients that are the result of camera calibration Returns ------- (rvec, tvec): ndarray 3-vector dtype=float64, ndarray 3-vector dtype=float64 rvec - the rotation vector representing the rotation of the camera relative to the chessboard. The direction of the vector represents the axis of rotation and its magnitude the amount of rotation. tvec - the translation vector representing the offset of the camera relative to the chessboard origin.''') def cvFindExtrinsicCameraParams2(object_points, image_points, intrinsic_matrix, distortion_coeffs): validate_array(object_points) validate_array(image_points) validate_array(intrinsic_matrix) assert_ndims(object_points, [2]) assert_dtype(object_points, [FLOAT32, FLOAT64]) assert object_points.shape[1] == 3, 'object_points should be nx3' assert_ndims(image_points, [2]) assert_dtype(image_points, [FLOAT32, FLOAT64]) assert image_points.shape[1] == 2, 'image_points should be nx2' assert_dtype(intrinsic_matrix, [FLOAT64]) assert intrinsic_matrix.shape == (3, 3), 'instrinsics should be 3x3' assert_dtype(distortion_coeffs, [FLOAT64]) assert distortion_coeffs.shape == (5,), 'distortions should be 5-vector' # allocate the numpy return arrays cdef np.npy_intp shape[1] shape[0] = 3 cdef np.ndarray rvec = new_array(1, shape, FLOAT64) cdef np.ndarray tvec = new_array(1, shape, FLOAT64) # allocate the cv images cdef IplImage obj_img cdef IplImage img_img cdef IplImage intr_img cdef IplImage dist_img cdef IplImage rot_img cdef IplImage tran_img populate_iplimage(object_points, &obj_img) populate_iplimage(image_points, &img_img) populate_iplimage(intrinsic_matrix, &intr_img) populate_iplimage(distortion_coeffs, &dist_img) populate_iplimage(rvec, &rot_img) populate_iplimage(tvec, &tran_img) # allocate the cv mats cdef CvMat* cvobj = cvmat_ptr_from_iplimage(&obj_img) cdef CvMat* cvimg = cvmat_ptr_from_iplimage(&img_img) cdef CvMat* cvint = cvmat_ptr_from_iplimage(&intr_img) cdef CvMat* cvdis = cvmat_ptr_from_iplimage(&dist_img) cdef CvMat* cvrot = cvmat_ptr_from_iplimage(&rot_img) cdef CvMat* cvtrn = cvmat_ptr_from_iplimage(&tran_img) # the last argument is new to OpenCV 2.0 and tells it NOT to use # an extrinsics guess c_cvFindExtrinsicCameraParams2(cvobj, cvimg, cvint, cvdis, cvrot, cvtrn, 0) PyMem_Free(cvobj) PyMem_Free(cvimg) PyMem_Free(cvint) PyMem_Free(cvdis) PyMem_Free(cvrot) PyMem_Free(cvtrn) return (rvec, tvec) #--------------------- # cvFindFundamentalMat #--------------------- @cvdoc(package='cv', group='calibration', doc=\ '''cvFindFundamentalMat(points1, points2, int method=CV_FM_RANSAC, double param1=1, double param2=0.99) Calculates the fundamental matrix from the corresponding points in two images. Parameters ---------- points1 : ndarray, Nx2 or Nx3, dtype=float Points from the first image. points2 : ndarray, Nx3 or Nx3, dtype=float Points from the second image (same length as ``points1``). method : integer CV_FM_7POINT - use 7-point algorithm (N = 7) CV_FM_8POINT - use 8-point algorithm (N = 8) CV_FM_RANSAC - use RANSAC algorithm (N >= 8) CV_FM_LMEDS - use LMedS algorithm (N >= 8) param1 : float In RANSAC, the maximum distance from point to epipolar lines (in pixels) beyond which the point is considered an outlier. param2 : float In RANSAC and LMedS, the level of confidence (probability) that the estimated matrix is correct. Returns ------- fundamental_matrix : ndarray, 3x3 or 3x3x3 Fundamental matrix. The 7-point method may return up to three matrices, stored as a 3x3x3 array. If no matrix could be found, None is returned. status : ndarray, length N, dtype=bool Currently, this is only a placeholder for future use. In future, should indicate whether a data-point is an inlier (True) or outlier (False). Only used by RANSAC and MLedS; other methods set all True.''') def cvFindFundamentalMat(points1, points2, int method=CV_FM_RANSAC, double param1=1, double param2=0.99): validate_array(points1) validate_array(points2) assert_ndims(points1, [2]) assert_ndims(points2, [2]) assert_dtype(points1, [FLOAT32, FLOAT64]) assert_dtype(points2, [FLOAT32, FLOAT64]) if not points1.shape[1] in (2, 3): raise ValueError("Points should be Nx2 or Nx3 arrays") if not method in (CV_FM_7POINT, CV_FM_8POINT, CV_FM_RANSAC, CV_FM_LMEDS): raise ValueError("Invalid method specified") if not points1.shape[0] == points2.shape[0]: raise ValueError("Points1 and points2 should be of equal length.") # allocate the numpy return arrays cdef np.npy_intp fundamental_shape[2] if (method == CV_FM_7POINT): fundamental_shape[0] = 9 else: fundamental_shape[0] = 3 fundamental_shape[1] = 3 cdef np.ndarray F = new_array(2, fundamental_shape, FLOAT64) ## The code snippet below creates the ``status`` matrix ## that may optionally be provided. I could not get this ## to work with OpenCV 2.1. cdef np.npy_intp status_shape[2] status_shape[0] = points1.shape[0] status_shape[1] = 1 cdef np.ndarray status = new_array(2, status_shape, UINT8) status.fill(0) ## cdef IplImage status_img ## populate_iplimage(status, &status_img) ## cdef CvMat* cvstatus = cvmat_ptr_from_iplimage(&status_img) # Allocate cv images cdef IplImage points1_img cdef IplImage points2_img cdef IplImage F_img populate_iplimage(points1, &points1_img) populate_iplimage(points2, &points2_img) populate_iplimage(F, &F_img) # Allocate cv matrices cdef CvMat* cvpoints1 = cvmat_ptr_from_iplimage(&points1_img) cdef CvMat* cvpoints2 = cvmat_ptr_from_iplimage(&points2_img) cdef CvMat* cvF = cvmat_ptr_from_iplimage(&F_img) cdef int m = c_cvFindFundamentalMat(cvpoints1, cvpoints2, cvF, method, param1, param2, NULL) PyMem_Free(cvpoints1) PyMem_Free(cvpoints2) PyMem_Free(cvF) # PyMem_Free(cvstatus) if m == 0: return (None, status) else: return (F.reshape((m, 3, 3)).squeeze(), status) #------------------------ # cvFindChessboardCorners #------------------------ @cvdoc(package='cv', group='calibration', doc=\ '''cvDrawChessboardCorners(src, pattern_size, corners, in_place=False) Renders found chessboard corners into an image. Parameters ---------- src : ndarray, dim 3, dtype: uint8 Image to draw into. pattern_size : 2-tuple, (h, w) Number of inner corners (h,w) corners : ndarray, nx2, dtype=float32 Corners found in the image. See cvFindChessboardCorners and cvFindCornerSubPix in_place: bool If true, perform the drawing on the submitted image. If false, a copy of the image will be made and drawn to. Returns ------- out/None : ndarray or none If in_place is True, the function returns None. Otherwise, the function returns a new image with the corners drawn into it.''') def cvDrawChessboardCorners(np.ndarray src, pattern_size, np.ndarray corners, in_place=False): validate_array(src) assert_nchannels(src, [3]) assert_dtype(src, [UINT8]) assert_ndims(corners, [2]) assert_dtype(corners, [FLOAT32]) cdef np.ndarray out if not in_place: out = src.copy() else: out = src cdef CvSize cvpattern_size cvpattern_size.height = pattern_size[0] cvpattern_size.width = pattern_size[1] cdef IplImage outimg populate_iplimage(out, &outimg) cdef CvPoint2D32f* cvcorners = array_as_cvPoint2D32f_ptr(corners) cdef int ncount = pattern_size[0] * pattern_size[1] cdef int pattern_was_found if corners.shape[0] == ncount: pattern_was_found = 1 else: pattern_was_found = 0 c_cvDrawChessboardCorners(&outimg, cvpattern_size, cvcorners, ncount, pattern_was_found) if in_place: return None else: return out #------------ # cvFloodFill #------------ @cvdoc(package='cv', group='image', doc=\ '''cvFloodFill(np.ndarray src, seed_point, new_val, low_diff, high_diff, mask=None, connect_diag=False, mask_only=False, mask_fillval=None, fixed_range=False) Fills a connected component with the given color. Parameters ---------- src : ndarray, ndims=[2, 3], dtypes[uint8, float32] The source image seed_point : (x, y) int tuple The starting point of the fill in image pixel coordinates. new_val : scalar double or 3-tuple (R, G, B) doubles The color value of the repainted area. If a scalar, the RGB values are all set equal to the scalar. low_diff : scalar double or 3-tuple (R, G, B) doubles Maximal lower brightness/color difference between the currently observed pixel and one of its neighbors belonging to the component, or a seed pixel being added to the component. Must be positive. high_diff : scalar double or 3-tuple (R, G, B) doubles Maximal upper brightness/color difference between the currently observed pixel and one of its neighbors belonging to the component, or a seed pixel being added to the component. Must be positive. mask : ndarray 2d, dtype=uint8 or None The mask in which to draw the results and/or use as a mask. See the opencv documentation for more details. If not None, the mask shape must be 2 pixels wider and taller than src. connect_diag : bool If True, implies connectivity across the diagonals in addition to the standard horizontal and vertical directions. mask_only : bool If True, fill the mask instead of the image. Mask must not be None mask_fillval : int 0 - 255 or None The value to fill the mask if mask is not None. If None, defaults to 1 fixed_range : bool If True, fills relative to seed value, else, fills relative to neighbors value. Returns ------- None : None This is an in-place operation which draws into src and/or image depending on the flags set in the input arguments''') def cvFloodFill(np.ndarray src, seed_point, new_val, low_diff, high_diff, mask=None, connect_diag=False, mask_only=False, mask_fillval=None, fixed_range=False): validate_array(src) assert_ndims(src, [2, 3]) assert_dtype(src, [UINT8, FLOAT32]) # src cdef IplImage srcimg populate_iplimage(src, &srcimg) # seed_point if len(seed_point) != 2: raise ValueError('seed_point should be an (x, y) tuple of ints') cdef CvPoint cv_seed_point cdef int x = seed_point[0] cdef int y = seed_point[1] cdef int xmax = src.shape[1] cdef int ymax = src.shape[0] if x < 0 or x > xmax or y < 0 or y > ymax: raise ValueError('seed_point must be image pixel coordinates') cv_seed_point.x = x cv_seed_point.y = y # loop counter cdef int i cdef double temp # new_val cdef CvScalar cv_new_val if hasattr(new_val, '__len__'): if len(new_val) != 3: raise ValueError('If not a scalar, new_val must be 3 tuple') for i in range(3): cv_new_val.val[i] = new_val[i] else: temp = new_val for i in range(3): cv_new_val.val[i] = temp # low_diff cdef CvScalar cv_low_diff if hasattr(low_diff, '__len__'): if len(low_diff) != 3: raise ValueError('If not a scalar, low_diff must be 3 tuple') for i in range(3): cv_low_diff.val[i] = low_diff[i] else: temp = low_diff for i in range(3): cv_low_diff.val[i] = temp # high_diff cdef CvScalar cv_high_diff if hasattr(high_diff, '__len__'): if len(high_diff) != 3: raise ValueError('If not a scalar, high_diff must be 3 tuple') for i in range(3): cv_high_diff.val[i] = high_diff[i] else: temp = high_diff for i in range(3): cv_high_diff.val[i] = temp # mask cdef IplImage maskimg cdef IplImage* maskimgptr = NULL if mask is not None: validate_array(mask) assert_ndims(mask, [2]) assert_dtype(mask, [UINT8]) if mask.shape[0] != (src.shape[0] + 2) or \ mask.shape[1] != (src.shape[1] + 2): raise ValueError('mask must be 2 pixels wider and taller than src.') populate_iplimage(mask, &maskimg) maskimgptr = &maskimg # flags cdef int flags # connect_diag cdef int cv_connect_diag = 4 if connect_diag: cv_connect_diag = 8 # mask_only cdef int cv_mask_only = 0 if mask_only: if mask is None: raise ValueError('If mask_only==True, mask must not be None') cv_mask_only = (1 << 17) # mask_fillval cdef int cv_mask_fillval = (1 << 8) if mask_fillval: if mask_fillval < 0 or mask_fillval > 255: raise ValueError('mask_fillval must be in range 0-255') cv_mask_fillval = ((mask_fillval) << 8) # fixed_range cdef int cv_fixed_range = 0 if fixed_range: cv_fixed_range = (1 << 16) flags = cv_connect_diag | cv_mask_only | cv_mask_fillval | cv_fixed_range c_cvFloodFill(&srcimg, cv_seed_point, cv_new_val, cv_low_diff, cv_high_diff, NULL, flags, maskimgptr) return None #---------------- # cvMatchTemplate #---------------- @cvdoc(package='cv', group='image', doc=\ '''cvMatchTemplate(src, template, method) Compares a template against overlapped image regions and returns a match array dependent on the match method requested. Parameters ---------- src : ndarray, ndims=[2, 3], dtype=[uint8, float32] The source image. template : ndarray, ndim=src.ndim, dtype=src.dtype The template to match in the source. method : int The method to use for matching. One of: CV_TM_SQDIFF CV_TM_SQDIFF_NORMED CV_TM_CCORR CV_TM_CCORR_NORMED CV_TM_CCOEFF CV_TM_CCOEFF_NORMED Returns ------- out : ndarray, 2d, dtype=float3d The results of the template matching. The size of this array (H - h + 1) x (W - w + 1) where (H, W) is (Height, Width) of src and (h, w) is (height, width) of template. Notes ----- After the function finishes the comparison, the best matches can be found as global minimums (CV_TM_SQDIFF) or maximums (CV_TM_CCORR and CV_TM_CCOEFF) using the appropriate numpy functions. In the case of a color image, template summation in the numerator and each sum in the denominator is done over all of the channels (and separate mean values are used for each channel).''') def cvMatchTemplate(np.ndarray src, np.ndarray template, int method): validate_array(src) validate_array(template) assert_ndims(src, [2, 3]) assert_dtype(src, [UINT8, FLOAT32]) assert_ndims(template, [src.ndim]) assert_dtype(template, [src.dtype]) if method not in [CV_TM_SQDIFF_NORMED, CV_TM_CCORR, CV_TM_CCORR_NORMED, CV_TM_CCOEFF, CV_TM_CCOEFF_NORMED]: raise ValueError('Unknown method type') if src.shape[0] <= template.shape[0] or src.shape[1] <= template.shape[1]: raise ValueError('template must be smaller than source image') cdef np.npy_intp outshape[2] outshape[0] = (src.shape[0] - template.shape[0] + 1) outshape[1] = (src.shape[1] - template.shape[1] + 1) cdef np.ndarray out = new_array(2, outshape, FLOAT32) cdef IplImage srcimg cdef IplImage templateimg cdef IplImage outimg populate_iplimage(src, &srcimg) populate_iplimage(template, &templateimg) populate_iplimage(out, &outimg) c_cvMatchTemplate(&srcimg, &templateimg, &outimg, method) return out