diff --git a/modules/calib3d/include/opencv2/calib3d/calib3d.hpp b/modules/calib3d/include/opencv2/calib3d/calib3d.hpp index 16fcd2bb33..47a4e124af 100644 --- a/modules/calib3d/include/opencv2/calib3d/calib3d.hpp +++ b/modules/calib3d/include/opencv2/calib3d/calib3d.hpp @@ -432,10 +432,7 @@ namespace cv { //! converts rotation vector to rotation matrix or vice versa using Rodrigues transformation -CV_EXPORTS_W void Rodrigues(const Mat& src, CV_OUT Mat& dst); - -//! converts rotation vector to rotation matrix or vice versa using Rodrigues transformation. Also computes the Jacobian matrix -CV_EXPORTS_AS(RodriguesJ) void Rodrigues(const Mat& src, CV_OUT Mat& dst, CV_OUT Mat& jacobian); +CV_EXPORTS_W void Rodrigues(const InputArray& src, OutputArray dst, OutputArray jacobian=OutputArray()); //! type of the robust estimation algorithm enum @@ -445,128 +442,93 @@ enum }; //! computes the best-fit perspective transformation mapping srcPoints to dstPoints. -CV_EXPORTS_AS(findHomographyAndOutliers) Mat findHomography( const Mat& srcPoints, - const Mat& dstPoints, - vector& mask, int method=0, - double ransacReprojThreshold=3 ); - -//! computes the best-fit perspective transformation mapping srcPoints to dstPoints. -CV_EXPORTS_W Mat findHomography( const Mat& srcPoints, - const Mat& dstPoints, - int method=0, double ransacReprojThreshold=3 ); - -//! computes the best-fit affine transformation that maps one 3D point set to another (RANSAC algorithm is used) -CV_EXPORTS int estimateAffine3D(const Mat& from, const Mat& to, CV_OUT Mat& dst, - CV_OUT vector& outliers, - double param1 = 3.0, double param2 = 0.99); +CV_EXPORTS_W Mat findHomography( const InputArray& srcPoints, + const InputArray& dstPoints, + int method=0, double ransacReprojThreshold=3, + OutputArray mask=OutputArray()); //! Computes RQ decomposition of 3x3 matrix -CV_EXPORTS void RQDecomp3x3( const Mat& M, Mat& R, Mat& Q ); - -//! Computes RQ decomposition of 3x3 matrix. Also, decomposes the output orthogonal matrix into the 3 primitive rotation matrices -CV_EXPORTS_W Vec3d RQDecomp3x3( const Mat& M, Mat& R, Mat& Q, - CV_OUT Mat& Qx, CV_OUT Mat& Qy, CV_OUT Mat& Qz ); +CV_EXPORTS_W Vec3d RQDecomp3x3( const InputArray& src, OutputArray mtxR, OutputArray mtxQ, + OutputArray Qx=OutputArray(), + OutputArray Qy=OutputArray(), + OutputArray Qz=OutputArray()); //! Decomposes the projection matrix into camera matrix and the rotation martix and the translation vector -CV_EXPORTS void decomposeProjectionMatrix( const Mat& projMatrix, Mat& cameraMatrix, - Mat& rotMatrix, Mat& transVect ); - -//! Decomposes the projection matrix into camera matrix and the rotation martix and the translation vector. The rotation matrix is further decomposed -CV_EXPORTS_W void decomposeProjectionMatrix( const Mat& projMatrix, CV_OUT Mat& cameraMatrix, - CV_OUT Mat& rotMatrix, CV_OUT Mat& transVect, - CV_OUT Mat& rotMatrixX, CV_OUT Mat& rotMatrixY, - CV_OUT Mat& rotMatrixZ, CV_OUT Vec3d& eulerAngles ); +CV_EXPORTS_W void decomposeProjectionMatrix( const InputArray& projMatrix, OutputArray cameraMatrix, + OutputArray rotMatrix, OutputArray transVect, + OutputArray rotMatrixX=OutputArray(), + OutputArray rotMatrixY=OutputArray(), + OutputArray rotMatrixZ=OutputArray(), + OutputArray eulerAngles=OutputArray() ); //! computes derivatives of the matrix product w.r.t each of the multiplied matrix coefficients -CV_EXPORTS_W void matMulDeriv( const Mat& A, const Mat& B, CV_OUT Mat& dABdA, CV_OUT Mat& dABdB ); - -//! composes 2 [R|t] transformations together -CV_EXPORTS_W void composeRT( const Mat& rvec1, const Mat& tvec1, - const Mat& rvec2, const Mat& tvec2, - CV_OUT Mat& rvec3, CV_OUT Mat& tvec3 ); +CV_EXPORTS_W void matMulDeriv( const InputArray& A, const InputArray& B, + OutputArray dABdA, + OutputArray dABdB ); //! composes 2 [R|t] transformations together. Also computes the derivatives of the result w.r.t the arguments -CV_EXPORTS_AS(composeRT_J) void composeRT( const Mat& rvec1, const Mat& tvec1, - const Mat& rvec2, const Mat& tvec2, - CV_OUT Mat& rvec3, CV_OUT Mat& tvec3, - CV_OUT Mat& dr3dr1, CV_OUT Mat& dr3dt1, - CV_OUT Mat& dr3dr2, CV_OUT Mat& dr3dt2, - CV_OUT Mat& dt3dr1, CV_OUT Mat& dt3dt1, - CV_OUT Mat& dt3dr2, CV_OUT Mat& dt3dt2 ); - -//! projects points from the model coordinate space to the image coordinates. Takes the intrinsic and extrinsic camera parameters into account -CV_EXPORTS_W void projectPoints( const Mat& objectPoints, - const Mat& rvec, const Mat& tvec, - const Mat& cameraMatrix, - const Mat& distCoeffs, - CV_OUT vector& imagePoints ); +CV_EXPORTS_W void composeRT( const InputArray& rvec1, const InputArray& tvec1, + const InputArray& rvec2, const InputArray& tvec2, + OutputArray rvec3, OutputArray tvec3, + OutputArray dr3dr1=OutputArray(), OutputArray dr3dt1=OutputArray(), + OutputArray dr3dr2=OutputArray(), OutputArray dr3dt2=OutputArray(), + OutputArray dt3dr1=OutputArray(), OutputArray dt3dt1=OutputArray(), + OutputArray dt3dr2=OutputArray(), OutputArray dt3dt2=OutputArray() ); //! projects points from the model coordinate space to the image coordinates. Also computes derivatives of the image coordinates w.r.t the intrinsic and extrinsic camera parameters -CV_EXPORTS_AS(projectPointsJ) void projectPoints( const Mat& objectPoints, - const Mat& rvec, const Mat& tvec, - const Mat& cameraMatrix, - const Mat& distCoeffs, - CV_OUT vector& imagePoints, - CV_OUT Mat& dpdrot, CV_OUT Mat& dpdt, CV_OUT Mat& dpdf, - CV_OUT Mat& dpdc, CV_OUT Mat& dpddist, - double aspectRatio=0 ); +CV_EXPORTS_W void projectPoints( const InputArray& objectPoints, + const InputArray& rvec, const InputArray& tvec, + const InputArray& cameraMatrix, const InputArray& distCoeffs, + OutputArray imagePoints, + OutputArray jacobian=OutputArray(), + double aspectRatio=0 ); //! computes the camera pose from a few 3D points and the corresponding projections. The outliers are not handled. -CV_EXPORTS_W void solvePnP( const Mat& objectPoints, - const Mat& imagePoints, - const Mat& cameraMatrix, - const Mat& distCoeffs, - CV_OUT Mat& rvec, CV_OUT Mat& tvec, +CV_EXPORTS_W void solvePnP( const InputArray& objectPoints, const InputArray& imagePoints, + const InputArray& cameraMatrix, const InputArray& distCoeffs, + OutputArray rvec, OutputArray tvec, bool useExtrinsicGuess=false ); //! computes the camera pose from a few 3D points and the corresponding projections. The outliers are possible. -CV_EXPORTS_W void solvePnPRansac( const Mat& objectPoints, - const Mat& imagePoints, - const Mat& cameraMatrix, - const Mat& distCoeffs, - CV_OUT Mat& rvec, - CV_OUT Mat& tvec, +CV_EXPORTS_W void solvePnPRansac( const InputArray& objectPoints, + const InputArray& imagePoints, + const InputArray& cameraMatrix, + const InputArray& distCoeffs, + OutputArray rvec, + OutputArray tvec, bool useExtrinsicGuess = false, int iterationsCount = 100, float reprojectionError = 8.0, int minInliersCount = 100, - CV_OUT vector* inliers = NULL ); + OutputArray inliers = OutputArray() ); //! initializes camera matrix from a few 3D points and the corresponding projections. -CV_EXPORTS_W Mat initCameraMatrix2D( const vector >& objectPoints, - const vector >& imagePoints, - Size imageSize, double aspectRatio=1. ); - +CV_EXPORTS_W Mat initCameraMatrix2D( const InputArrayOfArrays& objectPoints, + const InputArrayOfArrays& imagePoints, + Size imageSize, double aspectRatio=1. ); enum { CALIB_CB_ADAPTIVE_THRESH = 1, CALIB_CB_NORMALIZE_IMAGE = 2, CALIB_CB_FILTER_QUADS = 4, CALIB_CB_FAST_CHECK = 8 }; //! finds checkerboard pattern of the specified size in the image -CV_EXPORTS_W bool findChessboardCorners( const Mat& image, Size patternSize, - CV_OUT vector& corners, +CV_EXPORTS_W bool findChessboardCorners( const InputArray& image, Size patternSize, + OutputArray corners, int flags=CALIB_CB_ADAPTIVE_THRESH+ CALIB_CB_NORMALIZE_IMAGE ); //! finds subpixel-accurate positions of the chessboard corners -CV_EXPORTS bool find4QuadCornerSubpix(const Mat& img, std::vector& corners, - Size region_size); +CV_EXPORTS bool find4QuadCornerSubpix(const InputArray& img, InputOutputArray corners, Size region_size); //! draws the checkerboard pattern (found or partly found) in the image -CV_EXPORTS_W void drawChessboardCorners( Mat& image, Size patternSize, - const Mat& corners, - bool patternWasFound ); - -CV_EXPORTS void drawChessboardCorners( Mat& image, Size patternSize, - const vector& corners, - bool patternWasFound ); +CV_EXPORTS_W void drawChessboardCorners( InputOutputArray image, Size patternSize, + const InputArray& corners, bool patternWasFound ); enum { CALIB_CB_SYMMETRIC_GRID = 1, CALIB_CB_ASYMMETRIC_GRID = 2, CALIB_CB_CLUSTERING = 4, CALIB_CB_WHITE_CIRCLES = 8 }; //! finds circles' grid pattern of the specified size in the image -CV_EXPORTS_W bool findCirclesGrid( const Mat& image, Size patternSize, - CV_OUT vector& centers, - int flags=CALIB_CB_SYMMETRIC_GRID ); +CV_EXPORTS_W bool findCirclesGrid( const InputArray& image, Size patternSize, + OutputArray centers, int flags=CALIB_CB_SYMMETRIC_GRID ); enum { @@ -590,16 +552,16 @@ enum }; //! finds intrinsic and extrinsic camera parameters from several fews of a known calibration pattern. -CV_EXPORTS_W double calibrateCamera( const vector >& objectPoints, - const vector >& imagePoints, +CV_EXPORTS_W double calibrateCamera( const InputArrayOfArrays& objectPoints, + const InputArrayOfArrays& imagePoints, Size imageSize, - CV_IN_OUT Mat& cameraMatrix, - CV_IN_OUT Mat& distCoeffs, - CV_OUT vector& rvecs, CV_OUT vector& tvecs, + CV_IN_OUT InputOutputArray cameraMatrix, + CV_IN_OUT InputOutputArray distCoeffs, + OutputArray rvecs, OutputArray tvecs, int flags=0 ); //! computes several useful camera characteristics from the camera matrix, camera frame resolution and the physical sensor size. -CV_EXPORTS_W void calibrationMatrixValues( const Mat& cameraMatrix, +CV_EXPORTS_W void calibrationMatrixValues( const InputArray& cameraMatrix, Size imageSize, double apertureWidth, double apertureHeight, @@ -610,64 +572,58 @@ CV_EXPORTS_W void calibrationMatrixValues( const Mat& cameraMatrix, CV_OUT double& aspectRatio ); //! finds intrinsic and extrinsic parameters of a stereo camera -CV_EXPORTS_W double stereoCalibrate( const vector >& objectPoints, - const vector >& imagePoints1, - const vector >& imagePoints2, - CV_IN_OUT Mat& cameraMatrix1, CV_IN_OUT Mat& distCoeffs1, - CV_IN_OUT Mat& cameraMatrix2, CV_IN_OUT Mat& distCoeffs2, - Size imageSize, CV_OUT Mat& R, CV_OUT Mat& T, - CV_OUT Mat& E, CV_OUT Mat& F, +CV_EXPORTS_W double stereoCalibrate( const InputArrayOfArrays& objectPoints, + const InputArrayOfArrays& imagePoints1, + const InputArrayOfArrays& imagePoints2, + CV_IN_OUT InputOutputArray cameraMatrix1, + CV_IN_OUT InputOutputArray distCoeffs1, + CV_IN_OUT InputOutputArray cameraMatrix2, + CV_IN_OUT InputOutputArray distCoeffs2, + Size imageSize, OutputArray R, + OutputArray T, OutputArray E, OutputArray F, TermCriteria criteria = TermCriteria(TermCriteria::COUNT+ TermCriteria::EPS, 30, 1e-6), int flags=CALIB_FIX_INTRINSIC ); //! computes the rectification transformation for a stereo camera from its intrinsic and extrinsic parameters -CV_EXPORTS void stereoRectify( const Mat& cameraMatrix1, const Mat& distCoeffs1, - const Mat& cameraMatrix2, const Mat& distCoeffs2, - Size imageSize, const Mat& R, const Mat& T, - CV_OUT Mat& R1, CV_OUT Mat& R2, - CV_OUT Mat& P1, CV_OUT Mat& P2, CV_OUT Mat& Q, - int flags=CALIB_ZERO_DISPARITY ); - -//! computes the rectification transformation for a stereo camera from its intrinsic and extrinsic parameters -CV_EXPORTS_W void stereoRectify( const Mat& cameraMatrix1, const Mat& distCoeffs1, - const Mat& cameraMatrix2, const Mat& distCoeffs2, - Size imageSize, const Mat& R, const Mat& T, - CV_OUT Mat& R1, CV_OUT Mat& R2, - CV_OUT Mat& P1, CV_OUT Mat& P2, CV_OUT Mat& Q, - double alpha, Size newImageSize=Size(), - CV_OUT Rect* validPixROI1=0, CV_OUT Rect* validPixROI2=0, - int flags=CALIB_ZERO_DISPARITY ); +CV_EXPORTS void stereoRectify( const InputArray& cameraMatrix1, const InputArray& distCoeffs1, + const InputArray& cameraMatrix2, const InputArray& distCoeffs2, + Size imageSize, const InputArray& R, const InputArray& T, + OutputArray R1, OutputArray R2, + OutputArray P1, OutputArray P2, + OutputArray Q, int flags=CALIB_ZERO_DISPARITY, + double alpha=-1, Size newImageSize=Size(), + CV_OUT Rect* validPixROI1=0, CV_OUT Rect* validPixROI2=0 ); //! computes the rectification transformation for an uncalibrated stereo camera (zero distortion is assumed) -CV_EXPORTS_W bool stereoRectifyUncalibrated( const Mat& points1, const Mat& points2, - const Mat& F, Size imgSize, - CV_OUT Mat& H1, CV_OUT Mat& H2, +CV_EXPORTS_W bool stereoRectifyUncalibrated( const InputArray& points1, const InputArray& points2, + const InputArray& F, Size imgSize, + OutputArray H1, OutputArray H2, double threshold=5 ); //! computes the rectification transformations for 3-head camera, where all the heads are on the same line. -CV_EXPORTS_W float rectify3Collinear( const Mat& cameraMatrix1, const Mat& distCoeffs1, - const Mat& cameraMatrix2, const Mat& distCoeffs2, - const Mat& cameraMatrix3, const Mat& distCoeffs3, - const vector >& imgpt1, - const vector >& imgpt3, - Size imageSize, const Mat& R12, const Mat& T12, - const Mat& R13, const Mat& T13, - CV_OUT Mat& R1, CV_OUT Mat& R2, CV_OUT Mat& R3, - CV_OUT Mat& P1, CV_OUT Mat& P2, CV_OUT Mat& P3, CV_OUT Mat& Q, - double alpha, Size newImgSize, +CV_EXPORTS_W float rectify3Collinear( const InputArray& cameraMatrix1, const InputArray& distCoeffs1, + const InputArray& cameraMatrix2, const InputArray& distCoeffs2, + const InputArray& cameraMatrix3, const InputArray& distCoeffs3, + const InputArrayOfArrays& imgpt1, const InputArrayOfArrays& imgpt3, + Size imageSize, const InputArray& R12, const InputArray& T12, + const InputArray& R13, const InputArray& T13, + OutputArray R1, OutputArray R2, OutputArray R3, + OutputArray P1, OutputArray P2, OutputArray P3, + OutputArray Q, double alpha, Size newImgSize, CV_OUT Rect* roi1, CV_OUT Rect* roi2, int flags ); //! returns the optimal new camera matrix -CV_EXPORTS_W Mat getOptimalNewCameraMatrix( const Mat& cameraMatrix, const Mat& distCoeffs, +CV_EXPORTS_W Mat getOptimalNewCameraMatrix( const InputArray& cameraMatrix, const InputArray& distCoeffs, Size imageSize, double alpha, Size newImgSize=Size(), CV_OUT Rect* validPixROI=0); //! converts point coordinates from normal pixel coordinates to homogeneous coordinates ((x,y)->(x,y,1)) -CV_EXPORTS void convertPointsHomogeneous( const Mat& src, CV_OUT vector& dst ); +CV_EXPORTS void convertPointsToHomogeneous( const InputArray& src, OutputArray dst ); + //! converts point coordinates from homogeneous to normal pixel coordinates ((x,y,z)->(x/z, y/z)) -CV_EXPORTS void convertPointsHomogeneous( const Mat& src, CV_OUT vector& dst ); +CV_EXPORTS void convertPointsFromHomogeneous( const InputArray& src, OutputArray dst ); //! the algorithm for finding fundamental matrix enum @@ -679,19 +635,15 @@ enum }; //! finds fundamental matrix from a set of corresponding 2D points -CV_EXPORTS Mat findFundamentalMat( const Mat& points1, const Mat& points2, - CV_OUT vector& mask, int method=FM_RANSAC, - double param1=3., double param2=0.99 ); - -//! finds fundamental matrix from a set of corresponding 2D points -CV_EXPORTS_W Mat findFundamentalMat( const Mat& points1, const Mat& points2, +CV_EXPORTS_W Mat findFundamentalMat( const InputArray& points1, const InputArray& points2, int method=FM_RANSAC, - double param1=3., double param2=0.99 ); + double param1=3., double param2=0.99, + OutputArray mask=OutputArray()); //! finds coordinates of epipolar lines corresponding the specified points -CV_EXPORTS void computeCorrespondEpilines( const Mat& points1, - int whichImage, const Mat& F, - CV_OUT vector& lines ); +CV_EXPORTS void computeCorrespondEpilines( const InputArray& points1, + int whichImage, const InputArray& F, + OutputArray lines ); template<> CV_EXPORTS void Ptr::delete_obj(); @@ -713,7 +665,8 @@ public: //! the method that reinitializes the state. The previous content is destroyed void init(int preset, int ndisparities=0, int SADWindowSize=21); //! the stereo correspondence operator. Finds the disparity for the specified rectified stereo pair - CV_WRAP_AS(compute) void operator()( const Mat& left, const Mat& right, Mat& disparity, int disptype=CV_16S ); + CV_WRAP_AS(compute) void operator()( const InputArray& left, const InputArray& right, + OutputArray disparity, int disptype=CV_16S ); //! pointer to the underlying CvStereoBMState Ptr state; @@ -743,7 +696,8 @@ public: virtual ~StereoSGBM(); //! the stereo correspondence operator that computes disparity map for the specified rectified stereo pair - CV_WRAP_AS(compute) virtual void operator()(const Mat& left, const Mat& right, Mat& disp); + CV_WRAP_AS(compute) virtual void operator()(const InputArray& left, const InputArray& right, + OutputArray disp); CV_PROP_RW int minDisparity; CV_PROP_RW int numberOfDisparities; @@ -762,7 +716,8 @@ protected: }; //! filters off speckles (small regions of incorrectly computed disparity) -CV_EXPORTS_W void filterSpeckles( Mat& img, double newVal, int maxSpeckleSize, double maxDiff, Mat& buf ); +CV_EXPORTS_W void filterSpeckles( InputOutputArray img, double newVal, int maxSpeckleSize, double maxDiff, + InputOutputArray buf=InputOutputArray() ); //! computes valid disparity ROI from the valid ROIs of the rectified images (that are returned by cv::stereoRectify()) CV_EXPORTS_W Rect getValidDisparityROI( Rect roi1, Rect roi2, @@ -770,16 +725,20 @@ CV_EXPORTS_W Rect getValidDisparityROI( Rect roi1, Rect roi2, int SADWindowSize ); //! validates disparity using the left-right check. The matrix "cost" should be computed by the stereo correspondence algorithm -CV_EXPORTS_W void validateDisparity( Mat& disparity, const Mat& cost, +CV_EXPORTS_W void validateDisparity( InputOutputArray disparity, const InputArray& cost, int minDisparity, int numberOfDisparities, int disp12MaxDisp=1 ); //! reprojects disparity image to 3D: (x,y,d)->(X,Y,Z) using the matrix Q returned by cv::stereoRectify -CV_EXPORTS_W void reprojectImageTo3D( const Mat& disparity, - CV_OUT Mat& _3dImage, const Mat& Q, +CV_EXPORTS_W void reprojectImageTo3D( const InputArray& disparity, + OutputArray _3dImage, const InputArray& Q, bool handleMissingValues=false, int ddepth=-1 ); +CV_EXPORTS_W int estimateAffine3D(const InputArray& _from, const InputArray& _to, + OutputArray _out, OutputArray _outliers, + double param1=3, double param2=0.99); + } #endif diff --git a/modules/calib3d/src/calibinit.cpp b/modules/calib3d/src/calibinit.cpp index afb223186d..15645b87fe 100644 --- a/modules/calib3d/src/calibinit.cpp +++ b/modules/calib3d/src/calibinit.cpp @@ -1894,49 +1894,43 @@ cvDrawChessboardCorners( CvArr* _image, CvSize pattern_size, } } -namespace cv -{ - -bool findChessboardCorners( const Mat& image, Size patternSize, - vector& corners, int flags ) +bool cv::findChessboardCorners( const InputArray& _image, Size patternSize, + OutputArray corners, int flags ) { int count = patternSize.area()*2; - corners.resize(count); - CvMat _image = image; - bool ok = cvFindChessboardCorners(&_image, patternSize, - (CvPoint2D32f*)&corners[0], &count, flags ) > 0; - if(count >= 0) - corners.resize(count); + vector tmpcorners(count+1); + CvMat c_image = _image.getMat(); + bool ok = cvFindChessboardCorners(&c_image, patternSize, + (CvPoint2D32f*)&tmpcorners[0], &count, flags ) > 0; + if( count > 0 ) + { + tmpcorners.resize(count); + Mat(tmpcorners).copyTo(corners); + } + else + corners.release(); return ok; } -void drawChessboardCorners( Mat& image, Size patternSize, - const Mat& corners, +void cv::drawChessboardCorners( InputOutputArray _image, Size patternSize, + const InputArray& _corners, bool patternWasFound ) { - if( corners.cols == 0 || corners.rows == 0 ) + Mat corners = _corners.getMat(); + if( !corners.empty() ) return; - CvMat _image = image; + CvMat c_image = _image.getMat(); int nelems = corners.checkVector(2, CV_32F, true); CV_Assert(nelems >= 0); - cvDrawChessboardCorners( &_image, patternSize, (CvPoint2D32f*)corners.data, + cvDrawChessboardCorners( &c_image, patternSize, (CvPoint2D32f*)corners.data, nelems, patternWasFound ); } - -void drawChessboardCorners( Mat& image, Size patternSize, - const vector& corners, - bool patternWasFound ) -{ - if( corners.empty() ) - return; - CvMat _image = image; - cvDrawChessboardCorners( &_image, patternSize, (CvPoint2D32f*)&corners[0], - (int)corners.size(), patternWasFound ); -} -bool findCirclesGrid( const Mat& image, Size patternSize, - vector& centers, int flags ) +bool cv::findCirclesGrid( const InputArray& _image, Size patternSize, + OutputArray _centers, int flags ) { + Mat image = _image.getMat(); + vector centers; SimpleBlobDetector::Params params; if(flags & CALIB_CB_WHITE_CIRCLES) { @@ -1957,6 +1951,7 @@ bool findCirclesGrid( const Mat& image, Size patternSize, { CirclesGridClusterFinder circlesGridClusterFinder; circlesGridClusterFinder.findGrid(points, patternSize, centers); + Mat(centers).copyTo(_centers); return !centers.empty(); } @@ -2005,10 +2000,10 @@ bool findCirclesGrid( const Mat& image, Size patternSize, if (i != 0) { Mat orgPointsMat; - transform(Mat(centers), orgPointsMat, H.inv()); - convertPointsHomogeneous(orgPointsMat, centers); + transform(centers, orgPointsMat, H.inv()); + convertPointsFromHomogeneous(orgPointsMat, centers); } - + Mat(centers).copyTo(_centers); return true; } @@ -2020,10 +2015,8 @@ bool findCirclesGrid( const Mat& image, Size patternSize, H = CirclesGridFinder::rectifyGrid(boxFinder.getDetectedGridSize(), centers, points, points); } } - + Mat(centers).copyTo(_centers); return false; } -} - /* End of file. */ diff --git a/modules/calib3d/src/calibration.cpp b/modules/calib3d/src/calibration.cpp index 695664e664..bb364f0113 100644 --- a/modules/calib3d/src/calibration.cpp +++ b/modules/calib3d/src/calibration.cpp @@ -2753,10 +2753,11 @@ CV_IMPL int cvStereoRectifyUncalibrated( } -void cv::reprojectImageTo3D( const Mat& disparity, - Mat& _3dImage, const Mat& Q, +void cv::reprojectImageTo3D( const InputArray& _disparity, + OutputArray __3dImage, const InputArray& _Qmat, bool handleMissingValues, int dtype ) { + Mat disparity = _disparity.getMat(), Q = _Qmat.getMat(); int stype = disparity.type(); CV_Assert( stype == CV_8UC1 || stype == CV_16SC1 || @@ -2771,7 +2772,8 @@ void cv::reprojectImageTo3D( const Mat& disparity, CV_Assert( dtype == CV_16SC3 || dtype == CV_32SC3 || dtype == CV_32FC3 ); } - _3dImage.create(disparity.size(), CV_MAKETYPE(dtype, 3)); + __3dImage.create(disparity.size(), CV_MAKETYPE(dtype, 3)); + Mat _3dImage = __3dImage.getMat(); const double bigZ = 10000.; double q[4][4]; @@ -3092,45 +3094,56 @@ cvDecomposeProjectionMatrix( const CvMat *projMatr, CvMat *calibMatr, namespace cv { -static void collectCalibrationData( const vector >& objectPoints, - const vector >& imagePoints, - const vector >& imagePoints2, - Mat& objPtMat, Mat& imgPtMat, Mat* imgPtMat2, +static void collectCalibrationData( const InputArrayOfArrays& objectPoints, + const InputArrayOfArrays& imagePoints1, + const InputArrayOfArrays& imagePoints2, + Mat& objPtMat, Mat& imgPtMat1, Mat* imgPtMat2, Mat& npoints ) { - size_t i, j = 0, ni = 0, nimages = objectPoints.size(), total = 0; - CV_Assert(nimages > 0 && nimages == imagePoints.size() && - (!imgPtMat2 || nimages == imagePoints2.size())); + int nimages = (int)objectPoints.total(); + int i, j = 0, ni = 0, total = 0; + CV_Assert(nimages > 0 && nimages == (int)imagePoints1.total() && + (!imgPtMat2 || nimages == (int)imagePoints2.total())); for( i = 0; i < nimages; i++ ) { - ni = objectPoints[i].size(); - CV_Assert(ni == imagePoints[i].size() && (!imgPtMat2 || ni == imagePoints2[i].size())); + ni = objectPoints.getMat(i).checkVector(3, CV_32F); + CV_Assert( ni >= 0 ); total += ni; } npoints.create(1, (int)nimages, CV_32S); - objPtMat.create(1, (int)total, DataType::type); - imgPtMat.create(1, (int)total, DataType::type); + objPtMat.create(1, (int)total, CV_32FC3); + imgPtMat1.create(1, (int)total, CV_32FC2); Point2f* imgPtData2 = 0; if( imgPtMat2 ) { - imgPtMat2->create(1, (int)total, DataType::type); + imgPtMat2->create(1, (int)total, CV_32FC2); imgPtData2 = imgPtMat2->ptr(); } Point3f* objPtData = objPtMat.ptr(); - Point2f* imgPtData = imgPtMat.ptr(); + Point2f* imgPtData1 = imgPtMat1.ptr(); for( i = 0; i < nimages; i++, j += ni ) { - ni = objectPoints[i].size(); - ((int*)npoints.data)[i] = (int)ni; - std::copy(objectPoints[i].begin(), objectPoints[i].end(), objPtData + j); - std::copy(imagePoints[i].begin(), imagePoints[i].end(), imgPtData + j); - if( imgPtMat2 ) - std::copy(imagePoints2[i].begin(), imagePoints2[i].end(), imgPtData2 + j); + Mat objpt = objectPoints.getMat(i); + Mat imgpt1 = imagePoints1.getMat(i); + ni = objpt.checkVector(3, CV_32F); + int ni1 = imgpt1.checkVector(2, CV_32F); + CV_Assert( ni > 0 && ni == ni1 ); + npoints.at(i) = ni; + memcpy( objPtData + j, objpt.data, ni*sizeof(objPtData[0]) ); + memcpy( imgPtData1 + j, imgpt1.data, ni*sizeof(imgPtData1[0]) ); + + if( imgPtData2 ) + { + Mat imgpt2 = imagePoints2.getMat(i); + int ni2 = imgpt2.checkVector(2, CV_32F); + CV_Assert( ni == ni2 ); + memcpy( imgPtData2 + j, imgpt2.data, ni*sizeof(imgPtData2[0]) ); + } } } @@ -3162,126 +3175,153 @@ static Mat prepareDistCoeffs(Mat& distCoeffs0, int rtype) } -void cv::Rodrigues(const Mat& src, Mat& dst) +void cv::Rodrigues(const InputArray& _src, OutputArray _dst, OutputArray _jacobian) { + Mat src = _src.getMat(); bool v2m = src.cols == 1 || src.rows == 1; - dst.create(3, v2m ? 3 : 1, src.depth()); - CvMat _src = src, _dst = dst; - bool ok = cvRodrigues2(&_src, &_dst, 0) > 0; - if( !ok ) - dst = Scalar(0); -} - -void cv::Rodrigues(const Mat& src, Mat& dst, Mat& jacobian) -{ - bool v2m = src.cols == 1 || src.rows == 1; - dst.create(3, v2m ? 3 : 1, src.depth()); - jacobian.create(v2m ? Size(9, 3) : Size(3, 9), src.depth()); - CvMat _src = src, _dst = dst, _jacobian = jacobian; - bool ok = cvRodrigues2(&_src, &_dst, &_jacobian) > 0; + _dst.create(3, v2m ? 3 : 1, src.depth()); + Mat dst = _dst.getMat(); + CvMat _csrc = src, _cdst = dst, _cjacobian; + if( _jacobian.needed() ) + { + _jacobian.create(v2m ? Size(9, 3) : Size(3, 9), src.depth()); + _cjacobian = _jacobian.getMat(); + } + bool ok = cvRodrigues2(&_csrc, &_cdst, _jacobian.needed() ? &_cjacobian : 0) > 0; if( !ok ) dst = Scalar(0); } -void cv::matMulDeriv( const Mat& A, const Mat& B, Mat& dABdA, Mat& dABdB ) -{ - dABdA.create(A.rows*B.cols, A.rows*A.cols, A.type()); - dABdB.create(A.rows*B.cols, B.rows*B.cols, A.type()); - CvMat matA = A, matB = B, _dABdA = dABdA, _dABdB = dABdB; - cvCalcMatMulDeriv(&matA, &matB, &_dABdA, &_dABdB); -} - -void cv::composeRT( const Mat& rvec1, const Mat& tvec1, - const Mat& rvec2, const Mat& tvec2, - Mat& rvec3, Mat& tvec3 ) +void cv::matMulDeriv( const InputArray& _Amat, const InputArray& _Bmat, + OutputArray _dABdA, OutputArray _dABdB ) { - rvec3.create(rvec1.size(), rvec1.type()); - tvec3.create(tvec1.size(), tvec1.type()); - CvMat _rvec1 = rvec1, _tvec1 = tvec1, _rvec2 = rvec2, - _tvec2 = tvec2, _rvec3 = rvec3, _tvec3 = tvec3; - cvComposeRT(&_rvec1, &_tvec1, &_rvec2, &_tvec2, &_rvec3, &_tvec3, 0, 0, 0, 0, 0, 0, 0, 0); + Mat A = _Amat.getMat(), B = _Bmat.getMat(); + _dABdA.create(A.rows*B.cols, A.rows*A.cols, A.type()); + _dABdB.create(A.rows*B.cols, B.rows*B.cols, A.type()); + CvMat matA = A, matB = B, c_dABdA = _dABdA.getMat(), c_dABdB = _dABdB.getMat(); + cvCalcMatMulDeriv(&matA, &matB, &c_dABdA, &c_dABdB); } -void cv::composeRT( const Mat& rvec1, const Mat& tvec1, - const Mat& rvec2, const Mat& tvec2, - Mat& rvec3, Mat& tvec3, - Mat& dr3dr1, Mat& dr3dt1, - Mat& dr3dr2, Mat& dr3dt2, - Mat& dt3dr1, Mat& dt3dt1, - Mat& dt3dr2, Mat& dt3dt2 ) +void cv::composeRT( const InputArray& _rvec1, const InputArray& _tvec1, + const InputArray& _rvec2, const InputArray& _tvec2, + OutputArray _rvec3, OutputArray _tvec3, + OutputArray _dr3dr1, OutputArray _dr3dt1, + OutputArray _dr3dr2, OutputArray _dr3dt2, + OutputArray _dt3dr1, OutputArray _dt3dt1, + OutputArray _dt3dr2, OutputArray _dt3dt2 ) { + Mat rvec1 = _rvec1.getMat(), tvec1 = _tvec1.getMat(); + Mat rvec2 = _rvec2.getMat(), tvec2 = _tvec2.getMat(); int rtype = rvec1.type(); - rvec3.create(rvec1.size(), rtype); - tvec3.create(tvec1.size(), rtype); - dr3dr1.create(3, 3, rtype); dr3dt1.create(3, 3, rtype); - dr3dr2.create(3, 3, rtype); dr3dt2.create(3, 3, rtype); - dt3dr1.create(3, 3, rtype); dt3dt1.create(3, 3, rtype); - dt3dr2.create(3, 3, rtype); dt3dt2.create(3, 3, rtype); - - CvMat _rvec1 = rvec1, _tvec1 = tvec1, _rvec2 = rvec2, - _tvec2 = tvec2, _rvec3 = rvec3, _tvec3 = tvec3; - CvMat _dr3dr1 = dr3dr1, _dr3dt1 = dr3dt1, _dr3dr2 = dr3dr2, _dr3dt2 = dr3dt2; - CvMat _dt3dr1 = dt3dr1, _dt3dt1 = dt3dt1, _dt3dr2 = dt3dr2, _dt3dt2 = dt3dt2; - cvComposeRT(&_rvec1, &_tvec1, &_rvec2, &_tvec2, &_rvec3, &_tvec3, - &_dr3dr1, &_dr3dt1, &_dr3dr2, &_dr3dt2, - &_dt3dr1, &_dt3dt1, &_dt3dr2, &_dt3dt2); -} - - -void cv::projectPoints( const Mat& opoints, - const Mat& rvec, const Mat& tvec, - const Mat& cameraMatrix, - const Mat& distCoeffs, - vector& ipoints ) -{ - CV_Assert(opoints.isContinuous() && opoints.depth() == CV_32F && - ((opoints.rows == 1 && opoints.channels() == 3) || - opoints.cols*opoints.channels() == 3)); + _rvec3.create(rvec1.size(), rtype); + _tvec3.create(tvec1.size(), rtype); + Mat rvec3 = _rvec3.getMat(), tvec3 = _tvec3.getMat(); + + CvMat c_rvec1 = rvec1, c_tvec1 = tvec1, c_rvec2 = rvec2, + c_tvec2 = tvec2, c_rvec3 = rvec3, c_tvec3 = tvec3; + CvMat c_dr3dr1, c_dr3dt1, c_dr3dr2, c_dr3dt2, c_dt3dr1, c_dt3dt1, c_dt3dr2, c_dt3dt2; + CvMat *p_dr3dr1=0, *p_dr3dt1=0, *p_dr3dr2=0, *p_dr3dt2=0, *p_dt3dr1=0, *p_dt3dt1=0, *p_dt3dr2=0, *p_dt3dt2=0; + + if( _dr3dr1.needed() ) + { + _dr3dr1.create(3, 3, rtype); + p_dr3dr1 = &(c_dr3dr1 = _dr3dr1.getMat()); + } + + if( _dr3dt1.needed() ) + { + _dr3dt1.create(3, 3, rtype); + p_dr3dt1 = &(c_dr3dt1 = _dr3dt1.getMat()); + } + + if( _dr3dr2.needed() ) + { + _dr3dr2.create(3, 3, rtype); + p_dr3dr2 = &(c_dr3dr2 = _dr3dr2.getMat()); + } + + if( _dr3dt2.needed() ) + { + _dr3dt2.create(3, 3, rtype); + p_dr3dt2 = &(c_dr3dt2 = _dr3dt2.getMat()); + } + + if( _dt3dr1.needed() ) + { + _dt3dr1.create(3, 3, rtype); + p_dt3dr1 = &(c_dt3dr1 = _dt3dr1.getMat()); + } + + if( _dt3dt1.needed() ) + { + _dt3dt1.create(3, 3, rtype); + p_dt3dt1 = &(c_dt3dt1 = _dt3dt1.getMat()); + } + + if( _dt3dr2.needed() ) + { + _dt3dr2.create(3, 3, rtype); + p_dt3dr2 = &(c_dt3dr2 = _dt3dr2.getMat()); + } - ipoints.resize(opoints.cols*opoints.rows*opoints.channels()/3); - CvMat _objectPoints = opoints, _imagePoints = Mat(ipoints); - CvMat _rvec = rvec, _tvec = tvec, _cameraMatrix = cameraMatrix, _distCoeffs = distCoeffs; + if( _dt3dt2.needed() ) + { + _dt3dt2.create(3, 3, rtype); + p_dt3dt2 = &(c_dt3dt2 = _dt3dt2.getMat()); + } - cvProjectPoints2( &_objectPoints, &_rvec, &_tvec, &_cameraMatrix, - distCoeffs.data ? &_distCoeffs : 0, - &_imagePoints, 0, 0, 0, 0, 0, 0 ); + cvComposeRT(&c_rvec1, &c_tvec1, &c_rvec2, &c_tvec2, &c_rvec3, &c_tvec3, + p_dr3dr1, p_dr3dt1, p_dr3dr2, p_dr3dt2, + p_dt3dr1, p_dt3dt1, p_dt3dr2, p_dt3dt2); } -void cv::projectPoints( const Mat& opoints, - const Mat& rvec, const Mat& tvec, - const Mat& cameraMatrix, - const Mat& distCoeffs, - vector& ipoints, - Mat& dpdrot, Mat& dpdt, Mat& dpdf, - Mat& dpdc, Mat& dpddist, + +void cv::projectPoints( const InputArray& _opoints, + const InputArray& _rvec, + const InputArray& _tvec, + const InputArray& _cameraMatrix, + const InputArray& _distCoeffs, + OutputArray _ipoints, + OutputArray _jacobian, double aspectRatio ) { - CV_Assert(opoints.isContinuous() && opoints.depth() == CV_32F && - ((opoints.rows == 1 && opoints.channels() == 3) || - opoints.cols*opoints.channels() == 3)); - - int npoints = opoints.cols*opoints.rows*opoints.channels()/3; - ipoints.resize(npoints); - dpdrot.create(npoints*2, 3, CV_64F); - dpdt.create(npoints*2, 3, CV_64F); - dpdf.create(npoints*2, 2, CV_64F); - dpdc.create(npoints*2, 2, CV_64F); - dpddist.create(npoints*2, distCoeffs.rows + distCoeffs.cols - 1, CV_64F); - CvMat _objectPoints = opoints, _imagePoints = Mat(ipoints); - CvMat _rvec = rvec, _tvec = tvec, _cameraMatrix = cameraMatrix, _distCoeffs = distCoeffs; - CvMat _dpdrot = dpdrot, _dpdt = dpdt, _dpdf = dpdf, _dpdc = dpdc, _dpddist = dpddist; - - cvProjectPoints2( &_objectPoints, &_rvec, &_tvec, &_cameraMatrix, &_distCoeffs, - &_imagePoints, &_dpdrot, &_dpdt, &_dpdf, &_dpdc, &_dpddist, aspectRatio ); + Mat opoints = _opoints.getMat(); + int npoints = opoints.checkVector(3), depth = opoints.depth(); + CV_Assert(npoints >= 0 && (depth == CV_32F || depth == CV_64F)); + + CvMat dpdrot, dpdt, dpdf, dpdc, dpddist; + CvMat *pdpdrot=0, *pdpdt=0, *pdpdf=0, *pdpdc=0, *pdpddist=0; + + _ipoints.create(npoints, 1, CV_MAKETYPE(depth, 2), -1, true); + CvMat imagePoints = _ipoints.getMat(); + CvMat objectPoints = opoints; + CvMat cameraMatrix = _cameraMatrix.getMat(); + CvMat rvec = _rvec.getMat(), tvec = _tvec.getMat(); + CvMat distCoeffs = _distCoeffs.getMat(); + int ndistCoeffs = distCoeffs.rows + distCoeffs.cols - 1; + + if( _jacobian.needed() ) + { + _jacobian.create(npoints*2, 3+3+2+2+ndistCoeffs, CV_64F); + Mat jacobian = _jacobian.getMat(); + pdpdrot = &(dpdrot = jacobian.colRange(0, 3)); + pdpdt = &(dpdt = jacobian.colRange(3, 6)); + pdpdf = &(dpdf = jacobian.colRange(6, 8)); + pdpdc = &(dpdc = jacobian.colRange(8, 10)); + pdpddist = &(dpddist = jacobian.colRange(10, 10+ndistCoeffs)); + } + + cvProjectPoints2( &objectPoints, &rvec, &tvec, &cameraMatrix, &distCoeffs, + &imagePoints, pdpdrot, pdpdt, pdpdf, pdpdc, pdpddist, aspectRatio ); } -cv::Mat cv::initCameraMatrix2D( const vector >& objectPoints, - const vector >& imagePoints, +cv::Mat cv::initCameraMatrix2D( const InputArrayOfArrays& objectPoints, + const InputArrayOfArrays& imagePoints, Size imageSize, double aspectRatio ) { Mat objPt, imgPt, npoints, cameraMatrix(3, 3, CV_64F); - collectCalibrationData( objectPoints, imagePoints, vector >(), + collectCalibrationData( objectPoints, imagePoints, InputArrayOfArrays(), objPt, imgPt, 0, npoints ); CvMat _objPt = objPt, _imgPt = imgPt, _npoints = npoints, _cameraMatrix = cameraMatrix; cvInitIntrinsicParams2D( &_objPt, &_imgPt, &_npoints, @@ -3290,60 +3330,73 @@ cv::Mat cv::initCameraMatrix2D( const vector >& objectPoints, } -double cv::calibrateCamera( const vector >& objectPoints, - const vector >& imagePoints, - Size imageSize, Mat& cameraMatrix, Mat& distCoeffs, - vector& rvecs, vector& tvecs, int flags ) +double cv::calibrateCamera( const InputArrayOfArrays& _objectPoints, + const InputArrayOfArrays& _imagePoints, + Size imageSize, InputOutputArray _cameraMatrix, InputOutputArray _distCoeffs, + OutputArray _rvecs, OutputArray _tvecs, int flags ) { int rtype = CV_64F; + Mat cameraMatrix = _cameraMatrix.getMat(); cameraMatrix = prepareCameraMatrix(cameraMatrix, rtype); + Mat distCoeffs = _distCoeffs.getMat(); distCoeffs = prepareDistCoeffs(distCoeffs, rtype); if( !(flags & CALIB_RATIONAL_MODEL) ) distCoeffs = distCoeffs.rows == 1 ? distCoeffs.colRange(0, 5) : distCoeffs.rowRange(0, 5); - size_t i, nimages = objectPoints.size(); + size_t i, nimages = _objectPoints.total(); CV_Assert( nimages > 0 ); Mat objPt, imgPt, npoints, rvecM((int)nimages, 3, CV_64FC1), tvecM((int)nimages, 3, CV_64FC1); - collectCalibrationData( objectPoints, imagePoints, vector >(), + collectCalibrationData( _objectPoints, _imagePoints, InputArrayOfArrays(), objPt, imgPt, 0, npoints ); - CvMat _objPt = objPt, _imgPt = imgPt, _npoints = npoints; - CvMat _cameraMatrix = cameraMatrix, _distCoeffs = distCoeffs; - CvMat _rvecM = rvecM, _tvecM = tvecM; - - double reprojErr = cvCalibrateCamera2(&_objPt, &_imgPt, &_npoints, imageSize, - &_cameraMatrix, &_distCoeffs, &_rvecM, - &_tvecM, flags ); - rvecs.resize(nimages); - tvecs.resize(nimages); + CvMat c_objPt = objPt, c_imgPt = imgPt, c_npoints = npoints; + CvMat c_cameraMatrix = cameraMatrix, c_distCoeffs = distCoeffs; + CvMat c_rvecM = rvecM, c_tvecM = tvecM; + + double reprojErr = cvCalibrateCamera2(&c_objPt, &c_imgPt, &c_npoints, imageSize, + &c_cameraMatrix, &c_distCoeffs, &c_rvecM, + &c_tvecM, flags ); + _rvecs.create(nimages, 1, CV_64FC3); + _tvecs.create(nimages, 1, CV_64FC3); + for( i = 0; i < nimages; i++ ) { - rvecM.row((int)i).copyTo(rvecs[i]); - tvecM.row((int)i).copyTo(tvecs[i]); + _rvecs.create(3, 1, CV_64F, i, true); + _tvecs.create(3, 1, CV_64F, i, true); + Mat rv = _rvecs.getMat(i), tv = _tvecs.getMat(i); + memcpy(rv.data, rvecM.ptr(i), 3*sizeof(double)); + memcpy(tv.data, tvecM.ptr(i), 3*sizeof(double)); } + cameraMatrix.copyTo(_cameraMatrix); + distCoeffs.copyTo(_distCoeffs); + return reprojErr; } -void cv::calibrationMatrixValues( const Mat& cameraMatrix, Size imageSize, +void cv::calibrationMatrixValues( const InputArray& _cameraMatrix, Size imageSize, double apertureWidth, double apertureHeight, double& fovx, double& fovy, double& focalLength, Point2d& principalPoint, double& aspectRatio ) { - CvMat _cameraMatrix = cameraMatrix; - cvCalibrationMatrixValues( &_cameraMatrix, imageSize, apertureWidth, apertureHeight, + CvMat c_cameraMatrix = _cameraMatrix.getMat(); + cvCalibrationMatrixValues( &c_cameraMatrix, imageSize, apertureWidth, apertureHeight, &fovx, &fovy, &focalLength, (CvPoint2D64f*)&principalPoint, &aspectRatio ); } -double cv::stereoCalibrate( const vector >& objectPoints, - const vector >& imagePoints1, - const vector >& imagePoints2, - Mat& cameraMatrix1, Mat& distCoeffs1, - Mat& cameraMatrix2, Mat& distCoeffs2, - Size imageSize, Mat& R, Mat& T, - Mat& E, Mat& F, TermCriteria criteria, +double cv::stereoCalibrate( const InputArrayOfArrays& _objectPoints, + const InputArrayOfArrays& _imagePoints1, + const InputArrayOfArrays& _imagePoints2, + InputOutputArray _cameraMatrix1, InputOutputArray _distCoeffs1, + InputOutputArray _cameraMatrix2, InputOutputArray _distCoeffs2, + Size imageSize, OutputArray _Rmat, OutputArray _Tmat, + OutputArray _Emat, OutputArray _Fmat, TermCriteria criteria, int flags ) { int rtype = CV_64F; + Mat cameraMatrix1 = _cameraMatrix1.getMat(); + Mat cameraMatrix2 = _cameraMatrix2.getMat(); + Mat distCoeffs1 = _distCoeffs1.getMat(); + Mat distCoeffs2 = _distCoeffs2.getMat(); cameraMatrix1 = prepareCameraMatrix(cameraMatrix1, rtype); cameraMatrix2 = prepareCameraMatrix(cameraMatrix2, rtype); distCoeffs1 = prepareDistCoeffs(distCoeffs1, rtype); @@ -3355,176 +3408,210 @@ double cv::stereoCalibrate( const vector >& objectPoints, distCoeffs2 = distCoeffs2.rows == 1 ? distCoeffs2.colRange(0, 5) : distCoeffs2.rowRange(0, 5); } - R.create(3, 3, rtype); - T.create(3, 1, rtype); - E.create(3, 3, rtype); - F.create(3, 3, rtype); + _Rmat.create(3, 3, rtype); + _Tmat.create(3, 1, rtype); Mat objPt, imgPt, imgPt2, npoints; - collectCalibrationData( objectPoints, imagePoints1, imagePoints2, + collectCalibrationData( _objectPoints, _imagePoints1, _imagePoints2, objPt, imgPt, &imgPt2, npoints ); - CvMat _objPt = objPt, _imgPt = imgPt, _imgPt2 = imgPt2, _npoints = npoints; - CvMat _cameraMatrix1 = cameraMatrix1, _distCoeffs1 = distCoeffs1; - CvMat _cameraMatrix2 = cameraMatrix2, _distCoeffs2 = distCoeffs2; - CvMat matR = R, matT = T, matE = E, matF = F; - - return cvStereoCalibrate(&_objPt, &_imgPt, &_imgPt2, &_npoints, &_cameraMatrix1, - &_distCoeffs1, &_cameraMatrix2, &_distCoeffs2, imageSize, - &matR, &matT, &matE, &matF, criteria, flags ); -} - + CvMat c_objPt = objPt, c_imgPt = imgPt, c_imgPt2 = imgPt2, c_npoints = npoints; + CvMat c_cameraMatrix1 = cameraMatrix1, c_distCoeffs1 = distCoeffs1; + CvMat c_cameraMatrix2 = cameraMatrix2, c_distCoeffs2 = distCoeffs2; + CvMat c_matR = _Rmat.getMat(), c_matT = _Tmat.getMat(), c_matE, c_matF, *p_matE = 0, *p_matF = 0; + + if( _Emat.needed() ) + { + _Emat.create(3, 3, rtype); + p_matE = &(c_matE = _Emat.getMat()); + } + if( _Fmat.needed() ) + { + _Fmat.create(3, 3, rtype); + p_matF = &(c_matF = _Fmat.getMat()); + } -void cv::stereoRectify( const Mat& cameraMatrix1, const Mat& distCoeffs1, - const Mat& cameraMatrix2, const Mat& distCoeffs2, - Size imageSize, const Mat& R, const Mat& T, - Mat& R1, Mat& R2, Mat& P1, Mat& P2, Mat& Q, - int flags ) -{ - int rtype = CV_64F; - R1.create(3, 3, rtype); - R2.create(3, 3, rtype); - P1.create(3, 4, rtype); - P2.create(3, 4, rtype); - Q.create(4, 4, rtype); - CvMat _cameraMatrix1 = cameraMatrix1, _distCoeffs1 = distCoeffs1; - CvMat _cameraMatrix2 = cameraMatrix2, _distCoeffs2 = distCoeffs2; - CvMat matR = R, matT = T, _R1 = R1, _R2 = R2, _P1 = P1, _P2 = P2, matQ = Q; - cvStereoRectify( &_cameraMatrix1, &_cameraMatrix2, &_distCoeffs1, &_distCoeffs2, - imageSize, &matR, &matT, &_R1, &_R2, &_P1, &_P2, &matQ, flags ); + double err = cvStereoCalibrate(&c_objPt, &c_imgPt, &c_imgPt2, &c_npoints, &c_cameraMatrix1, + &c_distCoeffs1, &c_cameraMatrix2, &c_distCoeffs2, imageSize, + &c_matR, &c_matT, p_matE, p_matF, criteria, flags ); + + cameraMatrix1.copyTo(_cameraMatrix1); + cameraMatrix2.copyTo(_cameraMatrix2); + distCoeffs1.copyTo(_distCoeffs1); + distCoeffs2.copyTo(_distCoeffs2); + + return err; } -void cv::stereoRectify( const Mat& cameraMatrix1, const Mat& distCoeffs1, - const Mat& cameraMatrix2, const Mat& distCoeffs2, - Size imageSize, const Mat& R, const Mat& T, - Mat& R1, Mat& R2, Mat& P1, Mat& P2, Mat& Q, + +void cv::stereoRectify( const InputArray& _cameraMatrix1, const InputArray& _distCoeffs1, + const InputArray& _cameraMatrix2, const InputArray& _distCoeffs2, + Size imageSize, const InputArray& _Rmat, const InputArray& _Tmat, + OutputArray _Rmat1, OutputArray _Rmat2, + OutputArray _Pmat1, OutputArray _Pmat2, + OutputArray _Qmat, int flags, double alpha, Size newImageSize, - Rect* validPixROI1, Rect* validPixROI2, - int flags ) + Rect* validPixROI1, Rect* validPixROI2 ) { + CvMat c_cameraMatrix1 = _cameraMatrix1.getMat(); + CvMat c_cameraMatrix2 = _cameraMatrix2.getMat(); + CvMat c_distCoeffs1 = _distCoeffs1.getMat(); + CvMat c_distCoeffs2 = _distCoeffs2.getMat(); + CvMat c_R = _Rmat.getMat(), c_T = _Tmat.getMat(); + int rtype = CV_64F; - R1.create(3, 3, rtype); - R2.create(3, 3, rtype); - P1.create(3, 4, rtype); - P2.create(3, 4, rtype); - Q.create(4, 4, rtype); - CvMat _cameraMatrix1 = cameraMatrix1, _distCoeffs1 = distCoeffs1; - CvMat _cameraMatrix2 = cameraMatrix2, _distCoeffs2 = distCoeffs2; - CvMat matR = R, matT = T, _R1 = R1, _R2 = R2, _P1 = P1, _P2 = P2, matQ = Q; - cvStereoRectify( &_cameraMatrix1, &_cameraMatrix2, &_distCoeffs1, &_distCoeffs2, - imageSize, &matR, &matT, &_R1, &_R2, &_P1, &_P2, &matQ, flags, - alpha, newImageSize, (CvRect*)validPixROI1, (CvRect*)validPixROI2); + _Rmat1.create(3, 3, rtype); + _Rmat2.create(3, 3, rtype); + _Pmat1.create(3, 4, rtype); + _Pmat2.create(3, 4, rtype); + CvMat c_R1 = _Rmat1.getMat(), c_R2 = _Rmat2.getMat(), c_P1 = _Pmat1.getMat(), c_P2 = _Pmat2.getMat(); + CvMat c_Q, *p_Q = 0; + + if( _Qmat.needed() ) + { + _Qmat.create(4, 4, rtype); + p_Q = &(c_Q = _Qmat.getMat()); + } + + cvStereoRectify( &c_cameraMatrix1, &c_cameraMatrix2, &c_distCoeffs1, &c_distCoeffs2, + imageSize, &c_R, &c_T, &c_R1, &c_R2, &c_P1, &c_P2, p_Q, flags, alpha, + newImageSize, (CvRect*)validPixROI1, (CvRect*)validPixROI2); } -bool cv::stereoRectifyUncalibrated( const Mat& points1, const Mat& points2, - const Mat& F, Size imgSize, - Mat& H1, Mat& H2, double threshold ) +bool cv::stereoRectifyUncalibrated( const InputArray& _points1, const InputArray& _points2, + const InputArray& _Fmat, Size imgSize, + OutputArray _Hmat1, OutputArray _Hmat2, double threshold ) { int rtype = CV_64F; - H1.create(3, 3, rtype); - H2.create(3, 3, rtype); - CvMat _pt1 = points1, _pt2 = points2, matF, *pF=0, _H1 = H1, _H2 = H2; + _Hmat1.create(3, 3, rtype); + _Hmat2.create(3, 3, rtype); + Mat F = _Fmat.getMat(); + CvMat c_pt1 = _points1.getMat(), c_pt2 = _points2.getMat(); + CvMat c_F, *p_F=0, c_H1 = _Hmat1.getMat(), c_H2 = _Hmat2.getMat(); if( F.size() == Size(3, 3) ) - pF = &(matF = F); - return cvStereoRectifyUncalibrated(&_pt1, &_pt2, pF, imgSize, &_H1, &_H2, threshold) > 0; + p_F = &(c_F = F); + return cvStereoRectifyUncalibrated(&c_pt1, &c_pt2, p_F, imgSize, &c_H1, &c_H2, threshold) > 0; } -cv::Mat cv::getOptimalNewCameraMatrix( const Mat& cameraMatrix, const Mat& distCoeffs, - Size imgSize, double alpha, Size newImgSize, - Rect* validPixROI ) +cv::Mat cv::getOptimalNewCameraMatrix( const InputArray& _cameraMatrix, + const InputArray& _distCoeffs, + Size imgSize, double alpha, Size newImgSize, + Rect* validPixROI ) { - Mat newCameraMatrix(3, 3, cameraMatrix.type()); - CvMat _cameraMatrix = cameraMatrix, - _distCoeffs = distCoeffs, - _newCameraMatrix = newCameraMatrix; - cvGetOptimalNewCameraMatrix(&_cameraMatrix, &_distCoeffs, imgSize, - alpha, &_newCameraMatrix, + CvMat c_cameraMatrix = _cameraMatrix.getMat(), c_distCoeffs = _distCoeffs.getMat(); + + Mat newCameraMatrix(3, 3, CV_MAT_TYPE(c_cameraMatrix.type)); + CvMat c_newCameraMatrix = newCameraMatrix; + + cvGetOptimalNewCameraMatrix(&c_cameraMatrix, &c_distCoeffs, imgSize, + alpha, &c_newCameraMatrix, newImgSize, (CvRect*)validPixROI); return newCameraMatrix; } -void cv::RQDecomp3x3( const Mat& M, Mat& R, Mat& Q ) +cv::Vec3d cv::RQDecomp3x3( const InputArray& _Mmat, + OutputArray _Rmat, + OutputArray _Qmat, + OutputArray _Qx, + OutputArray _Qy, + OutputArray _Qz ) { - R.create(3, 3, M.type()); - Q.create(3, 3, M.type()); - - CvMat matM = M, matR = R, matQ = Q; - cvRQDecomp3x3(&matM, &matR, &matQ, 0, 0, 0, 0); -} - - -cv::Vec3d cv::RQDecomp3x3( const Mat& M, Mat& R, Mat& Q, - Mat& Qx, Mat& Qy, Mat& Qz ) -{ - R.create(3, 3, M.type()); - Q.create(3, 3, M.type()); + Mat M = _Mmat.getMat(); + _Rmat.create(3, 3, M.type()); + _Qmat.create(3, 3, M.type()); Vec3d eulerAngles; - CvMat matM = M, matR = R, matQ = Q, _Qx = Qx, _Qy = Qy, _Qz = Qz; - cvRQDecomp3x3(&matM, &matR, &matQ, &_Qx, &_Qy, &_Qz, (CvPoint3D64f*)&eulerAngles[0]); + CvMat matM = M, matR = _Rmat.getMat(), matQ = _Qmat.getMat(), Qx, Qy, Qz, *pQx=0, *pQy=0, *pQz=0; + if( _Qx.needed() ) + { + _Qx.create(3, 3, M.type()); + pQx = &(Qx = _Qx.getMat()); + } + if( _Qy.needed() ) + { + _Qy.create(3, 3, M.type()); + pQy = &(Qy = _Qy.getMat()); + } + if( _Qz.needed() ) + { + _Qz.create(3, 3, M.type()); + pQz = &(Qz = _Qz.getMat()); + } + cvRQDecomp3x3(&matM, &matR, &matQ, pQx, pQy, pQz, (CvPoint3D64f*)&eulerAngles[0]); return eulerAngles; } -void cv::decomposeProjectionMatrix( const Mat& projMatrix, Mat& cameraMatrix, - Mat& rotMatrix, Mat& transVect ) +void cv::decomposeProjectionMatrix( const InputArray& _projMatrix, OutputArray _cameraMatrix, + OutputArray _rotMatrix, OutputArray _transVect, + OutputArray _rotMatrixX, OutputArray _rotMatrixY, + OutputArray _rotMatrixZ, OutputArray _eulerAngles ) { + Mat projMatrix = _projMatrix.getMat(); int type = projMatrix.type(); - cameraMatrix.create(3, 3, type); - rotMatrix.create(3, 3, type); - transVect.create(4, 1, type); - CvMat _projMatrix = projMatrix, _cameraMatrix = cameraMatrix; - CvMat _rotMatrix = rotMatrix, _transVect = transVect; - cvDecomposeProjectionMatrix(&_projMatrix, &_cameraMatrix, &_rotMatrix, - &_transVect, 0, 0, 0, 0); -} - - -void cv::decomposeProjectionMatrix( const Mat& projMatrix, Mat& cameraMatrix, - Mat& rotMatrix, Mat& transVect, - Mat& rotMatrixX, Mat& rotMatrixY, - Mat& rotMatrixZ, Vec3d& eulerAngles ) -{ - int type = projMatrix.type(); - cameraMatrix.create(3, 3, type); - rotMatrix.create(3, 3, type); - transVect.create(4, 1, type); - rotMatrixX.create(3, 3, type); - rotMatrixY.create(3, 3, type); - rotMatrixZ.create(3, 3, type); - CvMat _projMatrix = projMatrix, _cameraMatrix = cameraMatrix; - CvMat _rotMatrix = rotMatrix, _transVect = transVect; - CvMat _rotMatrixX = rotMatrixX, _rotMatrixY = rotMatrixY; - CvMat _rotMatrixZ = rotMatrixZ; - cvDecomposeProjectionMatrix(&_projMatrix, &_cameraMatrix, &_rotMatrix, - &_transVect, &_rotMatrixX, &_rotMatrixY, - &_rotMatrixZ, (CvPoint3D64f*)&eulerAngles[0]); + _cameraMatrix.create(3, 3, type); + _rotMatrix.create(3, 3, type); + _transVect.create(4, 1, type); + CvMat c_projMatrix = projMatrix, c_cameraMatrix = _cameraMatrix.getMat(); + CvMat c_rotMatrix = _rotMatrix.getMat(), c_transVect = _transVect.getMat(); + CvMat c_rotMatrixX, *p_rotMatrixX = 0; + CvMat c_rotMatrixY, *p_rotMatrixY = 0; + CvMat c_rotMatrixZ, *p_rotMatrixZ = 0; + CvPoint3D64f *p_eulerAngles = 0; + + if( _rotMatrixX.needed() ) + { + _rotMatrixX.create(3, 3, type); + p_rotMatrixX = &(c_rotMatrixX = _rotMatrixX.getMat()); + } + if( _rotMatrixY.needed() ) + { + _rotMatrixY.create(3, 3, type); + p_rotMatrixY = &(c_rotMatrixY = _rotMatrixY.getMat()); + } + if( _rotMatrixZ.needed() ) + { + _rotMatrixZ.create(3, 3, type); + p_rotMatrixZ = &(c_rotMatrixZ = _rotMatrixZ.getMat()); + } + if( _eulerAngles.needed() ) + { + _eulerAngles.create(3, 1, CV_64F, -1, true); + p_eulerAngles = (CvPoint3D64f*)_eulerAngles.getMat().data; + } + + cvDecomposeProjectionMatrix(&c_projMatrix, &c_cameraMatrix, &c_rotMatrix, + &c_transVect, p_rotMatrixX, p_rotMatrixY, + p_rotMatrixZ, p_eulerAngles); } namespace cv { -static void adjust3rdMatrix(const vector >& imgpt1_0, - const vector >& imgpt3_0, +static void adjust3rdMatrix(const InputArrayOfArrays& _imgpt1_0, + const InputArrayOfArrays& _imgpt3_0, const Mat& cameraMatrix1, const Mat& distCoeffs1, const Mat& cameraMatrix3, const Mat& distCoeffs3, const Mat& R1, const Mat& R3, const Mat& P1, Mat& P3 ) { + size_t n1 = _imgpt1_0.total(), n3 = _imgpt3_0.total(); vector imgpt1, imgpt3; - for( int i = 0; i < (int)std::min(imgpt1_0.size(), imgpt3_0.size()); i++ ) + for( int i = 0; i < (int)std::min(n1, n3); i++ ) { - if( !imgpt1_0[i].empty() && !imgpt3_0[i].empty() ) - { - std::copy(imgpt1_0[i].begin(), imgpt1_0[i].end(), std::back_inserter(imgpt1)); - std::copy(imgpt3_0[i].begin(), imgpt3_0[i].end(), std::back_inserter(imgpt3)); - } + Mat pt1 = _imgpt1_0.getMat(i), pt3 = _imgpt3_0.getMat(i); + int ni1 = pt1.checkVector(2, CV_32F), ni3 = pt3.checkVector(2, CV_32F); + CV_Assert( ni1 > 0 && ni1 == ni3 ); + const Point2f* pt1data = pt1.ptr(); + const Point2f* pt3data = pt3.ptr(); + std::copy(pt1data, pt1data + ni1, std::back_inserter(imgpt1)); + std::copy(pt3data, pt3data + ni3, std::back_inserter(imgpt3)); } - undistortPoints(Mat(imgpt1), imgpt1, cameraMatrix1, distCoeffs1, R1, P1); - undistortPoints(Mat(imgpt3), imgpt3, cameraMatrix3, distCoeffs3, R3, P3); + undistortPoints(imgpt1, imgpt1, cameraMatrix1, distCoeffs1, R1, P1); + undistortPoints(imgpt3, imgpt3, cameraMatrix3, distCoeffs3, R3, P3); double y1_ = 0, y2_ = 0, y1y1_ = 0, y1y2_ = 0; size_t n = imgpt1.size(); @@ -3555,20 +3642,31 @@ static void adjust3rdMatrix(const vector >& imgpt1_0, } -float cv::rectify3Collinear( const Mat& cameraMatrix1, const Mat& distCoeffs1, - const Mat& cameraMatrix2, const Mat& distCoeffs2, - const Mat& cameraMatrix3, const Mat& distCoeffs3, - const vector >& imgpt1, - const vector >& imgpt3, - Size imageSize, const Mat& R12, const Mat& T12, const Mat& R13, const Mat& T13, - Mat& R1, Mat& R2, Mat& R3, Mat& P1, Mat& P2, Mat& P3, Mat& Q, +float cv::rectify3Collinear( const InputArray& _cameraMatrix1, const InputArray& _distCoeffs1, + const InputArray& _cameraMatrix2, const InputArray& _distCoeffs2, + const InputArray& _cameraMatrix3, const InputArray& _distCoeffs3, + const InputArrayOfArrays& _imgpt1, + const InputArrayOfArrays& _imgpt3, + Size imageSize, const InputArray& _Rmat12, const InputArray& _Tmat12, + const InputArray& _Rmat13, const InputArray& _Tmat13, + OutputArray _Rmat1, OutputArray _Rmat2, OutputArray _Rmat3, + OutputArray _Pmat1, OutputArray _Pmat2, OutputArray _Pmat3, + OutputArray _Qmat, double alpha, Size /*newImgSize*/, Rect* roi1, Rect* roi2, int flags ) { // first, rectify the 1-2 stereo pair - stereoRectify( cameraMatrix1, distCoeffs1, cameraMatrix2, distCoeffs2, - imageSize, R12, T12, R1, R2, P1, P2, Q, - alpha, imageSize, roi1, roi2, flags ); + stereoRectify( _cameraMatrix1, _distCoeffs1, _cameraMatrix2, _distCoeffs2, + imageSize, _Rmat12, _Tmat12, _Rmat1, _Rmat2, _Pmat1, _Pmat2, _Qmat, + flags, alpha, imageSize, roi1, roi2 ); + + Mat R12 = _Rmat12.getMat(), R13 = _Rmat13.getMat(), T12 = _Tmat12.getMat(), T13 = _Tmat13.getMat(); + + _Rmat3.create(3, 3, CV_64F); + _Pmat3.create(3, 4, CV_64F); + + Mat P1 = _Pmat1.getMat(), P2 = _Pmat2.getMat(); + Mat R3 = _Rmat3.getMat(), P3 = _Pmat3.getMat(); // recompute rectification transforms for cameras 1 & 2. Mat om, r_r, r_r13; @@ -3608,8 +3706,9 @@ float cv::rectify3Collinear( const Mat& cameraMatrix1, const Mat& distCoeffs1, P3.at(0,3) *= P3.at(0,0); P3.at(1,3) *= P3.at(1,1); - if( !imgpt1.empty() && imgpt3.empty() ) - adjust3rdMatrix(imgpt1, imgpt3, cameraMatrix1, distCoeffs1, cameraMatrix3, distCoeffs3, R1, R3, P1, P3); + if( !_imgpt1.empty() && _imgpt3.empty() ) + adjust3rdMatrix(_imgpt1, _imgpt3, _cameraMatrix1.getMat(), _distCoeffs1.getMat(), + _cameraMatrix3.getMat(), _distCoeffs3.getMat(), _Rmat1.getMat(), R3, P1, P3); return (float)((P3.at(idx,3)/P3.at(idx,idx))/ (P2.at(idx,3)/P2.at(idx,idx))); diff --git a/modules/calib3d/src/circlesgrid.cpp b/modules/calib3d/src/circlesgrid.cpp index 40e174b429..42cd520d23 100644 --- a/modules/calib3d/src/circlesgrid.cpp +++ b/modules/calib3d/src/circlesgrid.cpp @@ -280,9 +280,9 @@ void CirclesGridClusterFinder::rectifyPatternPoints(const cv::Size &patternSize, Mat homography = findHomography(Mat(sortedCorners), Mat(idealPoints), 0); Mat rectifiedPointsMat; - transform(Mat(patternPoints), rectifiedPointsMat, homography); + transform(patternPoints, rectifiedPointsMat, homography); rectifiedPatternPoints.clear(); - convertPointsHomogeneous(rectifiedPointsMat, rectifiedPatternPoints); + convertPointsFromHomogeneous(rectifiedPointsMat, rectifiedPatternPoints); } void CirclesGridClusterFinder::parsePatternPoints(const cv::Size &patternSize, const std::vector &patternPoints, const std::vector &rectifiedPatternPoints, std::vector ¢ers) @@ -727,7 +727,7 @@ Mat CirclesGridFinder::rectifyGrid(Size detectedGridSize, const vector& Mat dstKeypointsMat; transform(Mat(srcKeypoints), dstKeypointsMat, H); vector dstKeypoints; - convertPointsHomogeneous(dstKeypointsMat, dstKeypoints); + convertPointsFromHomogeneous(dstKeypointsMat, dstKeypoints); warpedKeypoints.clear(); for (size_t i = 0; i < dstKeypoints.size(); i++) @@ -969,7 +969,7 @@ void CirclesGridFinder::findBasis(const vector &samples, vector basisIndices; diff --git a/modules/calib3d/src/fundam.cpp b/modules/calib3d/src/fundam.cpp index 41e648fbe8..fab93bf60a 100644 --- a/modules/calib3d/src/fundam.cpp +++ b/modules/calib3d/src/fundam.cpp @@ -1044,114 +1044,95 @@ CV_IMPL void cvConvertPointsHomogeneous( const CvMat* src, CvMat* dst ) } } -namespace cv +cv::Mat cv::findHomography( const InputArray& _points1, const InputArray& _points2, + int method, double ransacReprojThreshold, OutputArray _mask ) { - -static Mat _findHomography( const Mat& points1, const Mat& points2, - int method, double ransacReprojThreshold, - vector* mask ) -{ - CV_Assert(points1.isContinuous() && points2.isContinuous() && - points1.type() == points2.type() && - ((points1.rows == 1 && points1.channels() == 2) || - points1.cols*points1.channels() == 2) && - ((points2.rows == 1 && points2.channels() == 2) || - points2.cols*points2.channels() == 2)); + Mat points1 = _points1.getMat(), points2 = _points2.getMat(); + int npoints = points1.checkVector(2); + CV_Assert( npoints >= 0 && points2.checkVector(2) == npoints && + points1.type() == points2.type()); Mat H(3, 3, CV_64F); - CvMat _pt1 = Mat(points1), _pt2 = Mat(points2); - CvMat matH = H, _mask, *pmask = 0; - if( mask ) + CvMat _pt1 = points1, _pt2 = points2; + CvMat matH = H, c_mask, *p_mask = 0; + if( _mask.needed() ) { - mask->resize(points1.cols*points1.rows*points1.channels()/2); - pmask = &(_mask = cvMat(1, (int)mask->size(), CV_8U, (void*)&(*mask)[0])); + _mask.create(npoints, 1, CV_8U, -1, true); + p_mask = &(c_mask = _mask.getMat()); } - bool ok = cvFindHomography( &_pt1, &_pt2, &matH, method, ransacReprojThreshold, pmask ) > 0; + bool ok = cvFindHomography( &_pt1, &_pt2, &matH, method, ransacReprojThreshold, p_mask ) > 0; if( !ok ) H = Scalar(0); return H; } -static Mat _findFundamentalMat( const Mat& points1, const Mat& points2, +cv::Mat cv::findFundamentalMat( const InputArray& _points1, const InputArray& _points2, int method, double param1, double param2, - vector* mask ) + OutputArray _mask ) { - CV_Assert(points1.checkVector(2) >= 0 && points2.checkVector(2) >= 0 && - (points1.depth() == CV_32F || points1.depth() == CV_32S) && - points1.depth() == points2.depth()); + Mat points1 = _points1.getMat(), points2 = _points2.getMat(); + int npoints = points1.checkVector(2); + CV_Assert( npoints >= 0 && points2.checkVector(2) == npoints && + points1.type() == points2.type()); Mat F(3, 3, CV_64F); - CvMat _pt1 = Mat(points1), _pt2 = Mat(points2); - CvMat matF = F, _mask, *pmask = 0; - if( mask ) + CvMat _pt1 = points1, _pt2 = points2; + CvMat matF = F, c_mask, *p_mask = 0; + if( _mask.needed() ) { - mask->resize(points1.cols*points1.rows*points1.channels()/2); - pmask = &(_mask = cvMat(1, (int)mask->size(), CV_8U, (void*)&(*mask)[0])); + _mask.create(npoints, 1, CV_8U, -1, true); + p_mask = &(c_mask = _mask.getMat()); } - int n = cvFindFundamentalMat( &_pt1, &_pt2, &matF, method, param1, param2, pmask ); + int n = cvFindFundamentalMat( &_pt1, &_pt2, &matF, method, param1, param2, p_mask ); if( n <= 0 ) F = Scalar(0); return F; } - -} - - -cv::Mat cv::findHomography( const Mat& srcPoints, const Mat& dstPoints, - vector& mask, int method, - double ransacReprojThreshold ) -{ - return _findHomography(srcPoints, dstPoints, method, ransacReprojThreshold, &mask); -} -cv::Mat cv::findHomography( const Mat& srcPoints, const Mat& dstPoints, - int method, double ransacReprojThreshold ) +void cv::computeCorrespondEpilines( const InputArray& _points, int whichImage, + const InputArray& _Fmat, OutputArray _lines ) { - return _findHomography(srcPoints, dstPoints, method, ransacReprojThreshold, 0); -} - + Mat points = _points.getMat(); + int npoints = points.checkVector(2); + CV_Assert( npoints >= 0 && (points.depth() == CV_32F || points.depth() == CV_32S)); -cv::Mat cv::findFundamentalMat( const Mat& points1, const Mat& points2, - vector& mask, int method, double param1, double param2 ) -{ - return _findFundamentalMat( points1, points2, method, param1, param2, &mask ); + _lines.create(npoints, 1, CV_32FC3, -1, true); + CvMat c_points = points, c_lines = _lines.getMat(), c_F = _Fmat.getMat(); + cvComputeCorrespondEpilines(&c_points, whichImage, &c_F, &c_lines); } -cv::Mat cv::findFundamentalMat( const Mat& points1, const Mat& points2, - int method, double param1, double param2 ) +void cv::convertPointsFromHomogeneous( const InputArray& _src, OutputArray _dst ) { - return _findFundamentalMat( points1, points2, method, param1, param2, 0 ); -} - -void cv::computeCorrespondEpilines( const Mat& points, int whichImage, - const Mat& F, vector& lines ) -{ - CV_Assert(points.checkVector(2) >= 0 && - (points.depth() == CV_32F || points.depth() == CV_32S)); - - lines.resize(points.cols*points.rows*points.channels()/2); - CvMat _points = points, _lines = Mat(lines), matF = F; - cvComputeCorrespondEpilines(&_points, whichImage, &matF, &_lines); -} - -void cv::convertPointsHomogeneous( const Mat& src, vector& dst ) -{ - int srccn = src.checkVector(2) >= 0 ? 2 : src.checkVector(4) >= 0 ? 4 : -1; - CV_Assert( srccn > 0 && (src.depth() == CV_32F || src.depth() == CV_32S)); + Mat src = _src.getMat(); + int npoints = src.checkVector(3), cn = 3; + if( npoints < 0 ) + { + npoints = src.checkVector(4); + if( npoints >= 0 ) + cn = 4; + } + CV_Assert( npoints >= 0 && (src.depth() == CV_32F || src.depth() == CV_32S)); - dst.resize(src.cols*src.rows*src.channels()/srccn); - CvMat _src = src, _dst = Mat(dst); - cvConvertPointsHomogeneous(&_src, &_dst); + _dst.create(npoints, 1, CV_MAKETYPE(CV_32F, cn-1)); + CvMat c_src = src, c_dst = _dst.getMat(); + cvConvertPointsHomogeneous(&c_src, &c_dst); } -void cv::convertPointsHomogeneous( const Mat& src, vector& dst ) +void cv::convertPointsToHomogeneous( const InputArray& _src, OutputArray _dst ) { - CV_Assert(src.checkVector(3) >= 0 && - (src.depth() == CV_32F || src.depth() == CV_32S)); + Mat src = _src.getMat(); + int npoints = src.checkVector(2), cn = 2; + if( npoints < 0 ) + { + npoints = src.checkVector(3); + if( npoints >= 0 ) + cn = 3; + } + CV_Assert( npoints >= 0 && (src.depth() == CV_32F || src.depth() == CV_32S)); - dst.resize(src.cols*src.rows*src.channels()/3); - CvMat _src = Mat(src), _dst = Mat(dst); - cvConvertPointsHomogeneous(&_src, &_dst); + _dst.create(npoints, 1, CV_MAKETYPE(CV_32F, cn+1)); + CvMat c_src = src, c_dst = _dst.getMat(); + cvConvertPointsHomogeneous(&c_src, &c_dst); } /* End of file. */ diff --git a/modules/calib3d/src/modelest.cpp b/modules/calib3d/src/modelest.cpp index c21a071884..33f451ce92 100644 --- a/modules/calib3d/src/modelest.cpp +++ b/modules/calib3d/src/modelest.cpp @@ -452,34 +452,34 @@ bool cv::Affine3DEstimator::checkSubset( const CvMat* ms1, int count ) return j == i; } -int cv::estimateAffine3D(const Mat& from, const Mat& to, Mat& out, vector& outliers, double param1, double param2) +int cv::estimateAffine3D(const InputArray& _from, const InputArray& _to, + OutputArray _out, OutputArray _outliers, + double param1, double param2) { - int count = from.cols*from.rows*from.channels()/3; + Mat from = _from.getMat(), to = _to.getMat(); + int count = from.checkVector(3, CV_32F); - CV_Assert( count >= 4 && from.isContinuous() && to.isContinuous() && - from.depth() == CV_32F && to.depth() == CV_32F && - ((from.rows == 1 && from.channels() == 3) || from.cols*from.channels() == 3) && - ((to.rows == 1 && to.channels() == 3) || to.cols*to.channels() == 3) && - count == to.cols*to.rows*to.channels()/3); + CV_Assert( count >= 0 && to.checkVector(3, CV_32F) == count ); - out.create(3, 4, CV_64F); - outliers.resize(count); - fill(outliers.begin(), outliers.end(), (uchar)1); - - vector dFrom; - vector dTo; + _out.create(3, 4, CV_64F); + Mat out = _out.getMat(); + + _outliers.create(count, 1, CV_8U, -1, true); + Mat outliers = _outliers.getMat(); + outliers = Scalar::all(1); - copy(from.ptr(), from.ptr() + count, back_inserter(dFrom)); - copy(to.ptr(), to.ptr() + count, back_inserter(dTo)); + Mat dFrom, dTo; + from.convertTo(dFrom, CV_64F); + to.convertTo(dTo, CV_64F); CvMat F3x4 = out; - CvMat mask = cvMat( 1, count, CV_8U, &outliers[0] ); - CvMat m1 = cvMat( 1, count, CV_64FC3, &dFrom[0] ); - CvMat m2 = cvMat( 1, count, CV_64FC3, &dTo[0] ); + CvMat mask = outliers; + CvMat m1 = dFrom; + CvMat m2 = dTo; const double epsilon = numeric_limits::epsilon(); param1 = param1 <= 0 ? 3 : param1; param2 = (param2 < epsilon) ? 0.99 : (param2 > 1 - epsilon) ? 0.99 : param2; - return Affine3DEstimator().runRANSAC(&m1,& m2, &F3x4, &mask, param1, param2 ); + return Affine3DEstimator().runRANSAC(&m1, &m2, &F3x4, &mask, param1, param2 ); } diff --git a/modules/calib3d/src/quadsubpix.cpp b/modules/calib3d/src/quadsubpix.cpp index d995bf773b..bd32d644a7 100644 --- a/modules/calib3d/src/quadsubpix.cpp +++ b/modules/calib3d/src/quadsubpix.cpp @@ -223,9 +223,15 @@ int segment_hist_max(const Mat& hist, int& low_thresh, int& high_thresh) return 1; } } + +} -bool find4QuadCornerSubpix(const Mat& img, std::vector& corners, Size region_size) +bool cv::find4QuadCornerSubpix(const InputArray& _img, InputOutputArray _corners, Size region_size) { + Mat img = _img.getMat(), cornersM = _corners.getMat(); + int ncorners = cornersM.checkVector(2, CV_32F); + CV_Assert( ncorners >= 0 ); + Point2f* corners = cornersM.ptr(); const int nbins = 256; float ranges[] = {0, 256}; const float* _ranges = ranges; @@ -238,7 +244,7 @@ bool find4QuadCornerSubpix(const Mat& img, std::vector& corners, Size r Mat black_comp, white_comp; - for(size_t i = 0; i < corners.size(); i++) + for(int i = 0; i < ncorners; i++) { int channels = 0; Rect roi(cvRound(corners[i].x - region_size.width), cvRound(corners[i].y - region_size.height), @@ -362,5 +368,3 @@ bool find4QuadCornerSubpix(const Mat& img, std::vector& corners, Size r return true; } - -}; // namespace std diff --git a/modules/calib3d/src/solvepnp.cpp b/modules/calib3d/src/solvepnp.cpp index ab0ed910d5..c121892bcf 100644 --- a/modules/calib3d/src/solvepnp.cpp +++ b/modules/calib3d/src/solvepnp.cpp @@ -1,324 +1,329 @@ /*M/////////////////////////////////////////////////////////////////////////////////////// -// -// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. -// -// By downloading, copying, installing or using the software you agree to this license. -// If you do not agree to this license, do not download, install, -// copy or use the software. -// -// -// License Agreement -// For Open Source Computer Vision Library -// -// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. -// Copyright (C) 2009, Willow Garage Inc., all rights reserved. -// Third party copyrights are property of their respective owners. -// -// Redistribution and use in source and binary forms, with or without modification, -// are permitted provided that the following conditions are met: -// -// * Redistribution's of source code must retain the above copyright notice, -// this list of conditions and the following disclaimer. -// -// * Redistribution's in binary form must reproduce the above copyright notice, -// this list of conditions and the following disclaimer in the documentation -// and/or other materials provided with the distribution. -// -// * The name of the copyright holders may not be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// This software is provided by the copyright holders and contributors "as is" and -// any express or implied warranties, including, but not limited to, the implied -// warranties of merchantability and fitness for a particular purpose are disclaimed. -// In no event shall the Intel Corporation or contributors be liable for any direct, -// indirect, incidental, special, exemplary, or consequential damages -// (including, but not limited to, procurement of substitute goods or services; -// loss of use, data, or profits; or business interruption) however caused -// and on any theory of liability, whether in contract, strict liability, -// or tort (including negligence or otherwise) arising in any way out of -// the use of this software, even if advised of the possibility of such damage. -// -//M*/ + // + // IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. + // + // By downloading, copying, installing or using the software you agree to this license. + // If you do not agree to this license, do not download, install, + // copy or use the software. + // + // + // License Agreement + // For Open Source Computer Vision Library + // + // Copyright (C) 2000-2008, Intel Corporation, all rights reserved. + // Copyright (C) 2009, Willow Garage Inc., all rights reserved. + // Third party copyrights are property of their respective owners. + // + // Redistribution and use in source and binary forms, with or without modification, + // are permitted provided that the following conditions are met: + // + // * Redistribution's of source code must retain the above copyright notice, + // this list of conditions and the following disclaimer. + // + // * Redistribution's in binary form must reproduce the above copyright notice, + // this list of conditions and the following disclaimer in the documentation + // and/or other materials provided with the distribution. + // + // * The name of the copyright holders may not be used to endorse or promote products + // derived from this software without specific prior written permission. + // + // This software is provided by the copyright holders and contributors "as is" and + // any express or implied warranties, including, but not limited to, the implied + // warranties of merchantability and fitness for a particular purpose are disclaimed. + // In no event shall the Intel Corporation or contributors be liable for any direct, + // indirect, incidental, special, exemplary, or consequential damages + // (including, but not limited to, procurement of substitute goods or services; + // loss of use, data, or profits; or business interruption) however caused + // and on any theory of liability, whether in contract, strict liability, + // or tort (including negligence or otherwise) arising in any way out of + // the use of this software, even if advised of the possibility of such damage. + // + //M*/ #include "precomp.hpp" using namespace cv; -void cv::solvePnP( const Mat& opoints, const Mat& ipoints, - const Mat& cameraMatrix, const Mat& distCoeffs, - Mat& rvec, Mat& tvec, bool useExtrinsicGuess ) +void cv::solvePnP( const InputArray& _opoints, const InputArray& _ipoints, + const InputArray& _cameraMatrix, const InputArray& _distCoeffs, + OutputArray _rvec, OutputArray _tvec, bool useExtrinsicGuess ) { - CV_Assert(opoints.isContinuous() && opoints.depth() == CV_32F && - ((opoints.rows == 1 && opoints.channels() == 3) || - opoints.cols*opoints.channels() == 3) && - ipoints.isContinuous() && ipoints.depth() == CV_32F && - ((ipoints.rows == 1 && ipoints.channels() == 2) || - ipoints.cols*ipoints.channels() == 2)); - - rvec.create(3, 1, CV_64F); - tvec.create(3, 1, CV_64F); - CvMat _objectPoints = opoints, _imagePoints = ipoints; - CvMat _cameraMatrix = cameraMatrix, _distCoeffs = distCoeffs; - CvMat _rvec = rvec, _tvec = tvec; - cvFindExtrinsicCameraParams2(&_objectPoints, &_imagePoints, &_cameraMatrix, - distCoeffs.data ? &_distCoeffs : 0, - &_rvec, &_tvec, useExtrinsicGuess ); + Mat opoints = _opoints.getMat(), ipoints = _ipoints.getMat(); + int npoints = opoints.checkVector(3, CV_32F); + CV_Assert( npoints >= 0 && npoints == ipoints.checkVector(2, CV_32F) ); + + _rvec.create(3, 1, CV_64F); + _tvec.create(3, 1, CV_64F); + CvMat c_objectPoints = opoints, c_imagePoints = ipoints; + CvMat c_cameraMatrix = _cameraMatrix.getMat(), c_distCoeffs = _distCoeffs.getMat(); + CvMat c_rvec = _rvec.getMat(), c_tvec = _tvec.getMat(); + cvFindExtrinsicCameraParams2(&c_objectPoints, &c_imagePoints, &c_cameraMatrix, + c_distCoeffs.rows*c_distCoeffs.cols ? &c_distCoeffs : 0, + &c_rvec, &c_tvec, useExtrinsicGuess ); } namespace cv { - namespace pnpransac - { - const int MIN_POINTS_COUNT = 4; - - void project3dPoints(const Mat& points, const Mat& rvec, const Mat& tvec, Mat& modif_points) - { - modif_points.create(1, points.cols, CV_32FC3); - Mat R(3, 3, CV_64FC1); - Rodrigues(rvec, R); - Mat transformation(3, 4, CV_64F); - Mat r = transformation.colRange(0, 2); - R.copyTo(r); - Mat t = transformation.colRange(3, 4); - tvec.copyTo(t); - transform(points, modif_points, transformation); - } - - class Mutex + namespace pnpransac { - public: - Mutex() {} - void lock() + const int MIN_POINTS_COUNT = 4; + + void project3dPoints(const Mat& points, const Mat& rvec, const Mat& tvec, Mat& modif_points) { - #ifdef HAVE_TBB - slock.acquire(resultsMutex); - #endif + modif_points.create(1, points.cols, CV_32FC3); + Mat R(3, 3, CV_64FC1); + Rodrigues(rvec, R); + Mat transformation(3, 4, CV_64F); + Mat r = transformation.colRange(0, 2); + R.copyTo(r); + Mat t = transformation.colRange(3, 4); + tvec.copyTo(t); + transform(points, modif_points, transformation); } - - void unlock() + + class Mutex { - #ifdef HAVE_TBB - slock.release(); - #endif - } - - private: - #ifdef HAVE_TBB - tbb::mutex resultsMutex; - tbb::mutex::scoped_lock slock; - #endif - }; - - struct CameraParameters - { - void init(Mat _intrinsics, Mat _distCoeffs) - { - _intrinsics.copyTo(intrinsics); - _distCoeffs.copyTo(distortion); - } - - Mat intrinsics; - Mat distortion; - }; - - struct Parameters - { - int iterationsCount; - float reprojectionError; - int minInliersCount; - bool useExtrinsicGuess; - CameraParameters camera; - }; - - void pnpTask(const vector& pointsMask, const Mat& objectPoints, const Mat& imagePoints, - const Parameters& params, vector& inliers, Mat& rvec, Mat& tvec, - const Mat& rvecInit, const Mat& tvecInit, Mutex& resultsMutex) - { - Mat modelObjectPoints(1, MIN_POINTS_COUNT, CV_32FC3), modelImagePoints(1, MIN_POINTS_COUNT, CV_32FC2); - for (size_t i = 0, colIndex = 0; i < pointsMask.size(); i++) - { - if (pointsMask[i]) - { - Mat colModelImagePoints = modelImagePoints(Rect(colIndex, 0, 1, 1)); - imagePoints.col(i).copyTo(colModelImagePoints); - Mat colModelObjectPoints = modelObjectPoints(Rect(colIndex, 0, 1, 1)); - objectPoints.col(i).copyTo(colModelObjectPoints); - colIndex = colIndex+1; - } - } - - //filter same 3d points, hang in solvePnP - double eps = 1e-10; - int num_same_points = 0; - for (int i = 0; i < MIN_POINTS_COUNT; i++) - for (int j = i + 1; j < MIN_POINTS_COUNT; j++) + public: + Mutex() {} + void lock() + { +#ifdef HAVE_TBB + slock.acquire(resultsMutex); +#endif + } + + void unlock() + { +#ifdef HAVE_TBB + slock.release(); +#endif + } + + private: +#ifdef HAVE_TBB + tbb::mutex resultsMutex; + tbb::mutex::scoped_lock slock; +#endif + }; + + struct CameraParameters { - if (norm(modelObjectPoints.at(0, i) - modelObjectPoints.at(0, j)) < eps) - num_same_points++; - } - if (num_same_points > 0) - return; - - Mat localRvec, localTvec; - rvecInit.copyTo(localRvec); - tvecInit.copyTo(localTvec); - - solvePnP(modelObjectPoints, modelImagePoints, params.camera.intrinsics, params.camera.distortion, localRvec, localTvec, params.useExtrinsicGuess); - - vector projected_points; - projected_points.resize(objectPoints.cols); - projectPoints(objectPoints, localRvec, localTvec, params.camera.intrinsics, params.camera.distortion, projected_points); - - Mat rotatedPoints; - project3dPoints(objectPoints, localRvec, localTvec, rotatedPoints); - - vector localInliers; - for (size_t i = 0; i < objectPoints.cols; i++) - { - Point2f p(imagePoints.at(0, i)[0], imagePoints.at(0, i)[1]); - if ((norm(p - projected_points[i]) < params.reprojectionError) - && (rotatedPoints.at(0, i)[2] > 0)) //hack + void init(Mat _intrinsics, Mat _distCoeffs) + { + _intrinsics.copyTo(intrinsics); + _distCoeffs.copyTo(distortion); + } + + Mat intrinsics; + Mat distortion; + }; + + struct Parameters { - localInliers.push_back(i); - } - } - - if (localInliers.size() > inliers.size()) - { - resultsMutex.lock(); - - inliers.clear(); - inliers.resize(localInliers.size()); - memcpy(&inliers[0], &localInliers[0], sizeof(int) * localInliers.size()); - localRvec.copyTo(rvec); - localTvec.copyTo(tvec); - - resultsMutex.unlock(); - } - } - - class PnPSolver - { - public: - void operator()( const BlockedRange& r ) const + int iterationsCount; + float reprojectionError; + int minInliersCount; + bool useExtrinsicGuess; + CameraParameters camera; + }; + + void pnpTask(const vector& pointsMask, const Mat& objectPoints, const Mat& imagePoints, + const Parameters& params, vector& inliers, Mat& rvec, Mat& tvec, + const Mat& rvecInit, const Mat& tvecInit, Mutex& resultsMutex) { - vector pointsMask(objectPoints.cols, 0); - memset(&pointsMask[0], 1, MIN_POINTS_COUNT ); - for( size_t i=r.begin(); i!=r.end(); ++i ) + Mat modelObjectPoints(1, MIN_POINTS_COUNT, CV_32FC3), modelImagePoints(1, MIN_POINTS_COUNT, CV_32FC2); + for (size_t i = 0, colIndex = 0; i < pointsMask.size(); i++) + { + if (pointsMask[i]) + { + Mat colModelImagePoints = modelImagePoints(Rect(colIndex, 0, 1, 1)); + imagePoints.col(i).copyTo(colModelImagePoints); + Mat colModelObjectPoints = modelObjectPoints(Rect(colIndex, 0, 1, 1)); + objectPoints.col(i).copyTo(colModelObjectPoints); + colIndex = colIndex+1; + } + } + + //filter same 3d points, hang in solvePnP + double eps = 1e-10; + int num_same_points = 0; + for (int i = 0; i < MIN_POINTS_COUNT; i++) + for (int j = i + 1; j < MIN_POINTS_COUNT; j++) + { + if (norm(modelObjectPoints.at(0, i) - modelObjectPoints.at(0, j)) < eps) + num_same_points++; + } + if (num_same_points > 0) + return; + + Mat localRvec, localTvec; + rvecInit.copyTo(localRvec); + tvecInit.copyTo(localTvec); + + solvePnP(modelObjectPoints, modelImagePoints, params.camera.intrinsics, params.camera.distortion, localRvec, localTvec, params.useExtrinsicGuess); + + vector projected_points; + projected_points.resize(objectPoints.cols); + projectPoints(objectPoints, localRvec, localTvec, params.camera.intrinsics, params.camera.distortion, projected_points); + + Mat rotatedPoints; + project3dPoints(objectPoints, localRvec, localTvec, rotatedPoints); + + vector localInliers; + for (int i = 0; i < objectPoints.cols; i++) + { + Point2f p(imagePoints.at(0, i)[0], imagePoints.at(0, i)[1]); + if ((norm(p - projected_points[i]) < params.reprojectionError) + && (rotatedPoints.at(0, i)[2] > 0)) //hack + { + localInliers.push_back(i); + } + } + + if (localInliers.size() > inliers.size()) { - generateVar(pointsMask); - pnpTask(pointsMask, objectPoints, imagePoints, parameters, - inliers, rvec, tvec, initRvec, initTvec, syncMutex); - if ((int)inliers.size() > parameters.minInliersCount) - { - #ifdef HAVE_TBB - tbb::task::self().cancel_group_execution(); - #else - break; - #endif - } + resultsMutex.lock(); + + inliers.clear(); + inliers.resize(localInliers.size()); + memcpy(&inliers[0], &localInliers[0], sizeof(int) * localInliers.size()); + localRvec.copyTo(rvec); + localTvec.copyTo(tvec); + + resultsMutex.unlock(); } } - PnPSolver(const Mat& objectPoints, const Mat& imagePoints, const Parameters& parameters, - Mat& rvec, Mat& tvec, vector& inliers): - objectPoints(objectPoints), imagePoints(imagePoints), parameters(parameters), - rvec(rvec), tvec(tvec), inliers(inliers) + + class PnPSolver { - rvec.copyTo(initRvec); - tvec.copyTo(initTvec); - } - private: - const Mat& objectPoints; - const Mat& imagePoints; - const Parameters& parameters; - vector& inliers; - Mat &rvec, &tvec; - Mat initRvec, initTvec; - - static RNG generator; - static Mutex syncMutex; - - void generateVar(vector& mask) const - { - size_t size = mask.size(); - for (size_t i = 0; i < size; i++) - { - int i1 = generator.uniform(0, size); - int i2 = generator.uniform(0, size); - char curr = mask[i1]; - mask[i1] = mask[i2]; - mask[i2] = curr; - } - } - }; - - Mutex PnPSolver::syncMutex; - RNG PnPSolver::generator; - - } + public: + void operator()( const BlockedRange& r ) const + { + vector pointsMask(objectPoints.cols, 0); + memset(&pointsMask[0], 1, MIN_POINTS_COUNT ); + for( int i=r.begin(); i!=r.end(); ++i ) + { + generateVar(pointsMask); + pnpTask(pointsMask, objectPoints, imagePoints, parameters, + inliers, rvec, tvec, initRvec, initTvec, syncMutex); + if ((int)inliers.size() > parameters.minInliersCount) + { +#ifdef HAVE_TBB + tbb::task::self().cancel_group_execution(); +#else + break; +#endif + } + } + } + PnPSolver(const Mat& objectPoints, const Mat& imagePoints, const Parameters& parameters, + Mat& rvec, Mat& tvec, vector& inliers): + objectPoints(objectPoints), imagePoints(imagePoints), parameters(parameters), + rvec(rvec), tvec(tvec), inliers(inliers) + { + rvec.copyTo(initRvec); + tvec.copyTo(initTvec); + } + private: + const Mat& objectPoints; + const Mat& imagePoints; + const Parameters& parameters; + Mat &rvec, &tvec; + vector& inliers; + Mat initRvec, initTvec; + + static RNG generator; + static Mutex syncMutex; + + void generateVar(vector& mask) const + { + size_t size = mask.size(); + for (size_t i = 0; i < size; i++) + { + int i1 = generator.uniform(0, size); + int i2 = generator.uniform(0, size); + char curr = mask[i1]; + mask[i1] = mask[i2]; + mask[i2] = curr; + } + } + }; + + Mutex PnPSolver::syncMutex; + RNG PnPSolver::generator; + + } } -void cv::solvePnPRansac(const Mat& opoints, const Mat& ipoints, - const Mat& cameraMatrix, const Mat& distCoeffs, Mat& rvec, Mat& tvec, bool useExtrinsicGuess, - int iterationsCount, float reprojectionError, int minInliersCount, vector* inliers) +void cv::solvePnPRansac(const InputArray& _opoints, const InputArray& _ipoints, + const InputArray& _cameraMatrix, const InputArray& _distCoeffs, + OutputArray _rvec, OutputArray _tvec, bool useExtrinsicGuess, + int iterationsCount, float reprojectionError, int minInliersCount, + OutputArray _inliers) { - - CV_Assert(opoints.isContinuous()); - CV_Assert(opoints.depth() == CV_32F); - CV_Assert((opoints.rows == 1 && opoints.channels() == 3) || opoints.cols*opoints.channels() == 3); - CV_Assert(ipoints.isContinuous()); - CV_Assert(ipoints.depth() == CV_32F); - CV_Assert((ipoints.rows == 1 && ipoints.channels() == 2) || ipoints.cols*ipoints.channels() == 2); - - rvec.create(3, 1, CV_64FC1); - tvec.create(3, 1, CV_64FC1); - - Mat objectPoints = opoints.reshape(3, 1), imagePoints = ipoints.reshape(2, 1); - - if (minInliersCount <= 0) - minInliersCount = objectPoints.cols; - cv::pnpransac::Parameters params; - params.iterationsCount = iterationsCount; - params.minInliersCount = minInliersCount; - params.reprojectionError = reprojectionError; - params.useExtrinsicGuess = useExtrinsicGuess; - params.camera.init(cameraMatrix, distCoeffs); - - vector localInliers; - Mat localRvec, localTvec; - rvec.copyTo(localRvec); - tvec.copyTo(localTvec); - - if (objectPoints.cols >= pnpransac::MIN_POINTS_COUNT) - { - parallel_for(BlockedRange(0,iterationsCount), cv::pnpransac::PnPSolver(objectPoints, imagePoints, params, - localRvec, localTvec, localInliers)); - } - - if (localInliers.size() >= pnpransac::MIN_POINTS_COUNT) - { - size_t pointsCount = localInliers.size(); - Mat inlierObjectPoints(1, pointsCount, CV_32FC3), inlierImagePoints(1, pointsCount, CV_32FC2); - int index; - for (size_t i = 0; i < localInliers.size(); i++) + Mat opoints = _opoints.getMat(), ipoints = _ipoints.getMat(); + Mat cameraMatrix = _cameraMatrix.getMat(), distCoeffs = _distCoeffs.getMat(); + + CV_Assert(opoints.isContinuous()); + CV_Assert(opoints.depth() == CV_32F); + CV_Assert((opoints.rows == 1 && opoints.channels() == 3) || opoints.cols*opoints.channels() == 3); + CV_Assert(ipoints.isContinuous()); + CV_Assert(ipoints.depth() == CV_32F); + CV_Assert((ipoints.rows == 1 && ipoints.channels() == 2) || ipoints.cols*ipoints.channels() == 2); + + _rvec.create(3, 1, CV_64FC1); + _tvec.create(3, 1, CV_64FC1); + Mat rvec = _rvec.getMat(); + Mat tvec = _tvec.getMat(); + + Mat objectPoints = opoints.reshape(3, 1), imagePoints = ipoints.reshape(2, 1); + + if (minInliersCount <= 0) + minInliersCount = objectPoints.cols; + cv::pnpransac::Parameters params; + params.iterationsCount = iterationsCount; + params.minInliersCount = minInliersCount; + params.reprojectionError = reprojectionError; + params.useExtrinsicGuess = useExtrinsicGuess; + params.camera.init(cameraMatrix, distCoeffs); + + vector localInliers; + Mat localRvec, localTvec; + rvec.copyTo(localRvec); + tvec.copyTo(localTvec); + + if (objectPoints.cols >= pnpransac::MIN_POINTS_COUNT) + { + parallel_for(BlockedRange(0,iterationsCount), cv::pnpransac::PnPSolver(objectPoints, imagePoints, params, + localRvec, localTvec, localInliers)); + } + + if (localInliers.size() >= (size_t)pnpransac::MIN_POINTS_COUNT) + { + size_t pointsCount = localInliers.size(); + Mat inlierObjectPoints(1, pointsCount, CV_32FC3), inlierImagePoints(1, pointsCount, CV_32FC2); + int index; + for (size_t i = 0; i < localInliers.size(); i++) + { + index = localInliers[i]; + Mat colInlierImagePoints = inlierImagePoints(Rect(i, 0, 1, 1)); + imagePoints.col(index).copyTo(colInlierImagePoints); + Mat colInlierObjectPoints = inlierObjectPoints(Rect(i, 0, 1, 1)); + objectPoints.col(index).copyTo(colInlierObjectPoints); + } + solvePnP(inlierObjectPoints, inlierImagePoints, params.camera.intrinsics, params.camera.distortion, localRvec, localTvec, true); + localRvec.copyTo(rvec); + localTvec.copyTo(tvec); + if (_inliers.needed()) + Mat(localInliers).copyTo(_inliers); + } + else { - index = localInliers[i]; - Mat colInlierImagePoints = inlierImagePoints(Rect(i, 0, 1, 1)); - imagePoints.col(index).copyTo(colInlierImagePoints); - Mat colInlierObjectPoints = inlierObjectPoints(Rect(i, 0, 1, 1)); - objectPoints.col(index).copyTo(colInlierObjectPoints); + tvec.setTo(Scalar(0)); + Mat R = Mat::eye(3, 3, CV_64F); + Rodrigues(R, rvec); + if( _inliers.needed() ) + _inliers.release(); } - solvePnP(inlierObjectPoints, inlierImagePoints, params.camera.intrinsics, params.camera.distortion, localRvec, localTvec, true); - localRvec.copyTo(rvec); - localTvec.copyTo(tvec); - if (inliers) - *inliers = localInliers; - } - else - { - tvec.setTo(Scalar(0)); - Mat R = Mat::ones(3, 3, CV_64F); - Rodrigues(R, rvec); - } - return; + return; } diff --git a/modules/calib3d/src/stereobm.cpp b/modules/calib3d/src/stereobm.cpp index 485d73d13c..8f9fe00236 100644 --- a/modules/calib3d/src/stereobm.cpp +++ b/modules/calib3d/src/stereobm.cpp @@ -920,10 +920,13 @@ void StereoBM::init(int _preset, int _ndisparities, int _SADWindowSize) state->SADWindowSize = _SADWindowSize; } -void StereoBM::operator()( const Mat& left, const Mat& right, Mat& disparity, int disptype ) +void StereoBM::operator()( const InputArray& _left, const InputArray& _right, + OutputArray _disparity, int disptype ) { + Mat left = _left.getMat(), right = _right.getMat(); CV_Assert( disptype == CV_16S || disptype == CV_32F ); - disparity.create(left.size(), disptype); + _disparity.create(left.size(), disptype); + Mat disparity = _disparity.getMat(); findStereoCorrespondenceBM(left, right, disparity, state); } diff --git a/modules/calib3d/src/stereosgbm.cpp b/modules/calib3d/src/stereosgbm.cpp index 275cd36d47..fd0ffcd560 100644 --- a/modules/calib3d/src/stereosgbm.cpp +++ b/modules/calib3d/src/stereosgbm.cpp @@ -819,8 +819,49 @@ static void computeDisparitySGBM( const Mat& img1, const Mat& img2, typedef cv::Point_ Point2s; -void filterSpeckles( Mat& img, double _newval, int maxSpeckleSize, double _maxDiff, Mat& _buf ) +void StereoSGBM::operator ()( const InputArray& _left, const InputArray& _right, + OutputArray _disp ) { + Mat left = _left.getMat(), right = _right.getMat(); + CV_Assert( left.size() == right.size() && left.type() == right.type() && + left.depth() == DataType::depth ); + + _disp.create( left.size(), CV_16S ); + Mat disp = _disp.getMat(); + + computeDisparitySGBM( left, right, disp, *this, buffer ); + medianBlur(disp, disp, 3); + + if( speckleWindowSize > 0 ) + filterSpeckles(disp, (minDisparity - 1)*DISP_SCALE, speckleWindowSize, DISP_SCALE*speckleRange, buffer); +} + + +Rect getValidDisparityROI( Rect roi1, Rect roi2, + int minDisparity, + int numberOfDisparities, + int SADWindowSize ) +{ + int SW2 = SADWindowSize/2; + int minD = minDisparity, maxD = minDisparity + numberOfDisparities - 1; + + int xmin = max(roi1.x, roi2.x + maxD) + SW2; + int xmax = min(roi1.x + roi1.width, roi2.x + roi2.width - minD) - SW2; + int ymin = max(roi1.y, roi2.y) + SW2; + int ymax = min(roi1.y + roi1.height, roi2.y + roi2.height) - SW2; + + Rect r(xmin, ymin, xmax - xmin, ymax - ymin); + + return r.width > 0 && r.height > 0 ? r : Rect(); +} + +} + +void cv::filterSpeckles( InputOutputArray _img, double _newval, int maxSpeckleSize, + double _maxDiff, InputOutputArray __buf ) +{ + Mat img = _img.getMat(); + Mat temp, &_buf = __buf.needed() ? __buf.getMatRef() : temp; CV_Assert( img.type() == CV_16SC1 ); int newVal = cvRound(_newval); @@ -916,44 +957,11 @@ void filterSpeckles( Mat& img, double _newval, int maxSpeckleSize, double _maxDi } } } - - -void StereoSGBM::operator ()( const Mat& left, const Mat& right, Mat& disp ) -{ - CV_Assert( left.size() == right.size() && left.type() == right.type() && - left.depth() == DataType::depth ); - - disp.create( left.size(), CV_16S ); - - computeDisparitySGBM( left, right, disp, *this, buffer ); - medianBlur(disp, disp, 3); - if( speckleWindowSize > 0 ) - filterSpeckles(disp, (minDisparity - 1)*DISP_SCALE, speckleWindowSize, DISP_SCALE*speckleRange, buffer); -} - - -Rect getValidDisparityROI( Rect roi1, Rect roi2, - int minDisparity, - int numberOfDisparities, - int SADWindowSize ) -{ - int SW2 = SADWindowSize/2; - int minD = minDisparity, maxD = minDisparity + numberOfDisparities - 1; - - int xmin = max(roi1.x, roi2.x + maxD) + SW2; - int xmax = min(roi1.x + roi1.width, roi2.x + roi2.width - minD) - SW2; - int ymin = max(roi1.y, roi2.y) + SW2; - int ymax = min(roi1.y + roi1.height, roi2.y + roi2.height) - SW2; - - Rect r(xmin, ymin, xmax - xmin, ymax - ymin); - - return r.width > 0 && r.height > 0 ? r : Rect(); -} - - -void validateDisparity( Mat& disp, const Mat& cost, int minDisparity, int numberOfDisparities, int disp12MaxDiff ) +void cv::validateDisparity( InputOutputArray _disp, const InputArray& _cost, int minDisparity, + int numberOfDisparities, int disp12MaxDiff ) { + Mat disp = _disp.getMat(), cost = _cost.getMat(); int cols = disp.cols, rows = disp.rows; int minD = minDisparity, maxD = minDisparity + numberOfDisparities; int x, minX1 = max(maxD, 0), maxX1 = cols + min(minD, 0); @@ -1030,8 +1038,6 @@ void validateDisparity( Mat& disp, const Mat& cost, int minDisparity, int number } } } - -} CvRect cvGetValidDisparityROI( CvRect roi1, CvRect roi2, int minDisparity, int numberOfDisparities, int SADWindowSize ) diff --git a/modules/calib3d/test/test_cameracalibration.cpp b/modules/calib3d/test/test_cameracalibration.cpp index c14b70b5f5..eb24c5ced5 100644 --- a/modules/calib3d/test/test_cameracalibration.cpp +++ b/modules/calib3d/test/test_cameracalibration.cpp @@ -1244,8 +1244,13 @@ void CV_ProjectPointsTest_CPP::project( const Mat& objectPoints, const Mat& rvec const Mat& cameraMatrix, const Mat& distCoeffs, vector& imagePoints, Mat& dpdrot, Mat& dpdt, Mat& dpdf, Mat& dpdc, Mat& dpddist, double aspectRatio) { - projectPoints( objectPoints, rvec, tvec, cameraMatrix, distCoeffs, imagePoints, - dpdrot, dpdt, dpdf, dpdc, dpddist, aspectRatio ); + Mat J; + projectPoints( objectPoints, rvec, tvec, cameraMatrix, distCoeffs, imagePoints, J, aspectRatio); + J.colRange(0, 3).copyTo(dpdrot); + J.colRange(3, 6).copyTo(dpdt); + J.colRange(6, 8).copyTo(dpdf); + J.colRange(8, 10).copyTo(dpdc); + J.colRange(10, J.cols).copyTo(dpddist); } ///////////////////////////////// Stereo Calibration ///////////////////////////////////// @@ -1696,7 +1701,7 @@ void CV_StereoCalibrationTest_CPP::rectify( const Mat& cameraMatrix1, const Mat& Rect* validPixROI1, Rect* validPixROI2, int flags ) { stereoRectify( cameraMatrix1, distCoeffs1, cameraMatrix2, distCoeffs2, - imageSize, R, T, R1, R2, P1, P2, Q, alpha, newImageSize,validPixROI1, validPixROI2, flags ); + imageSize, R, T, R1, R2, P1, P2, Q, flags, alpha, newImageSize,validPixROI1, validPixROI2 ); } bool CV_StereoCalibrationTest_CPP::rectifyUncalibrated( const Mat& points1, diff --git a/modules/calib3d/test/test_solvepnp_ransac.cpp b/modules/calib3d/test/test_solvepnp_ransac.cpp index ea306dd611..b2e8c1cff2 100644 --- a/modules/calib3d/test/test_solvepnp_ransac.cpp +++ b/modules/calib3d/test/test_solvepnp_ransac.cpp @@ -104,8 +104,8 @@ protected: Mat rvec, tvec; vector inliers; - solvePnPRansac(Mat(points), Mat(points1), intrinsics, dist_coeffs, rvec, tvec, - false, 1000, 2.0, -1, &inliers); + solvePnPRansac(points, points1, intrinsics, dist_coeffs, rvec, tvec, + false, 1000, 2.0, -1, inliers); bool isTestSuccess = inliers.size() == 475; diff --git a/modules/core/include/opencv2/core/core.hpp b/modules/core/include/opencv2/core/core.hpp index a4edcb1db1..9751a5abcc 100644 --- a/modules/core/include/opencv2/core/core.hpp +++ b/modules/core/include/opencv2/core/core.hpp @@ -14,7 +14,7 @@ // For Open Source Computer Vision Library // // Copyright (C) 2000-2008, Intel Corporation, all rights reserved. -// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2009-2011, Willow Garage Inc., all rights reserved. // Third party copyrights are property of their respective owners. // // Redistribution and use in source and binary forms, with or without modification, @@ -121,7 +121,7 @@ enum { DFT_INVERSE=1, DFT_SCALE=2, DFT_ROWS=4, DFT_COMPLEX_OUTPUT=16, DFT_REAL_O class CV_EXPORTS Exception : public std::exception { public: - /*! + /*! Default constructor */ Exception() { code = 0; line = 0; } @@ -129,16 +129,16 @@ public: Full constructor. Normally the constuctor is not called explicitly. Instead, the macros CV_Error(), CV_Error_() and CV_Assert() are used. */ - Exception(int _code, const string& _err, const string& _func, const string& _file, int _line) - : code(_code), err(_err), func(_func), file(_file), line(_line) + Exception(int _code, const string& _err, const string& _func, const string& _file, int _line) + : code(_code), err(_err), func(_func), file(_file), line(_line) { formatMessage(); } - virtual ~Exception() throw() {} + virtual ~Exception() throw() {} /*! \return the error description and the context as a text string. */ - virtual const char *what() const throw() { return msg.c_str(); } + virtual const char *what() const throw() { return msg.c_str(); } void formatMessage() { @@ -148,13 +148,13 @@ public: msg = format("%s:%d: error: (%d) %s\n", file.c_str(), line, code, err.c_str()); } - string msg; ///< the formatted error message + string msg; ///< the formatted error message - int code; ///< error code @see CVStatus - string err; ///< error description - string func; ///< function name. Available only when the compiler supports __func__ macro - string file; ///< source file name where the error has occured - int line; ///< line number in the source file where the error has occured + int code; ///< error code @see CVStatus + string err; ///< error description + string func; ///< function name. Available only when the compiler supports __func__ macro + string file; ///< source file name where the error has occured + int line; ///< line number in the source file where the error has occured }; @@ -641,6 +641,8 @@ typedef Vec Vec4w; typedef Vec Vec2i; typedef Vec Vec3i; typedef Vec Vec4i; +typedef Vec Vec6i; +typedef Vec Vec8i; typedef Vec Vec2f; typedef Vec Vec3f; @@ -748,7 +750,7 @@ public: Point3_(); Point3_(_Tp _x, _Tp _y, _Tp _z); Point3_(const Point3_& pt); - explicit Point3_(const Point_<_Tp>& pt); + explicit Point3_(const Point_<_Tp>& pt); Point3_(const CvPoint3D32f& pt); Point3_(const Vec<_Tp, 3>& v); @@ -1252,10 +1254,90 @@ public: protected: _Tp* obj; //< the object pointer. - int* refcount; //< the associated bbbbbbbbbbbbbbbbbb reference counter + int* refcount; //< the associated reference counter +}; + + +//////////////////////// Input/Output Array Arguments ///////////////////////////////// + +/*! + Proxy datatype for passing Mat's and vector<>'s as input parameters + */ +class CV_EXPORTS InputArray +{ +public: + enum { KIND_SHIFT=16, NONE=0< InputArray(const vector<_Tp>& vec); + template InputArray(const vector >& vec); + InputArray(const vector& vec); + template InputArray(const Matx<_Tp, m, n>& matx); + InputArray(const double& val); + Mat getMat(int i=-1) const; + void getMatVector(vector& mv) const; + int kind() const; + Size size(int i=-1) const; + size_t total(int i=-1) const; + int type(int i=-1) const; + int depth(int i=-1) const; + int channels(int i=-1) const; + bool empty() const; + + int flags; + void* obj; + Size sz; +}; + + +enum +{ + DEPTH_MASK_8U = 1 << CV_8U, + DEPTH_MASK_8S = 1 << CV_8S, + DEPTH_MASK_16U = 1 << CV_16U, + DEPTH_MASK_16S = 1 << CV_16S, + DEPTH_MASK_32S = 1 << CV_32S, + DEPTH_MASK_32F = 1 << CV_32F, + DEPTH_MASK_64F = 1 << CV_64F, + DEPTH_MASK_ALL = (DEPTH_MASK_64F<<1)-1, + DEPTH_MASK_ALL_BUT_8S = DEPTH_MASK_ALL & ~DEPTH_MASK_8S, + DEPTH_MASK_FLT = DEPTH_MASK_32F + DEPTH_MASK_64F +}; + + +/*! + Proxy datatype for passing Mat's and vector<>'s as input parameters + */ +class CV_EXPORTS OutputArray : public InputArray +{ +public: + OutputArray(); + OutputArray(Mat& m); + template OutputArray(vector<_Tp>& vec); + template OutputArray(vector >& vec); + OutputArray(vector& vec); + template OutputArray(Matx<_Tp, m, n>& matx); + bool fixedSize() const; + bool fixedType() const; + bool needed() const; + Mat& getMatRef(int i=-1); + void create(Size sz, int type, int i=-1, bool allocateVector=false, int fixedDepthMask=0); + void create(int rows, int cols, int type, int i=-1, bool allowTransposed=false, int fixedDepthMask=0); + void create(int dims, const int* size, int type, int i=-1, bool allowTransposed=false, int fixedDepthMask=0); + void release(); + void clear(); }; -//////////////////////////////// Mat //////////////////////////////// +typedef InputArray InputArrayOfArrays; +typedef OutputArray OutputArrayOfArrays; + +typedef OutputArray InputOutputArray; + +/////////////////////////////////////// Mat /////////////////////////////////////////// enum { MAGIC_MASK=0xFFFF0000, TYPE_MASK=0x00000FFF, DEPTH_MASK=7 }; @@ -1563,19 +1645,18 @@ public: Mat clone() const; //! copies the matrix content to "m". // It calls m.create(this->size(), this->type()). - void copyTo( Mat& m ) const; - template void copyTo( vector<_Tp>& v ) const; + void copyTo( OutputArray m ) const; //! copies those matrix elements to "m" that are marked with non-zero mask elements. - void copyTo( Mat& m, const Mat& mask ) const; + void copyTo( OutputArray m, const InputArray& mask ) const; //! converts matrix to another datatype with optional scalng. See cvConvertScale. - void convertTo( Mat& m, int rtype, double alpha=1, double beta=0 ) const; + void convertTo( OutputArray m, int rtype, double alpha=1, double beta=0 ) const; void assignTo( Mat& m, int type=-1 ) const; //! sets every matrix element to s Mat& operator = (const Scalar& s); //! sets some of the matrix elements to s, according to the mask - Mat& setTo(const Scalar& s, const Mat& mask=Mat()); + Mat& setTo(const Scalar& s, const InputArray& mask=InputArray()); //! creates alternative matrix header for the same data, with different // number of channels and/or different number of rows. see cvReshape. Mat reshape(int _cn, int _rows=0) const; @@ -1586,13 +1667,13 @@ public: //! matrix inversion by means of matrix expressions MatExpr inv(int method=DECOMP_LU) const; //! per-element matrix multiplication by means of matrix expressions - MatExpr mul(const Mat& m, double scale=1) const; + MatExpr mul(const InputArray& m, double scale=1) const; MatExpr mul(const MatExpr& m, double scale=1) const; //! computes cross-product of 2 3D vectors - Mat cross(const Mat& m) const; + Mat cross(const InputArray& m) const; //! computes dot-product - double dot(const Mat& m) const; + double dot(const InputArray& m) const; //! Matlab-style matrix initialization static MatExpr zeros(int rows, int cols, int type); @@ -1809,7 +1890,7 @@ public: MStep step; }; - + /*! Random Number Generator @@ -1830,9 +1911,9 @@ public: operator ushort(); operator short(); operator unsigned(); - //! returns a random integer sampled uniformly from [0, N). - unsigned operator()(unsigned N); - unsigned operator ()(); + //! returns a random integer sampled uniformly from [0, N). + unsigned operator()(unsigned N); + unsigned operator ()(); operator int(); operator float(); operator double(); @@ -1842,14 +1923,12 @@ public: float uniform(float a, float b); //! returns uniformly distributed double-precision floating-point random number from [a,b) range double uniform(double a, double b); - void fill( Mat& mat, int distType, const Scalar& a, const Scalar& b ); - //! returns Gaussian random variate with mean zero. - double gaussian(double sigma); + void fill( InputOutputArray mat, int distType, const InputArray& a, const InputArray& b ); + //! returns Gaussian random variate with mean zero. + double gaussian(double sigma); uint64 state; }; - - /*! @@ -1879,6 +1958,7 @@ public: double epsilon; // the desired accuracy }; + //! swaps two matrices CV_EXPORTS void swap(Mat& a, Mat& b); @@ -1886,79 +1966,75 @@ CV_EXPORTS void swap(Mat& a, Mat& b); CV_EXPORTS Mat cvarrToMat(const CvArr* arr, bool copyData=false, bool allowND=true, int coiMode=0); //! extracts Channel of Interest from CvMat or IplImage and makes cv::Mat out of it. -CV_EXPORTS void extractImageCOI(const CvArr* arr, CV_OUT Mat& coiimg, int coi=-1); +CV_EXPORTS void extractImageCOI(const CvArr* arr, OutputArray coiimg, int coi=-1); //! inserts single-channel cv::Mat into a multi-channel CvMat or IplImage -CV_EXPORTS void insertImageCOI(const Mat& coiimg, CvArr* arr, int coi=-1); - +CV_EXPORTS void insertImageCOI(const InputArray& coiimg, CvArr* arr, int coi=-1); + //! adds one matrix to another (dst = src1 + src2) -CV_EXPORTS_W void add(const Mat& src1, const Mat& src2, CV_OUT Mat& dst, const Mat& mask CV_WRAP_DEFAULT(Mat())); +CV_EXPORTS_W void add(const InputArray& src1, const InputArray& src2, OutputArray dst, + const InputArray& mask=InputArray(), int dtype=-1); //! subtracts one matrix from another (dst = src1 - src2) -CV_EXPORTS_W void subtract(const Mat& src1, const Mat& src2, CV_OUT Mat& dst, const Mat& mask CV_WRAP_DEFAULT(Mat())); -//! adds one matrix to another (dst = src1 + src2) -CV_EXPORTS void add(const Mat& src1, const Mat& src2, CV_OUT Mat& dst); -//! subtracts one matrix from another (dst = src1 - src2) -CV_EXPORTS void subtract(const Mat& src1, const Mat& src2, CV_OUT Mat& dst); -//! adds scalar to a matrix (dst = src1 + src2) -CV_EXPORTS_W void add(const Mat& src1, const Scalar& src2, CV_OUT Mat& dst, const Mat& mask=Mat()); -//! subtracts scalar from a matrix (dst = src1 - src2) -CV_EXPORTS_W void subtract(const Mat& src1, const Scalar& src2, CV_OUT Mat& dst, const Mat& mask=Mat()); -//! subtracts matrix from scalar (dst = src1 - src2) -CV_EXPORTS_W void subtract(const Scalar& src1, const Mat& src2, CV_OUT Mat& dst, const Mat& mask=Mat()); +CV_EXPORTS_W void subtract(const InputArray& src1, const InputArray& src2, OutputArray dst, + const InputArray& mask=InputArray(), int dtype=-1); //! computes element-wise weighted product of the two arrays (dst = scale*src1*src2) -CV_EXPORTS_W void multiply(const Mat& src1, const Mat& src2, CV_OUT Mat& dst, double scale=1); +CV_EXPORTS_W void multiply(const InputArray& src1, const InputArray& src2, + OutputArray dst, double scale=1, int dtype=-1); + //! computes element-wise weighted quotient of the two arrays (dst = scale*src1/src2) -CV_EXPORTS_W void divide(const Mat& src1, const Mat& src2, CV_OUT Mat& dst, double scale=1); +CV_EXPORTS_W void divide(const InputArray& src1, const InputArray& src2, OutputArray dst, + double scale=1, int dtype=-1); + //! computes element-wise weighted reciprocal of an array (dst = scale/src2) -CV_EXPORTS_W void divide(double scale, const Mat& src2, CV_OUT Mat& dst); +CV_EXPORTS_W void divide(double scale, const InputArray& src2, + OutputArray dst, int dtype=-1); //! adds scaled array to another one (dst = alpha*src1 + src2) -CV_EXPORTS_W void scaleAdd(const Mat& src1, double alpha, const Mat& src2, CV_OUT Mat& dst); +CV_EXPORTS_W void scaleAdd(const InputArray& src1, double alpha, const InputArray& src2, OutputArray dst); + //! computes weighted sum of two arrays (dst = alpha*src1 + beta*src2 + gamma) -CV_EXPORTS_W void addWeighted(const Mat& src1, double alpha, const Mat& src2, - double beta, double gamma, CV_OUT Mat& dst); +CV_EXPORTS_W void addWeighted(const InputArray& src1, double alpha, const InputArray& src2, + double beta, double gamma, OutputArray dst, int dtype=-1); + //! scales array elements, computes absolute values and converts the results to 8-bit unsigned integers: dst(i)=saturate_castabs(src(i)*alpha+beta) -CV_EXPORTS_W void convertScaleAbs(const Mat& src, CV_OUT Mat& dst, double alpha=1, double beta=0); -//! transforms 8-bit unsigned integers using lookup table: dst(i)=lut(src(i)) -CV_EXPORTS_W void LUT(const Mat& src, const Mat& lut, CV_OUT Mat& dst); +CV_EXPORTS_W void convertScaleAbs(const InputArray& src, OutputArray dst, + double alpha=1, double beta=0); +//! transforms array of numbers using a lookup table: dst(i)=lut(src(i)) +CV_EXPORTS_W void LUT(const InputArray& src, const InputArray& lut, OutputArray dst, + int interpolation=0); //! computes sum of array elements -CV_EXPORTS_W Scalar sum(const Mat& src); +CV_EXPORTS_W Scalar sum(const InputArray& src); //! computes the number of nonzero array elements -CV_EXPORTS_W int countNonZero( const Mat& src ); - -//! computes mean value of array elements -CV_EXPORTS Scalar mean(const Mat& src); +CV_EXPORTS_W int countNonZero( const InputArray& src ); //! computes mean value of selected array elements -CV_EXPORTS_W Scalar mean(const Mat& src, const Mat& mask CV_WRAP_DEFAULT(Mat())); +CV_EXPORTS_W Scalar mean(const InputArray& src, const InputArray& mask=InputArray()); //! computes mean value and standard deviation of all or selected array elements -CV_EXPORTS_W void meanStdDev(const Mat& src, CV_OUT Scalar& mean, CV_OUT Scalar& stddev, const Mat& mask=Mat()); -//! computes norm of array -CV_EXPORTS double norm(const Mat& src1, int normType=NORM_L2); -//! computes norm of the difference between two arrays -CV_EXPORTS double norm(const Mat& src1, const Mat& src2, int normType=NORM_L2); +CV_EXPORTS_W void meanStdDev(const InputArray& src, OutputArray mean, OutputArray stddev, + const InputArray& mask=InputArray()); //! computes norm of the selected array part -CV_EXPORTS_W double norm(const Mat& src1, int normType, const Mat& mask CV_WRAP_DEFAULT(Mat())); +CV_EXPORTS_W double norm(const InputArray& src1, int normType=NORM_L2, const InputArray& mask=InputArray()); //! computes norm of selected part of the difference between two arrays -CV_EXPORTS_W double norm(const Mat& src1, const Mat& src2, - int normType, const Mat& mask CV_WRAP_DEFAULT(Mat())); +CV_EXPORTS_W double norm(const InputArray& src1, const InputArray& src2, + int normType=NORM_L2, const InputArray& mask=InputArray()); //! scales and shifts array elements so that either the specified norm (alpha) or the minimum (alpha) and maximum (beta) array values get the specified values -CV_EXPORTS_W void normalize( const Mat& src, CV_OUT Mat& dst, double alpha=1, double beta=0, - int norm_type=NORM_L2, int rtype=-1, const Mat& mask=Mat()); +CV_EXPORTS_W void normalize( const InputArray& src, OutputArray dst, double alpha=1, double beta=0, + int norm_type=NORM_L2, int dtype=-1, const InputArray& mask=InputArray()); //! finds global minimum and maximum array elements and returns their values and their locations -CV_EXPORTS_W void minMaxLoc(const Mat& src, CV_OUT double* minVal, - CV_OUT double* maxVal=0, CV_OUT Point* minLoc=0, - CV_OUT Point* maxLoc=0, const Mat& mask=Mat()); -CV_EXPORTS void minMaxIdx(const Mat& src, double* minVal, double* maxVal, - int* minIdx=0, int* maxIdx=0, const Mat& mask=Mat()); +CV_EXPORTS_W void minMaxLoc(const InputArray& src, CV_OUT double* minVal, + CV_OUT double* maxVal=0, CV_OUT Point* minLoc=0, + CV_OUT Point* maxLoc=0, const InputArray& mask=InputArray()); +CV_EXPORTS void minMaxIdx(const InputArray& src, double* minVal, double* maxVal, + int* minIdx=0, int* maxIdx=0, const InputArray& mask=InputArray()); //! transforms 2D matrix to 1D row or column vector by taking sum, minimum, maximum or mean value over all the rows -CV_EXPORTS_W void reduce(const Mat& src, CV_OUT Mat& dst, int dim, int rtype, int dtype=-1); +CV_EXPORTS_W void reduce(const InputArray& src, OutputArray dst, int dim, int rtype, int dtype=-1); + //! makes multi-channel array out of several single-channel arrays -CV_EXPORTS void merge(const Mat* mv, size_t count, CV_OUT Mat& dst); +CV_EXPORTS void merge(const Mat* mv, size_t count, OutputArray dst); //! makes multi-channel array out of several single-channel arrays -CV_EXPORTS_W void merge(const vector& mv, Mat& dst); +CV_EXPORTS_W void merge(const vector& mv, OutputArray dst); //! copies each plane of a multi-channel array to a dedicated array CV_EXPORTS void split(const Mat& src, Mat* mvbegin); @@ -1969,133 +2045,131 @@ CV_EXPORTS_W void split(const Mat& m, vector& mv); CV_EXPORTS void mixChannels(const Mat* src, size_t nsrcs, Mat* dst, size_t ndsts, const int* fromTo, size_t npairs); CV_EXPORTS void mixChannels(const vector& src, vector& dst, - const int* fromTo, int npairs); + const int* fromTo, size_t npairs); //! reverses the order of the rows, columns or both in a matrix -CV_EXPORTS_W void flip(const Mat& src, CV_OUT Mat& dst, int flipCode); +CV_EXPORTS_W void flip(const InputArray& src, OutputArray dst, int flipCode); //! replicates the input matrix the specified number of times in the horizontal and/or vertical direction -CV_EXPORTS_W void repeat(const Mat& src, int ny, int nx, CV_OUT Mat& dst); +CV_EXPORTS_W void repeat(const InputArray& src, int ny, int nx, OutputArray dst); CV_EXPORTS Mat repeat(const Mat& src, int ny, int nx); -CV_EXPORTS void hconcat(const Mat* src, size_t nsrc, Mat& dst); -CV_EXPORTS void hconcat(const Mat& src1, const Mat& src2, Mat& dst); -CV_EXPORTS_W void hconcat(const vector& src, CV_OUT Mat& dst); +CV_EXPORTS void hconcat(const Mat* src, size_t nsrc, OutputArray dst); +CV_EXPORTS void hconcat(const InputArray& src1, const InputArray& src2, OutputArray dst); +CV_EXPORTS_W void hconcat(const InputArray& src, OutputArray dst); -CV_EXPORTS void vconcat(const Mat* src, size_t nsrc, Mat& dst); -CV_EXPORTS void vconcat(const Mat& src1, const Mat& src2, Mat& dst); -CV_EXPORTS_W void vconcat(const vector& src, CV_OUT Mat& dst); +CV_EXPORTS void vconcat(const Mat* src, size_t nsrc, OutputArray dst); +CV_EXPORTS void vconcat(const InputArray& src1, const InputArray& src2, OutputArray dst); +CV_EXPORTS_W void vconcat(const InputArray& src, OutputArray dst); //! computes bitwise conjunction of the two arrays (dst = src1 & src2) -CV_EXPORTS_W void bitwise_and(const Mat& src1, const Mat& src2, CV_OUT Mat& dst, const Mat& mask=Mat()); +CV_EXPORTS_W void bitwise_and(const InputArray& src1, const InputArray& src2, + OutputArray dst, const InputArray& mask=InputArray()); //! computes bitwise disjunction of the two arrays (dst = src1 | src2) -CV_EXPORTS_W void bitwise_or(const Mat& src1, const Mat& src2, CV_OUT Mat& dst, const Mat& mask=Mat()); +CV_EXPORTS_W void bitwise_or(const InputArray& src1, const InputArray& src2, + OutputArray dst, const InputArray& mask=InputArray()); //! computes bitwise exclusive-or of the two arrays (dst = src1 ^ src2) -CV_EXPORTS_W void bitwise_xor(const Mat& src1, const Mat& src2, CV_OUT Mat& dst, const Mat& mask=Mat()); -//! computes bitwise conjunction of an array and scalar (dst = src1 & src2) -CV_EXPORTS_W void bitwise_and(const Mat& src1, const Scalar& src2, CV_OUT Mat& dst, const Mat& mask=Mat()); -//! computes bitwise disjunction of an array and scalar (dst = src1 | src2) -CV_EXPORTS_W void bitwise_or(const Mat& src1, const Scalar& src2, CV_OUT Mat& dst, const Mat& mask=Mat()); -//! computes bitwise exclusive-or of an array and scalar (dst = src1 ^ src2) -CV_EXPORTS_W void bitwise_xor(const Mat& src1, const Scalar& src2, CV_OUT Mat& dst, const Mat& mask=Mat()); +CV_EXPORTS_W void bitwise_xor(const InputArray& src1, const InputArray& src2, + OutputArray dst, const InputArray& mask=InputArray()); //! inverts each bit of array (dst = ~src) -CV_EXPORTS_W void bitwise_not(const Mat& src, CV_OUT Mat& dst); +CV_EXPORTS_W void bitwise_not(const InputArray& src, OutputArray dst, + const InputArray& mask=InputArray()); //! computes element-wise absolute difference of two arrays (dst = abs(src1 - src2)) -CV_EXPORTS_W void absdiff(const Mat& src1, const Mat& src2, CV_OUT Mat& dst); -//! computes element-wise absolute difference of array and scalar (dst = abs(src1 - src2)) -CV_EXPORTS_W void absdiff(const Mat& src1, const Scalar& src2, CV_OUT Mat& dst); +CV_EXPORTS_W void absdiff(const InputArray& src1, const InputArray& src2, OutputArray dst); //! set mask elements for those array elements which are within the element-specific bounding box (dst = lowerb <= src && src < upperb) -CV_EXPORTS_W void inRange(const Mat& src, const Mat& lowerb, - const Mat& upperb, CV_OUT Mat& dst); -//! set mask elements for those array elements which are within the fixed bounding box (dst = lowerb <= src && src < upperb) -CV_EXPORTS_W void inRange(const Mat& src, const Scalar& lowerb, - const Scalar& upperb, CV_OUT Mat& dst); +CV_EXPORTS_W void inRange(const InputArray& src, const InputArray& lowerb, + const InputArray& upperb, OutputArray dst); //! compares elements of two arrays (dst = src1 src2) -CV_EXPORTS_W void compare(const Mat& src1, const Mat& src2, CV_OUT Mat& dst, int cmpop); -//! compares elements of array with scalar (dst = src1 src2) -CV_EXPORTS_W void compare(const Mat& src1, double s, CV_OUT Mat& dst, int cmpop); +CV_EXPORTS_W void compare(const InputArray& src1, const InputArray& src2, OutputArray dst, int cmpop); //! computes per-element minimum of two arrays (dst = min(src1, src2)) -CV_EXPORTS_W void min(const Mat& src1, const Mat& src2, CV_OUT Mat& dst); +CV_EXPORTS_W void min(const InputArray& src1, const InputArray& src2, OutputArray dst); +//! computes per-element maximum of two arrays (dst = max(src1, src2)) +CV_EXPORTS_W void max(const InputArray& src1, const InputArray& src2, OutputArray dst); + +//! computes per-element minimum of two arrays (dst = min(src1, src2)) +CV_EXPORTS void min(const Mat& src1, const Mat& src2, Mat& dst); //! computes per-element minimum of array and scalar (dst = min(src1, src2)) -CV_EXPORTS_W void min(const Mat& src1, double src2, CV_OUT Mat& dst); +CV_EXPORTS void min(const Mat& src1, double src2, Mat& dst); //! computes per-element maximum of two arrays (dst = max(src1, src2)) -CV_EXPORTS_W void max(const Mat& src1, const Mat& src2, CV_OUT Mat& dst); +CV_EXPORTS void max(const Mat& src1, const Mat& src2, Mat& dst); //! computes per-element maximum of array and scalar (dst = max(src1, src2)) -CV_EXPORTS_W void max(const Mat& src1, double src2, CV_OUT Mat& dst); - +CV_EXPORTS void max(const Mat& src1, double src2, Mat& dst); + //! computes square root of each matrix element (dst = src**0.5) -CV_EXPORTS_W void sqrt(const Mat& src, CV_OUT Mat& dst); +CV_EXPORTS_W void sqrt(const InputArray& src, OutputArray dst); //! raises the input matrix elements to the specified power (b = a**power) -CV_EXPORTS_W void pow(const Mat& src, double power, CV_OUT Mat& dst); +CV_EXPORTS_W void pow(const InputArray& src, double power, OutputArray dst); //! computes exponent of each matrix element (dst = e**src) -CV_EXPORTS_W void exp(const Mat& src, CV_OUT Mat& dst); +CV_EXPORTS_W void exp(const InputArray& src, OutputArray dst); //! computes natural logarithm of absolute value of each matrix element: dst = log(abs(src)) -CV_EXPORTS_W void log(const Mat& src, CV_OUT Mat& dst); +CV_EXPORTS_W void log(const InputArray& src, OutputArray dst); //! computes cube root of the argument CV_EXPORTS_W float cubeRoot(float val); //! computes the angle in degrees (0..360) of the vector (x,y) CV_EXPORTS_W float fastAtan2(float y, float x); //! converts polar coordinates to Cartesian -CV_EXPORTS_W void polarToCart(const Mat& magnitude, const Mat& angle, - CV_OUT Mat& x, CV_OUT Mat& y, bool angleInDegrees=false); +CV_EXPORTS_W void polarToCart(const InputArray& magnitude, const InputArray& angle, + OutputArray x, OutputArray y, bool angleInDegrees=false); //! converts Cartesian coordinates to polar -CV_EXPORTS_W void cartToPolar(const Mat& x, const Mat& y, - CV_OUT Mat& magnitude, CV_OUT Mat& angle, - bool angleInDegrees=false); +CV_EXPORTS_W void cartToPolar(const InputArray& x, const InputArray& y, + OutputArray magnitude, OutputArray angle, + bool angleInDegrees=false); //! computes angle (angle(i)) of each (x(i), y(i)) vector -CV_EXPORTS_W void phase(const Mat& x, const Mat& y, CV_OUT Mat& angle, +CV_EXPORTS_W void phase(const InputArray& x, const InputArray& y, OutputArray angle, bool angleInDegrees=false); //! computes magnitude (magnitude(i)) of each (x(i), y(i)) vector -CV_EXPORTS_W void magnitude(const Mat& x, const Mat& y, CV_OUT Mat& magnitude); +CV_EXPORTS_W void magnitude(const InputArray& x, const InputArray& y, OutputArray magnitude); //! checks that each matrix element is within the specified range. -CV_EXPORTS_W bool checkRange(const Mat& a, bool quiet=true, CV_OUT Point* pt=0, +CV_EXPORTS_W bool checkRange(const InputArray& a, bool quiet=true, CV_OUT Point* pt=0, double minVal=-DBL_MAX, double maxVal=DBL_MAX); //! implements generalized matrix product algorithm GEMM from BLAS -CV_EXPORTS_W void gemm(const Mat& src1, const Mat& src2, double alpha, - const Mat& src3, double gamma, CV_OUT Mat& dst, int flags=0); +CV_EXPORTS_W void gemm(const InputArray& src1, const InputArray& src2, double alpha, + const InputArray& src3, double gamma, OutputArray dst, int flags=0); //! multiplies matrix by its transposition from the left or from the right -CV_EXPORTS_W void mulTransposed( const Mat& src, CV_OUT Mat& dst, bool aTa, - const Mat& delta=Mat(), - double scale=1, int rtype=-1 ); +CV_EXPORTS_W void mulTransposed( const InputArray& src, OutputArray dst, bool aTa, + const InputArray& delta=InputArray(), + double scale=1, int dtype=-1 ); //! transposes the matrix -CV_EXPORTS_W void transpose(const Mat& src, CV_OUT Mat& dst); +CV_EXPORTS_W void transpose(const InputArray& src, OutputArray dst); //! performs affine transformation of each element of multi-channel input matrix -CV_EXPORTS_W void transform(const Mat& src, CV_OUT Mat& dst, const Mat& m ); +CV_EXPORTS_W void transform(const InputArray& src, OutputArray dst, const InputArray& m ); //! performs perspective transformation of each element of multi-channel input matrix -CV_EXPORTS_W void perspectiveTransform(const Mat& src, CV_OUT Mat& dst, const Mat& m ); +CV_EXPORTS_W void perspectiveTransform(const InputArray& src, OutputArray dst, const InputArray& m ); //! extends the symmetrical matrix from the lower half or from the upper half -CV_EXPORTS_W void completeSymm(Mat& mtx, bool lowerToUpper=false); +CV_EXPORTS_W void completeSymm(InputOutputArray mtx, bool lowerToUpper=false); //! initializes scaled identity matrix -CV_EXPORTS_W void setIdentity(Mat& mtx, const Scalar& s=Scalar(1)); +CV_EXPORTS_W void setIdentity(InputOutputArray mtx, const Scalar& s=Scalar(1)); //! computes determinant of a square matrix -CV_EXPORTS_W double determinant(const Mat& mtx); +CV_EXPORTS_W double determinant(const InputArray& mtx); //! computes trace of a matrix -CV_EXPORTS_W Scalar trace(const Mat& mtx); +CV_EXPORTS_W Scalar trace(const InputArray& mtx); //! computes inverse or pseudo-inverse matrix -CV_EXPORTS_W double invert(const Mat& src, CV_OUT Mat& dst, int flags=DECOMP_LU); +CV_EXPORTS_W double invert(const InputArray& src, OutputArray dst, int flags=DECOMP_LU); //! solves linear system or a least-square problem -CV_EXPORTS_W bool solve(const Mat& src1, const Mat& src2, CV_OUT Mat& dst, int flags=DECOMP_LU); +CV_EXPORTS_W bool solve(const InputArray& src1, const InputArray& src2, + OutputArray dst, int flags=DECOMP_LU); //! sorts independently each matrix row or each matrix column -CV_EXPORTS_W void sort(const Mat& src, CV_OUT Mat& dst, int flags); +CV_EXPORTS_W void sort(const InputArray& src, OutputArray dst, int flags); //! sorts independently each matrix row or each matrix column -CV_EXPORTS_W void sortIdx(const Mat& src, CV_OUT Mat& dst, int flags); +CV_EXPORTS_W void sortIdx(const InputArray& src, OutputArray dst, int flags); //! finds real roots of a cubic polynomial -CV_EXPORTS_W int solveCubic(const Mat& coeffs, CV_OUT Mat& roots); +CV_EXPORTS_W int solveCubic(const InputArray& coeffs, OutputArray roots); //! finds real and complex roots of a polynomial -CV_EXPORTS_W double solvePoly(const Mat& coeffs, CV_OUT Mat& roots, int maxIters=300); +CV_EXPORTS_W double solvePoly(const InputArray& coeffs, OutputArray roots, int maxIters=300); //! finds eigenvalues of a symmetric matrix -CV_EXPORTS bool eigen(const Mat& src, CV_OUT Mat& eigenvalues, int lowindex=-1, +CV_EXPORTS bool eigen(const InputArray& src, OutputArray eigenvalues, int lowindex=-1, int highindex=-1); //! finds eigenvalues and eigenvectors of a symmetric matrix -CV_EXPORTS bool eigen(const Mat& src, CV_OUT Mat& eigenvalues, CV_OUT Mat& eigenvectors, +CV_EXPORTS bool eigen(const InputArray& src, OutputArray eigenvalues, + OutputArray eigenvectors, int lowindex=-1, int highindex=-1); //! computes covariation matrix of a set of samples CV_EXPORTS void calcCovarMatrix( const Mat* samples, int nsamples, Mat& covar, Mat& mean, int flags, int ctype=CV_64F); //! computes covariation matrix of a set of samples -CV_EXPORTS_W void calcCovarMatrix( const Mat& samples, CV_OUT Mat& covar, CV_OUT Mat& mean, - int flags, int ctype=CV_64F); +CV_EXPORTS_W void calcCovarMatrix( const InputArray& samples, OutputArray covar, + OutputArray mean, int flags, int ctype=CV_64F); /*! Principal Component Analysis @@ -2157,17 +2231,17 @@ public: //! default constructor PCA(); //! the constructor that performs PCA - PCA(const Mat& data, const Mat& mean, int flags, int maxComponents=0); + PCA(const InputArray& data, const InputArray& mean, int flags, int maxComponents=0); //! operator that performs PCA. The previously stored data, if any, is released - PCA& operator()(const Mat& data, const Mat& mean, int flags, int maxComponents=0); + PCA& operator()(const InputArray& data, const InputArray& mean, int flags, int maxComponents=0); //! projects vector from the original space to the principal components subspace - Mat project(const Mat& vec) const; + Mat project(const InputArray& vec) const; //! projects vector from the original space to the principal components subspace - void project(const Mat& vec, CV_OUT Mat& result) const; + void project(const InputArray& vec, OutputArray result) const; //! reconstructs the original vector from the projection - Mat backProject(const Mat& vec) const; + Mat backProject(const InputArray& vec) const; //! reconstructs the original vector from the projection - void backProject(const Mat& vec, CV_OUT Mat& result) const; + void backProject(const InputArray& vec, OutputArray result) const; Mat eigenvectors; //!< eigenvectors of the covariation matrix Mat eigenvalues; //!< eigenvalues of the covariation matrix @@ -2194,17 +2268,19 @@ public: //! the default constructor SVD(); //! the constructor that performs SVD - SVD( const Mat& src, int flags=0 ); + SVD( const InputArray& src, int flags=0 ); //! the operator that performs SVD. The previously allocated SVD::u, SVD::w are SVD::vt are released. - SVD& operator ()( const Mat& src, int flags=0 ); + SVD& operator ()( const InputArray& src, int flags=0 ); //! decomposes matrix and stores the results to user-provided matrices - static void compute( const Mat& src, CV_OUT Mat& w, CV_OUT Mat& u, CV_OUT Mat& vt, int flags=0 ); + static void compute( const InputArray& src, OutputArray w, + OutputArray u, OutputArray vt, int flags=0 ); //! computes singular values of a matrix - static void compute( const Mat& src, CV_OUT Mat& w, int flags=0 ); + static void compute( const InputArray& src, OutputArray w, int flags=0 ); //! performs back substitution - static void backSubst( const Mat& w, const Mat& u, const Mat& vt, - const Mat& rhs, CV_OUT Mat& dst ); + static void backSubst( const InputArray& w, const InputArray& u, + const InputArray& vt, const InputArray& rhs, + OutputArray dst ); template static void compute( const Matx<_Tp, m, n>& a, Matx<_Tp, nm, 1>& w, Matx<_Tp, m, nm>& u, Matx<_Tp, n, nm>& vt ); @@ -2214,29 +2290,29 @@ public: const Matx<_Tp, m, nm>& u, const Matx<_Tp, n, nm>& vt, const Matx<_Tp, m, nb>& rhs, Matx<_Tp, n, nb>& dst ); //! finds dst = arg min_{|dst|=1} |m*dst| - static void solveZ( const Mat& src, CV_OUT Mat& dst ); + static void solveZ( const InputArray& src, OutputArray dst ); //! performs back substitution, so that dst is the solution or pseudo-solution of m*dst = rhs, where m is the decomposed matrix - void backSubst( const Mat& rhs, CV_OUT Mat& dst ) const; + void backSubst( const InputArray& rhs, OutputArray dst ) const; Mat u, w, vt; }; //! computes Mahalanobis distance between two vectors: sqrt((v1-v2)'*icovar*(v1-v2)), where icovar is the inverse covariation matrix -CV_EXPORTS_W double Mahalanobis(const Mat& v1, const Mat& v2, const Mat& icovar); +CV_EXPORTS_W double Mahalanobis(const InputArray& v1, const InputArray& v2, const InputArray& icovar); //! a synonym for Mahalanobis -CV_EXPORTS double Mahalonobis(const Mat& v1, const Mat& v2, const Mat& icovar); +CV_EXPORTS double Mahalonobis(const InputArray& v1, const InputArray& v2, const InputArray& icovar); //! performs forward or inverse 1D or 2D Discrete Fourier Transformation -CV_EXPORTS_W void dft(const Mat& src, CV_OUT Mat& dst, int flags=0, int nonzeroRows=0); +CV_EXPORTS_W void dft(const InputArray& src, OutputArray dst, int flags=0, int nonzeroRows=0); //! performs inverse 1D or 2D Discrete Fourier Transformation -CV_EXPORTS_W void idft(const Mat& src, CV_OUT Mat& dst, int flags=0, int nonzeroRows=0); +CV_EXPORTS_W void idft(const InputArray& src, OutputArray dst, int flags=0, int nonzeroRows=0); //! performs forward or inverse 1D or 2D Discrete Cosine Transformation -CV_EXPORTS_W void dct(const Mat& src, CV_OUT Mat& dst, int flags=0); +CV_EXPORTS_W void dct(const InputArray& src, OutputArray dst, int flags=0); //! performs inverse 1D or 2D Discrete Cosine Transformation -CV_EXPORTS_W void idct(const Mat& src, CV_OUT Mat& dst, int flags=0); +CV_EXPORTS_W void idct(const InputArray& src, OutputArray dst, int flags=0); //! computes element-wise product of the two Fourier spectrums. The second spectrum can optionally be conjugated before the multiplication -CV_EXPORTS_W void mulSpectrums(const Mat& a, const Mat& b, CV_OUT Mat& c, - int flags, bool conjB=false); +CV_EXPORTS_W void mulSpectrums(const InputArray& a, const InputArray& b, OutputArray c, + int flags, bool conjB=false); //! computes the minimal vector size vecsize1 >= vecsize so that the dft() of the vector of length vecsize1 can be computed efficiently CV_EXPORTS_W int getOptimalDFTSize(int vecsize); @@ -2250,9 +2326,9 @@ enum KMEANS_USE_INITIAL_LABELS=1 // Uses the user-provided labels for K-Means initialization }; //! clusters the input data using k-Means algorithm -CV_EXPORTS_W double kmeans( const Mat& data, int K, CV_OUT Mat& bestLabels, - TermCriteria criteria, int attempts, - int flags, CV_OUT Mat* centers=0 ); +CV_EXPORTS_W double kmeans( const InputArray& data, int K, CV_OUT InputOutputArray bestLabels, + TermCriteria criteria, int attempts, + int flags, OutputArray centers=OutputArray() ); //! returns the thread-local Random number generator CV_EXPORTS RNG& theRNG(); @@ -2261,13 +2337,13 @@ CV_EXPORTS RNG& theRNG(); template static inline _Tp randu() { return (_Tp)theRNG(); } //! fills array with uniformly-distributed random numbers from the range [low, high) -CV_EXPORTS_W void randu(CV_OUT Mat& dst, const Scalar& low, const Scalar& high); +CV_EXPORTS_W void randu(CV_IN_OUT OutputArray dst, const InputArray& low, const InputArray& high); //! fills array with normally-distributed random numbers with the specified mean and the standard deviation -CV_EXPORTS_W void randn(CV_OUT Mat& dst, const Scalar& mean, const Scalar& stddev); +CV_EXPORTS_W void randn(CV_IN_OUT OutputArray dst, const InputArray& mean, const InputArray& stddev); //! shuffles the input array elements -CV_EXPORTS void randShuffle(Mat& dst, double iterFactor=1., RNG* rng=0); +CV_EXPORTS void randShuffle(InputOutputArray dst, double iterFactor=1., RNG* rng=0); //! draws the line segment (pt1, pt2) in the image CV_EXPORTS_W void line(Mat& img, Point pt1, Point pt2, const Scalar& color, @@ -2351,8 +2427,8 @@ public: //! converts elliptic arc to a polygonal curve CV_EXPORTS_W void ellipse2Poly( Point center, Size axes, int angle, - int arcStart, int arcEnd, int delta, - CV_OUT vector& pts ); + int arcStart, int arcEnd, int delta, + CV_OUT vector& pts ); enum { @@ -2828,6 +2904,7 @@ template class CV_EXPORTS Au { public: typedef _Tp value_type; + enum { buffer_padding = (int)((16 + sizeof(_Tp) - 1)/sizeof(_Tp)) }; //! the default contructor AutoBuffer(); @@ -2851,7 +2928,7 @@ protected: //! size of the real buffer size_t size; //! pre-allocated buffer - _Tp buf[fixed_size]; + _Tp buf[fixed_size+buffer_padding]; }; /////////////////////////// multi-dimensional dense matrix ////////////////////////// @@ -2912,9 +2989,11 @@ public: //! the default constructor NAryMatIterator(); //! the full constructor taking arbitrary number of n-dim matrices + NAryMatIterator(const Mat** arrays, uchar** ptrs, int narrays=-1); + //! the full constructor taking arbitrary number of n-dim matrices NAryMatIterator(const Mat** arrays, Mat* planes, int narrays=-1); //! the separate iterator initialization method - void init(const Mat** arrays, Mat* planes, int narrays=-1); + void init(const Mat** arrays, Mat* planes, uchar** ptrs, int narrays=-1); //! proceeds to the next plane of every iterated matrix NAryMatIterator& operator ++(); @@ -2925,12 +3004,17 @@ public: const Mat** arrays; //! the current planes Mat* planes; + //! data pointers + uchar** ptrs; //! the number of arrays int narrays; - //! the number of planes in each array - int nplanes; + //! the number of hyper-planes that the iterator steps through + size_t nplanes; + //! the size of each segment (in elements) + size_t size; protected: - int iterdepth, idx; + int iterdepth; + size_t idx; }; //typedef NAryMatIterator NAryMatNDIterator; @@ -3081,7 +3165,7 @@ public: \param try1d if true and m is a single-column matrix (Nx1), then the sparse matrix will be 1-dimensional. */ - SparseMat(const Mat& m); + explicit SparseMat(const Mat& m); //! converts old-style sparse matrix to the new-style. All the data is copied SparseMat(const CvSparseMat* m); //! the destructor @@ -3563,39 +3647,30 @@ public: //! the default constructor CV_WRAP KDTree(); //! the full constructor that builds the search tree - CV_WRAP KDTree(const Mat& _points, bool copyAndReorderPoints=false); + CV_WRAP KDTree(const InputArray& points, bool copyAndReorderPoints=false); //! the full constructor that builds the search tree - CV_WRAP KDTree(const Mat& _points, const Mat& _labels, bool copyAndReorderPoints=false); + CV_WRAP KDTree(const InputArray& points, const InputArray& _labels, + bool copyAndReorderPoints=false); //! builds the search tree - CV_WRAP void build(const Mat& _points, bool copyAndReorderPoints=false); + CV_WRAP void build(const InputArray& points, bool copyAndReorderPoints=false); //! builds the search tree - CV_WRAP void build(const Mat& _points, const Mat& _labels, bool copyAndReorderPoints=false); + CV_WRAP void build(const InputArray& points, const InputArray& labels, + bool copyAndReorderPoints=false); //! finds the K nearest neighbors of "vec" while looking at Emax (at most) leaves - int findNearest(const float* vec, - int K, int Emax, int* neighborsIdx, - Mat* neighbors=0, float* dist=0, int* labels=0) const; - //! finds the K nearest neighbors while looking at Emax (at most) leaves - int findNearest(const float* vec, int K, int Emax, - vector* neighborsIdx, - Mat* neighbors=0, - vector* dist=0, - vector* labels=0) const; - CV_WRAP int findNearest(const vector& vec, int K, int Emax, - CV_OUT vector* neighborsIdx, - CV_OUT Mat* neighbors=0, - CV_OUT vector* dist=0, - CV_OUT vector* labels=0) const; + CV_WRAP int findNearest(const InputArray& vec, int K, int Emax, + OutputArray neighborsIdx, + OutputArray neighbors=OutputArray(), + OutputArray dist=OutputArray(), + OutputArray labels=OutputArray()) const; //! finds all the points from the initial set that belong to the specified box - void findOrthoRange(const float* minBounds, const float* maxBounds, - vector* neighborsIdx, Mat* neighbors=0, - vector* labels=0) const; - CV_WRAP void findOrthoRange(const vector& minBounds, const vector& maxBounds, - CV_OUT vector* neighborsIdx, CV_OUT Mat* neighbors=0, - CV_OUT vector* labels=0) const; + CV_WRAP void findOrthoRange(const InputArray& minBounds, + const InputArray& maxBounds, + OutputArray neighborsIdx, + OutputArray neighbors=OutputArray(), + OutputArray labels=OutputArray()) const; //! returns vectors with the specified indices - void getPoints(const int* idx, size_t nidx, Mat& pts, vector* labels=0) const; - //! returns vectors with the specified indices - CV_WRAP void getPoints(const vector& idxs, Mat& pts, CV_OUT vector* labels=0) const; + CV_WRAP void getPoints(const InputArray& idx, OutputArray pts, + OutputArray labels=OutputArray()) const; //! return a vector with the specified index const float* getPoint(int ptidx, int* label=0) const; //! returns the search space dimensionality @@ -4042,7 +4117,7 @@ public: int index; }; -#if 0 + class CV_EXPORTS AlgorithmImpl; /*! @@ -4088,7 +4163,6 @@ protected: Ptr impl; }; -#endif } diff --git a/modules/core/include/opencv2/core/mat.hpp b/modules/core/include/opencv2/core/mat.hpp index 22b65fa53b..41cd458a4f 100644 --- a/modules/core/include/opencv2/core/mat.hpp +++ b/modules/core/include/opencv2/core/mat.hpp @@ -608,21 +608,6 @@ template inline MatIterator_<_Tp> Mat::end() return it; } - -template inline void Mat::copyTo(vector<_Tp>& v) const -{ - int n = checkVector(DataType<_Tp>::channels); - if( empty() || n == 0 ) - { - v.clear(); - return; - } - CV_Assert( n > 0 ); - v.resize(n); - Mat temp(dims, size.p, DataType<_Tp>::type, &v[0]); - convertTo(temp, DataType<_Tp>::type); -} - template inline Mat::operator vector<_Tp>() const { vector<_Tp> v; @@ -726,10 +711,12 @@ static inline Mat cvarrToMatND(const CvArr* arr, bool copyData=false, int coiMod ///////////////////////////////////////////// SVD ////////////////////////////////////////////////////// inline SVD::SVD() {} -inline SVD::SVD( const Mat& m, int flags ) { operator ()(m, flags); } -inline void SVD::solveZ( const Mat& m, Mat& dst ) +inline SVD::SVD( const InputArray& m, int flags ) { operator ()(m, flags); } +inline void SVD::solveZ( const InputArray& m, OutputArray _dst ) { SVD svd(m); + _dst.create(svd.vt.cols, 1, svd.vt.type()); + Mat dst = _dst.getMat(); svd.vt.row(svd.vt.rows-1).reshape(1,svd.vt.cols).copyTo(dst); } @@ -1075,6 +1062,22 @@ process( const Mat_& m1, const Mat_& m2, Mat_& m3, Op op ) } } + +/////////////////////////////// Input/Output Arrays ///////////////////////////////// + +template InputArray::InputArray(const vector<_Tp>& vec) + : flags(STD_VECTOR + DataType<_Tp>::type), obj((void*)&vec) {} + +template InputArray::InputArray(const vector >& vec) + : flags(STD_VECTOR_VECTOR + DataType<_Tp>::type), obj((void*)&vec) {} + +template InputArray::InputArray(const Matx<_Tp, m, n>& mtx) + : flags(MATX + DataType<_Tp>::type), obj((void*)&mtx), sz(n, m) {} + +template OutputArray::OutputArray(vector<_Tp>& vec) : InputArray(vec) {} +template OutputArray::OutputArray(vector >& vec) : InputArray(vec) {} +template OutputArray::OutputArray(Matx<_Tp, m, n>& mtx) : InputArray(mtx) {} + //////////////////////////////////// Matrix Expressions ///////////////////////////////////////// class CV_EXPORTS MatOp @@ -1113,6 +1116,9 @@ public: virtual void transpose(const MatExpr& expr, MatExpr& res) const; virtual void matmul(const MatExpr& expr1, const MatExpr& expr2, MatExpr& res) const; virtual void invert(const MatExpr& expr, int method, MatExpr& res) const; + + virtual Size size(const MatExpr& expr) const; + virtual int type(const MatExpr& expr) const; }; @@ -1152,6 +1158,9 @@ public: MatExpr mul(const MatExpr& e, double scale=1) const; MatExpr mul(const Mat& m, double scale=1) const; + Size size() const; + int type() const; + const MatOp* op; int flags; diff --git a/modules/core/include/opencv2/core/operations.hpp b/modules/core/include/opencv2/core/operations.hpp index 10c94f3b07..45a6c6e87c 100644 --- a/modules/core/include/opencv2/core/operations.hpp +++ b/modules/core/include/opencv2/core/operations.hpp @@ -2298,10 +2298,17 @@ inline Point LineIterator::pos() const /////////////////////////////// AutoBuffer //////////////////////////////////////// template inline AutoBuffer<_Tp, fixed_size>::AutoBuffer() -: ptr(buf), size(fixed_size) {} +{ + ptr = alignPtr(buf, 16); + size = fixed_size; +} template inline AutoBuffer<_Tp, fixed_size>::AutoBuffer(size_t _size) -: ptr(buf), size(fixed_size) { allocate(_size); } +{ + ptr = alignPtr(buf, 16); + size = fixed_size; + allocate(_size); +} template inline AutoBuffer<_Tp, fixed_size>::~AutoBuffer() { deallocate(); } @@ -2320,10 +2327,11 @@ template inline void AutoBuffer<_Tp, fixed_size template inline void AutoBuffer<_Tp, fixed_size>::deallocate() { - if( ptr != buf ) + _Tp* buf0 = alignPtr(buf, 16); + if( ptr != buf0 ) { cv::deallocate<_Tp>(ptr, size); - ptr = buf; + ptr = buf0; size = fixed_size; } } @@ -3550,7 +3558,6 @@ template static inline std::ostream& operator << (std::ostream& ou return out; } -#if 0 template struct AlgorithmParamType {}; template<> struct AlgorithmParamType { enum { type = CV_PARAM_TYPE_INT }; }; template<> struct AlgorithmParamType { enum { type = CV_PARAM_TYPE_REAL }; }; @@ -3594,7 +3601,6 @@ template void Algorithm::setParamRange(int propId, const _Tp& minV { setParamRange_(propId, AlgorithmParamType<_Tp>::type, &minVal, &maxVal); } -#endif } diff --git a/modules/core/src/arithm.cpp b/modules/core/src/arithm.cpp index 8675ddd338..01018969dd 100644 --- a/modules/core/src/arithm.cpp +++ b/modules/core/src/arithm.cpp @@ -11,7 +11,7 @@ // For Open Source Computer Vision Library // // Copyright (C) 2000-2008, Intel Corporation, all rights reserved. -// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2009-2011, Willow Garage Inc., all rights reserved. // Third party copyrights are property of their respective owners. // // Redistribution and use in source and binary forms, with or without modification, @@ -42,118 +42,317 @@ /* //////////////////////////////////////////////////////////////////// // -// Matrix arithmetic and logical operations: +, -, *, /, &, |, ^, ~, abs ... +// Arithmetic and logical operations: +, -, *, /, &, |, ^, ~, abs ... // // */ #include "precomp.hpp" -#ifdef HAVE_IPP -#include "ippversion.h" -#endif - namespace cv { -#if CV_SSE2 +#if ARITHM_USE_IPP +struct IPPArithmInitializer +{ + IPPArithmInitializer(void) + { + IppStatus status = ippStaticInit(); + } +}; -enum { ARITHM_SIMD = CV_CPU_SSE2 }; +IPPArithmInitializer ippArithmInitializer; +#endif -template struct VBinOp8 +struct NOP {}; + +template +void vBinOp8(const T* src1, size_t step1, const T* src2, size_t step2, T* dst, size_t step, Size sz) { - int operator()(const uchar* src1, const uchar* src2, uchar* dst, int len) const + Op8 op8; + Op op; + + for( ; sz.height--; src1 += step1/sizeof(src1[0]), + src2 += step2/sizeof(src2[0]), + dst += step/sizeof(dst[0]) ) { int x = 0; - for( ; x <= len - 32; x += 32 ) + + #if CV_SSE2 + if( USE_SSE2 ) { - __m128i r0 = _mm_loadu_si128((const __m128i*)(src1 + x)); - __m128i r1 = _mm_loadu_si128((const __m128i*)(src1 + x + 16)); - r0 = op(r0,_mm_loadu_si128((const __m128i*)(src2 + x))); - r1 = op(r1,_mm_loadu_si128((const __m128i*)(src2 + x + 16))); - _mm_storeu_si128((__m128i*)(dst + x), r0); - _mm_storeu_si128((__m128i*)(dst + x + 16), r1); + for( ; x <= sz.width - 32; x += 32 ) + { + __m128i r0 = _mm_loadu_si128((const __m128i*)(src1 + x)); + __m128i r1 = _mm_loadu_si128((const __m128i*)(src1 + x + 16)); + r0 = op8(r0,_mm_loadu_si128((const __m128i*)(src2 + x))); + r1 = op8(r1,_mm_loadu_si128((const __m128i*)(src2 + x + 16))); + _mm_storeu_si128((__m128i*)(dst + x), r0); + _mm_storeu_si128((__m128i*)(dst + x + 16), r1); + } + for( ; x <= sz.width - 8; x += 8 ) + { + __m128i r0 = _mm_loadl_epi64((const __m128i*)(src1 + x)); + r0 = op8(r0,_mm_loadl_epi64((const __m128i*)(src2 + x))); + _mm_storel_epi64((__m128i*)(dst + x), r0); + } } - for( ; x <= len - 8; x += 8 ) + #endif + + for( ; x <= sz.width - 4; x += 4 ) { - __m128i r0 = _mm_loadl_epi64((const __m128i*)(src1 + x)); - r0 = op(r0,_mm_loadl_epi64((const __m128i*)(src2 + x))); - _mm_storel_epi64((__m128i*)(dst + x), r0); + T v0 = op(src1[x], src2[x]); + T v1 = op(src1[x+1], src2[x+1]); + dst[x] = v0; dst[x+1] = v1; + v0 = op(src1[x+2], src2[x+2]); + v1 = op(src1[x+3], src2[x+3]); + dst[x+2] = v0; dst[x+3] = v1; } - return x; + + for( ; x < sz.width; x++ ) + dst[x] = op(src1[x], src2[x]); } - Op8 op; -}; +} -template struct VBinOp16 +template +void vBinOp16(const T* src1, size_t step1, const T* src2, size_t step2, + T* dst, size_t step, Size sz) { - int operator()(const T* src1, const T* src2, T* dst, int len) const + Op16 op16; + Op op; + + for( ; sz.height--; src1 += step1/sizeof(src1[0]), + src2 += step2/sizeof(src2[0]), + dst += step/sizeof(dst[0]) ) { int x = 0; - for( ; x <= len - 16; x += 16 ) + + #if CV_SSE2 + if( USE_SSE2 ) { - __m128i r0 = _mm_loadu_si128((const __m128i*)(src1 + x)); - __m128i r1 = _mm_loadu_si128((const __m128i*)(src1 + x + 8)); - r0 = op(r0,_mm_loadu_si128((const __m128i*)(src2 + x))); - r1 = op(r1,_mm_loadu_si128((const __m128i*)(src2 + x + 8))); - _mm_storeu_si128((__m128i*)(dst + x), r0); - _mm_storeu_si128((__m128i*)(dst + x + 8), r1); + for( ; x <= sz.width - 16; x += 16 ) + { + __m128i r0 = _mm_loadu_si128((const __m128i*)(src1 + x)); + __m128i r1 = _mm_loadu_si128((const __m128i*)(src1 + x + 8)); + r0 = op16(r0,_mm_loadu_si128((const __m128i*)(src2 + x))); + r1 = op16(r1,_mm_loadu_si128((const __m128i*)(src2 + x + 8))); + _mm_storeu_si128((__m128i*)(dst + x), r0); + _mm_storeu_si128((__m128i*)(dst + x + 16), r1); + } + for( ; x <= sz.width - 4; x += 4 ) + { + __m128i r0 = _mm_loadl_epi64((const __m128i*)(src1 + x)); + r0 = op16(r0,_mm_loadl_epi64((const __m128i*)(src2 + x))); + _mm_storel_epi64((__m128i*)(dst + x), r0); + } } - for( ; x <= len - 4; x += 4 ) + else + #endif + + for( ; x <= sz.width - 4; x += 4 ) { - __m128i r0 = _mm_loadl_epi64((const __m128i*)(src1 + x)); - r0 = op(r0,_mm_loadl_epi64((const __m128i*)(src2 + x))); - _mm_storel_epi64((__m128i*)(dst + x), r0); + T v0 = op(src1[x], src2[x]); + T v1 = op(src1[x+1], src2[x+1]); + dst[x] = v0; dst[x+1] = v1; + v0 = op(src1[x+2], src2[x+2]); + v1 = op(src1[x+3], src2[x+3]); + dst[x+2] = v0; dst[x+3] = v1; } - return x; + + for( ; x < sz.width; x++ ) + dst[x] = op(src1[x], src2[x]); } - Op16 op; -}; +} -template struct VBinOp32f + +template +void vBinOp32s(const int* src1, size_t step1, const int* src2, size_t step2, + int* dst, size_t step, Size sz) { - int operator()(const float* src1, const float* src2, float* dst, int len) const + Op32 op32; + Op op; + + for( ; sz.height--; src1 += step1/sizeof(src1[0]), + src2 += step2/sizeof(src2[0]), + dst += step/sizeof(dst[0]) ) { int x = 0; - if( (((size_t)src1|(size_t)src2|(size_t)dst)&15) == 0 ) - for( ; x <= len - 8; x += 8 ) + +#if CV_SSE2 + if( USE_SSE2 ) + { + if( (((size_t)src1|(size_t)src2|(size_t)dst)&15) == 0 ) + for( ; x <= sz.width - 8; x += 8 ) + { + __m128i r0 = _mm_load_si128((const __m128i*)(src1 + x)); + __m128i r1 = _mm_load_si128((const __m128i*)(src1 + x + 4)); + r0 = op32(r0,_mm_load_si128((const __m128i*)(src2 + x))); + r1 = op32(r1,_mm_load_si128((const __m128i*)(src2 + x + 4))); + _mm_store_si128((__m128i*)(dst + x), r0); + _mm_store_si128((__m128i*)(dst + x + 16), r1); + } + else + for( ; x <= sz.width - 8; x += 8 ) + { + __m128i r0 = _mm_loadu_si128((const __m128i*)(src1 + x)); + __m128i r1 = _mm_loadu_si128((const __m128i*)(src1 + x + 4)); + r0 = op32(r0,_mm_loadu_si128((const __m128i*)(src2 + x))); + r1 = op32(r1,_mm_loadu_si128((const __m128i*)(src2 + x + 4))); + _mm_storeu_si128((__m128i*)(dst + x), r0); + _mm_storeu_si128((__m128i*)(dst + x + 16), r1); + } + } +#endif + + for( ; x <= sz.width - 4; x += 4 ) + { + int v0 = op(src1[x], src2[x]); + int v1 = op(src1[x+1], src2[x+1]); + dst[x] = v0; dst[x+1] = v1; + v0 = op(src1[x+2], src2[x+2]); + v1 = op(src1[x+3], src2[x+3]); + dst[x+2] = v0; dst[x+3] = v1; + } + + for( ; x < sz.width; x++ ) + dst[x] = op(src1[x], src2[x]); + } +} + + +template +void vBinOp32f(const float* src1, size_t step1, const float* src2, size_t step2, + float* dst, size_t step, Size sz) +{ + Op32 op32; + Op op; + + for( ; sz.height--; src1 += step1/sizeof(src1[0]), + src2 += step2/sizeof(src2[0]), + dst += step/sizeof(dst[0]) ) + { + int x = 0; + + #if CV_SSE2 + if( USE_SSE2 ) + { + if( (((size_t)src1|(size_t)src2|(size_t)dst)&15) == 0 ) + for( ; x <= sz.width - 8; x += 8 ) + { + __m128 r0 = _mm_load_ps(src1 + x); + __m128 r1 = _mm_load_ps(src1 + x + 4); + r0 = op32(r0,_mm_load_ps(src2 + x)); + r1 = op32(r1,_mm_load_ps(src2 + x + 4)); + _mm_store_ps(dst + x, r0); + _mm_store_ps(dst + x + 4, r1); + } + else + for( ; x <= sz.width - 8; x += 8 ) + { + __m128 r0 = _mm_loadu_ps(src1 + x); + __m128 r1 = _mm_loadu_ps(src1 + x + 4); + r0 = op32(r0,_mm_loadu_ps(src2 + x)); + r1 = op32(r1,_mm_loadu_ps(src2 + x + 4)); + _mm_storeu_ps(dst + x, r0); + _mm_storeu_ps(dst + x + 4, r1); + } + } + #endif + for( ; x <= sz.width - 4; x += 4 ) + { + float v0 = op(src1[x], src2[x]); + float v1 = op(src1[x+1], src2[x+1]); + dst[x] = v0; dst[x+1] = v1; + v0 = op(src1[x+2], src2[x+2]); + v1 = op(src1[x+3], src2[x+3]); + dst[x+2] = v0; dst[x+3] = v1; + } + + for( ; x < sz.width; x++ ) + dst[x] = op(src1[x], src2[x]); + } +} + +template +void vBinOp64f(const double* src1, size_t step1, const double* src2, size_t step2, + double* dst, size_t step, Size sz) +{ + Op64 op64; + Op op; + + for( ; sz.height--; src1 += step1/sizeof(src1[0]), + src2 += step2/sizeof(src2[0]), + dst += step/sizeof(dst[0]) ) + { + int x = 0; + + #if CV_SSE2 + if( USE_SSE2 && (((size_t)src1|(size_t)src2|(size_t)dst)&15) == 0 ) + for( ; x <= sz.width - 4; x += 4 ) { - __m128 r0 = _mm_load_ps(src1 + x); - __m128 r1 = _mm_load_ps(src1 + x + 4); - r0 = op(r0,_mm_load_ps(src2 + x)); - r1 = op(r1,_mm_load_ps(src2 + x + 4)); - _mm_store_ps(dst + x, r0); - _mm_store_ps(dst + x + 4, r1); + __m128d r0 = _mm_load_pd(src1 + x); + __m128d r1 = _mm_load_pd(src1 + x + 2); + r0 = op64(r0,_mm_load_pd(src2 + x)); + r1 = op64(r1,_mm_load_pd(src2 + x + 2)); + _mm_store_pd(dst + x, r0); + _mm_store_pd(dst + x + 2, r1); } else - for( ; x <= len - 8; x += 8 ) - { - __m128 r0 = _mm_loadu_ps(src1 + x); - __m128 r1 = _mm_loadu_ps(src1 + x + 4); - r0 = op(r0,_mm_loadu_ps(src2 + x)); - r1 = op(r1,_mm_loadu_ps(src2 + x + 4)); - _mm_storeu_ps(dst + x, r0); - _mm_storeu_ps(dst + x + 4, r1); - } - return x; + #endif + for( ; x <= sz.width - 4; x += 4 ) + { + double v0 = op(src1[x], src2[x]); + double v1 = op(src1[x+1], src2[x+1]); + dst[x] = v0; dst[x+1] = v1; + v0 = op(src1[x+2], src2[x+2]); + v1 = op(src1[x+3], src2[x+3]); + dst[x+2] = v0; dst[x+3] = v1; + } + + for( ; x < sz.width; x++ ) + dst[x] = op(src1[x], src2[x]); } - Op32f op; -}; - +} + +#if CV_SSE2 + struct _VAdd8u { __m128i operator()(const __m128i& a, const __m128i& b) const { return _mm_adds_epu8(a,b); }}; struct _VSub8u { __m128i operator()(const __m128i& a, const __m128i& b) const { return _mm_subs_epu8(a,b); }}; struct _VMin8u { __m128i operator()(const __m128i& a, const __m128i& b) const { return _mm_min_epu8(a,b); }}; struct _VMax8u { __m128i operator()(const __m128i& a, const __m128i& b) const { return _mm_max_epu8(a,b); }}; -struct _VCmpGT8u { __m128i operator()(const __m128i& a, const __m128i& b) const -{ - __m128i delta = _mm_set1_epi32(0x80808080); - return _mm_cmpgt_epi8(_mm_xor_si128(a,delta),_mm_xor_si128(b,delta)); -}}; -struct _VCmpEQ8u { __m128i operator()(const __m128i& a, const __m128i& b) const { return _mm_cmpeq_epi8(a,b); }}; struct _VAbsDiff8u { __m128i operator()(const __m128i& a, const __m128i& b) const { return _mm_add_epi8(_mm_subs_epu8(a,b),_mm_subs_epu8(b,a)); } }; + +struct _VAdd8s { __m128i operator()(const __m128i& a, const __m128i& b) const { return _mm_adds_epi8(a,b); }}; +struct _VSub8s { __m128i operator()(const __m128i& a, const __m128i& b) const { return _mm_subs_epi8(a,b); }}; +struct _VMin8s +{ + __m128i operator()(const __m128i& a, const __m128i& b) const + { + __m128i m = _mm_cmpgt_epi8(a, b); + return _mm_xor_si128(a, _mm_and_si128(_mm_xor_si128(a, b), m)); + } +}; +struct _VMax8s +{ + __m128i operator()(const __m128i& a, const __m128i& b) const + { + __m128i m = _mm_cmpgt_epi8(b, a); + return _mm_xor_si128(a, _mm_and_si128(_mm_xor_si128(a, b), m)); + } +}; +struct _VAbsDiff8s +{ + __m128i operator()(const __m128i& a, const __m128i& b) const + { + __m128i d = _mm_subs_epi8(a, b); + __m128i m = _mm_cmpgt_epi8(b, a); + return _mm_subs_epi8(_mm_xor_si128(d, m), m); + } +}; + struct _VAdd16u { __m128i operator()(const __m128i& a, const __m128i& b) const { return _mm_adds_epu16(a,b); }}; struct _VSub16u { __m128i operator()(const __m128i& a, const __m128i& b) const { return _mm_subs_epu16(a,b); }}; struct _VMin16u @@ -171,6 +370,7 @@ struct _VAbsDiff16u __m128i operator()(const __m128i& a, const __m128i& b) const { return _mm_add_epi16(_mm_subs_epu16(a,b),_mm_subs_epu16(b,a)); } }; + struct _VAdd16s { __m128i operator()(const __m128i& a, const __m128i& b) const { return _mm_adds_epi16(a,b); }}; struct _VSub16s { __m128i operator()(const __m128i& a, const __m128i& b) const { return _mm_subs_epi16(a,b); }}; struct _VMin16s { __m128i operator()(const __m128i& a, const __m128i& b) const { return _mm_min_epi16(a,b); }}; @@ -183,6 +383,35 @@ struct _VAbsDiff16s return _mm_subs_epi16(M, m); } }; + +struct _VAdd32s { __m128i operator()(const __m128i& a, const __m128i& b) const { return _mm_add_epi32(a,b); }}; +struct _VSub32s { __m128i operator()(const __m128i& a, const __m128i& b) const { return _mm_sub_epi32(a,b); }}; +struct _VMin32s +{ + __m128i operator()(const __m128i& a, const __m128i& b) const + { + __m128i m = _mm_cmpgt_epi32(a, b); + return _mm_xor_si128(a, _mm_and_si128(_mm_xor_si128(a, b), m)); + } +}; +struct _VMax32s +{ + __m128i operator()(const __m128i& a, const __m128i& b) const + { + __m128i m = _mm_cmpgt_epi32(b, a); + return _mm_xor_si128(a, _mm_and_si128(_mm_xor_si128(a, b), m)); + } +}; +struct _VAbsDiff32s +{ + __m128i operator()(const __m128i& a, const __m128i& b) const + { + __m128i d = _mm_sub_epi32(a, b); + __m128i m = _mm_cmpgt_epi32(b, a); + return _mm_sub_epi32(_mm_xor_si128(d, m), m); + } +}; + struct _VAdd32f { __m128 operator()(const __m128& a, const __m128& b) const { return _mm_add_ps(a,b); }}; struct _VSub32f { __m128 operator()(const __m128& a, const __m128& b) const { return _mm_sub_ps(a,b); }}; struct _VMin32f { __m128 operator()(const __m128& a, const __m128& b) const { return _mm_min_ps(a,b); }}; @@ -196,862 +425,968 @@ struct _VAbsDiff32f } }; +struct _VAdd64f { __m128d operator()(const __m128d& a, const __m128d& b) const { return _mm_add_pd(a,b); }}; +struct _VSub64f { __m128d operator()(const __m128d& a, const __m128d& b) const { return _mm_sub_pd(a,b); }}; +struct _VMin64f { __m128d operator()(const __m128d& a, const __m128d& b) const { return _mm_min_pd(a,b); }}; +struct _VMax64f { __m128d operator()(const __m128d& a, const __m128d& b) const { return _mm_max_pd(a,b); }}; + +static int CV_DECL_ALIGNED(16) v64f_absmask[] = { 0xffffffff, 0x7fffffff, 0xffffffff, 0x7fffffff }; +struct _VAbsDiff64f +{ + __m128d operator()(const __m128d& a, const __m128d& b) const + { + return _mm_and_pd(_mm_sub_pd(a,b), *(const __m128d*)v64f_absmask); + } +}; + struct _VAnd8u { __m128i operator()(const __m128i& a, const __m128i& b) const { return _mm_and_si128(a,b); }}; struct _VOr8u { __m128i operator()(const __m128i& a, const __m128i& b) const { return _mm_or_si128(a,b); }}; struct _VXor8u { __m128i operator()(const __m128i& a, const __m128i& b) const { return _mm_xor_si128(a,b); }}; +struct _VNot8u { __m128i operator()(const __m128i& a, const __m128i&) const { return _mm_andnot_si128(_mm_setzero_si128(),a); }}; + +#endif -typedef VBinOp8<_VAdd8u> VAdd8u; -typedef VBinOp8<_VSub8u> VSub8u; -typedef VBinOp8<_VMin8u> VMin8u; -typedef VBinOp8<_VMax8u> VMax8u; -typedef VBinOp8<_VAbsDiff8u> VAbsDiff8u; -typedef VBinOp8<_VCmpEQ8u> VCmpEQ8u; -typedef VBinOp8<_VCmpGT8u> VCmpGT8u; - -typedef VBinOp16 VAdd16u; -typedef VBinOp16 VSub16u; -typedef VBinOp16 VMin16u; -typedef VBinOp16 VMax16u; -typedef VBinOp16 VAbsDiff16u; - -typedef VBinOp16 VAdd16s; -typedef VBinOp16 VSub16s; -typedef VBinOp16 VMin16s; -typedef VBinOp16 VMax16s; -typedef VBinOp16 VAbsDiff16s; - -typedef VBinOp32f<_VAdd32f> VAdd32f; -typedef VBinOp32f<_VSub32f> VSub32f; -typedef VBinOp32f<_VMin32f> VMin32f; -typedef VBinOp32f<_VMax32f> VMax32f; -typedef VBinOp32f<_VAbsDiff32f> VAbsDiff32f; - -typedef VBinOp8<_VAnd8u> VAnd8u; -typedef VBinOp8<_VOr8u> VOr8u; -typedef VBinOp8<_VXor8u> VXor8u; - +#if CV_SSE2 +#define IF_SIMD(op) op #else - -enum { ARITHM_SIMD = CV_CPU_NONE }; - -typedef NoVec VAdd8u; -typedef NoVec VSub8u; -typedef NoVec VMin8u; -typedef NoVec VMax8u; -typedef NoVec VAbsDiff8u; -typedef NoVec VCmpEQ8u; -typedef NoVec VCmpGT8u; - -typedef NoVec VAdd16u; -typedef NoVec VSub16u; -typedef NoVec VMin16u; -typedef NoVec VMax16u; -typedef NoVec VAbsDiff16u; - -typedef NoVec VAdd16s; -typedef NoVec VSub16s; -typedef NoVec VMin16s; -typedef NoVec VMax16s; -typedef NoVec VAbsDiff16s; - -typedef NoVec VAdd32f; -typedef NoVec VSub32f; -typedef NoVec VMin32f; -typedef NoVec VMax32f; -typedef NoVec VAbsDiff32f; - -typedef NoVec VAnd8u; -typedef NoVec VOr8u; -typedef NoVec VXor8u; - +#define IF_SIMD(op) NOP #endif - - -#if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7) -struct IPPArithmInitializer + +template<> inline uchar OpAdd::operator ()(uchar a, uchar b) const +{ return CV_FAST_CAST_8U(a + b); } +template<> inline uchar OpSub::operator ()(uchar a, uchar b) const +{ return CV_FAST_CAST_8U(a - b); } + +template struct OpAbsDiff { - IPPArithmInitializer(void) - { - IppStatus status = ippStaticInit(); - } + typedef T type1; + typedef T type2; + typedef T rtype; + T operator()(T a, T b) const { return (T)std::abs(a - b); } }; -IPPArithmInitializer ippArithmInitializer; +template<> inline short OpAbsDiff::operator ()(short a, short b) const +{ return saturate_cast(std::abs(a - b)); } -struct ippAdd8u +template<> inline schar OpAbsDiff::operator ()(schar a, schar b) const +{ return saturate_cast(std::abs(a - b)); } + +template struct OpAbsDiffS { - int operator()(const Ipp8u* src1, const Ipp8u* src2, Ipp8u* dst, int len) const - { - ippsAdd_8u_Sfs(src1,src2,dst,len,0); - return len; - } + typedef T type1; + typedef WT type2; + typedef T rtype; + T operator()(T a, WT b) const { return saturate_cast(std::abs(a - b)); } }; -struct ippAdd16u +template struct OpAnd { - int operator()(const Ipp16u* src1, const Ipp16u* src2, Ipp16u* dst, int len) const - { - ippsAdd_16u_Sfs(src1,src2,dst,len,0); - return len; - } + typedef T type1; + typedef T type2; + typedef T rtype; + T operator()( T a, T b ) const { return a & b; } }; -struct ippAdd16s +template struct OpOr { - int operator()(const Ipp16s* src1, const Ipp16s* src2, Ipp16s* dst, int len) const - { - ippsAdd_16s_Sfs(src1,src2,dst,len,0); - return len; - } + typedef T type1; + typedef T type2; + typedef T rtype; + T operator()( T a, T b ) const { return a | b; } }; -struct ippAdd32s +template struct OpXor { - int operator()(const Ipp32s* src1, const Ipp32s* src2, Ipp32s* dst, int len) const - { - ippsAdd_32s_Sfs(src1,src2,dst,len,0); - return len; - } + typedef T type1; + typedef T type2; + typedef T rtype; + T operator()( T a, T b ) const { return a ^ b; } }; -struct ippAdd32f +template struct OpNot { - int operator()(const Ipp32f* src1, const Ipp32f* src2, Ipp32f* dst, int len) const - { - ippsAdd_32f(src1,src2,dst,len); - return len; - } + typedef T type1; + typedef T type2; + typedef T rtype; + T operator()( T a, T ) const { return ~a; } }; + +static inline void fixSteps(Size sz, size_t elemSize, size_t& step1, size_t& step2, size_t& step) +{ + if( sz.height == 1 ) + step1 = step2 = step = sz.width*elemSize; +} + +static void add8u( const uchar* src1, size_t step1, + const uchar* src2, size_t step2, + uchar* dst, size_t step, Size sz, void* ) +{ + IF_IPP(fixSteps(sz, sizeof(dst[0]), step1, step2, step); + ippiAdd_8u_C1RSfs(src1, (int)step1, src2, (int)step2, dst, (IppiSize&)sz, 0), + (vBinOp8, IF_SIMD(_VAdd8u)>(src1, step1, src2, step2, dst, step, sz))); +} -struct ippAdd64f +static void add8s( const schar* src1, size_t step1, + const schar* src2, size_t step2, + schar* dst, size_t step, Size sz, void* ) { - int operator()(const Ipp64f* src1, const Ipp64f* src2, Ipp64f* dst, int len) const - { - ippsAdd_64f(src1,src2,dst,len); - return len; - } -}; + vBinOp8, IF_SIMD(_VAdd8s)>(src1, step1, src2, step2, dst, step, sz); +} -struct ippSub8u +static void add16u( const ushort* src1, size_t step1, + const ushort* src2, size_t step2, + ushort* dst, size_t step, Size sz, void* ) { - int operator()(const Ipp8u* src1, const Ipp8u* src2, Ipp8u* dst, int len) const - { - ippsSub_8u_Sfs(src2,src1,dst,len,0); - return len; - } -}; + IF_IPP(fixSteps(sz, sizeof(dst[0]), step1, step2, step); + ippiAdd_16u_C1RSfs(src1, (int)step1, src2, (int)step2, dst, (IppiSize&)sz, 0), + (vBinOp16, IF_SIMD(_VAdd16u)>(src1, step1, src2, step2, dst, step, sz))); +} -struct ippSub16u +static void add16s( const short* src1, size_t step1, + const short* src2, size_t step2, + short* dst, size_t step, Size sz, void* ) { - int operator()(const Ipp16u* src1, const Ipp16u* src2, Ipp16u* dst, int len) const - { - ippsSub_16u_Sfs(src2,src1,dst,len,0); - return len; - } -}; + IF_IPP(fixSteps(sz, sizeof(dst[0]), step1, step2, step); + ippiAdd_16s_C1RSfs(src1, (int)step1, src2, (int)step2, dst, (IppiSize&)sz, 0), + (vBinOp16, IF_SIMD(_VAdd16s)>(src1, step1, src2, step2, dst, step, sz))); +} -struct ippSub16s +static void add32s( const int* src1, size_t step1, + const int* src2, size_t step2, + int* dst, size_t step, Size sz, void* ) { - int operator()(const Ipp16s* src1, const Ipp16s* src2, Ipp16s* dst, int len) const - { - ippsSub_16s_Sfs(src2,src1,dst,len,0); - return len; - } -}; + vBinOp32s, IF_SIMD(_VAdd32s)>(src1, step1, src2, step2, dst, step, sz); +} -struct ippSub32s +static void add32f( const float* src1, size_t step1, + const float* src2, size_t step2, + float* dst, size_t step, Size sz, void* ) { - int operator()(const Ipp32s* src1, const Ipp32s* src2, Ipp32s* dst, int len) const - { - ippsSub_32s_Sfs(src2,src1,dst,len,0); - return len; - } -}; + IF_IPP(fixSteps(sz, sizeof(dst[0]), step1, step2, step); + ippiAdd_32f_C1RSfs(src1, (int)step1, src2, (int)step2, dst, (IppiSize&)sz, 0), + (vBinOp32f, IF_SIMD(_VAdd32f)>(src1, step1, src2, step2, dst, step, sz))); +} -struct ippSub32f +static void add64f( const double* src1, size_t step1, + const double* src2, size_t step2, + double* dst, size_t step, Size sz, void* ) { - int operator()(const Ipp32f* src1, const Ipp32f* src2, Ipp32f* dst, int len) const - { - ippsSub_32f(src2,src1,dst,len); - return len; - } -}; + vBinOp64f, IF_SIMD(_VAdd64f)>(src1, step1, src2, step2, dst, step, sz); +} -struct ippSub64f +static void sub8u( const uchar* src1, size_t step1, + const uchar* src2, size_t step2, + uchar* dst, size_t step, Size sz, void* ) { - int operator()(const Ipp64f* src1, const Ipp64f* src2, Ipp64f* dst, int len) const - { - ippsSub_64f(src2,src1,dst,len); - return len; - } -}; + IF_IPP(fixSteps(sz, sizeof(dst[0]), step1, step2, step); + ippiSub_8u_C1RSfs(src2, (int)step2, src1, (int)step1, dst, (IppiSize&)sz, 0), + (vBinOp8, IF_SIMD(_VSub8u)>(src1, step1, src2, step2, dst, step, sz))); +} -struct ippMax8u +static void sub8s( const schar* src1, size_t step1, + const schar* src2, size_t step2, + schar* dst, size_t step, Size sz, void* ) { - int operator()(const Ipp8u* src1, const Ipp8u* src2, Ipp8u* dst, int len) const - { - ippsMaxEvery_8u(src1,src2,dst,len); - return len; - } -}; + vBinOp8, IF_SIMD(_VSub8s)>(src1, step1, src2, step2, dst, step, sz); +} -struct ippMax16u +static void sub16u( const ushort* src1, size_t step1, + const ushort* src2, size_t step2, + ushort* dst, size_t step, Size sz, void* ) { - int operator()(const Ipp16u* src1, const Ipp16u* src2, Ipp16u* dst, int len) const - { - ippsMaxEvery_16u(src1,src2,dst,len); - return len; - } -}; + IF_IPP(fixSteps(sz, sizeof(dst[0]), step1, step2, step); + ippiSub_16u_C1RSfs(src2, (int)step2, src1, (int)step1, dst, (IppiSize&)sz, 0), + (vBinOp16, IF_SIMD(_VSub16u)>(src1, step1, src2, step2, dst, step, sz))); +} -struct ippMax32f +static void sub16s( const short* src1, size_t step1, + const short* src2, size_t step2, + short* dst, size_t step, Size sz, void* ) { - int operator()(const Ipp32f* src1, const Ipp32f* src2, Ipp32f* dst, int len) const - { - ippsMaxEvery_32f(src1,src2,dst,len); - return len; - } -}; + IF_IPP(fixSteps(sz, sizeof(dst[0]), step1, step2, step); + ippiSub_16s_C1RSfs(src2, (int)step2, src1, (int)step1, dst, (IppiSize&)sz, 0), + (vBinOp16, IF_SIMD(_VSub16s)>(src1, step1, src2, step2, dst, step, sz))); +} -struct ippMax64f +static void sub32s( const int* src1, size_t step1, + const int* src2, size_t step2, + int* dst, size_t step, Size sz, void* ) { - int operator()(const Ipp64f* src1, const Ipp64f* src2, Ipp64f* dst, int len) const - { - ippsMaxEvery_64f(src1,src2,dst,len); - return len; - } -}; + vBinOp32s, IF_SIMD(_VSub32s)>(src1, step1, src2, step2, dst, step, sz); +} -struct ippMin8u +static void sub32f( const float* src1, size_t step1, + const float* src2, size_t step2, + float* dst, size_t step, Size sz, void* ) { - int operator()(const Ipp8u* src1, const Ipp8u* src2, Ipp8u* dst, int len) const - { - ippsMinEvery_8u(src1,src2,dst,len); - return len; - } -}; + IF_IPP(fixSteps(sz, sizeof(dst[0]), step1, step2, step); + ippiSub_32f_C1RSfs(src2, (int)step2, src1, (int)step1, dst, (IppiSize&)sz, 0), + (vBinOp32f, IF_SIMD(_VSub32f)>(src1, step1, src2, step2, dst, step, sz))); +} -struct ippMin16u +static void sub64f( const double* src1, size_t step1, + const double* src2, size_t step2, + double* dst, size_t step, Size sz, void* ) { - int operator()(const Ipp16u* src1, const Ipp16u* src2, Ipp16u* dst, int len) const - { - ippsMinEvery_16u(src1,src2,dst,len); - return len; - } -}; + vBinOp64f, IF_SIMD(_VSub64f)>(src1, step1, src2, step2, dst, step, sz); +} -struct ippMin32f +template<> inline uchar OpMin::operator ()(uchar a, uchar b) const { return CV_MIN_8U(a, b); } +template<> inline uchar OpMax::operator ()(uchar a, uchar b) const { return CV_MAX_8U(a, b); } + +static void max8u( const uchar* src1, size_t step1, + const uchar* src2, size_t step2, + uchar* dst, size_t step, Size sz, void* ) { - int operator()(const Ipp32f* src1, const Ipp32f* src2, Ipp32f* dst, int len) const - { - ippsMinEvery_32f(src1,src2,dst,len); - return len; - } -}; + IF_IPP(fixSteps(sz, sizeof(dst[0]), step1, step2, step); + ippiMaxEvery_8u_C1R(src1, (int)step1, src2, (int)step2, dst, (IppiSize&)sz), + (vBinOp8, IF_SIMD(_VMax8u)>(src1, step1, src2, step2, dst, step, sz))); +} -struct ippMin64f +static void max8s( const schar* src1, size_t step1, + const schar* src2, size_t step2, + schar* dst, size_t step, Size sz, void* ) { - int operator()(const Ipp64f* src1, const Ipp64f* src2, Ipp64f* dst, int len) const - { - ippsMinEvery_64f(src1,src2,dst,len); - return len; - } -}; + vBinOp8, IF_SIMD(_VMax8s)>(src1, step1, src2, step2, dst, step, sz); +} -struct ippAbsDiff8u +static void max16u( const ushort* src1, size_t step1, + const ushort* src2, size_t step2, + ushort* dst, size_t step, Size sz, void* ) { - int operator()(const Ipp8u* src1, const Ipp8u* src2, Ipp8u* dst, int len) const - { - int step = len * sizeof(Ipp8u); - IppiSize roi = { len, 1 }; - ippiAbsDiff_8u_C1R(src1,step,src2,step,dst,step,roi); - return len; - } -}; + IF_IPP(fixSteps(sz, sizeof(dst[0]), step1, step2, step); + ippiMaxEvery_16u_C1R(src1, (int)step1, src2, (int)step2, dst, (IppiSize&)sz), + (vBinOp16, IF_SIMD(_VMax16u)>(src1, step1, src2, step2, dst, step, sz))); +} -struct ippAbsDiff16u +static void max16s( const short* src1, size_t step1, + const short* src2, size_t step2, + short* dst, size_t step, Size sz, void* ) { - int operator()(const Ipp16u* src1, const Ipp16u* src2, Ipp16u* dst, int len) const - { - int step = len * sizeof(Ipp16u); - IppiSize roi = { len, 1 }; - ippiAbsDiff_16u_C1R(src1,step,src2,step,dst,step,roi); - return len; - } -}; + IF_IPP(fixSteps(sz, sizeof(dst[0]), step1, step2, step); + ippiMaxEvery_16s_C1R(src1, (int)step1, src2, (int)step2, dst, (IppiSize&)sz), + (vBinOp16, IF_SIMD(_VMax16s)>(src1, step1, src2, step2, dst, step, sz))); +} -struct ippAbsDiff32f +static void max32s( const int* src1, size_t step1, + const int* src2, size_t step2, + int* dst, size_t step, Size sz, void* ) { - int operator()(const Ipp32f* src1, const Ipp32f* src2, Ipp32f* dst, int len) const - { - int step = len * sizeof(Ipp32f); - IppiSize roi = { len, 1 }; - ippiAbsDiff_32f_C1R(src1,step,src2,step,dst,step,roi); - return len; - } -}; + vBinOp32s, IF_SIMD(_VMax32s)>(src1, step1, src2, step2, dst, step, sz); +} -struct ippAnd8u +static void max32f( const float* src1, size_t step1, + const float* src2, size_t step2, + float* dst, size_t step, Size sz, void* ) { - int operator()(const Ipp8u* src1, const Ipp8u* src2, Ipp8u* dst, int len) const - { - ippsAnd_8u(src1,src2,dst,len); - return len; - } -}; + IF_IPP(fixSteps(sz, sizeof(dst[0]), step1, step2, step); + ippiMaxEvery_32f_C1R(src1, (int)step1, src2, (int)step2, dst, (IppiSize&)sz), + (vBinOp32f, IF_SIMD(_VMax32f)>(src1, step1, src2, step2, dst, step, sz))); +} -struct ippOr8u +static void max64f( const double* src1, size_t step1, + const double* src2, size_t step2, + double* dst, size_t step, Size sz, void* ) { - int operator()(const Ipp8u* src1, const Ipp8u* src2, Ipp8u* dst, int len) const - { - ippsOr_8u(src1,src2,dst,len); - return len; - } -}; + vBinOp64f, IF_SIMD(_VMax64f)>(src1, step1, src2, step2, dst, step, sz); +} -struct ippXor8u +static void min8u( const uchar* src1, size_t step1, + const uchar* src2, size_t step2, + uchar* dst, size_t step, Size sz, void* ) { - int operator()(const Ipp8u* src1, const Ipp8u* src2, Ipp8u* dst, int len) const - { - ippsXor_8u(src1,src2,dst,len); - return len; - } -}; + IF_IPP(fixSteps(sz, sizeof(dst[0]), step1, step2, step); + ippiMinEvery_8u_C1R(src1, (int)step1, src2, (int)step2, dst, (IppiSize&)sz), + (vBinOp8, IF_SIMD(_VMin8u)>(src1, step1, src2, step2, dst, step, sz))); +} -#endif // defined(HAVE_IPP) +static void min8s( const schar* src1, size_t step1, + const schar* src2, size_t step2, + schar* dst, size_t step, Size sz, void* ) +{ + vBinOp8, IF_SIMD(_VMin8s)>(src1, step1, src2, step2, dst, step, sz); +} +static void min16u( const ushort* src1, size_t step1, + const ushort* src2, size_t step2, + ushort* dst, size_t step, Size sz, void* ) +{ + IF_IPP(fixSteps(sz, sizeof(dst[0]), step1, step2, step); + ippiMinEvery_16u_C1R(src1, (int)step1, src2, (int)step2, dst, (IppiSize&)sz), + (vBinOp16, IF_SIMD(_VMin16u)>(src1, step1, src2, step2, dst, step, sz))); +} -/****************************************************************************************\ -* logical operations * -\****************************************************************************************/ +static void min16s( const short* src1, size_t step1, + const short* src2, size_t step2, + short* dst, size_t step, Size sz, void* ) +{ + IF_IPP(fixSteps(sz, sizeof(dst[0]), step1, step2, step); + ippiMinEvery_16s_C1R(src1, (int)step1, src2, (int)step2, dst, (IppiSize&)sz), + (vBinOp16, IF_SIMD(_VMin16s)>(src1, step1, src2, step2, dst, step, sz))); +} -template struct AndOp +static void min32s( const int* src1, size_t step1, + const int* src2, size_t step2, + int* dst, size_t step, Size sz, void* ) { - typedef T type1; - typedef T type2; - typedef T rtype; - T operator()( T a, T b ) const { return a & b; } -}; + vBinOp32s, IF_SIMD(_VMin32s)>(src1, step1, src2, step2, dst, step, sz); +} -template struct OrOp +static void min32f( const float* src1, size_t step1, + const float* src2, size_t step2, + float* dst, size_t step, Size sz, void* ) { - typedef T type1; - typedef T type2; - typedef T rtype; - T operator()( T a, T b ) const { return a | b; } -}; + IF_IPP(fixSteps(sz, sizeof(dst[0]), step1, step2, step); + ippiMinEvery_32f_C1R(src1, (int)step1, src2, (int)step2, dst, (IppiSize&)sz), + (vBinOp32f, IF_SIMD(_VMin32f)>(src1, step1, src2, step2, dst, step, sz))); +} -template struct XorOp +static void min64f( const double* src1, size_t step1, + const double* src2, size_t step2, + double* dst, size_t step, Size sz, void* ) { - typedef T type1; - typedef T type2; - typedef T rtype; - T operator()( T a, T b ) const { return a ^ b; } -}; + vBinOp64f, IF_SIMD(_VMin64f)>(src1, step1, src2, step2, dst, step, sz); +} -template static void -bitwiseOp_( const Mat& srcmat1, const Mat& srcmat2, Mat& dstmat ) +static void absdiff8u( const uchar* src1, size_t step1, + const uchar* src2, size_t step2, + uchar* dst, size_t step, Size sz, void* ) { - OPB opb; OPI opi; OPV opv; - const uchar* src1 = srcmat1.data; - const uchar* src2 = srcmat2.data; - uchar* dst = dstmat.data; - size_t step1 = srcmat1.step, step2 = srcmat2.step, step = dstmat.step; - Size size = getContinuousSize( srcmat1, srcmat2, dstmat, (int)srcmat1.elemSize() ); - bool useSIMD = checkHardwareSupport(ARITHM_SIMD); + IF_IPP(fixSteps(sz, sizeof(dst[0]), step1, step2, step); + ippiAbsDiff_8u_C1R(src1, (int)step1, src2, (int)step2, dst, (IppiSize&)sz), + (vBinOp8, IF_SIMD(_VAbsDiff8u)>(src1, step1, src2, step2, dst, step, sz))); +} - for( ; size.height--; src1 += step1, src2 += step2, dst += step ) - { - int i = useSIMD ? opv(src1, src2, dst, size.width) : 0; +static void absdiff8s( const schar* src1, size_t step1, + const schar* src2, size_t step2, + schar* dst, size_t step, Size sz, void* ) +{ + vBinOp8, IF_SIMD(_VAbsDiff8s)>(src1, step1, src2, step2, dst, step, sz); +} - if( (((size_t)src1 | (size_t)src2 | (size_t)dst) & 3) == 0 ) - { - for( ; i <= size.width - 16; i += 16 ) - { - int t0 = opi(((const int*)(src1+i))[0], ((const int*)(src2+i))[0]); - int t1 = opi(((const int*)(src1+i))[1], ((const int*)(src2+i))[1]); +static void absdiff16u( const ushort* src1, size_t step1, + const ushort* src2, size_t step2, + ushort* dst, size_t step, Size sz, void* ) +{ + IF_IPP(fixSteps(sz, sizeof(dst[0]), step1, step2, step); + ippiAbsDiff_16u_C1R(src1, (int)step1, src2, (int)step2, dst, (IppiSize&)sz), + (vBinOp16, IF_SIMD(_VAbsDiff16u)>(src1, step1, src2, step2, dst, step, sz))); +} - ((int*)(dst+i))[0] = t0; - ((int*)(dst+i))[1] = t1; +static void absdiff16s( const short* src1, size_t step1, + const short* src2, size_t step2, + short* dst, size_t step, Size sz, void* ) +{ + IF_IPP(fixSteps(sz, sizeof(dst[0]), step1, step2, step); + ippiAbsDiff_16s_C1R(src1, (int)step1, src2, (int)step2, dst, (IppiSize&)sz), + (vBinOp16, IF_SIMD(_VAbsDiff16s)>(src1, step1, src2, step2, dst, step, sz))); +} - t0 = opi(((const int*)(src1+i))[2], ((const int*)(src2+i))[2]); - t1 = opi(((const int*)(src1+i))[3], ((const int*)(src2+i))[3]); +static void absdiff32s( const int* src1, size_t step1, + const int* src2, size_t step2, + int* dst, size_t step, Size sz, void* ) +{ + vBinOp32s, IF_SIMD(_VAbsDiff32s)>(src1, step1, src2, step2, dst, step, sz); +} - ((int*)(dst+i))[2] = t0; - ((int*)(dst+i))[3] = t1; - } +static void absdiff32f( const float* src1, size_t step1, + const float* src2, size_t step2, + float* dst, size_t step, Size sz, void* ) +{ + IF_IPP(fixSteps(sz, sizeof(dst[0]), step1, step2, step); + ippiAbsDiff_32f_C1R(src1, (int)step1, src2, (int)step2, dst, (IppiSize&)sz), + (vBinOp32f, IF_SIMD(_VAbsDiff32f)>(src1, step1, src2, step2, dst, step, sz))); +} - for( ; i <= size.width - 4; i += 4 ) - { - int t = opi(*(const int*)(src1+i), *(const int*)(src2+i)); - *(int*)(dst+i) = t; - } - } +static void absdiff64f( const double* src1, size_t step1, + const double* src2, size_t step2, + double* dst, size_t step, Size sz, void* ) +{ + vBinOp64f, IF_SIMD(_VAbsDiff64f)>(src1, step1, src2, step2, dst, step, sz); +} + - for( ; i < size.width; i++ ) - dst[i] = opb(src1[i], src2[i]); +static void and8u( const uchar* src1, size_t step1, + const uchar* src2, size_t step2, + uchar* dst, size_t step, Size sz, void* ) +{ + IF_IPP(fixSteps(sz, sizeof(dst[0]), step1, step2, step); + ippiAnd_8u_C1R(src1, (int)step1, src2, (int)step2, dst, (IppiSize&)sz), + (vBinOp8, IF_SIMD(_VAnd8u)>(src1, step1, src2, step2, dst, step, sz))); +} + +static void or8u( const uchar* src1, size_t step1, + const uchar* src2, size_t step2, + uchar* dst, size_t step, Size sz, void* ) +{ + IF_IPP(fixSteps(sz, sizeof(dst[0]), step1, step2, step); + ippiOr_8u_C1R(src1, (int)step1, src2, (int)step2, dst, (IppiSize&)sz), + (vBinOp8, IF_SIMD(_VOr8u)>(src1, step1, src2, step2, dst, step, sz))); +} + +static void xor8u( const uchar* src1, size_t step1, + const uchar* src2, size_t step2, + uchar* dst, size_t step, Size sz, void* ) +{ + IF_IPP(fixSteps(sz, sizeof(dst[0]), step1, step2, step); + ippiXor_8u_C1R(src1, (int)step1, src2, (int)step2, dst, (IppiSize&)sz), + (vBinOp8, IF_SIMD(_VXor8u)>(src1, step1, src2, step2, dst, step, sz))); +} + +static void not8u( const uchar* src1, size_t step1, + const uchar* src2, size_t step2, + uchar* dst, size_t step, Size sz, void* ) +{ + IF_IPP(fixSteps(sz, sizeof(dst[0]), step1, step2, step); + ippiNot_8u_C1R(src1, (int)step1, dst, (IppiSize&)sz), + (vBinOp8, IF_SIMD(_VNot8u)>(src1, step1, src2, step2, dst, step, sz))); +} + +/****************************************************************************************\ +* logical operations * +\****************************************************************************************/ + +static inline bool checkScalar(const Mat& sc, int atype, int sckind, int akind) +{ + if( sc.dims > 2 || (sc.cols != 1 && sc.rows != 1) || !sc.isContinuous() ) + return false; + int cn = CV_MAT_CN(atype); + if( akind == InputArray::MATX && sckind != InputArray::MATX ) + return false; + return sc.size() == Size(1, 1) || sc.size() == Size(1, cn) || sc.size() == Size(cn, 1) || + (sc.size() == Size(1, 4) && sc.type() == CV_64F && cn <= 4); +} + +static void convertAndUnrollScalar( const Mat& sc, int buftype, uchar* scbuf, size_t blocksize ) +{ + int scn = (int)sc.total(), cn = CV_MAT_CN(buftype); + size_t esz = CV_ELEM_SIZE(buftype); + getConvertFunc(sc.depth(), buftype)(sc.data, 0, 0, 0, scbuf, 0, Size(std::min(cn, scn), 1), 0); + // unroll the scalar + if( scn < cn ) + { + CV_Assert( scn == 1 ); + size_t esz1 = CV_ELEM_SIZE1(buftype); + for( size_t i = esz1; i < esz; i++ ) + scbuf[i] = scbuf[i - esz1]; + } + for( size_t i = esz; i < blocksize*esz; i++ ) + scbuf[i] = scbuf[i - esz]; + +} + +void binary_op(const InputArray& _src1, const InputArray& _src2, OutputArray& _dst, + const InputArray& _mask, const BinaryFunc* tab, bool bitwise) +{ + int kind1 = _src1.kind(), kind2 = _src2.kind(); + Mat src1 = _src1.getMat(), src2 = _src2.getMat(); + bool haveMask = !_mask.empty(), haveScalar = false; + BinaryFunc func; + int c; + + if( src1.dims <= 2 && src2.dims <= 2 && kind1 == kind2 && + src1.size() == src2.size() && src1.type() == src2.type() && !haveMask ) + { + _dst.create(src1.size(), src1.type()); + Mat dst = _dst.getMat(); + if( bitwise ) + { + func = *tab; + c = (int)src1.elemSize(); + } + else + { + func = tab[src1.depth()]; + c = src1.channels(); + } + + Size sz = getContinuousSize(src1, src2, dst, c); + func(src1.data, src1.step, src2.data, src2.step, dst.data, dst.step, sz, 0); + return; + } + + if( (kind1 == InputArray::MATX) + (kind2 == InputArray::MATX) == 1 || + src1.size != src2.size || src1.type() != src2.type() ) + { + if( checkScalar(src1, src2.type(), kind1, kind2) ) + // src1 is a scalar; swap it with src2 + swap(src1, src2); + else if( !checkScalar(src2, src1.type(), kind2, kind1) ) + CV_Error( CV_StsUnmatchedSizes, + "The operation is neither 'array op array' (where arrays have the same size and type), " + "nor 'array op scalar', nor 'scalar op array'" ); + haveScalar = true; + } + + size_t esz = src1.elemSize(); + size_t blocksize0 = (BLOCK_SIZE + esz-1)/esz; + int cn = src1.channels(); + BinaryFunc copymask = 0; + Mat mask; + + if( haveMask ) + { + mask = _mask.getMat(); + CV_Assert( (mask.type() == CV_8UC1 || mask.type() == CV_8SC1) ); + CV_Assert( mask.size == src1.size ); + copymask = getCopyMaskFunc(esz); + } + + AutoBuffer _buf; + uchar *scbuf = 0, *maskbuf = 0; + + _dst.create(src1.dims, src1.size, src1.type()); + Mat dst = _dst.getMat(); + + if( bitwise ) + { + func = *tab; + c = (int)esz; + } + else + { + func = tab[src1.depth()]; + c = cn; } -} - - -template static void -bitwiseSOp_( const Mat& srcmat, Mat& dstmat, const Scalar& _scalar ) -{ - OPB opb; OPI opi; OPV opv; - const uchar* src0 = srcmat.data; - uchar* dst0 = dstmat.data; - size_t step1 = srcmat.step, step = dstmat.step; - Size size = getContinuousSize( srcmat, dstmat, (int)srcmat.elemSize() ); - const int delta = 96; - uchar scalar[delta]; - scalarToRawData(_scalar, scalar, srcmat.type(), (int)(delta/srcmat.elemSize1()) ); - bool useSIMD = checkHardwareSupport(ARITHM_SIMD); - - for( ; size.height--; src0 += step1, dst0 += step ) + + if( !haveScalar ) { - const uchar* src = (const uchar*)src0; - uchar* dst = dst0; - int i, len = size.width; - - if( (((size_t)src|(size_t)dst) & 3) == 0 ) + const Mat* arrays[] = { &src1, &src2, &dst, &mask, 0 }; + uchar* ptrs[4]; + + NAryMatIterator it(arrays, ptrs); + size_t total = it.size, blocksize = total; + + if( haveMask ) + { + blocksize = std::min(blocksize, blocksize0); + _buf.allocate(blocksize*esz); + maskbuf = _buf; + } + + for( size_t i = 0; i < it.nplanes; i++, ++it ) { - while( (len -= delta) >= 0 ) + for( size_t j = 0; j < total; j += blocksize ) { - i = useSIMD ? opv(src, scalar, dst, delta) : 0; - for( ; i < delta; i += 16 ) + int bsz = (int)std::min(total - j, blocksize); + + func( ptrs[0], 0, ptrs[1], 0, haveMask ? maskbuf : ptrs[2], 0, Size(bsz*c, 1), 0 ); + if( haveMask ) { - int t0 = opi(((const int*)(src+i))[0], ((const int*)(scalar+i))[0]); - int t1 = opi(((const int*)(src+i))[1], ((const int*)(scalar+i))[1]); - ((int*)(dst+i))[0] = t0; - ((int*)(dst+i))[1] = t1; - - t0 = opi(((const int*)(src+i))[2], ((const int*)(scalar+i))[2]); - t1 = opi(((const int*)(src+i))[3], ((const int*)(scalar+i))[3]); - ((int*)(dst+i))[2] = t0; - ((int*)(dst+i))[3] = t1; + copymask( maskbuf, 0, ptrs[3], 0, ptrs[2], 0, Size(bsz, 1), &esz ); + ptrs[3] += bsz; } - src += delta; - dst += delta; + + bsz *= (int)esz; + ptrs[0] += bsz; ptrs[1] += bsz; ptrs[2] += bsz; } } - else + } + else + { + const Mat* arrays[] = { &src1, &dst, &mask, 0 }; + uchar* ptrs[3]; + + NAryMatIterator it(arrays, ptrs); + size_t total = it.size, blocksize = std::min(total, blocksize0); + + _buf.allocate(blocksize*(haveMask ? 2 : 1)*esz + 32); + scbuf = _buf; + maskbuf = alignPtr(scbuf + blocksize*esz, 16); + + convertAndUnrollScalar( src2, src1.type(), scbuf, blocksize); + + for( size_t i = 0; i < it.nplanes; i++, ++it ) { - while( (len -= delta) >= 0 ) + for( size_t j = 0; j < total; j += blocksize ) { - for( i = 0; i < delta; i += 4 ) + int bsz = (int)std::min(total - j, blocksize); + + func( ptrs[0], 0, scbuf, 0, haveMask ? maskbuf : ptrs[1], 0, Size(bsz*c, 1), 0 ); + if( haveMask ) { - uchar t0 = opb(src[i], scalar[i]); - uchar t1 = opb(src[i+1], scalar[i+1]); - dst[i] = t0; dst[i+1] = t1; - - t0 = opb(src[i+2], scalar[i+2]); - t1 = opb(src[i+3], scalar[i+3]); - dst[i+2] = t0; dst[i+3] = t1; + copymask( maskbuf, 0, ptrs[2], 0, ptrs[1], 0, Size(bsz, 1), &esz ); + ptrs[2] += bsz; } - src += delta; - dst += delta; + + bsz *= (int)esz; + ptrs[0] += bsz; ptrs[1] += bsz; } } - - for( len += delta, i = 0; i < len; i++ ) - dst[i] = opb(src[i],scalar[i]); } } - - -static void -binaryOp( const Mat& src1, const Mat& src2, Mat& dst, BinaryFunc func, int dsttype=-1 ) + +static BinaryFunc maxTab[] = { - if( dsttype == -1 ) - dsttype = src1.type(); - CV_Assert( src1.type() == src2.type() && func != 0 ); - - if( src1.dims > 2 || src2.dims > 2 ) - { - dst.create(src1.dims, src1.size, dsttype); - const Mat* arrays[] = { &src1, &src2, &dst, 0 }; - Mat planes[3]; - NAryMatIterator it(arrays, planes); + (BinaryFunc)max8u, (BinaryFunc)max8s, (BinaryFunc)max16u, (BinaryFunc)max16s, + (BinaryFunc)max32s, (BinaryFunc)max32f, (BinaryFunc)max64f, 0 +}; - for( int i = 0; i < it.nplanes; i++, ++it ) - func(it.planes[0], it.planes[1], it.planes[2]); - return; - } +static BinaryFunc minTab[] = +{ + (BinaryFunc)min8u, (BinaryFunc)min8s, (BinaryFunc)min16u, (BinaryFunc)min16s, + (BinaryFunc)min32s, (BinaryFunc)min32f, (BinaryFunc)min64f, 0 +}; - CV_Assert( src1.size() == src2.size() ); - dst.create( src1.size(), dsttype ); - func( src1, src2, dst ); } - - -static void -binaryMaskOp( const Mat& src1, const Mat& src2, Mat& dst, - const Mat& mask, BinaryFunc func ) + +void cv::bitwise_and(const InputArray& a, const InputArray& b, OutputArray c, const InputArray& mask) { - CV_Assert( src1.type() == src2.type() && func != 0 ); - - if( src1.dims > 2 || src2.dims > 2 ) - { - dst.create(src1.dims, src1.size, src1.type()); - const Mat* arrays[] = { &src1, &src2, &dst, &mask, 0 }; - Mat planes[4]; - NAryMatIterator it(arrays, planes); - - if( !mask.data ) - for( int i = 0; i < it.nplanes; i++, ++it ) - func(it.planes[0], it.planes[1], it.planes[2]); - else - for( int i = 0; i < it.nplanes; i++, ++it ) - binaryMaskOp(it.planes[0], it.planes[1], - it.planes[2], it.planes[3], - func); - return; - } - - CV_Assert( src1.size() == src2.size() ); - dst.create( src1.size(), src1.type() ); - - if( !mask.data ) - func(src1, src2, dst); - else - { - AutoBuffer buf; - size_t esz = dst.elemSize(), buf_step = dst.cols*esz; - CopyMaskFunc copym_func = getCopyMaskFunc((int)esz); - int y, dy; - - CV_Assert(mask.type() == CV_8UC1 && mask.size() == dst.size()); - dy = std::min(std::max((int)(CV_MAX_LOCAL_SIZE/buf_step), 1), dst.rows); - buf.allocate( buf_step*dy ); - - for( y = 0; y < dst.rows; y += dy ) - { - dy = std::min(dy, dst.rows - y); - Mat dstpart = dst.rowRange(y, y + dy); - Mat temp(dy, dst.cols, dst.type(), (uchar*)buf ); - func( src1.rowRange(y, y + dy), src2.rowRange(y, y + dy), temp ); - copym_func( temp, dstpart, mask.rowRange(y, y + dy) ); - } - } + BinaryFunc f = and8u; + binary_op(a, b, c, mask, &f, true); } - -static void -binarySMaskOp( const Mat& src1, const Scalar& s, Mat& dst, - const Mat& mask, BinarySFuncCn func ) +void cv::bitwise_or(const InputArray& a, const InputArray& b, OutputArray c, const InputArray& mask) { - CV_Assert( func != 0 ); - - if( src1.dims > 2 ) - { - dst.create(src1.dims, src1.size, src1.type()); - const Mat* arrays[] = { &src1, &dst, &mask, 0 }; - Mat planes[3]; - NAryMatIterator it(arrays, planes); - - if( !mask.data ) - for( int i = 0; i < it.nplanes; i++, ++it ) - func(it.planes[0], it.planes[1], s); - else - for( int i = 0; i < it.nplanes; i++, ++it ) - binarySMaskOp(it.planes[0], s, it.planes[1], - it.planes[2], func); - return; - } - - dst.create( src1.size(), src1.type() ); - - if( !mask.data ) - func(src1, dst, s); - else - { - AutoBuffer buf; - size_t esz = dst.elemSize(), buf_step = dst.cols*esz; - CopyMaskFunc copym_func = getCopyMaskFunc((int)esz); - int y, dy; - - CV_Assert(mask.type() == CV_8UC1 && mask.size() == dst.size()); - dy = std::min(std::max((int)(CV_MAX_LOCAL_SIZE/buf_step), 1), dst.rows); - buf.allocate( buf_step*dy ); - - for( y = 0; y < dst.rows; y += dy ) - { - dy = std::min(dy, dst.rows - y); - Mat dstpart = dst.rowRange(y, y + dy); - Mat temp(dy, dst.cols, dst.type(), (uchar*)buf); - func( src1.rowRange(y, y + dy), temp, s ); - copym_func( temp, dstpart, mask.rowRange(y, y + dy) ); - } - } + BinaryFunc f = or8u; + binary_op(a, b, c, mask, &f, true); } - -void bitwise_and(const Mat& a, const Mat& b, Mat& c, const Mat& mask) +void cv::bitwise_xor(const InputArray& a, const InputArray& b, OutputArray c, const InputArray& mask) { -#if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7) - binaryMaskOp(a, b, c, mask, bitwiseOp_, AndOp, ippAnd8u>); -#else - binaryMaskOp(a, b, c, mask, bitwiseOp_, AndOp, VAnd8u>); -#endif + BinaryFunc f = xor8u; + binary_op(a, b, c, mask, &f, true); } -void bitwise_or(const Mat& a, const Mat& b, Mat& c, const Mat& mask) +void cv::bitwise_not(const InputArray& a, OutputArray c, const InputArray& mask) { -#if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7) - binaryMaskOp(a, b, c, mask, bitwiseOp_, OrOp, ippOr8u>); -#else - binaryMaskOp(a, b, c, mask, bitwiseOp_, OrOp, VOr8u>); -#endif + BinaryFunc f = not8u; + binary_op(a, a, c, mask, &f, true); } -void bitwise_xor(const Mat& a, const Mat& b, Mat& c, const Mat& mask) +void cv::max( const InputArray& src1, const InputArray& src2, OutputArray dst ) { -#if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7) - binaryMaskOp(a, b, c, mask, bitwiseOp_, XorOp, ippXor8u>); -#else - binaryMaskOp(a, b, c, mask, bitwiseOp_, XorOp, VXor8u>); -#endif + binary_op(src1, src2, dst, InputArray(), maxTab, false ); } -void bitwise_and(const Mat& a, const Scalar& s, Mat& c, const Mat& mask) +void cv::min( const InputArray& src1, const InputArray& src2, OutputArray dst ) { - binarySMaskOp(a, s, c, mask, - bitwiseSOp_, AndOp, VAnd8u>); + binary_op(src1, src2, dst, InputArray(), minTab, false ); } -void bitwise_or(const Mat& a, const Scalar& s, Mat& c, const Mat& mask) +void cv::max(const Mat& src1, const Mat& src2, Mat& dst) { - binarySMaskOp(a, s, c, mask, - bitwiseSOp_, OrOp, VOr8u>); + OutputArray _dst(dst); + binary_op(src1, src2, _dst, InputArray(), maxTab, false ); +} + +void cv::min(const Mat& src1, const Mat& src2, Mat& dst) +{ + OutputArray _dst(dst); + binary_op(src1, src2, _dst, InputArray(), minTab, false ); } + +void cv::max(const Mat& src1, double src2, Mat& dst) +{ + OutputArray _dst(dst); + binary_op(src1, src2, _dst, InputArray(), maxTab, false ); +} -void bitwise_xor(const Mat& a, const Scalar& s, Mat& c, const Mat& mask) +void cv::min(const Mat& src1, double src2, Mat& dst) { - binarySMaskOp(a, s, c, mask, - bitwiseSOp_, XorOp, VXor8u>); + OutputArray _dst(dst); + binary_op(src1, src2, _dst, InputArray(), minTab, false ); } + +/****************************************************************************************\ +* add/subtract * +\****************************************************************************************/ +namespace cv +{ -void bitwise_not(const Mat& src, Mat& dst) +void arithm_op(const InputArray& _src1, const InputArray& _src2, OutputArray& _dst, + const InputArray& _mask, int dtype, BinaryFunc* tab, bool muldiv=false, void* usrdata=0) { - if( src.dims > 2 ) + int kind1 = _src1.kind(), kind2 = _src2.kind(); + Mat src1 = _src1.getMat(), src2 = _src2.getMat(); + bool haveMask = !_mask.empty(); + + if( kind1 == kind2 && src1.dims <= 2 && src2.dims <= 2 && + src1.size() == src2.size() && src1.type() == src2.type() && + !haveMask && ((!_dst.fixedType() && (dtype < 0 || CV_MAT_DEPTH(dtype) == src1.depth())) || + (_dst.fixedType() && _dst.type() == _src1.type())) ) { - dst.create(src.dims, src.size, src.type()); - const Mat* arrays[] = { &src, &dst, 0 }; - Mat planes[4]; - NAryMatIterator it(arrays, planes); - - for( int i = 0; i < it.nplanes; i++, ++it ) - bitwise_not(it.planes[0], it.planes[1]); + _dst.create(src1.size(), src1.type()); + Mat dst = _dst.getMat(); + Size sz = getContinuousSize(src1, src2, dst, src1.channels()); + tab[src1.depth()](src1.data, src1.step, src2.data, src2.step, dst.data, dst.step, sz, usrdata); return; } - - const uchar* sptr = src.data; - dst.create( src.size(), src.type() ); - uchar* dptr = dst.data; - Size size = getContinuousSize( src, dst, (int)src.elemSize() ); - - for( ; size.height--; sptr += src.step, dptr += dst.step ) + + bool haveScalar = false, swapped12 = false; + + if( (kind1 == InputArray::MATX) + (kind2 == InputArray::MATX) == 1 || + src1.size != src2.size || src1.channels() != src2.channels() ) { - int i = 0; - if( (((size_t)sptr | (size_t)dptr) & 3) == 0 ) + if( checkScalar(src1, src2.type(), kind1, kind2) ) + { + // src1 is a scalar; swap it with src2 + swap(src1, src2); + swapped12 = true; + } + else if( !checkScalar(src2, src1.type(), kind2, kind1) ) + CV_Error( CV_StsUnmatchedSizes, + "The operation is neither 'array op array' (where arrays have the same size and the same number of channels), " + "nor 'array op scalar', nor 'scalar op array'" ); + haveScalar = true; + } + + int cn = src1.channels(), depth1 = src1.depth(), depth2 = src2.depth(), wtype; + BinaryFunc cvtsrc1 = 0, cvtsrc2 = 0, cvtdst = 0; + + if( dtype < 0 ) + { + if( _dst.fixedType() ) + dtype = _dst.type(); + else + { + if( !haveScalar && src1.type() != src2.type() ) + CV_Error(CV_StsBadArg, + "When the input arrays in add/subtract/multiply/divide functions have different types, " + "the output array type must be explicitly specified"); + dtype = src1.type(); + } + } + dtype = CV_MAT_DEPTH(dtype); + + if( depth1 == depth2 && dtype == depth1 ) + wtype = dtype; + else if( !muldiv ) + { + wtype = depth1 <= CV_8S && depth2 <= CV_8S ? CV_16S : + depth1 <= CV_32S && depth2 <= CV_32S ? CV_32S : std::max(depth1, depth2); + wtype = std::max(wtype, dtype); + + // when the result of addition should be converted to an integer type, + // and just one of the input arrays is floating-point, it makes sense to convert that input to integer type before the operation, + // instead of converting the other input to floating-point and then converting the operation result back to integers. + if( dtype < CV_32F && (depth1 < CV_32F || depth2 < CV_32F) ) + wtype = CV_32S; + } + else + { + wtype = std::max(depth1, std::max(depth2, CV_32F)); + wtype = std::max(wtype, dtype); + } + + cvtsrc1 = depth1 == wtype ? 0 : getConvertFunc(depth1, wtype); + cvtsrc2 = depth2 == depth1 ? cvtsrc1 : depth2 == wtype ? 0 : getConvertFunc(depth2, wtype); + cvtdst = dtype == wtype ? 0 : getConvertFunc(wtype, dtype); + + dtype = CV_MAKETYPE(dtype, cn); + wtype = CV_MAKETYPE(wtype, cn); + + size_t esz1 = src1.elemSize(), esz2 = src2.elemSize(); + size_t dsz = CV_ELEM_SIZE(dtype), wsz = CV_ELEM_SIZE(wtype); + size_t blocksize0 = (size_t)(BLOCK_SIZE + wsz-1)/wsz; + BinaryFunc copymask = 0; + Mat mask; + + if( haveMask ) + { + mask = _mask.getMat(); + CV_Assert( (mask.type() == CV_8UC1 || mask.type() == CV_8SC1) ); + CV_Assert( mask.size == src1.size ); + copymask = getCopyMaskFunc(dsz); + } + + AutoBuffer _buf; + uchar *buf, *maskbuf = 0, *buf1 = 0, *buf2 = 0, *wbuf = 0; + size_t bufesz = (cvtsrc1 ? wsz : 0) + (cvtsrc2 || haveScalar ? wsz : 0) + (cvtdst ? wsz : 0) + (haveMask ? dsz : 0); + + _dst.create(src1.dims, src1.size, src1.type()); + Mat dst = _dst.getMat(); + BinaryFunc func = tab[CV_MAT_DEPTH(wtype)]; + + if( !haveScalar ) + { + const Mat* arrays[] = { &src1, &src2, &dst, &mask, 0 }; + uchar* ptrs[4]; + + NAryMatIterator it(arrays, ptrs); + size_t total = it.size, blocksize = total; + + if( haveMask || cvtsrc1 || cvtsrc2 || cvtdst ) + blocksize = std::min(blocksize, blocksize0); + + _buf.allocate(bufesz*blocksize + 64); + buf = _buf; + if( cvtsrc1 ) + buf1 = buf, buf = alignPtr(buf + blocksize*wsz, 16); + if( cvtsrc2 ) + buf2 = buf, buf = alignPtr(buf + blocksize*wsz, 16); + wbuf = maskbuf = buf; + if( cvtdst ) + buf = alignPtr(buf + blocksize*wsz, 16); + if( haveMask ) + maskbuf = buf; + + for( size_t i = 0; i < it.nplanes; i++, ++it ) { - for( ; i <= size.width - 16; i += 16 ) + for( size_t j = 0; j < total; j += blocksize ) { - int t0 = ~((const int*)(sptr+i))[0]; - int t1 = ~((const int*)(sptr+i))[1]; - - ((int*)(dptr+i))[0] = t0; - ((int*)(dptr+i))[1] = t1; - - t0 = ~((const int*)(sptr+i))[2]; - t1 = ~((const int*)(sptr+i))[3]; - - ((int*)(dptr+i))[2] = t0; - ((int*)(dptr+i))[3] = t1; + int bsz = (int)std::min(total - j, blocksize); + Size bszn(bsz*cn, 1); + const uchar *sptr1 = ptrs[0], *sptr2 = ptrs[1]; + uchar* dptr = ptrs[2]; + if( cvtsrc1 ) + { + cvtsrc1( sptr1, 0, 0, 0, buf1, 0, bszn, 0 ); + sptr1 = buf1; + } + if( ptrs[0] == ptrs[1] ) + sptr2 = sptr1; + else if( cvtsrc2 ) + { + cvtsrc2( sptr2, 0, 0, 0, buf2, 0, bszn, 0 ); + sptr2 = buf2; + } + + if( !haveMask && !cvtdst ) + func( sptr1, 0, sptr2, 0, dptr, 0, bszn, usrdata ); + else + { + func( sptr1, 0, sptr2, 0, wbuf, 0, bszn, usrdata ); + if( !haveMask ) + cvtdst( wbuf, 0, 0, 0, dptr, 0, bszn, 0 ); + else if( !cvtdst ) + { + copymask( wbuf, 0, ptrs[3], 0, dptr, 0, Size(bsz, 1), &dsz ); + ptrs[3] += bsz; + } + else + { + cvtdst( wbuf, 0, 0, 0, maskbuf, 0, bszn, 0 ); + copymask( maskbuf, 0, ptrs[3], 0, dptr, 0, Size(bsz, 1), &dsz ); + ptrs[3] += bsz; + } + } + ptrs[0] += bsz*esz1; ptrs[1] += bsz*esz2; ptrs[2] += bsz*dsz; } - - for( ; i <= size.width - 4; i += 4 ) - *(int*)(dptr+i) = ~*(const int*)(sptr+i); } - - for( ; i < size.width; i++ ) + } + else + { + const Mat* arrays[] = { &src1, &dst, &mask, 0 }; + uchar* ptrs[3]; + + NAryMatIterator it(arrays, ptrs); + size_t total = it.size, blocksize = std::min(total, blocksize0); + + _buf.allocate(bufesz*blocksize + 64); + buf = _buf; + if( cvtsrc1 ) + buf1 = buf, buf = alignPtr(buf + blocksize*wsz, 16); + buf2 = buf; buf = alignPtr(buf + blocksize*wsz, 16); + wbuf = maskbuf = buf; + if( cvtdst ) + buf = alignPtr(buf + blocksize*wsz, 16); + if( haveMask ) + maskbuf = buf; + + convertAndUnrollScalar( src2, wtype, buf2, blocksize); + + for( size_t i = 0; i < it.nplanes; i++, ++it ) { - dptr[i] = (uchar)(~sptr[i]); + for( size_t j = 0; j < total; j += blocksize ) + { + int bsz = (int)std::min(total - j, blocksize); + Size bszn(bsz*cn, 1); + const uchar *sptr1 = ptrs[0]; + const uchar* sptr2 = buf2; + uchar* dptr = ptrs[1]; + + if( cvtsrc1 ) + { + cvtsrc1( sptr1, 0, 0, 0, buf1, 0, bszn, 0 ); + sptr1 = buf1; + } + + if( swapped12 ) + std::swap(sptr1, sptr2); + + if( !haveMask && !cvtdst ) + func( sptr1, 0, sptr2, 0, dptr, 0, bszn, usrdata ); + else + { + func( sptr1, 0, sptr2, 0, wbuf, 0, bszn, usrdata ); + if( !haveMask ) + cvtdst( wbuf, 0, 0, 0, dptr, 0, bszn, 0 ); + else if( !cvtdst ) + { + copymask( wbuf, 0, ptrs[2], 0, dptr, 0, Size(bsz, 1), &dsz ); + ptrs[2] += bsz; + } + else + { + cvtdst( wbuf, 0, 0, 0, maskbuf, 0, bszn, 0 ); + copymask( maskbuf, 0, ptrs[2], 0, dptr, 0, Size(bsz, 1), &dsz ); + ptrs[2] += bsz; + } + } + ptrs[0] += bsz*esz1; ptrs[1] += bsz*dsz; + } } } } - -/****************************************************************************************\ -* add/subtract * -\****************************************************************************************/ - -template<> inline uchar OpAdd::operator ()(uchar a, uchar b) const -{ return CV_FAST_CAST_8U(a + b); } -template<> inline uchar OpSub::operator ()(uchar a, uchar b) const -{ return CV_FAST_CAST_8U(a - b); } - + static BinaryFunc addTab[] = { -#if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7) - binaryOpC1_, ippAdd8u>, - 0, - binaryOpC1_, ippAdd16u>, - binaryOpC1_, ippAdd16s>, - binaryOpC1_, ippAdd32s>, - binaryOpC1_, ippAdd32f>, - binaryOpC1_, ippAdd64f>, - 0 -#else - binaryOpC1_, VAdd8u>, - 0, - binaryOpC1_, VAdd16u>, - binaryOpC1_, VAdd16s>, - binaryOpC1_, NoVec>, - binaryOpC1_, VAdd32f>, - binaryOpC1_, NoVec>, - 0 -#endif + (BinaryFunc)add8u, (BinaryFunc)add8s, (BinaryFunc)add16u, (BinaryFunc)add16s, + (BinaryFunc)add32s, (BinaryFunc)add32f, (BinaryFunc)add64f, 0 }; - + static BinaryFunc subTab[] = { -#if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7) - binaryOpC1_, ippSub8u>, - 0, - binaryOpC1_, ippSub16u>, - binaryOpC1_, ippSub16s>, - binaryOpC1_, ippSub32s>, - binaryOpC1_, ippSub32f>, - binaryOpC1_, ippSub64f>, - 0 -#else - binaryOpC1_, VSub8u>, - 0, - binaryOpC1_, VSub16u>, - binaryOpC1_, VSub16s>, - binaryOpC1_, NoVec>, - binaryOpC1_, VSub32f>, - binaryOpC1_, NoVec>, - 0 -#endif + (BinaryFunc)sub8u, (BinaryFunc)sub8s, (BinaryFunc)sub16u, (BinaryFunc)sub16s, + (BinaryFunc)sub32s, (BinaryFunc)sub32f, (BinaryFunc)sub64f, 0 }; -void add( const Mat& src1, const Mat& src2, Mat& dst ) -{ - int type = src1.type(); - BinaryFunc func = addTab[CV_MAT_DEPTH(type)]; - CV_Assert( type == src2.type() && func != 0 ); - - if( src1.dims > 2 || src2.dims > 2 ) - { - dst.create(src1.dims, src1.size, src1.type()); - const Mat* arrays[] = {&src1, &src2, &dst, 0}; - Mat planes[3]; - NAryMatIterator it(arrays, planes); - - for( int i = 0; i < it.nplanes; i++, ++it ) - func( it.planes[0], it.planes[1], it.planes[2] ); - return; - } - - Size size = src1.size(); - CV_Assert( size == src2.size() ); - dst.create( size, type ); - func(src1, src2, dst); -} - -void subtract( const Mat& src1, const Mat& src2, Mat& dst ) +static BinaryFunc absdiffTab[] = { - int type = src1.type(); - BinaryFunc func = subTab[CV_MAT_DEPTH(type)]; - CV_Assert( type == src2.type() && func != 0 ); - - if( src1.dims > 2 || src2.dims > 2 ) - { - dst.create(src1.dims, src1.size, src1.type()); - const Mat* arrays[] = {&src1, &src2, &dst, 0}; - Mat planes[3]; - NAryMatIterator it(arrays, planes); - - for( int i = 0; i < it.nplanes; i++, ++it ) - func( it.planes[0], it.planes[1], it.planes[2] ); - return; - } - - Size size = src1.size(); - CV_Assert( size == src2.size() ); - dst.create( size, type ); - func(src1, src2, dst); -} + (BinaryFunc)absdiff8u, (BinaryFunc)absdiff8s, (BinaryFunc)absdiff16u, + (BinaryFunc)absdiff16s, (BinaryFunc)absdiff32s, (BinaryFunc)absdiff32f, + (BinaryFunc)absdiff64f, 0 +}; -void subtract(const Mat& a, const Scalar& s, Mat& c, const Mat& mask) -{ - add(a, -s, c, mask); } - -void add(const Mat& src1, const Mat& src2, Mat& dst, const Mat& mask) + +void cv::add( const InputArray& src1, const InputArray& src2, OutputArray dst, + const InputArray& mask, int dtype ) { - binaryMaskOp(src1, src2, dst, mask, addTab[src1.depth()] ); + arithm_op(src1, src2, dst, mask, dtype, addTab ); } -void subtract(const Mat& src1, const Mat& src2, Mat& dst, const Mat& mask) +void cv::subtract( const InputArray& src1, const InputArray& src2, OutputArray dst, + const InputArray& mask, int dtype ) { - binaryMaskOp(src1, src2, dst, mask, subTab[src1.depth()] ); + arithm_op(src1, src2, dst, mask, dtype, subTab ); } -void add(const Mat& src1, const Scalar& s, Mat& dst, const Mat& mask) +void cv::absdiff( const InputArray& src1, const InputArray& src2, OutputArray dst ) { - static BinarySFuncCn addSTab[] = - { - binarySOpCn_ >, - 0, - binarySOpCn_ >, - binarySOpCn_ >, - binarySOpCn_ >, - binarySOpCn_ >, - binarySOpCn_ >, - 0 - }; - int depth = src1.depth(); - binarySMaskOp(src1, s, dst, mask, addSTab[depth]); -} - -void subtract(const Scalar& s, const Mat& src1, Mat& dst, const Mat& mask) -{ - static BinarySFuncCn rsubSTab[] = - { - binarySOpCn_ >, - 0, - binarySOpCn_ >, - binarySOpCn_ >, - binarySOpCn_ >, - binarySOpCn_ >, - binarySOpCn_ >, - 0 - }; - int depth = src1.depth(); - binarySMaskOp(src1, s, dst, mask, rsubSTab[depth]); -} + arithm_op(src1, src2, dst, InputArray(), -1, absdiffTab); +} /****************************************************************************************\ * multiply/divide * \****************************************************************************************/ +namespace cv +{ + template static void -mul_( const Mat& srcmat1, const Mat& srcmat2, Mat& dstmat, double _scale ) +mul_( const T* src1, size_t step1, const T* src2, size_t step2, + T* dst, size_t step, Size size, WT scale ) { - const T* src1 = (const T*)srcmat1.data; - const T* src2 = (const T*)srcmat2.data; - T* dst = (T*)dstmat.data; - size_t step1 = srcmat1.step/sizeof(src1[0]); - size_t step2 = srcmat2.step/sizeof(src2[0]); - size_t step = dstmat.step/sizeof(dst[0]); - Size size = getContinuousSize( srcmat1, srcmat2, dstmat, dstmat.channels() ); + step1 /= sizeof(src1[0]); + step2 /= sizeof(src2[0]); + step /= sizeof(dst[0]); - if( fabs(_scale - 1.) < DBL_EPSILON ) + if( scale == (WT)1. ) { - for( ; size.height--; src1+=step1, src2+=step2, dst+=step ) + for( ; size.height--; src1 += step1, src2 += step2, dst += step ) { int i; for( i = 0; i <= size.width - 4; i += 4 ) @@ -1075,8 +1410,7 @@ mul_( const Mat& srcmat1, const Mat& srcmat2, Mat& dstmat, double _scale ) } else { - WT scale = (WT)_scale; - for( ; size.height--; src1+=step1, src2+=step2, dst+=step ) + for( ; size.height--; src1 += step1, src2 += step2, dst += step ) { int i; for( i = 0; i <= size.width - 4; i += 4 ) @@ -1096,56 +1430,15 @@ mul_( const Mat& srcmat1, const Mat& srcmat2, Mat& dstmat, double _scale ) } } -typedef void (*MulDivFunc)( const Mat& src1, const Mat& src2, - Mat& dst, double scale ); - -void multiply(const Mat& src1, const Mat& src2, Mat& dst, double scale) -{ - static MulDivFunc tab[] = - { - mul_, - 0, - mul_, - mul_, - mul_, - mul_, - mul_, - 0 - }; - - MulDivFunc func = tab[src1.depth()]; - CV_Assert( src1.type() == src2.type() && func != 0 ); - - if( src1.dims > 2 || src2.dims > 2 ) - { - dst.create(src1.dims, src1.size, src1.type()); - const Mat* arrays[] = {&src1, &src2, &dst, 0}; - Mat planes[3]; - NAryMatIterator it(arrays, planes); - - for( int i = 0; i < it.nplanes; i++, ++it ) - func( it.planes[0], it.planes[1], it.planes[2], scale ); - return; - } - - CV_Assert( src1.size() == src2.size() ); - dst.create( src1.size(), src1.type() ); - func( src1, src2, dst, scale ); -} - - template static void -div_( const Mat& srcmat1, const Mat& srcmat2, Mat& dstmat, double scale ) +div_( const T* src1, size_t step1, const T* src2, size_t step2, + T* dst, size_t step, Size size, double scale ) { - const T* src1 = (const T*)srcmat1.data; - const T* src2 = (const T*)srcmat2.data; - T* dst = (T*)dstmat.data; - size_t step1 = srcmat1.step/sizeof(src1[0]); - size_t step2 = srcmat2.step/sizeof(src2[0]); - size_t step = dstmat.step/sizeof(dst[0]); - Size size = getContinuousSize( srcmat1, srcmat2, dstmat, dstmat.channels() ); - - for( ; size.height--; src1+=step1, src2+=step2, dst+=step ) + step1 /= sizeof(src1[0]); + step2 /= sizeof(src2[0]); + step /= sizeof(dst[0]); + + for( ; size.height--; src1 += step1, src2 += step2, dst += step ) { int i = 0; for( ; i <= size.width - 4; i += 4 ) @@ -1157,12 +1450,12 @@ div_( const Mat& srcmat1, const Mat& srcmat2, Mat& dstmat, double scale ) double d = scale/(a * b); b *= d; a *= d; - + T z0 = saturate_cast(src2[i+1] * ((double)src1[i] * b)); T z1 = saturate_cast(src2[i] * ((double)src1[i+1] * b)); T z2 = saturate_cast(src2[i+3] * ((double)src1[i+2] * a)); T z3 = saturate_cast(src2[i+2] * ((double)src1[i+3] * a)); - + dst[i] = z0; dst[i+1] = z1; dst[i+2] = z2; dst[i+3] = z3; } @@ -1172,56 +1465,25 @@ div_( const Mat& srcmat1, const Mat& srcmat2, Mat& dstmat, double scale ) T z1 = src2[i+1] != 0 ? saturate_cast(src1[i+1]*scale/src2[i+1]) : 0; T z2 = src2[i+2] != 0 ? saturate_cast(src1[i+2]*scale/src2[i+2]) : 0; T z3 = src2[i+3] != 0 ? saturate_cast(src1[i+3]*scale/src2[i+3]) : 0; - + dst[i] = z0; dst[i+1] = z1; dst[i+2] = z2; dst[i+3] = z3; } } - + for( ; i < size.width; i++ ) dst[i] = src2[i] != 0 ? saturate_cast(src1[i]*scale/src2[i]) : 0; } } - -void divide(const Mat& src1, const Mat& src2, Mat& dst, double scale) -{ - static MulDivFunc tab[] = - { - div_, 0, div_, div_, - div_, div_, div_, 0 - }; - - MulDivFunc func = tab[src1.depth()]; - CV_Assert( src1.type() == src2.type() && func != 0 ); - - if( src1.dims > 2 || src2.dims > 2 ) - { - dst.create(src1.dims, src1.size, src1.type()); - const Mat* arrays[] = {&src1, &src2, &dst, 0}; - Mat planes[3]; - NAryMatIterator it(arrays, planes); - - for( int i = 0; i < it.nplanes; i++, ++it ) - func( it.planes[0], it.planes[1], it.planes[2], scale ); - return; - } - - CV_Assert( src1.size() == src2.size() ); - dst.create( src1.size(), src1.type() ); - func( src1, src2, dst, scale ); -} - template static void -recip_( double scale, const Mat& srcmat2, Mat& dstmat ) +recip_( const T*, size_t, const T* src2, size_t step2, + T* dst, size_t step, Size size, double scale ) { - const T* src2 = (const T*)srcmat2.data; - T* dst = (T*)dstmat.data; - size_t step2 = srcmat2.step/sizeof(src2[0]); - size_t step = dstmat.step/sizeof(dst[0]); - Size size = getContinuousSize( srcmat2, dstmat, dstmat.channels() ); - - for( ; size.height--; src2+=step2, dst+=step ) + step2 /= sizeof(src2[0]); + step /= sizeof(dst[0]); + + for( ; size.height--; src2 += step2, dst += step ) { int i = 0; for( ; i <= size.width - 4; i += 4 ) @@ -1233,12 +1495,12 @@ recip_( double scale, const Mat& srcmat2, Mat& dstmat ) double d = scale/(a * b); b *= d; a *= d; - + T z0 = saturate_cast(src2[i+1] * b); T z1 = saturate_cast(src2[i] * b); T z2 = saturate_cast(src2[i+3] * a); T z3 = saturate_cast(src2[i+2] * a); - + dst[i] = z0; dst[i+1] = z1; dst[i+2] = z2; dst[i+3] = z3; } @@ -1248,870 +1510,809 @@ recip_( double scale, const Mat& srcmat2, Mat& dstmat ) T z1 = src2[i+1] != 0 ? saturate_cast(scale/src2[i+1]) : 0; T z2 = src2[i+2] != 0 ? saturate_cast(scale/src2[i+2]) : 0; T z3 = src2[i+3] != 0 ? saturate_cast(scale/src2[i+3]) : 0; - + dst[i] = z0; dst[i+1] = z1; dst[i+2] = z2; dst[i+3] = z3; } } - + for( ; i < size.width; i++ ) dst[i] = src2[i] != 0 ? saturate_cast(scale/src2[i]) : 0; } } + + +static void mul8u( const uchar* src1, size_t step1, const uchar* src2, size_t step2, + uchar* dst, size_t step, Size sz, void* scale) +{ + mul_(src1, step1, src2, step2, dst, step, sz, (float)*(const double*)scale); +} + +static void mul8s( const schar* src1, size_t step1, const schar* src2, size_t step2, + schar* dst, size_t step, Size sz, void* scale) +{ + mul_(src1, step1, src2, step2, dst, step, sz, (float)*(const double*)scale); +} + +static void mul16u( const ushort* src1, size_t step1, const ushort* src2, size_t step2, + ushort* dst, size_t step, Size sz, void* scale) +{ + mul_(src1, step1, src2, step2, dst, step, sz, (float)*(const double*)scale); +} + +static void mul16s( const short* src1, size_t step1, const short* src2, size_t step2, + short* dst, size_t step, Size sz, void* scale) +{ + mul_(src1, step1, src2, step2, dst, step, sz, (float)*(const double*)scale); +} + +static void mul32s( const int* src1, size_t step1, const int* src2, size_t step2, + int* dst, size_t step, Size sz, void* scale) +{ + mul_(src1, step1, src2, step2, dst, step, sz, *(const double*)scale); +} + +static void mul32f( const float* src1, size_t step1, const float* src2, size_t step2, + float* dst, size_t step, Size sz, void* scale) +{ + mul_(src1, step1, src2, step2, dst, step, sz, (float)*(const double*)scale); +} + +static void mul64f( const double* src1, size_t step1, const double* src2, size_t step2, + double* dst, size_t step, Size sz, void* scale) +{ + mul_(src1, step1, src2, step2, dst, step, sz, *(const double*)scale); +} + +static void div8u( const uchar* src1, size_t step1, const uchar* src2, size_t step2, + uchar* dst, size_t step, Size sz, void* scale) +{ + if( src1 ) + div_(src1, step1, src2, step2, dst, step, sz, *(const double*)scale); + else + recip_(src1, step1, src2, step2, dst, step, sz, *(const double*)scale); +} + +static void div8s( const schar* src1, size_t step1, const schar* src2, size_t step2, + schar* dst, size_t step, Size sz, void* scale) +{ + div_(src1, step1, src2, step2, dst, step, sz, *(const double*)scale); +} + +static void div16u( const ushort* src1, size_t step1, const ushort* src2, size_t step2, + ushort* dst, size_t step, Size sz, void* scale) +{ + div_(src1, step1, src2, step2, dst, step, sz, *(const double*)scale); +} + +static void div16s( const short* src1, size_t step1, const short* src2, size_t step2, + short* dst, size_t step, Size sz, void* scale) +{ + div_(src1, step1, src2, step2, dst, step, sz, *(const double*)scale); +} + +static void div32s( const int* src1, size_t step1, const int* src2, size_t step2, + int* dst, size_t step, Size sz, void* scale) +{ + div_(src1, step1, src2, step2, dst, step, sz, *(const double*)scale); +} + +static void div32f( const float* src1, size_t step1, const float* src2, size_t step2, + float* dst, size_t step, Size sz, void* scale) +{ + div_(src1, step1, src2, step2, dst, step, sz, *(const double*)scale); +} + +static void div64f( const double* src1, size_t step1, const double* src2, size_t step2, + double* dst, size_t step, Size sz, void* scale) +{ + div_(src1, step1, src2, step2, dst, step, sz, *(const double*)scale); +} + +static void recip8u( const uchar* src1, size_t step1, const uchar* src2, size_t step2, + uchar* dst, size_t step, Size sz, void* scale) +{ + recip_(src1, step1, src2, step2, dst, step, sz, *(const double*)scale); +} + +static void recip8s( const schar* src1, size_t step1, const schar* src2, size_t step2, + schar* dst, size_t step, Size sz, void* scale) +{ + recip_(src1, step1, src2, step2, dst, step, sz, *(const double*)scale); +} + +static void recip16u( const ushort* src1, size_t step1, const ushort* src2, size_t step2, + ushort* dst, size_t step, Size sz, void* scale) +{ + recip_(src1, step1, src2, step2, dst, step, sz, *(const double*)scale); +} + +static void recip16s( const short* src1, size_t step1, const short* src2, size_t step2, + short* dst, size_t step, Size sz, void* scale) +{ + recip_(src1, step1, src2, step2, dst, step, sz, *(const double*)scale); +} -typedef void (*RecipFunc)( double scale, const Mat& src, Mat& dst ); +static void recip32s( const int* src1, size_t step1, const int* src2, size_t step2, + int* dst, size_t step, Size sz, void* scale) +{ + recip_(src1, step1, src2, step2, dst, step, sz, *(const double*)scale); +} + +static void recip32f( const float* src1, size_t step1, const float* src2, size_t step2, + float* dst, size_t step, Size sz, void* scale) +{ + recip_(src1, step1, src2, step2, dst, step, sz, *(const double*)scale); +} + +static void recip64f( const double* src1, size_t step1, const double* src2, size_t step2, + double* dst, size_t step, Size sz, void* scale) +{ + recip_(src1, step1, src2, step2, dst, step, sz, *(const double*)scale); +} + + +static BinaryFunc mulTab[] = +{ + (BinaryFunc)mul8u, (BinaryFunc)mul8s, (BinaryFunc)mul16u, + (BinaryFunc)mul16s, (BinaryFunc)mul32s, (BinaryFunc)mul32f, + (BinaryFunc)mul64f, 0 +}; + +static BinaryFunc divTab[] = +{ + (BinaryFunc)div8u, (BinaryFunc)div8s, (BinaryFunc)div16u, + (BinaryFunc)div16s, (BinaryFunc)div32s, (BinaryFunc)div32f, + (BinaryFunc)div64f, 0 +}; + +static BinaryFunc recipTab[] = +{ + (BinaryFunc)recip8u, (BinaryFunc)recip8s, (BinaryFunc)recip16u, + (BinaryFunc)recip16s, (BinaryFunc)recip32s, (BinaryFunc)recip32f, + (BinaryFunc)recip64f, 0 +}; -void divide(double scale, const Mat& src, Mat& dst) + +} + +void cv::multiply(const InputArray& src1, const InputArray& src2, + OutputArray dst, double scale, int dtype) { - static RecipFunc tab[] = - { - recip_, - 0, - recip_, - recip_, - recip_, - recip_, - recip_, - 0 - }; - - RecipFunc func = tab[src.depth()]; - CV_Assert( func != 0 ); - - if( src.dims > 2 ) - { - dst.create(src.dims, src.size, src.type()); - const Mat* arrays[] = {&src, &dst, 0}; - Mat planes[2]; - NAryMatIterator it(arrays, planes); - - for( int i = 0; i < it.nplanes; i++, ++it ) - func( scale, it.planes[0], it.planes[1] ); - return; - } + arithm_op(src1, src2, dst, InputArray(), dtype, mulTab, true, &scale); +} - dst.create( src.size(), src.type() ); - func( scale, src, dst ); +void cv::divide(const InputArray& src1, const InputArray& src2, + OutputArray dst, double scale, int dtype) +{ + arithm_op(src1, src2, dst, InputArray(), dtype, divTab, true, &scale); } +void cv::divide(double scale, const InputArray& src2, + OutputArray dst, int dtype) +{ + arithm_op(src2, src2, dst, InputArray(), dtype, recipTab, true, &scale); +} + /****************************************************************************************\ * addWeighted * \****************************************************************************************/ +namespace cv +{ + template static void -addWeighted_( const Mat& srcmat1, double _alpha, const Mat& srcmat2, - double _beta, double _gamma, Mat& dstmat ) -{ - const T* src1 = (const T*)srcmat1.data; - const T* src2 = (const T*)srcmat2.data; - T* dst = (T*)dstmat.data; - size_t step1 = srcmat1.step/sizeof(src1[0]); - size_t step2 = srcmat2.step/sizeof(src2[0]); - size_t step = dstmat.step/sizeof(dst[0]); - Size size = getContinuousSize( srcmat1, srcmat2, dstmat, dstmat.channels() ); - WT alpha = (WT)_alpha, beta = (WT)_beta, gamma = (WT)_gamma; - - for( ; size.height--; src1+=step1, src2+=step2, dst+=step ) +addWeighted_( const T* src1, size_t step1, const T* src2, size_t step2, + T* dst, size_t step, Size size, void* _scalars ) +{ + const double* scalars = (const double*)_scalars; + WT alpha = (WT)scalars[0], beta = (WT)scalars[1], gamma = (WT)scalars[2]; + step1 /= sizeof(src1[0]); + step2 /= sizeof(src2[0]); + step /= sizeof(dst[0]); + + for( ; size.height--; src1 += step1, src2 += step2, dst += step ) { - int i = 0; - for( ; i <= size.width - 4; i += 4 ) + int x = 0; + for( ; x <= size.width - 4; x += 4 ) { - T t0 = saturate_cast(src1[i]*alpha + src2[i]*beta + gamma); - T t1 = saturate_cast(src1[i+1]*alpha + src2[i+1]*beta + gamma); - dst[i] = t0; dst[i+1] = t1; + T t0 = saturate_cast(src1[x]*alpha + src2[x]*beta + gamma); + T t1 = saturate_cast(src1[x+1]*alpha + src2[x+1]*beta + gamma); + dst[x] = t0; dst[x+1] = t1; - t0 = saturate_cast(src1[i+2]*alpha + src2[i+2]*beta + gamma); - t1 = saturate_cast(src1[i+3]*alpha + src2[i+3]*beta + gamma); - dst[i+2] = t0; dst[i+3] = t1; + t0 = saturate_cast(src1[x+2]*alpha + src2[x+2]*beta + gamma); + t1 = saturate_cast(src1[x+3]*alpha + src2[x+3]*beta + gamma); + dst[x+2] = t0; dst[x+3] = t1; } - for( ; i < size.width; i++ ) - dst[i] = saturate_cast(src1[i]*alpha + src2[i]*beta + gamma); + for( ; x < size.width; x++ ) + dst[x] = saturate_cast(src1[x]*alpha + src2[x]*beta + gamma); } } static void -addWeighted8u( const Mat& srcmat1, double alpha, - const Mat& srcmat2, double beta, - double gamma, Mat& dstmat ) -{ - const int shift = 14; - if( srcmat1.rows*srcmat1.cols*srcmat1.channels() <= 256 || - fabs(alpha) > 256 || fabs(beta) > 256 || fabs(gamma) > 256*256 ) - { - addWeighted_(srcmat1, alpha, srcmat2, beta, gamma, dstmat); - return; - } - const uchar* src1 = srcmat1.data; - const uchar* src2 = srcmat2.data; - uchar* dst = dstmat.data; - size_t step1 = srcmat1.step; - size_t step2 = srcmat2.step; - size_t step = dstmat.step; - Size size = getContinuousSize( srcmat1, srcmat2, dstmat, dstmat.channels() ); - - int tab1[256], tab2[256]; - double t = 0; - int j, t0, t1, t2, t3; - - alpha *= 1 << shift; - gamma = gamma*(1 << shift) + (1 << (shift - 1)); - beta *= 1 << shift; - - for( j = 0; j < 256; j++ ) - { - tab1[j] = cvRound(t); - tab2[j] = cvRound(gamma); - t += alpha; - gamma += beta; - } - - t0 = (tab1[0] + tab2[0]) >> shift; - t1 = (tab1[0] + tab2[255]) >> shift; - t2 = (tab1[255] + tab2[0]) >> shift; - t3 = (tab1[255] + tab2[255]) >> shift; - - if( (unsigned)(t0+256) < 768 && (unsigned)(t1+256) < 768 && - (unsigned)(t2+256) < 768 && (unsigned)(t3+256) < 768 ) +addWeighted8u( const uchar* src1, size_t step1, + const uchar* src2, size_t step2, + uchar* dst, size_t step, Size size, + void* _scalars ) +{ + const double* scalars = (const double*)_scalars; + float alpha = (float)scalars[0], beta = (float)scalars[1], gamma = (float)scalars[2]; + + for( ; size.height--; src1 += step1, src2 += step2, dst += step ) { - // use faster table-based convertion back to 8u - for( ; size.height--; src1 += step1, src2 += step2, dst += step ) + int x = 0; + +#if CV_SSE2 + if( USE_SSE2 ) { - int i; - - for( i = 0; i <= size.width - 4; i += 4 ) - { - t0 = CV_FAST_CAST_8U((tab1[src1[i]] + tab2[src2[i]]) >> shift); - t1 = CV_FAST_CAST_8U((tab1[src1[i+1]] + tab2[src2[i+1]]) >> shift); - - dst[i] = (uchar)t0; - dst[i+1] = (uchar)t1; - - t0 = CV_FAST_CAST_8U((tab1[src1[i+2]] + tab2[src2[i+2]]) >> shift); - t1 = CV_FAST_CAST_8U((tab1[src1[i+3]] + tab2[src2[i+3]]) >> shift); - - dst[i+2] = (uchar)t0; - dst[i+3] = (uchar)t1; - } - - for( ; i < size.width; i++ ) + __m128 a4 = _mm_set1_ps(alpha), b4 = _mm_set1_ps(beta), g4 = _mm_set1_ps(gamma); + __m128i z = _mm_setzero_si128(); + + for( ; x <= size.width - 8; x += 8 ) { - t0 = CV_FAST_CAST_8U((tab1[src1[i]] + tab2[src2[i]]) >> shift); - dst[i] = (uchar)t0; + __m128i u = _mm_unpacklo_epi8(_mm_loadl_epi64((const __m128i*)(src1 + x)), z); + __m128i v = _mm_unpacklo_epi8(_mm_loadl_epi64((const __m128i*)(src2 + x)), z); + + __m128 u0 = _mm_cvtepi32_ps(_mm_unpacklo_epi16(u, z)); + __m128 u1 = _mm_cvtepi32_ps(_mm_unpackhi_epi16(u, z)); + __m128 v0 = _mm_cvtepi32_ps(_mm_unpacklo_epi16(v, z)); + __m128 v1 = _mm_cvtepi32_ps(_mm_unpackhi_epi16(v, z)); + + u0 = _mm_add_ps(_mm_mul_ps(u0, a4), _mm_mul_ps(v0, b4)); + u1 = _mm_add_ps(_mm_mul_ps(u1, a4), _mm_mul_ps(v1, b4)); + u0 = _mm_add_ps(u0, g4); u1 = _mm_add_ps(u1, g4); + + u = _mm_packs_epi32(_mm_cvtps_epi32(u0), _mm_cvtps_epi32(u1)); + u = _mm_packus_epi16(u, u); + + _mm_storel_epi64((__m128i*)(dst + x), u); } } - } - else - { - // use universal macro for convertion back to 8u - for( ; size.height--; src1 += step1, src2 += step2, dst += step ) +#endif + for( ; x <= size.width - 4; x += 4 ) { - int i; - - for( i = 0; i <= size.width - 4; i += 4 ) - { - t0 = (tab1[src1[i]] + tab2[src2[i]]) >> shift; - t1 = (tab1[src1[i+1]] + tab2[src2[i+1]]) >> shift; + float t0, t1; + t0 = CV_8TO32F(src1[x])*alpha + CV_8TO32F(src2[x])*beta + gamma; + t1 = CV_8TO32F(src1[x+1])*alpha + CV_8TO32F(src2[x+1])*beta + gamma; - dst[i] = CV_CAST_8U( t0 ); - dst[i+1] = CV_CAST_8U( t1 ); + dst[x] = saturate_cast(t0); + dst[x+1] = saturate_cast(t1); - t0 = (tab1[src1[i+2]] + tab2[src2[i+2]]) >> shift; - t1 = (tab1[src1[i+3]] + tab2[src2[i+3]]) >> shift; + t0 = CV_8TO32F(src1[x+2])*alpha + CV_8TO32F(src2[x+2])*beta + gamma; + t1 = CV_8TO32F(src1[x+3])*alpha + CV_8TO32F(src2[x+3])*beta + gamma; - dst[i+2] = CV_CAST_8U( t0 ); - dst[i+3] = CV_CAST_8U( t1 ); - } + dst[x+2] = saturate_cast(t0); + dst[x+3] = saturate_cast(t1); + } - for( ; i < size.width; i++ ) - { - t0 = (tab1[src1[i]] + tab2[src2[i]]) >> shift; - dst[i] = CV_CAST_8U( t0 ); - } + for( ; x < size.width; x++ ) + { + float t0 = CV_8TO32F(src1[x])*alpha + CV_8TO32F(src2[x])*beta + gamma; + dst[x] = saturate_cast(t0); } } } -typedef void (*AddWeightedFunc)( const Mat& src1, double alpha, const Mat& src2, - double beta, double gamma, Mat& dst ); - -void addWeighted( const Mat& src1, double alpha, const Mat& src2, - double beta, double gamma, Mat& dst ) +static void addWeighted8s( const schar* src1, size_t step1, const schar* src2, size_t step2, + schar* dst, size_t step, Size sz, void* scalars ) { - static AddWeightedFunc tab[] = - { - addWeighted8u, - 0, - addWeighted_, - addWeighted_, - addWeighted_, - addWeighted_, - addWeighted_, - 0 - }; - - AddWeightedFunc func = tab[src1.depth()]; - CV_Assert( src1.type() == src2.type() && func != 0 ); - - if( src1.dims > 2 || src2.dims > 2 ) - { - dst.create(src1.dims, src1.size, src1.type()); - const Mat* arrays[] = {&src1, &src2, &dst, 0}; - Mat planes[3]; - NAryMatIterator it(arrays, planes); - - for( int i = 0; i < it.nplanes; i++, ++it ) - func( it.planes[0], alpha, it.planes[1], beta, gamma, it.planes[2] ); - return; - } - - CV_Assert( src1.size() == src2.size() ); - dst.create( src1.size(), src1.type() ); - func( src1, alpha, src2, beta, gamma, dst ); + addWeighted_(src1, step1, src2, step2, dst, step, sz, scalars); } - -/****************************************************************************************\ -* absdiff * -\****************************************************************************************/ - -template struct OpAbsDiff +static void addWeighted16u( const ushort* src1, size_t step1, const ushort* src2, size_t step2, + ushort* dst, size_t step, Size sz, void* scalars ) { - typedef T type1; - typedef T type2; - typedef T rtype; - T operator()(T a, T b) { return (T)std::abs(a - b); } -}; - -template<> inline short OpAbsDiff::operator ()(short a, short b) -{ return saturate_cast(std::abs(a - b)); } + addWeighted_(src1, step1, src2, step2, dst, step, sz, scalars); +} -template struct OpAbsDiffS +static void addWeighted16s( const short* src1, size_t step1, const short* src2, size_t step2, + short* dst, size_t step, Size sz, void* scalars ) { - typedef T type1; - typedef WT type2; - typedef T rtype; - T operator()(T a, WT b) { return saturate_cast(std::abs(a - b)); } -}; + addWeighted_(src1, step1, src2, step2, dst, step, sz, scalars); +} -void absdiff( const Mat& src1, const Mat& src2, Mat& dst ) +static void addWeighted32s( const int* src1, size_t step1, const int* src2, size_t step2, + int* dst, size_t step, Size sz, void* scalars ) { - static BinaryFunc tab[] = - { -#if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7) - binaryOpC1_,ippAbsDiff8u>, - 0, - binaryOpC1_,ippAbsDiff16u>, - binaryOpC1_,VAbsDiff16s>, - binaryOpC1_,NoVec>, - binaryOpC1_,ippAbsDiff32f>, - binaryOpC1_,NoVec>, - 0 -#else - binaryOpC1_,VAbsDiff8u>, - 0, - binaryOpC1_,VAbsDiff16u>, - binaryOpC1_,VAbsDiff16s>, - binaryOpC1_,NoVec>, - binaryOpC1_,VAbsDiff32f>, - binaryOpC1_,NoVec>, - 0 -#endif - }; - - binaryOp(src1, src2, dst, tab[src1.depth()]); + addWeighted_(src1, step1, src2, step2, dst, step, sz, scalars); } - -void absdiff( const Mat& src1, const Scalar& s, Mat& dst ) +static void addWeighted32f( const float* src1, size_t step1, const float* src2, size_t step2, + float* dst, size_t step, Size sz, void* scalars ) { - static BinarySFuncCn tab[] = - { - binarySOpCn_ >, - 0, - binarySOpCn_ >, - binarySOpCn_ >, - binarySOpCn_ >, - binarySOpCn_ >, - binarySOpCn_ >, - 0 - }; - - BinarySFuncCn func = tab[src1.depth()]; - CV_Assert(src1.channels() <= 4 && func != 0); - - if( src1.dims > 2 ) - { - dst.create(src1.dims, src1.size, src1.type()); - const Mat* arrays[] = {&src1, &dst, 0}; - Mat planes[3]; - NAryMatIterator it(arrays, planes); + addWeighted_(src1, step1, src2, step2, dst, step, sz, scalars); +} - for( int i = 0; i < it.nplanes; i++, ++it ) - func( it.planes[0], it.planes[1], s ); - return; - } +static void addWeighted64f( const double* src1, size_t step1, const double* src2, size_t step2, + double* dst, size_t step, Size sz, void* scalars ) +{ + addWeighted_(src1, step1, src2, step2, dst, step, sz, scalars); +} - dst.create(src1.size(), src1.type()); - func( src1, dst, s ); +static BinaryFunc addWeightedTab[] = +{ + (BinaryFunc)addWeighted8u, (BinaryFunc)addWeighted8s, (BinaryFunc)addWeighted16u, + (BinaryFunc)addWeighted16s, (BinaryFunc)addWeighted32s, (BinaryFunc)addWeighted32f, + (BinaryFunc)addWeighted64f, 0 +}; + +} + +void cv::addWeighted( const InputArray& src1, double alpha, const InputArray& src2, + double beta, double gamma, OutputArray dst, int dtype ) +{ + double scalars[] = {alpha, beta, gamma}; + arithm_op(src1, src2, dst, InputArray(), dtype, addWeightedTab, true, scalars); } + /****************************************************************************************\ -* inRange[S] * +* compare * \****************************************************************************************/ -template struct InRangeC1 +namespace cv { - typedef T xtype; - typedef WT btype; - uchar operator()(xtype x, btype a, btype b) const - { return (uchar)-(a <= x && x < b); } -}; -template struct InRangeC2 +template static void +cmp_(const T* src1, size_t step1, const T* src2, size_t step2, + uchar* dst, size_t step, Size size, int code) { - typedef Vec xtype; - typedef Vec btype; - uchar operator()(const xtype& x, const btype& a, const btype& b) const + step1 /= sizeof(src1[0]); + step2 /= sizeof(src2[0]); + if( code == CMP_GE || code == CMP_LT ) { - return (uchar)-(a[0] <= x[0] && x[0] < b[0] && - a[1] <= x[1] && x[1] < b[1]); + std::swap(src1, src2); + std::swap(step1, step2); + code = code == CMP_GE ? CMP_LE : CMP_GT; } -}; - -template struct InRangeC3 -{ - typedef Vec xtype; - typedef Vec btype; - uchar operator()(const xtype& x, const btype& a, const btype& b) const + + if( code == CMP_GT || code == CMP_LE ) { - return (uchar)-(a[0] <= x[0] && x[0] < b[0] && - a[1] <= x[1] && x[1] < b[1] && - a[2] <= x[2] && x[2] < b[2]); + int m = code == CMP_GT ? 0 : 255; + for( ; size.height--; src1 += step1, src2 += step2, dst += step ) + { + int x = 0; + for( ; x <= size.width - 4; x += 4 ) + { + int t0, t1; + t0 = -(src1[x] > src2[x]) ^ m; + t1 = -(src1[x+1] > src2[x+1]) ^ m; + dst[x] = (uchar)t0; dst[x+1] = (uchar)t1; + t0 = -(src1[x+2] > src2[x+2]) ^ m; + t1 = -(src1[x+3] > src2[x+3]) ^ m; + dst[x+2] = (uchar)t0; dst[x+3] = (uchar)t1; + } + + for( ; x < size.width; x++ ) + dst[x] = (uchar)(-(src1[x] > src2[x]) ^ m); + } } -}; - -template struct InRangeC4 -{ - typedef Vec xtype; - typedef Vec btype; - uchar operator()(const xtype& x, const btype& a, const btype& b) const + else if( code == CMP_EQ || code == CMP_NE ) { - return (uchar)-(a[0] <= x[0] && x[0] < b[0] && - a[1] <= x[1] && x[1] < b[1] && - a[2] <= x[2] && x[2] < b[2] && - a[3] <= x[3] && x[3] < b[3]); + int m = code == CMP_EQ ? 0 : 255; + for( ; size.height--; src1 += step1, src2 += step2, dst += step ) + { + int x = 0; + for( ; x <= size.width - 4; x += 4 ) + { + int t0, t1; + t0 = -(src1[x] == src2[x]) ^ m; + t1 = -(src1[x+1] == src2[x+1]) ^ m; + dst[x] = (uchar)t0; dst[x+1] = (uchar)t1; + t0 = -(src1[x+2] == src2[x+2]) ^ m; + t1 = -(src1[x+3] == src2[x+3]) ^ m; + dst[x+2] = (uchar)t0; dst[x+3] = (uchar)t1; + } + + for( ; x < size.width; x++ ) + dst[x] = (uchar)(-(src1[x] == src2[x]) ^ m); + } } -}; - -template static void -inRange_( const Mat& srcmat1, const Mat& srcmat2, const Mat& srcmat3, Mat& dstmat ) +} + + +static void cmp8u(const uchar* src1, size_t step1, const uchar* src2, size_t step2, + uchar* dst, size_t step, Size size, void* _cmpop) { - Op op; - uchar* dst = dstmat.data; - size_t dstep = dstmat.step; - Size size = getContinuousSize( srcmat1, srcmat2, srcmat3, dstmat ); - - for( int y = 0; y < size.height; y++, dst += dstep ) - { - const typename Op::xtype* src1 = (const typename Op::xtype*)(srcmat1.data + srcmat1.step*y); - const typename Op::xtype* src2 = (const typename Op::xtype*)(srcmat2.data + srcmat2.step*y); - const typename Op::xtype* src3 = (const typename Op::xtype*)(srcmat3.data + srcmat3.step*y); - for( int x = 0; x < size.width; x++ ) - dst[x] = op( src1[x], src2[x], src3[x] ); - } + cmp_(src1, step1, src2, step2, dst, step, size, *(int*)_cmpop); } -template static void -inRangeS_( const Mat& srcmat1, const Scalar& _a, const Scalar& _b, Mat& dstmat ) +static void cmp8s(const schar* src1, size_t step1, const schar* src2, size_t step2, + uchar* dst, size_t step, Size size, void* _cmpop) { - Op op; - typedef typename Op::btype WT; - typedef typename DataType::channel_type WT1; - WT a, b; - uchar* dst = dstmat.data; - size_t dstep = dstmat.step; - Size size = getContinuousSize( srcmat1, dstmat ); - int cn = srcmat1.channels(); - scalarToRawData(_a, &a, CV_MAKETYPE(DataType::depth, cn)); - scalarToRawData(_b, &b, CV_MAKETYPE(DataType::depth, cn)); - - for( int y = 0; y < size.height; y++, dst += dstep ) - { - const typename Op::xtype* src1 = (const typename Op::xtype*)(srcmat1.data + srcmat1.step*y); - for( int x = 0; x < size.width; x++ ) - dst[x] = op( src1[x], a, b ); - } + cmp_(src1, step1, src2, step2, dst, step, size, *(int*)_cmpop); } -typedef void (*InRangeFunc)( const Mat& src1, const Mat& src2, const Mat& src3, Mat& dst ); -typedef void (*InRangeSFunc)( const Mat& src1, const Scalar& a, const Scalar& b, Mat& dst ); - -void inRange(const Mat& src, const Mat& lowerb, - const Mat& upperb, Mat& dst) +static void cmp16u(const ushort* src1, size_t step1, const ushort* src2, size_t step2, + uchar* dst, size_t step, Size size, void* _cmpop) { - static InRangeFunc tab[] = - { - inRange_ >, - 0, - inRange_ >, - inRange_ >, - inRange_ >, - inRange_ >, - inRange_ >, - 0, - - inRange_ >, - 0, - inRange_ >, - inRange_ >, - inRange_ >, - inRange_ >, - inRange_ >, - 0, - - inRange_ >, - 0, - inRange_ >, - inRange_ >, - inRange_ >, - inRange_ >, - inRange_ >, - 0, - - inRange_ >, - 0, - inRange_ >, - inRange_ >, - inRange_ >, - inRange_ >, - inRange_ >, - 0 - }; - - CV_Assert( src.type() == lowerb.type() && src.type() == upperb.type() && src.channels() <= 4 ); - - InRangeFunc func = tab[src.type()]; - CV_Assert( func != 0 ); - - if( src.dims > 2 || lowerb.dims > 2 || upperb.dims > 2 ) - { - dst.create(src.dims, src.size, CV_8U); - const Mat* arrays[] = {&src, &lowerb, &upperb, &dst, 0}; - Mat planes[4]; - NAryMatIterator it(arrays, planes); - - for( int i = 0; i < it.nplanes; i++, ++it ) - func( it.planes[0], it.planes[1], it.planes[2], it.planes[3] ); - return; - } - - CV_Assert( src.size() == lowerb.size() && src.size() == upperb.size() ); - dst.create(src.size(), CV_8U); - func( src, lowerb, upperb, dst ); + cmp_(src1, step1, src2, step2, dst, step, size, *(int*)_cmpop); } -void inRange(const Mat& src, const Scalar& lowerb, - const Scalar& upperb, Mat& dst) +static void cmp16s(const short* src1, size_t step1, const short* src2, size_t step2, + uchar* dst, size_t step, Size size, void* _cmpop) { - static InRangeSFunc tab[] = - { - inRangeS_ >, - 0, - inRangeS_ >, - inRangeS_ >, - inRangeS_ >, - inRangeS_ >, - inRangeS_ >, - 0, - - inRangeS_ >, - 0, - inRangeS_ >, - inRangeS_ >, - inRangeS_ >, - inRangeS_ >, - inRangeS_ >, - 0, - - inRangeS_ >, - 0, - inRangeS_ >, - inRangeS_ >, - inRangeS_ >, - inRangeS_ >, - inRangeS_ >, - 0, - - inRangeS_ >, - 0, - inRangeS_ >, - inRangeS_ >, - inRangeS_ >, - inRangeS_ >, - inRangeS_ >, - 0 - }; - - CV_Assert( src.channels() <= 4 ); - - InRangeSFunc func = tab[src.type()]; - CV_Assert( func != 0 ); - - if( src.dims > 2 ) - { - dst.create(src.dims, src.size, CV_8U); - const Mat* arrays[] = {&src, &dst, 0}; - Mat planes[2]; - NAryMatIterator it(arrays, planes); - - for( int i = 0; i < it.nplanes; i++, ++it ) - func( it.planes[0], lowerb, upperb, it.planes[1] ); - return; - } - - dst.create(src.size(), CV_8U); - func( src, lowerb, upperb, dst ); + cmp_(src1, step1, src2, step2, dst, step, size, *(int*)_cmpop); } -/****************************************************************************************\ -* compare * -\****************************************************************************************/ +static void cmp32s(const int* src1, size_t step1, const int* src2, size_t step2, + uchar* dst, size_t step, Size size, void* _cmpop) +{ + cmp_(src1, step1, src2, step2, dst, step, size, *(int*)_cmpop); +} -template struct CmpEQ +static void cmp32f(const float* src1, size_t step1, const float* src2, size_t step2, + uchar* dst, size_t step, Size size, void* _cmpop) { - typedef T type1; - typedef WT type2; - typedef uchar rtype; - uchar operator()(T a, WT b) const { return (uchar)-(a == b); } -}; + cmp_(src1, step1, src2, step2, dst, step, size, *(int*)_cmpop); +} -template struct CmpGT +static void cmp64f(const double* src1, size_t step1, const double* src2, size_t step2, + uchar* dst, size_t step, Size size, void* _cmpop) { - typedef T type1; - typedef WT type2; - typedef uchar rtype; - uchar operator()(T a, WT b) const { return (uchar)-(a > b); } + cmp_(src1, step1, src2, step2, dst, step, size, *(int*)_cmpop); +} + +static BinaryFunc cmpTab[] = +{ + (BinaryFunc)cmp8u, (BinaryFunc)cmp8s, (BinaryFunc)cmp16u, + (BinaryFunc)cmp16s, (BinaryFunc)cmp32s, (BinaryFunc)cmp32f, + (BinaryFunc)cmp64f, 0 }; -template struct CmpGE + +static double getMinVal(int depth) { - typedef T type1; - typedef WT type2; - typedef uchar rtype; - uchar operator()(T a, WT b) const { return (uchar)-(a >= b); } -}; + static const double tab[] = {0, -128, 0, -32768, INT_MIN, -FLT_MAX, -DBL_MAX, 0}; + return tab[depth]; +} -void compare( const Mat& src1, const Mat& src2, Mat& dst, int cmpOp ) +static double getMaxVal(int depth) { - static BinaryFunc tab[][8] = + static const double tab[] = {255, 127, 65535, 32767, INT_MAX, FLT_MAX, DBL_MAX, 0}; + return tab[depth]; +} + +} + +void cv::compare(const InputArray& _src1, const InputArray& _src2, OutputArray _dst, int op) +{ + CV_Assert( op == CMP_LT || op == CMP_LE || op == CMP_EQ || + op == CMP_NE || op == CMP_GE || op == CMP_GT ); + + int kind1 = _src1.kind(), kind2 = _src2.kind(); + Mat src1 = _src1.getMat(), src2 = _src2.getMat(); + + if( kind1 == kind2 && src1.dims <= 2 && src2.dims <= 2 && src1.size() == src2.size() && src1.type() == src2.type() ) { + _dst.create(src1.size(), CV_8UC1); + Mat dst = _dst.getMat(); + Size sz = getContinuousSize(src1, src2, dst, src1.channels()); + cmpTab[src1.depth()](src1.data, src1.step, src2.data, src2.step, dst.data, dst.step, sz, &op); + return; + } + + bool haveScalar = false; + + if( (kind1 == InputArray::MATX) + (kind2 == InputArray::MATX) == 1 || + src1.size != src2.size || src1.type() != src2.type() ) + { + if( checkScalar(src1, src2.type(), kind1, kind2) ) { - binaryOpC1_,VCmpGT8u>, - 0, - binaryOpC1_,NoVec>, - binaryOpC1_,NoVec>, - binaryOpC1_,NoVec>, - binaryOpC1_,NoVec>, - binaryOpC1_,NoVec>, - 0 - }, - - { - binaryOpC1_,VCmpEQ8u>, - 0, - binaryOpC1_,NoVec>, - binaryOpC1_,NoVec>, // same function as for ushort's - binaryOpC1_,NoVec>, - binaryOpC1_,NoVec>, - binaryOpC1_,NoVec>, - 0 - }, - }; - - CV_Assert(src1.channels() == 1); - - int depth = src1.depth(); - const Mat *psrc1 = &src1, *psrc2 = &src2; - bool invflag = false; - - switch( cmpOp ) + // src1 is a scalar; swap it with src2 + swap(src1, src2); + op = op == CMP_LT ? CMP_GT : op == CMP_LE ? CMP_GE : + op == CMP_GE ? CMP_LE : op == CMP_GT ? CMP_LT : op; + } + else if( !checkScalar(src2, src1.type(), kind2, kind1) ) + CV_Error( CV_StsUnmatchedSizes, + "The operation is neither 'array op array' (where arrays have the same size and the same type), " + "nor 'array op scalar', nor 'scalar op array'" ); + haveScalar = true; + } + + int cn = src1.channels(), depth1 = src1.depth(), depth2 = src2.depth(); + if( cn != 1 ) + CV_Error( CV_StsUnsupportedFormat, "compare() can only process single-channel arrays" ); + + size_t esz = src1.elemSize(); + size_t blocksize0 = (size_t)(BLOCK_SIZE + esz-1)/esz; + + _dst.create(src1.dims, src1.size, CV_8U); + Mat dst = _dst.getMat(); + BinaryFunc func = cmpTab[depth1]; + + if( !haveScalar ) { - case CMP_GT: - case CMP_EQ: - break; - - case CMP_GE: - std::swap( psrc1, psrc2 ); - invflag = true; - break; - - case CMP_LT: - std::swap( psrc1, psrc2 ); - break; - - case CMP_LE: - invflag = true; - break; - - case CMP_NE: - cmpOp = CMP_EQ; - invflag = true; - break; - - default: - CV_Error(CV_StsBadArg, "Unknown comparison method"); + const Mat* arrays[] = { &src1, &src2, &dst, 0 }; + uchar* ptrs[3]; + + NAryMatIterator it(arrays, ptrs); + size_t total = it.size; + + for( size_t i = 0; i < it.nplanes; i++, ++it ) + func( ptrs[0], 0, ptrs[1], 0, ptrs[2], 0, Size((int)total, 1), &op ); } - - BinaryFunc func = tab[cmpOp == CMP_EQ][depth]; - binaryOp(*psrc1, *psrc2, dst, func, CV_8U); - if( invflag ) - bitwise_not(dst, dst); -} - - -void compare( const Mat& src1, double value, Mat& dst, int cmpOp ) -{ - static BinarySFuncC1 tab[][8] = + else { + const Mat* arrays[] = { &src1, &dst, 0 }; + uchar* ptrs[2]; + + NAryMatIterator it(arrays, ptrs); + size_t total = it.size, blocksize = std::min(total, blocksize0); + + AutoBuffer _buf(blocksize*esz); + uchar *buf = _buf; + + if( depth1 > CV_32S ) + convertAndUnrollScalar( src2, depth1, buf, blocksize ); + else { - binarySOpC1_ >, - 0, - binarySOpC1_ >, - binarySOpC1_ >, - binarySOpC1_ >, - binarySOpC1_ >, - binarySOpC1_ >, - 0 - }, - - { - binarySOpC1_ >, - 0, - binarySOpC1_ >, - binarySOpC1_ >, - binarySOpC1_ >, - binarySOpC1_ >, - binarySOpC1_ >, - 0 - }, - + double fval=0; + getConvertFunc(depth2, CV_64F)(src2.data, 0, 0, 0, (uchar*)&fval, 0, Size(1,1), 0); + if( fval < getMinVal(depth1) ) + { + dst = Scalar::all(op == CMP_GT || op == CMP_GE || op == CMP_NE ? 255 : 0); + return; + } + + if( fval > getMaxVal(depth1) ) + { + dst = Scalar::all(op == CMP_LT || op == CMP_LE || op == CMP_NE ? 255 : 0); + return; + } + + int ival = cvRound(fval); + if( fval != ival ) + { + if( op == CMP_LT || op == CMP_GE ) + ival = cvCeil(fval); + else if( op == CMP_LE || op == CMP_GT ) + ival = cvFloor(fval); + else + { + dst = Scalar::all(op == CMP_NE ? 255 : 0); + return; + } + } + convertAndUnrollScalar(Mat(1, 1, CV_32S, &ival), depth1, buf, blocksize); + } + + for( size_t i = 0; i < it.nplanes; i++, ++it ) { - binarySOpC1_ >, - 0, - binarySOpC1_ >, - binarySOpC1_ >, - binarySOpC1_ >, - binarySOpC1_ >, - binarySOpC1_ >, - 0 - }, - }; - - int depth = src1.depth(); - bool invflag = false; - - switch( cmpOp ) - { - case CMP_GT: - case CMP_EQ: - case CMP_GE: - break; - - case CMP_LT: - invflag = true; - cmpOp = CMP_GE; - break; - - case CMP_LE: - invflag = true; - cmpOp = CMP_GT; - break; - - case CMP_NE: - invflag = true; - cmpOp = CMP_EQ; - break; - - default: - CV_Error(CV_StsBadArg, "Unknown comparison method"); + for( size_t j = 0; j < total; j += blocksize ) + { + int bsz = (int)std::min(total - j, blocksize); + func( ptrs[0], 0, buf, 0, ptrs[1], 0, Size(bsz, 1), &op); + ptrs[0] += bsz*esz; + ptrs[1] += bsz; + } + } } +} + +/****************************************************************************************\ +* inRange * +\****************************************************************************************/ - BinarySFuncC1 func = tab[cmpOp == CMP_EQ ? 0 : cmpOp == CMP_GT ? 1 : 2][depth]; - CV_Assert( func != 0 ); +namespace cv +{ - if( src1.dims > 2 ) +template static void +inRange_(const T* src1, size_t step1, const T* src2, size_t step2, + const T* src3, size_t step3, uchar* dst, size_t step, + Size size) +{ + step1 /= sizeof(src1[0]); + step2 /= sizeof(src2[0]); + step3 /= sizeof(src3[0]); + + for( ; size.height--; src1 += step1, src2 += step2, src3 += step3, dst += step ) { - dst.create(src1.dims, src1.size, CV_8UC(src1.channels())); - const Mat* arrays[] = {&src1, &dst, 0}; - Mat planes[2]; - NAryMatIterator it(arrays, planes); - - for( int i = 0; i < it.nplanes; i++, ++it ) + int x = 0; + for( ; x <= size.width - 4; x += 4 ) { - func( it.planes[0], it.planes[1], value ); - if( invflag ) - bitwise_not(it.planes[1], it.planes[1]); + int t0, t1; + t0 = src2[x] <= src1[x] && src1[x] <= src3[x]; + t1 = src2[x+1] <= src1[x+1] && src1[x+1] <= src3[x+1]; + dst[x] = (uchar)-t0; dst[x+1] = (uchar)-t1; + t0 = src2[x+2] <= src1[x+2] && src1[x+2] <= src3[x+2]; + t1 = src2[x+3] <= src1[x+3] && src1[x+3] <= src3[x+3]; + dst[x+2] = (uchar)-t0; dst[x+3] = (uchar)-t1; } - return; + + for( ; x < size.width; x++ ) + dst[x] = (uchar)-(src2[x] <= src1[x] && src1[x] <= src3[x]); } - - dst.create(src1.rows, src1.cols, CV_8UC(src1.channels())); - func( src1, dst, value ); - if( invflag ) - bitwise_not(dst, dst); } -/****************************************************************************************\ -* min/max * -\****************************************************************************************/ - -template struct MinOp + +static void inRange8u(const uchar* src1, size_t step1, const uchar* src2, size_t step2, + const uchar* src3, size_t step3, uchar* dst, size_t step, Size size) { - typedef T type1; - typedef T type2; - typedef T rtype; - T operator ()(T a, T b) const { return std::min(a, b); } -}; + inRange_(src1, step1, src2, step2, src3, step3, dst, step, size); +} -template struct MaxOp +static void inRange8s(const schar* src1, size_t step1, const schar* src2, size_t step2, + const schar* src3, size_t step3, uchar* dst, size_t step, Size size) { - typedef T type1; - typedef T type2; - typedef T rtype; - T operator ()(T a, T b) const { return std::max(a, b); } -}; - -template<> inline uchar MinOp::operator ()(uchar a, uchar b) const { return CV_MIN_8U(a, b); } -template<> inline uchar MaxOp::operator ()(uchar a, uchar b) const { return CV_MAX_8U(a, b); } + inRange_(src1, step1, src2, step2, src3, step3, dst, step, size); +} -void min( const Mat& src1, const Mat& src2, Mat& dst ) +static void inRange16u(const ushort* src1, size_t step1, const ushort* src2, size_t step2, + const ushort* src3, size_t step3, uchar* dst, size_t step, Size size) { - static BinaryFunc tab[] = - { -#if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7) - binaryOpC1_,ippMin8u>, - 0, - binaryOpC1_,ippMin16u>, - binaryOpC1_,VMin16s>, - binaryOpC1_,NoVec>, - binaryOpC1_,ippMin32f>, - binaryOpC1_,ippMin64f>, - 0 -#else - binaryOpC1_,VMin8u>, - 0, - binaryOpC1_,VMin16u>, - binaryOpC1_,VMin16s>, - binaryOpC1_,NoVec>, - binaryOpC1_,VMin32f>, - binaryOpC1_,NoVec>, - 0 -#endif - }; + inRange_(src1, step1, src2, step2, src3, step3, dst, step, size); +} - binaryOp(src1, src2, dst, tab[src1.depth()]); +static void inRange16s(const short* src1, size_t step1, const short* src2, size_t step2, + const short* src3, size_t step3, uchar* dst, size_t step, Size size) +{ + inRange_(src1, step1, src2, step2, src3, step3, dst, step, size); } -void max( const Mat& src1, const Mat& src2, Mat& dst ) +static void inRange32s(const int* src1, size_t step1, const int* src2, size_t step2, + const int* src3, size_t step3, uchar* dst, size_t step, Size size) { - static BinaryFunc tab[] = - { -#if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7) - binaryOpC1_,ippMax8u>, - 0, - binaryOpC1_,ippMax16u>, - binaryOpC1_,VMax16s>, - binaryOpC1_,NoVec>, - binaryOpC1_,ippMax32f>, - binaryOpC1_,ippMax64f>, - 0 -#else - binaryOpC1_,VMax8u>, - 0, - binaryOpC1_,VMax16u>, - binaryOpC1_,VMax16s>, - binaryOpC1_,NoVec>, - binaryOpC1_,VMax32f>, - binaryOpC1_,NoVec>, - 0 -#endif - }; + inRange_(src1, step1, src2, step2, src3, step3, dst, step, size); +} - binaryOp(src1, src2, dst, tab[src1.depth()]); +static void inRange32f(const float* src1, size_t step1, const float* src2, size_t step2, + const float* src3, size_t step3, uchar* dst, size_t step, Size size) +{ + inRange_(src1, step1, src2, step2, src3, step3, dst, step, size); } -void min( const Mat& src1, double value, Mat& dst ) +static void inRange64f(const double* src1, size_t step1, const double* src2, size_t step2, + const double* src3, size_t step3, uchar* dst, size_t step, Size size) { - static BinarySFuncC1 tab[] = - { - binarySOpC1_ >, - 0, - binarySOpC1_ >, - binarySOpC1_ >, - binarySOpC1_ >, - binarySOpC1_ >, - binarySOpC1_ >, - 0 - }; - - BinarySFuncC1 func = tab[src1.depth()]; - CV_Assert(func != 0); - - if( src1.dims > 2 ) - { - dst.create(src1.dims, src1.size, src1.type()); - const Mat* arrays[] = {&src1, &dst, 0}; - Mat planes[2]; - NAryMatIterator it(arrays, planes); + inRange_(src1, step1, src2, step2, src3, step3, dst, step, size); +} - for( int i = 0; i < it.nplanes; i++, ++it ) - func( it.planes[0], it.planes[1], value ); - return; +static void inRangeReduce(const uchar* src, uchar* dst, size_t len, int cn) +{ + int k = cn % 4 ? cn % 4 : 4; + size_t i, j; + if( k == 1 ) + for( i = j = 0; i < len; i++, j += cn ) + dst[i] = src[j]; + else if( k == 2 ) + for( i = j = 0; i < len; i++, j += cn ) + dst[i] = src[j] & src[j+1]; + else if( k == 3 ) + for( i = j = 0; i < len; i++, j += cn ) + dst[i] = src[j] & src[j+1] & src[j+2]; + else + for( i = j = 0; i < len; i++, j += cn ) + dst[i] = src[j] & src[j+1] & src[j+2] & src[j+3]; + + for( ; k < cn; k += 4 ) + { + for( i = 0, j = k; i < len; i++, j += cn ) + dst[i] &= src[j] & src[j+1] & src[j+2] & src[j+3]; } - - dst.create(src1.size(), src1.type()); - - return func( src1, dst, value ); } + +typedef void (*InRangeFunc)( const uchar* src1, size_t step1, const uchar* src2, size_t step2, + const uchar* src3, size_t step3, uchar* dst, size_t step, Size sz ); -void max( const Mat& src1, double value, Mat& dst ) +static InRangeFunc inRangeTab[] = { - static BinarySFuncC1 tab[] = - { - binarySOpC1_ >, - 0, - binarySOpC1_ >, - binarySOpC1_ >, - binarySOpC1_ >, - binarySOpC1_ >, - binarySOpC1_ >, - 0 - }; - - BinarySFuncC1 func = tab[src1.depth()]; - CV_Assert(func != 0); - - if( src1.dims > 2 ) + (InRangeFunc)inRange8u, (InRangeFunc)inRange8s, (InRangeFunc)inRange16u, + (InRangeFunc)inRange16s, (InRangeFunc)inRange32s, (InRangeFunc)inRange32f, + (InRangeFunc)inRange64f, 0 +}; + +} + +void cv::inRange(const InputArray& _src, const InputArray& _lowerb, + const InputArray& _upperb, OutputArray _dst) +{ + int skind = _src.kind(), lkind = _lowerb.kind(), ukind = _upperb.kind(); + Mat src = _src.getMat(), lb = _lowerb.getMat(), ub = _upperb.getMat(); + + bool lbScalar = false, ubScalar = false; + + if( (lkind == InputArray::MATX && skind != InputArray::MATX) || + src.size != lb.size || src.type() != lb.type() ) + { + if( !checkScalar(lb, src.type(), lkind, skind) ) + CV_Error( CV_StsUnmatchedSizes, + "The lower bounary is neither an array of the same size and same type as src, nor a scalar"); + lbScalar = true; + } + + if( (ukind == InputArray::MATX && skind != InputArray::MATX) || + src.size != ub.size || src.type() != ub.type() ) + { + if( !checkScalar(ub, src.type(), ukind, skind) ) + CV_Error( CV_StsUnmatchedSizes, + "The upper bounary is neither an array of the same size and same type as src, nor a scalar"); + ubScalar = true; + } + + CV_Assert( ((int)lbScalar ^ (int)ubScalar) == 0 ); + + int cn = src.channels(), depth = src.depth(); + + size_t esz = src.elemSize(); + size_t blocksize0 = (size_t)(BLOCK_SIZE + esz-1)/esz; + + _dst.create(src.dims, src.size, CV_8U); + Mat dst = _dst.getMat(); + InRangeFunc func = inRangeTab[depth]; + + const Mat* arrays_sc[] = { &src, &dst, 0 }; + const Mat* arrays_nosc[] = { &src, &dst, &lb, &ub, 0 }; + uchar* ptrs[4]; + + NAryMatIterator it(lbScalar && ubScalar ? arrays_sc : arrays_nosc, ptrs); + size_t total = it.size, blocksize = std::min(total, blocksize0); + + AutoBuffer _buf(blocksize*(((int)lbScalar + (int)ubScalar)*esz + cn) + 2*cn*sizeof(int) + 128); + uchar *buf = _buf, *mbuf = buf, *lbuf = 0, *ubuf = 0; + buf = alignPtr(buf + blocksize*cn, 16); + + if( lbScalar && ubScalar ) + { + lbuf = buf; + ubuf = buf = alignPtr(buf + blocksize*esz, 16); + + CV_Assert( lb.type() == ub.type() ); + int scdepth = lb.depth(); + + if( scdepth != depth && depth < CV_32S ) + { + int* ilbuf = (int*)alignPtr(buf + blocksize*esz, 16); + int* iubuf = ilbuf + cn; + + BinaryFunc sccvtfunc = getConvertFunc(scdepth, CV_32S); + sccvtfunc(lb.data, 0, 0, 0, (uchar*)ilbuf, 0, Size(cn, 1), 0); + sccvtfunc(ub.data, 0, 0, 0, (uchar*)iubuf, 0, Size(cn, 1), 0); + int minval = getMinVal(depth), maxval = getMaxVal(depth); + + for( int k = 0; k < cn; k++ ) + { + if( ilbuf[k] > iubuf[k] || ilbuf[k] > maxval || iubuf[k] < minval ) + ilbuf[k] = minval+1, iubuf[k] = minval; + } + lb = Mat(cn, 1, CV_32S, ilbuf); + ub = Mat(cn, 1, CV_32S, iubuf); + } + + convertAndUnrollScalar( lb, src.type(), lbuf, blocksize ); + convertAndUnrollScalar( ub, src.type(), ubuf, blocksize ); + } + + for( size_t i = 0; i < it.nplanes; i++, ++it ) { - dst.create(src1.dims, src1.size, src1.type()); - const Mat* arrays[] = {&src1, &dst, 0}; - Mat planes[2]; - NAryMatIterator it(arrays, planes); - - for( int i = 0; i < it.nplanes; i++, ++it ) - func( it.planes[0], it.planes[1], value ); - return; + for( size_t j = 0; j < total; j += blocksize ) + { + int bsz = (int)std::min(total - j, blocksize); + size_t delta = bsz*esz; + uchar *lptr = lbuf, *uptr = ubuf; + if( !lbScalar ) + { + lptr = ptrs[2]; + ptrs[2] += delta; + } + if( !ubScalar ) + { + int idx = !lbScalar ? 3 : 2; + uptr = ptrs[idx]; + ptrs[idx] += delta; + } + func( ptrs[0], 0, lptr, 0, uptr, 0, cn == 1 ? ptrs[1] : mbuf, 0, Size(bsz*cn, 1)); + if( cn > 1 ) + inRangeReduce(mbuf, ptrs[1], bsz, cn); + ptrs[0] += delta; + ptrs[1] += bsz; + } } - - dst.create(src1.size(), src1.type()); - - return func( src1, dst, value ); } -} // namespace cv - /****************************************************************************************\ * Earlier API: cvAdd etc. * \****************************************************************************************/ @@ -2168,7 +2369,7 @@ cvAndS( const CvArr* srcarr, CvScalar s, CvArr* dstarr, const CvArr* maskarr ) CV_Assert( src.size == dst.size && src.type() == dst.type() ); if( maskarr ) mask = cv::cvarrToMat(maskarr); - cv::bitwise_and( src, s, dst, mask ); + cv::bitwise_and( src, (const cv::Scalar&)s, dst, mask ); } @@ -2179,7 +2380,7 @@ cvOrS( const CvArr* srcarr, CvScalar s, CvArr* dstarr, const CvArr* maskarr ) CV_Assert( src.size == dst.size && src.type() == dst.type() ); if( maskarr ) mask = cv::cvarrToMat(maskarr); - cv::bitwise_or( src, s, dst, mask ); + cv::bitwise_or( src, (const cv::Scalar&)s, dst, mask ); } @@ -2190,7 +2391,7 @@ cvXorS( const CvArr* srcarr, CvScalar s, CvArr* dstarr, const CvArr* maskarr ) CV_Assert( src.size == dst.size && src.type() == dst.type() ); if( maskarr ) mask = cv::cvarrToMat(maskarr); - cv::bitwise_xor( src, s, dst, mask ); + cv::bitwise_xor( src, (const cv::Scalar&)s, dst, mask ); } @@ -2198,10 +2399,10 @@ CV_IMPL void cvAdd( const CvArr* srcarr1, const CvArr* srcarr2, CvArr* dstarr, c { cv::Mat src1 = cv::cvarrToMat(srcarr1), src2 = cv::cvarrToMat(srcarr2), dst = cv::cvarrToMat(dstarr), mask; - CV_Assert( src1.size == dst.size && src1.type() == dst.type() ); + CV_Assert( src1.size == dst.size && src1.channels() == dst.channels() ); if( maskarr ) mask = cv::cvarrToMat(maskarr); - cv::add( src1, src2, dst, mask ); + cv::add( src1, src2, dst, mask, dst.type() ); } @@ -2209,10 +2410,10 @@ CV_IMPL void cvSub( const CvArr* srcarr1, const CvArr* srcarr2, CvArr* dstarr, c { cv::Mat src1 = cv::cvarrToMat(srcarr1), src2 = cv::cvarrToMat(srcarr2), dst = cv::cvarrToMat(dstarr), mask; - CV_Assert( src1.size == dst.size && src1.type() == dst.type() ); + CV_Assert( src1.size == dst.size && src1.channels() == dst.channels() ); if( maskarr ) mask = cv::cvarrToMat(maskarr); - cv::subtract( src1, src2, dst, mask ); + cv::subtract( src1, src2, dst, mask, dst.type() ); } @@ -2220,10 +2421,10 @@ CV_IMPL void cvAddS( const CvArr* srcarr1, CvScalar value, CvArr* dstarr, const { cv::Mat src1 = cv::cvarrToMat(srcarr1), dst = cv::cvarrToMat(dstarr), mask; - CV_Assert( src1.size == dst.size && src1.type() == dst.type() ); + CV_Assert( src1.size == dst.size && src1.channels() == dst.channels() ); if( maskarr ) mask = cv::cvarrToMat(maskarr); - cv::add( src1, value, dst, mask ); + cv::add( src1, (const cv::Scalar&)value, dst, mask, dst.type() ); } @@ -2231,10 +2432,10 @@ CV_IMPL void cvSubRS( const CvArr* srcarr1, CvScalar value, CvArr* dstarr, const { cv::Mat src1 = cv::cvarrToMat(srcarr1), dst = cv::cvarrToMat(dstarr), mask; - CV_Assert( src1.size == dst.size && src1.type() == dst.type() ); + CV_Assert( src1.size == dst.size && src1.channels() == dst.channels() ); if( maskarr ) mask = cv::cvarrToMat(maskarr); - cv::subtract( value, src1, dst, mask ); + cv::subtract( (const cv::Scalar&)value, src1, dst, mask, dst.type() ); } @@ -2243,8 +2444,8 @@ CV_IMPL void cvMul( const CvArr* srcarr1, const CvArr* srcarr2, { cv::Mat src1 = cv::cvarrToMat(srcarr1), src2 = cv::cvarrToMat(srcarr2), dst = cv::cvarrToMat(dstarr); - CV_Assert( src1.size == dst.size && src1.type() == dst.type() ); - cv::multiply( src1, src2, dst, scale ); + CV_Assert( src1.size == dst.size && src1.channels() == dst.channels() ); + cv::multiply( src1, src2, dst, scale, dst.type() ); } @@ -2253,12 +2454,12 @@ CV_IMPL void cvDiv( const CvArr* srcarr1, const CvArr* srcarr2, { cv::Mat src2 = cv::cvarrToMat(srcarr2), dst = cv::cvarrToMat(dstarr), mask; - CV_Assert( src2.size == dst.size && src2.type() == dst.type() ); + CV_Assert( src2.size == dst.size && src2.channels() == dst.channels() ); if( srcarr1 ) - cv::divide( cv::cvarrToMat(srcarr1), src2, dst, scale ); + cv::divide( cv::cvarrToMat(srcarr1), src2, dst, scale, dst.type() ); else - cv::divide( scale, src2, dst ); + cv::divide( scale, src2, dst, dst.type() ); } @@ -2269,8 +2470,8 @@ cvAddWeighted( const CvArr* srcarr1, double alpha, { cv::Mat src1 = cv::cvarrToMat(srcarr1), src2 = cv::cvarrToMat(srcarr2), dst = cv::cvarrToMat(dstarr); - CV_Assert( src1.size == dst.size && src1.type() == dst.type() ); - cv::addWeighted( src1, alpha, src2, beta, gamma, dst ); + CV_Assert( src1.size == dst.size && src1.channels() == dst.channels() ); + cv::addWeighted( src1, alpha, src2, beta, gamma, dst, dst.type() ); } @@ -2290,7 +2491,7 @@ cvAbsDiffS( const CvArr* srcarr1, CvArr* dstarr, CvScalar scalar ) cv::Mat src1 = cv::cvarrToMat(srcarr1), dst = cv::cvarrToMat(dstarr); CV_Assert( src1.size == dst.size && src1.type() == dst.type() ); - cv::absdiff( src1, scalar, dst ); + cv::absdiff( src1, (const cv::Scalar&)scalar, dst ); } @@ -2311,7 +2512,7 @@ cvInRangeS( const void* srcarr1, CvScalar lowerb, CvScalar upperb, void* dstarr cv::Mat src1 = cv::cvarrToMat(srcarr1), dst = cv::cvarrToMat(dstarr); CV_Assert( src1.size == dst.size && dst.type() == CV_8U ); - cv::inRange( src1, lowerb, upperb, dst ); + cv::inRange( src1, (const cv::Scalar&)lowerb, (const cv::Scalar&)upperb, dst ); } @@ -2374,5 +2575,4 @@ cvMaxS( const void* srcarr1, double value, void* dstarr ) cv::max( src1, value, dst ); } - /* End of file. */ diff --git a/modules/core/src/array.cpp b/modules/core/src/array.cpp index 4da903b2c2..f065a1e41e 100644 --- a/modules/core/src/array.cpp +++ b/modules/core/src/array.cpp @@ -722,10 +722,10 @@ icvGetNodePtr( CvSparseMat* mat, const int* idx, int* _type, node->hashval = hashval; node->next = (CvSparseNode*)mat->hashtable[tabidx]; mat->hashtable[tabidx] = node; - CV_MEMCPY_INT( CV_NODE_IDX(mat,node), idx, mat->dims ); + memcpy(CV_NODE_IDX(mat,node), idx, mat->dims*sizeof(idx[0])); ptr = (uchar*)CV_NODE_VAL(mat,node); if( create_node > 0 ) - CV_ZERO_CHAR( ptr, CV_ELEM_SIZE(mat->type)); + memset( ptr, 0, CV_ELEM_SIZE(mat->type)); } if( _type ) @@ -1512,7 +1512,7 @@ cvScalarToRawData( const CvScalar* scalar, void* data, int type, int extend_to_1 do { offset -= pix_size; - CV_MEMCPY_AUTO( (char*)data + offset, data, pix_size ); + memcpy((char*)data + offset, data, pix_size); } while( offset > pix_size ); } @@ -2358,7 +2358,7 @@ cvClearND( CvArr* arr, const int* idx ) uchar* ptr; ptr = cvPtrND( arr, idx, &type ); if( ptr ) - CV_ZERO_CHAR( ptr, CV_ELEM_SIZE(type) ); + memset( ptr, 0, CV_ELEM_SIZE(type) ); } else icvDeleteNode( (CvSparseMat*)arr, idx, 0 ); diff --git a/modules/core/src/convert.cpp b/modules/core/src/convert.cpp index 96e1aab342..f7da74b523 100644 --- a/modules/core/src/convert.cpp +++ b/modules/core/src/convert.cpp @@ -11,7 +11,7 @@ // For Open Source Computer Vision Library // // Copyright (C) 2000-2008, Intel Corporation, all rights reserved. -// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2009-2011, Willow Garage Inc., all rights reserved. // Third party copyrights are property of their respective owners. // // Redistribution and use in source and binary forms, with or without modification, @@ -46,252 +46,251 @@ namespace cv { /****************************************************************************************\ -* split * +* split & merge * \****************************************************************************************/ template static void -splitC2_( const Mat& srcmat, Mat* dstmat ) +split_( const T* src, T** dst, int len, int cn ) { - Size size = getContinuousSize( srcmat, dstmat[0], dstmat[1] ); - for( int y = 0; y < size.height; y++ ) + int k = cn % 4 ? cn % 4 : 4; + int i, j; + if( k == 1 ) { - const T* src = (const T*)(srcmat.data + srcmat.step*y); - T* dst0 = (T*)(dstmat[0].data + dstmat[0].step*y); - T* dst1 = (T*)(dstmat[1].data + dstmat[1].step*y); - - for( int x = 0; x < size.width; x++ ) + T* dst0 = dst[0]; + for( i = j = 0; i < len; i++, j += cn ) + dst0[i] = src[j]; + } + else if( k == 2 ) + { + T *dst0 = dst[0], *dst1 = dst[1]; + for( i = j = 0; i < len; i++, j += cn ) { - T t0 = src[x*2], t1 = src[x*2+1]; - dst0[x] = t0; dst1[x] = t1; + dst0[i] = src[j]; + dst1[i] = src[j+1]; } } -} - -template static void -splitC3_( const Mat& srcmat, Mat* dstmat ) -{ - Size size = getContinuousSize( srcmat, dstmat[0], dstmat[1], dstmat[2] ); - for( int y = 0; y < size.height; y++ ) + else if( k == 3 ) { - const T* src = (const T*)(srcmat.data + srcmat.step*y); - T* dst0 = (T*)(dstmat[0].data + dstmat[0].step*y); - T* dst1 = (T*)(dstmat[1].data + dstmat[1].step*y); - T* dst2 = (T*)(dstmat[2].data + dstmat[2].step*y); - - for( int x = 0; x < size.width; x++ ) + T *dst0 = dst[0], *dst1 = dst[1], *dst2 = dst[2]; + for( i = j = 0; i < len; i++, j += cn ) { - T t0 = src[x*3], t1 = src[x*3+1], t2 = src[x*3+2]; - dst0[x] = t0; dst1[x] = t1; dst2[x] = t2; + dst0[i] = src[j]; + dst1[i] = src[j+1]; + dst2[i] = src[j+2]; } } -} - -template static void -splitC4_( const Mat& srcmat, Mat* dstmat ) -{ - Size size = getContinuousSize( srcmat, dstmat[0], dstmat[1], dstmat[2], dstmat[3] ); - for( int y = 0; y < size.height; y++ ) + else { - const T* src = (const T*)(srcmat.data + srcmat.step*y); - T* dst0 = (T*)(dstmat[0].data + dstmat[0].step*y); - T* dst1 = (T*)(dstmat[1].data + dstmat[1].step*y); - T* dst2 = (T*)(dstmat[2].data + dstmat[2].step*y); - T* dst3 = (T*)(dstmat[3].data + dstmat[3].step*y); - - for( int x = 0; x < size.width; x++ ) + T *dst0 = dst[0], *dst1 = dst[1], *dst2 = dst[2], *dst3 = dst[3]; + for( i = j = 0; i < len; i++, j += cn ) { - T t0 = src[x*4], t1 = src[x*4+1]; - dst0[x] = t0; dst1[x] = t1; - t0 = src[x*4+2]; t1 = src[x*4+3]; - dst2[x] = t0; dst3[x] = t1; + dst0[i] = src[j]; dst1[i] = src[j+1]; + dst2[i] = src[j+2]; dst3[i] = src[j+3]; + } + } + + for( ; k < cn; k += 4 ) + { + T *dst0 = dst[k], *dst1 = dst[k+1], *dst2 = dst[k+2], *dst3 = dst[k+3]; + for( i = 0, j = k; i < len; i++, j += cn ) + { + dst0[i] = src[j]; dst1[i] = src[j+1]; + dst2[i] = src[j+2]; dst3[i] = src[j+3]; } } } - -typedef void (*SplitFunc)(const Mat& src, Mat* dst); - -void split(const Mat& src, Mat* mv) + +template static void +merge_( const T** src, T* dst, int len, int cn ) { - static SplitFunc tab[] = + int k = cn % 4 ? cn % 4 : 4; + int i, j; + if( k == 1 ) { - splitC2_, splitC2_, splitC2_, 0, splitC2_, - splitC3_, splitC3_, splitC3_, 0, splitC3_, - splitC4_, splitC4_, splitC4_, 0, splitC4_ - }; - - int i, depth = src.depth(), cn = src.channels(); - - if( cn == 1 ) + const T* src0 = src[0]; + for( i = j = 0; i < len; i++, j += cn ) + dst[j] = src0[i]; + } + else if( k == 2 ) { - src.copyTo(mv[0]); - return; + const T *src0 = src[0], *src1 = src[1]; + for( i = j = 0; i < len; i++, j += cn ) + { + dst[j] = src0[i]; + dst[j+1] = src1[i]; + } } - - for( i = 0; i < cn; i++ ) - mv[i].create(src.dims, src.size, depth); - - if( cn <= 4 ) + else if( k == 3 ) { - SplitFunc func = tab[(cn-2)*5 + (src.elemSize1()>>1)]; - CV_Assert( func != 0 ); - - if( src.dims > 2 ) + const T *src0 = src[0], *src1 = src[1], *src2 = src[2]; + for( i = j = 0; i < len; i++, j += cn ) { - const Mat* arrays[5]; - Mat planes[5]; - arrays[0] = &src; - for( i = 0; i < cn; i++ ) - arrays[i+1] = &mv[i]; - NAryMatIterator it(arrays, planes, cn+1); - - for( int i = 0; i < it.nplanes; i++, ++it ) - func( it.planes[0], &it.planes[1] ); + dst[j] = src0[i]; + dst[j+1] = src1[i]; + dst[j+2] = src2[i]; } - else - func( src, mv ); } else { - AutoBuffer pairs(cn*2); - - for( i = 0; i < cn; i++ ) + const T *src0 = src[0], *src1 = src[1], *src2 = src[2], *src3 = src[3]; + for( i = j = 0; i < len; i++, j += cn ) { - pairs[i*2] = i; - pairs[i*2+1] = 0; + dst[j] = src0[i]; dst[j+1] = src1[i]; + dst[j+2] = src2[i]; dst[j+3] = src3[i]; } - mixChannels( &src, 1, mv, cn, &pairs[0], cn ); } -} -void split(const Mat& m, vector& mv) + for( ; k < cn; k += 4 ) + { + const T *src0 = src[k], *src1 = src[k+1], *src2 = src[k+2], *src3 = src[k+3]; + for( i = 0, j = k; i < len; i++, j += cn ) + { + dst[j] = src0[i]; dst[j+1] = src1[i]; + dst[j+2] = src2[i]; dst[j+3] = src3[i]; + } + } +} + +static void split8u(const uchar* src, uchar** dst, int len, int cn ) { - mv.resize(!m.empty() ? m.channels() : 0); - if(!m.empty()) - split(m, &mv[0]); + split_(src, dst, len, cn); } -/****************************************************************************************\ -* merge * -\****************************************************************************************/ +static void split16u(const ushort* src, ushort** dst, int len, int cn ) +{ + split_(src, dst, len, cn); +} -// input vector is made non-const to make sure that we do not copy Mat on each access -template static void -mergeC2_( const Mat* srcmat, Mat& dstmat ) +static void split32s(const int* src, int** dst, int len, int cn ) { - Size size = getContinuousSize( srcmat[0], srcmat[1], dstmat ); - for( int y = 0; y < size.height; y++ ) - { - const T* src0 = (const T*)(srcmat[0].data + srcmat[0].step*y); - const T* src1 = (const T*)(srcmat[1].data + srcmat[1].step*y); - T* dst = (T*)(dstmat.data + dstmat.step*y); + split_(src, dst, len, cn); +} + +static void split64s(const int64* src, int64** dst, int len, int cn ) +{ + split_(src, dst, len, cn); +} - for( int x = 0; x < size.width; x++ ) - { - T t0 = src0[x], t1 = src1[x]; - dst[x*2] = t0; dst[x*2+1] = t1; - } - } +static void merge8u(const uchar** src, uchar* dst, int len, int cn ) +{ + merge_(src, dst, len, cn); } -template static void -mergeC3_( const Mat* srcmat, Mat& dstmat ) +static void merge16u(const ushort** src, ushort* dst, int len, int cn ) { - Size size = getContinuousSize( srcmat[0], srcmat[1], srcmat[2], dstmat ); - for( int y = 0; y < size.height; y++ ) - { - const T* src0 = (const T*)(srcmat[0].data + srcmat[0].step*y); - const T* src1 = (const T*)(srcmat[1].data + srcmat[1].step*y); - const T* src2 = (const T*)(srcmat[2].data + srcmat[2].step*y); - T* dst = (T*)(dstmat.data + dstmat.step*y); + merge_(src, dst, len, cn); +} - for( int x = 0; x < size.width; x++ ) - { - T t0 = src0[x], t1 = src1[x], t2 = src2[x]; - dst[x*3] = t0; dst[x*3+1] = t1; dst[x*3+2] = t2; - } - } +static void merge32s(const int** src, int* dst, int len, int cn ) +{ + merge_(src, dst, len, cn); } -template static void -mergeC4_( const Mat* srcmat, Mat& dstmat ) +static void merge64s(const int64** src, int64* dst, int len, int cn ) +{ + merge_(src, dst, len, cn); +} + +typedef void (*SplitFunc)(const uchar* src, uchar** dst, int len, int cn); +typedef void (*MergeFunc)(const uchar** src, uchar* dst, int len, int cn); + +static SplitFunc splitTab[] = +{ + (SplitFunc)split8u, (SplitFunc)split8u, (SplitFunc)split16u, (SplitFunc)split16u, + (SplitFunc)split32s, (SplitFunc)split32s, (SplitFunc)split64s, 0 +}; + +static MergeFunc mergeTab[] = +{ + (MergeFunc)merge8u, (MergeFunc)merge8u, (MergeFunc)merge16u, (MergeFunc)merge16u, + (MergeFunc)merge32s, (MergeFunc)merge32s, (MergeFunc)merge64s, 0 +}; + +} + +void cv::split(const Mat& src, Mat* mv) { - Size size = getContinuousSize( srcmat[0], srcmat[1], srcmat[2], srcmat[3], dstmat ); - for( int y = 0; y < size.height; y++ ) + int k, depth = src.depth(), cn = src.channels(); + if( cn == 1 ) { - const T* src0 = (const T*)(srcmat[0].data + srcmat[0].step*y); - const T* src1 = (const T*)(srcmat[1].data + srcmat[1].step*y); - const T* src2 = (const T*)(srcmat[2].data + srcmat[2].step*y); - const T* src3 = (const T*)(srcmat[3].data + srcmat[3].step*y); - T* dst = (T*)(dstmat.data + dstmat.step*y); + src.copyTo(mv[0]); + return; + } - for( int x = 0; x < size.width; x++ ) + SplitFunc func = splitTab[depth]; + CV_Assert( func != 0 ); + + int esz = src.elemSize(), esz1 = src.elemSize1(); + int blocksize0 = (BLOCK_SIZE + esz-1)/esz; + AutoBuffer _buf((cn+1)*(sizeof(Mat*) + sizeof(uchar*)) + 16); + const Mat** arrays = (const Mat**)(uchar*)_buf; + uchar** ptrs = (uchar**)alignPtr(arrays + cn + 1, 16); + + arrays[0] = &src; + for( k = 0; k < cn; k++ ) + { + mv[k].create(src.dims, src.size, depth); + arrays[k+1] = &mv[k]; + } + + NAryMatIterator it(arrays, ptrs, cn+1); + int total = (int)it.size, blocksize = cn <= 4 ? total : std::min(total, blocksize0); + + for( size_t i = 0; i < it.nplanes; i++, ++it ) + { + for( int j = 0; j < total; j += blocksize ) { - T t0 = src0[x], t1 = src1[x]; - dst[x*4] = t0; dst[x*4+1] = t1; - t0 = src2[x]; t1 = src3[x]; - dst[x*4+2] = t0; dst[x*4+3] = t1; + int bsz = std::min(total - j, blocksize); + func( ptrs[0], &ptrs[1], bsz, cn ); + + if( j + blocksize < total ) + { + ptrs[0] += bsz*esz; + for( k = 0; k < cn; k++ ) + ptrs[k+1] += bsz*esz1; + } } } } - -typedef void (*MergeFunc)(const Mat* src, Mat& dst); - -void merge(const Mat* mv, size_t _n, Mat& dst) + +void cv::split(const Mat& m, vector& mv) { - static MergeFunc tab[] = - { - mergeC2_, mergeC2_, mergeC2_, 0, mergeC2_, - mergeC3_, mergeC3_, mergeC3_, 0, mergeC3_, - mergeC4_, mergeC4_, mergeC4_, 0, mergeC4_ - }; - - CV_Assert( mv && _n > 0 ); + mv.resize(!m.empty() ? m.channels() : 0); + if(!m.empty()) + split(m, &mv[0]); +} + +void cv::merge(const Mat* mv, size_t n, OutputArray _dst) +{ + CV_Assert( mv && n > 0 ); int depth = mv[0].depth(); bool allch1 = true; - int i, total = 0, n = (int)_n; + int k, cn = 0; + size_t i; for( i = 0; i < n; i++ ) { CV_Assert(mv[i].size == mv[0].size && mv[i].depth() == depth); allch1 = allch1 && mv[i].channels() == 1; - total += mv[i].channels(); + cn += mv[i].channels(); } - - CV_Assert( 0 < total && total <= CV_CN_MAX ); - - if( total == 1 ) + + CV_Assert( 0 < cn && cn <= CV_CN_MAX ); + _dst.create(mv[0].dims, mv[0].size, CV_MAKETYPE(depth, cn)); + Mat dst = _dst.getMat(); + + if( n == 1 ) { mv[0].copyTo(dst); return; } - - dst.create(mv[0].dims, mv[0].size, CV_MAKETYPE(depth, total)); - - if( allch1 && total <= 4 ) - { - MergeFunc func = tab[(total-2)*5 + (CV_ELEM_SIZE(depth)>>1)]; - CV_Assert( func != 0 ); - if( mv[0].dims > 2 ) - { - const Mat* arrays[5]; - Mat planes[5]; - arrays[total] = &dst; - for( i = 0; i < total; i++ ) - arrays[i] = &mv[i]; - NAryMatIterator it(arrays, planes, total+1); - - for( i = 0; i < it.nplanes; i++, ++it ) - func( &it.planes[0], it.planes[total] ); - } - else - func( mv, dst ); - } - else + + if( !allch1 ) { - AutoBuffer pairs(total*2); - int j, k, ni=0; - + AutoBuffer pairs(cn*2); + int j, ni=0; + for( i = 0, j = 0; i < n; i++, j += ni ) { ni = mv[i].channels(); @@ -301,104 +300,148 @@ void merge(const Mat* mv, size_t _n, Mat& dst) pairs[(j+k)*2+1] = j + k; } } - mixChannels( mv, n, &dst, 1, &pairs[0], total ); + mixChannels( mv, n, &dst, 1, &pairs[0], cn ); + return; + } + + size_t esz = dst.elemSize(), esz1 = dst.elemSize1(); + int blocksize0 = (BLOCK_SIZE + esz-1)/esz; + AutoBuffer _buf((cn+1)*(sizeof(Mat*) + sizeof(uchar*)) + 16); + const Mat** arrays = (const Mat**)(uchar*)_buf; + uchar** ptrs = (uchar**)alignPtr(arrays + cn + 1, 16); + + arrays[0] = &dst; + for( k = 0; k < cn; k++ ) + arrays[k+1] = &mv[k]; + + NAryMatIterator it(arrays, ptrs, cn+1); + int total = (int)it.size, blocksize = cn <= 4 ? total : std::min(total, blocksize0); + MergeFunc func = mergeTab[depth]; + + for( i = 0; i < it.nplanes; i++, ++it ) + { + for( int j = 0; j < total; j += blocksize ) + { + int bsz = std::min(total - j, blocksize); + func( (const uchar**)&ptrs[1], ptrs[0], bsz, cn ); + + if( j + blocksize < total ) + { + ptrs[0] += bsz*esz; + for( int k = 0; k < cn; k++ ) + ptrs[k+1] += bsz*esz1; + } + } } } -void merge(const vector& mv, Mat& dst) +void cv::merge(const vector& mv, OutputArray _dst) { - merge(!mv.empty() ? &mv[0] : 0, mv.size(), dst); -} + merge(!mv.empty() ? &mv[0] : 0, mv.size(), _dst); +} /****************************************************************************************\ * Generalized split/merge: mixing channels * \****************************************************************************************/ +namespace cv +{ + template static void -mixChannels_( const void** _src, const int* sdelta0, - const int* sdelta1, void** _dst, - const int* ddelta0, const int* ddelta1, - int n, Size size ) +mixChannels_( const T** src, const int* sdelta, + T** dst, const int* ddelta, + int len, int npairs ) { - const T** src = (const T**)_src; - T** dst = (T**)_dst; int i, k; - int block_size0 = n == 1 ? size.width : 1024; - - for( ; size.height--; ) + for( k = 0; k < npairs; k++ ) { - int remaining = size.width; - for( ; remaining > 0; ) + const T* s = src[k]; + T* d = dst[k]; + int ds = sdelta[k], dd = ddelta[k]; + if( s ) { - int block_size = MIN( remaining, block_size0 ); - for( k = 0; k < n; k++ ) + for( i = 0; i <= len - 2; i += 2, s += ds*2, d += dd*2 ) { - const T* s = src[k]; - T* d = dst[k]; - int ds = sdelta1[k], dd = ddelta1[k]; - if( s ) - { - for( i = 0; i <= block_size - 2; i += 2, s += ds*2, d += dd*2 ) - { - T t0 = s[0], t1 = s[ds]; - d[0] = t0; d[dd] = t1; - } - if( i < block_size ) - d[0] = s[0], s += ds, d += dd; - src[k] = s; - } - else - { - for( i=0; i <= block_size-2; i+=2, d+=dd*2 ) - d[0] = d[dd] = 0; - if( i < block_size ) - d[0] = 0, d += dd; - } - dst[k] = d; + T t0 = s[0], t1 = s[ds]; + d[0] = t0; d[dd] = t1; } - remaining -= block_size; + if( i < len ) + d[0] = s[0]; + } + else + { + for( i = 0; i <= len - 2; i += 2, d += dd*2 ) + d[0] = d[dd] = 0; + if( i < len ) + d[0] = 0; } - for( k = 0; k < n; k++ ) - src[k] += sdelta0[k], dst[k] += ddelta0[k]; } } -typedef void (*MixChannelsFunc)( const void** src, const int* sdelta0, - const int* sdelta1, void** dst, const int* ddelta0, const int* ddelta1, int n, Size size ); + +static void mixChannels8u( const uchar** src, const int* sdelta, + uchar** dst, const int* ddelta, + int len, int npairs ) +{ + mixChannels_(src, sdelta, dst, ddelta, len, npairs); +} + +static void mixChannels16u( const ushort** src, const int* sdelta, + ushort** dst, const int* ddelta, + int len, int npairs ) +{ + mixChannels_(src, sdelta, dst, ddelta, len, npairs); +} -void mixChannels( const Mat* src, size_t nsrcs, Mat* dst, size_t ndsts, const int* fromTo, size_t npairs ) +static void mixChannels32s( const int** src, const int* sdelta, + int** dst, const int* ddelta, + int len, int npairs ) +{ + mixChannels_(src, sdelta, dst, ddelta, len, npairs); +} + +static void mixChannels64s( const int64** src, const int* sdelta, + int64** dst, const int* ddelta, + int len, int npairs ) +{ + mixChannels_(src, sdelta, dst, ddelta, len, npairs); +} + +typedef void (*MixChannelsFunc)( const uchar** src, const int* sdelta, + uchar** dst, const int* ddelta, int len, int npairs ); + +static MixChannelsFunc mixchTab[] = +{ + (MixChannelsFunc)mixChannels8u, (MixChannelsFunc)mixChannels8u, (MixChannelsFunc)mixChannels16u, + (MixChannelsFunc)mixChannels16u, (MixChannelsFunc)mixChannels32s, (MixChannelsFunc)mixChannels32s, + (MixChannelsFunc)mixChannels64s, 0 +}; + +} + +void cv::mixChannels( const Mat* src, size_t nsrcs, Mat* dst, size_t ndsts, const int* fromTo, size_t npairs ) { if( npairs == 0 ) return; CV_Assert( src && nsrcs > 0 && dst && ndsts > 0 && fromTo && npairs > 0 ); - if( src[0].dims > 2 ) - { - size_t k, m = nsrcs, n = ndsts; - CV_Assert( n > 0 && m > 0 ); - AutoBuffer v(m + n); - AutoBuffer planes(m + n); - for( k = 0; k < m; k++ ) - v[k] = &src[k]; - for( k = 0; k < n; k++ ) - v[m + k] = &dst[k]; - NAryMatIterator it(v, planes, m + n); - - for( int i = 0; i < it.nplanes; i++, ++it ) - mixChannels( &it.planes[0], m, &it.planes[m], n, fromTo, npairs ); - return; - } + size_t i, j, k, esz1 = dst[0].elemSize1(); + int depth = dst[0].depth(); + + AutoBuffer buf((nsrcs + ndsts + 1)*(sizeof(Mat*) + sizeof(uchar*)) + npairs*(sizeof(uchar*)*2 + sizeof(int)*6)); + const Mat** arrays = (const Mat**)(uchar*)buf; + uchar** ptrs = (uchar**)(arrays + nsrcs + ndsts); + const uchar** srcs = (const uchar**)(ptrs + nsrcs + ndsts + 1); + uchar** dsts = (uchar**)(srcs + npairs); + int* tab = (int*)(dsts + npairs); + int *sdelta = (int*)(tab + npairs*4), *ddelta = sdelta + npairs; + + for( i = 0; i < nsrcs; i++ ) + arrays[i] = &src[i]; + for( i = 0; i < ndsts; i++ ) + arrays[i + nsrcs] = &dst[i]; + ptrs[nsrcs + ndsts] = 0; - size_t i, j; - int depth = dst[0].depth(), esz1 = (int)dst[0].elemSize1(); - Size size = dst[0].size(); - - AutoBuffer buf(npairs*(sizeof(void*)*2 + sizeof(int)*4)); - void** srcs = (void**)(uchar*)buf; - void** dsts = srcs + npairs; - int *s0 = (int*)(dsts + npairs), *s1 = s0 + npairs, *d0 = s1 + npairs, *d1 = d0 + npairs; - bool isContinuous = true; - for( i = 0; i < npairs; i++ ) { int i0 = fromTo[i*2], i1 = fromTo[i*2+1]; @@ -407,48 +450,54 @@ void mixChannels( const Mat* src, size_t nsrcs, Mat* dst, size_t ndsts, const in for( j = 0; j < nsrcs; i0 -= src[j].channels(), j++ ) if( i0 < src[j].channels() ) break; - CV_Assert(j < nsrcs && src[j].size() == size && src[j].depth() == depth); - isContinuous = isContinuous && src[j].isContinuous(); - srcs[i] = src[j].data + i0*esz1; - s1[i] = src[j].channels(); s0[i] = (int)src[j].step/esz1 - size.width*src[j].channels(); + CV_Assert(j < nsrcs && src[j].depth() == depth); + tab[i*4] = j; tab[i*4+1] = i0*esz1; + sdelta[i] = src[j].channels(); } else { - srcs[i] = 0; s1[i] = s0[i] = 0; + tab[i*4] = nsrcs + ndsts; tab[i*4+1] = 0; + sdelta[i] = 0; } for( j = 0; j < ndsts; i1 -= dst[j].channels(), j++ ) if( i1 < dst[j].channels() ) break; - CV_Assert(i1 >= 0 && j < ndsts && dst[j].size() == size && dst[j].depth() == depth); - isContinuous = isContinuous && dst[j].isContinuous(); - dsts[i] = dst[j].data + i1*esz1; - d1[i] = dst[j].channels(); d0[i] = (int)dst[j].step/esz1 - size.width*dst[j].channels(); + CV_Assert(i1 >= 0 && j < ndsts && dst[j].depth() == depth); + tab[i*4+2] = j + nsrcs; tab[i*4+3] = i1*esz1; + ddelta[i] = dst[j].channels(); } - MixChannelsFunc func = 0; - if( esz1 == 1 ) - func = mixChannels_; - else if( esz1 == 2 ) - func = mixChannels_; - else if( esz1 == 4 ) - func = mixChannels_; - else if( esz1 == 8 ) - func = mixChannels_; - else - CV_Error( CV_StsUnsupportedFormat, "" ); - - if( isContinuous ) + NAryMatIterator it(arrays, ptrs, nsrcs + ndsts); + int total = (int)it.size, blocksize = std::min(total, (int)((BLOCK_SIZE + esz1-1)/esz1)); + MixChannelsFunc func = mixchTab[depth]; + + for( i = 0; i < it.nplanes; i++, ++it ) { - size.width *= size.height; - size.height = 1; + for( k = 0; k < npairs; k++ ) + { + srcs[k] = ptrs[tab[k*4]] + tab[k*4+1]; + dsts[k] = ptrs[tab[k*4+2]] + tab[k*4+3]; + } + + for( int j = 0; j < total; j += blocksize ) + { + int bsz = std::min(total - j, blocksize); + func( srcs, sdelta, dsts, ddelta, bsz, (int)npairs ); + + if( j + blocksize < total ) + for( k = 0; k < npairs; k++ ) + { + srcs[k] += blocksize*sdelta[k]*esz1; + dsts[k] += blocksize*ddelta[k]*esz1; + } + } } - func( (const void**)srcs, s0, s1, dsts, d0, d1, (int)npairs, size ); } -void mixChannels(const vector& src, vector& dst, - const int* fromTo, int npairs) +void cv::mixChannels(const vector& src, vector& dst, + const int* fromTo, size_t npairs) { mixChannels(!src.empty() ? &src[0] : 0, src.size(), !dst.empty() ? &dst[0] : 0, dst.size(), fromTo, npairs); @@ -458,145 +507,74 @@ void mixChannels(const vector& src, vector& dst, * convertScale[Abs] * \****************************************************************************************/ -template struct OpCvt -{ - typedef sT type1; - typedef dT rtype; - rtype operator()(type1 x) const { return saturate_cast(x); } -}; - -template struct OpCvtFixPt -{ - typedef sT type1; - typedef dT rtype; - enum { fbits = _fbits }; - rtype operator()(type1 x) const - { - return saturate_cast((x + (1<<(fbits-1)))>>fbits); - } -}; - -template struct OpCvtAbs -{ - typedef sT type1; - typedef dT rtype; - rtype operator()(type1 x) const { return saturate_cast(std::abs(x)); } -}; - -template struct OpCvtAbsFixPt -{ - typedef sT type1; - typedef dT rtype; - enum { fbits = _fbits }; - - rtype operator()(type1 x) const - { - return saturate_cast((std::abs(x) + (1<<(fbits-1)))>>fbits); - } -}; - -template static void -cvtScaleLUT_( const Mat& srcmat, Mat& dstmat, double scale, double shift ) +namespace cv { - Op op; - typedef typename Op::rtype DT; - DT lut[256]; - int i, sdepth = srcmat.depth(), ddepth = dstmat.depth(); - double val = shift; - - for( i = 0; i < 128; i++, val += scale ) - lut[i] = op(val); - - if( sdepth == CV_8S ) - val = shift*2 - val; - - for( ; i < 256; i++, val += scale ) - lut[i] = op(val); - Mat _srcmat = srcmat; - if( sdepth == CV_8S ) - _srcmat = Mat(srcmat.size(), CV_8UC(srcmat.channels()), srcmat.data, srcmat.step); - LUT(_srcmat, Mat(1, 256, ddepth, lut), dstmat); -} - -template static void -cvtScale_( const Mat& srcmat, Mat& dstmat, double _scale, double _shift ) +template static void +cvtScaleAbs_( const T* src, size_t sstep, + DT* dst, size_t dstep, Size size, + WT scale, WT shift ) { - Op op; - typedef typename Op::type1 WT; - typedef typename Op::rtype DT; - Size size = getContinuousSize( srcmat, dstmat, srcmat.channels() ); - WT scale = saturate_cast(_scale), shift = saturate_cast(_shift); - - for( int y = 0; y < size.height; y++ ) + sstep /= sizeof(src[0]); + dstep /= sizeof(dst[0]); + + for( ; size.height--; src += sstep, dst += dstep ) { - const T* src = (const T*)(srcmat.data + srcmat.step*y); - DT* dst = (DT*)(dstmat.data + dstmat.step*y); int x = 0; - for( ; x <= size.width - 4; x += 4 ) { DT t0, t1; - t0 = op(src[x]*scale + shift); - t1 = op(src[x+1]*scale + shift); + t0 = saturate_cast
(std::abs(src[x]*scale + shift)); + t1 = saturate_cast
(std::abs(src[x+1]*scale + shift)); dst[x] = t0; dst[x+1] = t1; - t0 = op(src[x+2]*scale + shift); - t1 = op(src[x+3]*scale + shift); + t0 = saturate_cast
(std::abs(src[x+2]*scale + shift)); + t1 = saturate_cast
(std::abs(src[x+3]*scale + shift)); dst[x+2] = t0; dst[x+3] = t1; } - + for( ; x < size.width; x++ ) - dst[x] = op(src[x]*scale + shift); + dst[x] = saturate_cast
(std::abs(src[x]*scale + shift)); } -} - -template static void -cvtScaleInt_( const Mat& srcmat, Mat& dstmat, double _scale, double _shift ) +} + +template static void +cvtScale_( const T* src, size_t sstep, + DT* dst, size_t dstep, Size size, + WT scale, WT shift ) { - if( std::abs(_scale) > 1 || std::abs(_shift) > MAX_SHIFT ) - { - cvtScale_(srcmat, dstmat, _scale, _shift); - return; - } - OpFixPt op; - typedef typename OpFixPt::rtype DT; - Size size = getContinuousSize( srcmat, dstmat, srcmat.channels() ); - int scale = saturate_cast(_scale*(1<(_shift*(1<(src[x]*scale + shift); + t1 = saturate_cast
(src[x+1]*scale + shift); dst[x] = t0; dst[x+1] = t1; - t0 = op(src[x+2]*scale + shift); - t1 = op(src[x+3]*scale + shift); + t0 = saturate_cast
(src[x+2]*scale + shift); + t1 = saturate_cast
(src[x+3]*scale + shift); dst[x+2] = t0; dst[x+3] = t1; } for( ; x < size.width; x++ ) - dst[x] = op(src[x]*scale + shift); + dst[x] = saturate_cast
(src[x]*scale + shift); } } + template static void -cvt_( const Mat& srcmat, Mat& dstmat ) +cvt_( const T* src, size_t sstep, + DT* dst, size_t dstep, Size size ) { - Size size = getContinuousSize( srcmat, dstmat, srcmat.channels() ); - - for( int y = 0; y < size.height; y++ ) + sstep /= sizeof(src[0]); + dstep /= sizeof(dst[0]); + + for( ; size.height--; src += sstep, dst += dstep ) { - const T* src = (const T*)(srcmat.data + srcmat.step*y); - DT* dst = (DT*)(dstmat.data + dstmat.step*y); int x = 0; - for( ; x <= size.width - 4; x += 4 ) { DT t0, t1; @@ -607,322 +585,447 @@ cvt_( const Mat& srcmat, Mat& dstmat ) t1 = saturate_cast
(src[x+3]); dst[x+2] = t0; dst[x+3] = t1; } - + for( ; x < size.width; x++ ) dst[x] = saturate_cast
(src[x]); } } -static const int FBITS = 15; -#define ICV_SCALE(x) CV_DESCALE((x), FBITS) +template static void +cpy_( const T* src, size_t sstep, T* dst, size_t dstep, Size size ) +{ + sstep /= sizeof(src[0]); + dstep /= sizeof(dst[0]); + + for( ; size.height--; src += sstep, dst += dstep ) + memcpy(dst, src, size.width*sizeof(src[0])); +} + +#define DEF_CVT_SCALE_ABS_FUNC(suffix, tfunc, stype, dtype, wtype) \ +static void cvtScaleAbs##suffix( const stype* src, size_t sstep, const uchar*, size_t, \ + dtype* dst, size_t dstep, Size size, double* scale) \ +{ \ + tfunc(src, sstep, dst, dstep, size, (wtype)scale[0], (wtype)scale[1]); \ +} + +#define DEF_CVT_SCALE_FUNC(suffix, stype, dtype, wtype) \ +static void cvtScale##suffix( const stype* src, size_t sstep, const uchar*, size_t, \ +dtype* dst, size_t dstep, Size size, double* scale) \ +{ \ + cvtScale_(src, sstep, dst, dstep, size, (wtype)scale[0], (wtype)scale[1]); \ +} + + +#define DEF_CVT_FUNC(suffix, stype, dtype) \ +static void cvt##suffix( const stype* src, size_t sstep, const uchar*, size_t, \ + dtype* dst, size_t dstep, Size size, double*) \ +{ \ + cvt_(src, sstep, dst, dstep, size); \ +} -typedef void (*CvtFunc)( const Mat& src, Mat& dst ); -typedef void (*CvtScaleFunc)( const Mat& src, Mat& dst, double scale, double shift ); +#define DEF_CPY_FUNC(suffix, stype) \ +static void cvt##suffix( const stype* src, size_t sstep, const uchar*, size_t, \ +stype* dst, size_t dstep, Size size, double*) \ +{ \ + cpy_(src, sstep, dst, dstep, size); \ +} + + +DEF_CVT_SCALE_ABS_FUNC(8u, cvtScaleAbs_, uchar, uchar, float); +DEF_CVT_SCALE_ABS_FUNC(8s8u, cvtScaleAbs_, schar, uchar, float); +DEF_CVT_SCALE_ABS_FUNC(16u8u, cvtScaleAbs_, ushort, uchar, float); +DEF_CVT_SCALE_ABS_FUNC(16s8u, cvtScaleAbs_, short, uchar, float); +DEF_CVT_SCALE_ABS_FUNC(32s8u, cvtScaleAbs_, int, uchar, float); +DEF_CVT_SCALE_ABS_FUNC(32f8u, cvtScaleAbs_, float, uchar, float); +DEF_CVT_SCALE_ABS_FUNC(64f8u, cvtScaleAbs_, double, uchar, float); + +DEF_CVT_SCALE_FUNC(8u, uchar, uchar, float); +DEF_CVT_SCALE_FUNC(8s8u, schar, uchar, float); +DEF_CVT_SCALE_FUNC(16u8u, ushort, uchar, float); +DEF_CVT_SCALE_FUNC(16s8u, short, uchar, float); +DEF_CVT_SCALE_FUNC(32s8u, int, uchar, float); +DEF_CVT_SCALE_FUNC(32f8u, float, uchar, float); +DEF_CVT_SCALE_FUNC(64f8u, double, uchar, float); + +DEF_CVT_SCALE_FUNC(8u8s, uchar, schar, float); +DEF_CVT_SCALE_FUNC(8s, schar, schar, float); +DEF_CVT_SCALE_FUNC(16u8s, ushort, schar, float); +DEF_CVT_SCALE_FUNC(16s8s, short, schar, float); +DEF_CVT_SCALE_FUNC(32s8s, int, schar, float); +DEF_CVT_SCALE_FUNC(32f8s, float, schar, float); +DEF_CVT_SCALE_FUNC(64f8s, double, schar, float); + +DEF_CVT_SCALE_FUNC(8u16u, uchar, ushort, float); +DEF_CVT_SCALE_FUNC(8s16u, schar, ushort, float); +DEF_CVT_SCALE_FUNC(16u, ushort, ushort, float); +DEF_CVT_SCALE_FUNC(16s16u, short, ushort, float); +DEF_CVT_SCALE_FUNC(32s16u, int, ushort, float); +DEF_CVT_SCALE_FUNC(32f16u, float, ushort, float); +DEF_CVT_SCALE_FUNC(64f16u, double, ushort, float); + +DEF_CVT_SCALE_FUNC(8u16s, uchar, short, float); +DEF_CVT_SCALE_FUNC(8s16s, schar, short, float); +DEF_CVT_SCALE_FUNC(16u16s, ushort, short, float); +DEF_CVT_SCALE_FUNC(16s, short, short, float); +DEF_CVT_SCALE_FUNC(32s16s, int, short, float); +DEF_CVT_SCALE_FUNC(32f16s, float, short, float); +DEF_CVT_SCALE_FUNC(64f16s, double, short, float); + +DEF_CVT_SCALE_FUNC(8u32s, uchar, int, float); +DEF_CVT_SCALE_FUNC(8s32s, schar, int, float); +DEF_CVT_SCALE_FUNC(16u32s, ushort, int, float); +DEF_CVT_SCALE_FUNC(16s32s, short, int, float); +DEF_CVT_SCALE_FUNC(32s, int, int, double); +DEF_CVT_SCALE_FUNC(32f32s, float, int, float); +DEF_CVT_SCALE_FUNC(64f32s, double, int, double); + +DEF_CVT_SCALE_FUNC(8u32f, uchar, float, float); +DEF_CVT_SCALE_FUNC(8s32f, schar, float, float); +DEF_CVT_SCALE_FUNC(16u32f, ushort, float, float); +DEF_CVT_SCALE_FUNC(16s32f, short, float, float); +DEF_CVT_SCALE_FUNC(32s32f, int, float, double); +DEF_CVT_SCALE_FUNC(32f, float, float, float); +DEF_CVT_SCALE_FUNC(64f32f, double, float, double); + +DEF_CVT_SCALE_FUNC(8u64f, uchar, double, double); +DEF_CVT_SCALE_FUNC(8s64f, schar, double, double); +DEF_CVT_SCALE_FUNC(16u64f, ushort, double, double); +DEF_CVT_SCALE_FUNC(16s64f, short, double, double); +DEF_CVT_SCALE_FUNC(32s64f, int, double, double); +DEF_CVT_SCALE_FUNC(32f64f, float, double, double); +DEF_CVT_SCALE_FUNC(64f, double, double, double); + +DEF_CPY_FUNC(8u, uchar); +DEF_CVT_FUNC(8s8u, schar, uchar); +DEF_CVT_FUNC(16u8u, ushort, uchar); +DEF_CVT_FUNC(16s8u, short, uchar); +DEF_CVT_FUNC(32s8u, int, uchar); +DEF_CVT_FUNC(32f8u, float, uchar); +DEF_CVT_FUNC(64f8u, double, uchar); + +DEF_CVT_FUNC(8u8s, uchar, schar); +DEF_CVT_FUNC(16u8s, ushort, schar); +DEF_CVT_FUNC(16s8s, short, schar); +DEF_CVT_FUNC(32s8s, int, schar); +DEF_CVT_FUNC(32f8s, float, schar); +DEF_CVT_FUNC(64f8s, double, schar); + +DEF_CVT_FUNC(8u16u, uchar, ushort); +DEF_CVT_FUNC(8s16u, schar, ushort); +DEF_CPY_FUNC(16u, ushort); +DEF_CVT_FUNC(16s16u, short, ushort); +DEF_CVT_FUNC(32s16u, int, ushort); +DEF_CVT_FUNC(32f16u, float, ushort); +DEF_CVT_FUNC(64f16u, double, ushort); + +DEF_CVT_FUNC(8u16s, uchar, short); +DEF_CVT_FUNC(8s16s, schar, short); +DEF_CVT_FUNC(16u16s, ushort, short); +DEF_CVT_FUNC(32s16s, int, short); +DEF_CVT_FUNC(32f16s, float, short); +DEF_CVT_FUNC(64f16s, double, short); + +DEF_CVT_FUNC(8u32s, uchar, int); +DEF_CVT_FUNC(8s32s, schar, int); +DEF_CVT_FUNC(16u32s, ushort, int); +DEF_CVT_FUNC(16s32s, short, int); +DEF_CPY_FUNC(32s, int); +DEF_CVT_FUNC(32f32s, float, int); +DEF_CVT_FUNC(64f32s, double, int); + +DEF_CVT_FUNC(8u32f, uchar, float); +DEF_CVT_FUNC(8s32f, schar, float); +DEF_CVT_FUNC(16u32f, ushort, float); +DEF_CVT_FUNC(16s32f, short, float); +DEF_CVT_FUNC(32s32f, int, float); +DEF_CVT_FUNC(64f32f, double, float); + +DEF_CVT_FUNC(8u64f, uchar, double); +DEF_CVT_FUNC(8s64f, schar, double); +DEF_CVT_FUNC(16u64f, ushort, double); +DEF_CVT_FUNC(16s64f, short, double); +DEF_CVT_FUNC(32s64f, int, double); +DEF_CVT_FUNC(32f64f, float, double); +DEF_CPY_FUNC(64s, int64); + +static BinaryFunc cvtScaleAbsTab[] = +{ + (BinaryFunc)cvtScaleAbs8u, (BinaryFunc)cvtScaleAbs8s8u, (BinaryFunc)cvtScaleAbs16u8u, + (BinaryFunc)cvtScaleAbs16s8u, (BinaryFunc)cvtScaleAbs32s8u, (BinaryFunc)cvtScaleAbs32f8u, + (BinaryFunc)cvtScaleAbs64f8u, 0 +}; + +static BinaryFunc cvtScaleTab[][8] = +{ + { + (BinaryFunc)cvtScale8u, (BinaryFunc)cvtScale8s8u, (BinaryFunc)cvtScale16u8u, + (BinaryFunc)cvtScale16s8u, (BinaryFunc)cvtScale32s8u, (BinaryFunc)cvtScale32f8u, + (BinaryFunc)cvtScale64f8u, 0 + }, + { + (BinaryFunc)cvtScale8u8s, (BinaryFunc)cvtScale8s, (BinaryFunc)cvtScale16u8s, + (BinaryFunc)cvtScale16s8s, (BinaryFunc)cvtScale32s8s, (BinaryFunc)cvtScale32f8s, + (BinaryFunc)cvtScale64f8s, 0 + }, + { + (BinaryFunc)cvtScale8u16u, (BinaryFunc)cvtScale8s16u, (BinaryFunc)cvtScale16u, + (BinaryFunc)cvtScale16s16u, (BinaryFunc)cvtScale32s16u, (BinaryFunc)cvtScale32f16u, + (BinaryFunc)cvtScale64f16u, 0 + }, + { + (BinaryFunc)cvtScale8u16s, (BinaryFunc)cvtScale8s16s, (BinaryFunc)cvtScale16u16s, + (BinaryFunc)cvtScale16s, (BinaryFunc)cvtScale32s16s, (BinaryFunc)cvtScale32f16s, + (BinaryFunc)cvtScale64f16s, 0 + }, + { + (BinaryFunc)cvtScale8u32s, (BinaryFunc)cvtScale8s32s, (BinaryFunc)cvtScale16u32s, + (BinaryFunc)cvtScale16s32s, (BinaryFunc)cvtScale32s, (BinaryFunc)cvtScale32f32s, + (BinaryFunc)cvtScale64f32s, 0 + }, + { + (BinaryFunc)cvtScale8u32f, (BinaryFunc)cvtScale8s32f, (BinaryFunc)cvtScale16u32f, + (BinaryFunc)cvtScale16s32f, (BinaryFunc)cvtScale32s32f, (BinaryFunc)cvtScale32f, + (BinaryFunc)cvtScale64f32f, 0 + }, + { + (BinaryFunc)cvtScale8u64f, (BinaryFunc)cvtScale8s64f, (BinaryFunc)cvtScale16u64f, + (BinaryFunc)cvtScale16s64f, (BinaryFunc)cvtScale32s64f, (BinaryFunc)cvtScale32f64f, + (BinaryFunc)cvtScale64f, 0 + }, + { + 0, 0, 0, 0, 0, 0, 0, 0 + } +}; -void convertScaleAbs( const Mat& src0, Mat& dst, double scale, double shift ) +static BinaryFunc cvtTab[][8] = { - static CvtScaleFunc tab[] = { - cvtScaleLUT_ >, - cvtScaleLUT_ >, - cvtScaleInt_, OpCvtAbs, 0>, - cvtScaleInt_, OpCvtAbs, 1<<15>, - cvtScale_ >, - cvtScale_ >, - cvtScale_ >, 0 - }; - - Mat src = src0; - dst.create( src.dims, src.size, CV_8UC(src.channels()) ); - CvtScaleFunc func = tab[src.depth()]; + (BinaryFunc)cvt8u, (BinaryFunc)cvt8s8u, (BinaryFunc)cvt16u8u, + (BinaryFunc)cvt16s8u, (BinaryFunc)cvt32s8u, (BinaryFunc)cvt32f8u, + (BinaryFunc)cvt64f8u, 0 + }, + { + (BinaryFunc)cvt8u8s, (BinaryFunc)cvt8u, (BinaryFunc)cvt16u8s, + (BinaryFunc)cvt16s8s, (BinaryFunc)cvt32s8s, (BinaryFunc)cvt32f8s, + (BinaryFunc)cvt64f8s, 0 + }, + { + (BinaryFunc)cvt8u16u, (BinaryFunc)cvt8s16u, (BinaryFunc)cvt16u, + (BinaryFunc)cvt16s16u, (BinaryFunc)cvt32s16u, (BinaryFunc)cvt32f16u, + (BinaryFunc)cvt64f16u, 0 + }, + { + (BinaryFunc)cvt8u16s, (BinaryFunc)cvt8s16s, (BinaryFunc)cvt16u16s, + (BinaryFunc)cvt16u, (BinaryFunc)cvt32s16s, (BinaryFunc)cvt32f16s, + (BinaryFunc)cvt64f16s, 0 + }, + { + (BinaryFunc)cvt8u32s, (BinaryFunc)cvt8s32s, (BinaryFunc)cvt16u32s, + (BinaryFunc)cvt16s32s, (BinaryFunc)cvt32s, (BinaryFunc)cvt32f32s, + (BinaryFunc)cvt64f32s, 0 + }, + { + (BinaryFunc)cvt8u32f, (BinaryFunc)cvt8s32f, (BinaryFunc)cvt16u32f, + (BinaryFunc)cvt16s32f, (BinaryFunc)cvt32s32f, (BinaryFunc)cvt32s, + (BinaryFunc)cvt64f32f, 0 + }, + { + (BinaryFunc)cvt8u64f, (BinaryFunc)cvt8s64f, (BinaryFunc)cvt16u64f, + (BinaryFunc)cvt16s64f, (BinaryFunc)cvt32s64f, (BinaryFunc)cvt32f64f, + (BinaryFunc)cvt64s, 0 + }, + { + 0, 0, 0, 0, 0, 0, 0, 0 + } +}; + +BinaryFunc getConvertFunc(int sdepth, int ddepth) +{ + return cvtTab[CV_MAT_DEPTH(ddepth)][CV_MAT_DEPTH(sdepth)]; +} + +BinaryFunc getConvertScaleFunc(int sdepth, int ddepth) +{ + return cvtScaleTab[CV_MAT_DEPTH(ddepth)][CV_MAT_DEPTH(sdepth)]; +} + +} + +void cv::convertScaleAbs( const InputArray& _src, OutputArray _dst, double alpha, double beta ) +{ + Mat src = _src.getMat(); + int cn = src.channels(); + double scale[] = {alpha, beta}; + _dst.create( src.dims, src.size, CV_8UC(cn) ); + Mat dst = _dst.getMat(); + BinaryFunc func = cvtScaleAbsTab[src.depth()]; CV_Assert( func != 0 ); if( src.dims <= 2 ) { - func( src, dst, scale, shift ); + Size sz = getContinuousSize(src, dst, cn); + func( src.data, src.step, 0, 0, dst.data, dst.step, sz, scale ); } else { const Mat* arrays[] = {&src, &dst, 0}; - Mat planes[2]; - NAryMatIterator it(arrays, planes); + uchar* ptrs[2]; + NAryMatIterator it(arrays, ptrs); + Size sz((int)it.size*cn, 1); - for( int i = 0; i < it.nplanes; i++, ++it ) - func(it.planes[0], it.planes[1], scale, shift); + for( size_t i = 0; i < it.nplanes; i++, ++it ) + func( ptrs[0], 0, 0, 0, ptrs[1], 0, sz, scale ); } } - -void Mat::convertTo(Mat& dst, int _type, double alpha, double beta) const +void cv::Mat::convertTo(OutputArray _dst, int _type, double alpha, double beta) const { - static CvtFunc tab[8][8] = - { - {0, cvt_, cvt_, cvt_, - cvt_, cvt_, cvt_, 0}, - - {cvt_, 0, cvt_, cvt_, - cvt_, cvt_, cvt_, 0}, - - {cvt_, cvt_, 0, cvt_, - cvt_, cvt_, cvt_, 0}, - - {cvt_, cvt_, cvt_, 0, - cvt_, cvt_, cvt_, 0}, - - {cvt_, cvt_, cvt_, - cvt_, 0, cvt_, cvt_, 0}, - - {cvt_, cvt_, cvt_, - cvt_, cvt_, 0, cvt_, 0}, - - {cvt_, cvt_, cvt_, - cvt_, cvt_, cvt_, 0, 0}, - - {0,0,0,0,0,0,0,0} - }; - - static CvtScaleFunc stab[8][8] = - { - { - cvtScaleLUT_ >, - cvtScaleLUT_ >, - cvtScaleLUT_ >, - cvtScaleLUT_ >, - cvtScaleLUT_ >, - cvtScaleLUT_ >, - cvtScaleLUT_ >, 0 - }, - - { - // this is copy of the above section, - // since cvScaleLUT handles both 8u->? and 8s->? cases - cvtScaleLUT_ >, - cvtScaleLUT_ >, - cvtScaleLUT_ >, - cvtScaleLUT_ >, - cvtScaleLUT_ >, - cvtScaleLUT_ >, - cvtScaleLUT_ >, 0, - }, - - { - cvtScaleInt_, OpCvt, 0>, - cvtScaleInt_, OpCvt, 0>, - cvtScaleInt_, OpCvt, 0>, - cvtScaleInt_, OpCvt, 0>, - cvtScale_ >, - cvtScale_ >, - cvtScale_ >, 0, - }, - - { - cvtScaleInt_, OpCvt, 1<<15>, - cvtScaleInt_, OpCvt, 1<<15>, - cvtScaleInt_, OpCvt, 1<<15>, - cvtScaleInt_, OpCvt, 1<<15>, - cvtScale_ >, - cvtScale_ >, - cvtScale_ >, 0, - }, - - { - cvtScale_ >, - cvtScale_ >, - cvtScale_ >, - cvtScale_ >, - cvtScale_ >, - cvtScale_ >, - cvtScale_ >, 0, - }, - - { - cvtScale_ >, - cvtScale_ >, - cvtScale_ >, - cvtScale_ >, - cvtScale_ >, - cvtScale_ >, - cvtScale_ >, 0, - }, - - { - cvtScale_ >, - cvtScale_ >, - cvtScale_ >, - cvtScale_ >, - cvtScale_ >, - cvtScale_ >, - cvtScale_ >, 0, - } - }; - bool noScale = fabs(alpha-1) < DBL_EPSILON && fabs(beta) < DBL_EPSILON; if( _type < 0 ) - _type = type(); + _type = _dst.fixedType() ? _dst.type() : type(); else _type = CV_MAKETYPE(CV_MAT_DEPTH(_type), channels()); int sdepth = depth(), ddepth = CV_MAT_DEPTH(_type); if( sdepth == ddepth && noScale ) { - copyTo(dst); + copyTo(_dst); return; } - Mat temp; - const Mat* psrc = this; - if( sdepth != ddepth && data == dst.data ) - psrc = &(temp = *this); + Mat src = *this; - CvtFunc func = 0; - CvtScaleFunc scaleFunc = 0; - - if( noScale ) - { - func = tab[sdepth][ddepth]; - CV_Assert( func != 0 ); - } - else - { - scaleFunc = stab[sdepth][ddepth]; - CV_Assert( scaleFunc != 0 ); - } + BinaryFunc func = noScale ? getConvertFunc(sdepth, ddepth) : getConvertScaleFunc(sdepth, ddepth); + double scale[] = {alpha, beta}; + int cn = channels(); + CV_Assert( func != 0 ); if( dims <= 2 ) { - dst.create( size(), _type ); - if( func ) - func( *psrc, dst ); - else - scaleFunc( *psrc, dst, alpha, beta ); + _dst.create( size(), _type ); + Mat dst = _dst.getMat(); + Size sz = getContinuousSize(src, dst, cn); + func( src.data, src.step, 0, 0, dst.data, dst.step, sz, scale ); } else { - dst.create( dims, size, _type ); - const Mat* arrays[] = {psrc, &dst, 0}; - Mat planes[2]; - NAryMatIterator it(arrays, planes); + _dst.create( dims, size, _type ); + Mat dst = _dst.getMat(); + const Mat* arrays[] = {&src, &dst, 0}; + uchar* ptrs[2]; + NAryMatIterator it(arrays, ptrs); + Size sz((int)(it.size*cn), 1); - for( int i = 0; i < it.nplanes; i++, ++it ) - { - if( func ) - func(it.planes[0], it.planes[1]); - else - scaleFunc(it.planes[0], it.planes[1], alpha, beta); - } - } + for( size_t i = 0; i < it.nplanes; i++, ++it ) + func(ptrs[0], 0, 0, 0, ptrs[1], 0, sz, scale); + } } /****************************************************************************************\ * LUT Transform * \****************************************************************************************/ -template static void -LUT8u( const Mat& srcmat, Mat& dstmat, const Mat& lut ) +namespace cv { - int cn = lut.channels(); - int max_block_size = (1 << 10)*cn; - const T* _lut = (const T*)lut.data; - T lutp[4][256]; - int y, i, k; - Size size = getContinuousSize( srcmat, dstmat, srcmat.channels() ); +template static void +LUT8u_( const uchar* src, const T* lut, T* dst, int len, int cn ) +{ if( cn == 1 ) { - for( y = 0; y < size.height; y++ ) - { - const uchar* src = srcmat.data + srcmat.step*y; - T* dst = (T*)(dstmat.data + dstmat.step*y); - - for( i = 0; i < size.width; i++ ) - dst[i] = _lut[src[i]]; - } - return; + for( int i = 0; i < len; i++ ) + dst[i] = lut[src[i]]; } - - if( size.width*size.height < 256 ) + else { - for( y = 0; y < size.height; y++ ) - { - const uchar* src = srcmat.data + srcmat.step*y; - T* dst = (T*)(dstmat.data + dstmat.step*y); - - for( k = 0; k < cn; k++ ) - for( i = 0; i < size.width; i += cn ) - dst[i+k] = _lut[src[i+k]*cn+k]; - } - return; + for( int i = 0; i < len*cn; i += cn ) + for( int k = 0; k < cn; k++ ) + dst[i+k] = lut[src[i+k]*cn+k]; } +} - /* repack the lut to planar layout */ - for( k = 0; k < cn; k++ ) - for( i = 0; i < 256; i++ ) - lutp[k][i] = _lut[i*cn+k]; +static void LUT8u_8u( const uchar* src, const uchar* lut, uchar* dst, int len, int cn ) +{ + LUT8u_( src, lut, dst, len, cn ); +} - for( y = 0; y < size.height; y++ ) - { - const uchar* src = srcmat.data + srcmat.step*y; - T* dst = (T*)(dstmat.data + dstmat.step*y); +static void LUT8u_8s( const uchar* src, const schar* lut, schar* dst, int len, int cn ) +{ + LUT8u_( src, lut, dst, len, cn ); +} - for( i = 0; i < size.width; ) - { - int j, limit = std::min(size.width, i + max_block_size); - for( k = 0; k < cn; k++, src++, dst++ ) - { - const T* lut = lutp[k]; - for( j = i; j <= limit - cn*2; j += cn*2 ) - { - T t0 = lut[src[j]]; - T t1 = lut[src[j+cn]]; - dst[j] = t0; dst[j+cn] = t1; - } +static void LUT8u_16u( const uchar* src, const ushort* lut, ushort* dst, int len, int cn ) +{ + LUT8u_( src, lut, dst, len, cn ); +} - for( ; j < limit; j += cn ) - dst[j] = lut[src[j]]; - } - src -= cn; - dst -= cn; - i = limit; - } - } +static void LUT8u_16s( const uchar* src, const short* lut, short* dst, int len, int cn ) +{ + LUT8u_( src, lut, dst, len, cn ); } -typedef void (*LUTFunc)( const Mat& src, Mat& dst, const Mat& lut ); +static void LUT8u_32s( const uchar* src, const int* lut, int* dst, int len, int cn ) +{ + LUT8u_( src, lut, dst, len, cn ); +} + +static void LUT8u_32f( const uchar* src, const float* lut, float* dst, int len, int cn ) +{ + LUT8u_( src, lut, dst, len, cn ); +} + +static void LUT8u_64f( const uchar* src, const double* lut, double* dst, int len, int cn ) +{ + LUT8u_( src, lut, dst, len, cn ); +} + +typedef void (*LUTFunc)( const uchar* src, const uchar* lut, uchar* dst, int len, int cn ); + +static LUTFunc lutTab[] = +{ + (LUTFunc)LUT8u_8u, (LUTFunc)LUT8u_8s, (LUTFunc)LUT8u_16u, (LUTFunc)LUT8u_16s, + (LUTFunc)LUT8u_32s, (LUTFunc)LUT8u_32f, (LUTFunc)LUT8u_64f, 0 +}; -void LUT( const Mat& src, const Mat& lut, Mat& dst ) +} + +void cv::LUT( const InputArray& _src, const InputArray& _lut, OutputArray _dst, int interpolation ) { - int cn = src.channels(), esz1 = (int)lut.elemSize1(); + Mat src = _src.getMat(), lut = _lut.getMat(); + CV_Assert( interpolation == 0 ); + int cn = src.channels(); CV_Assert( (lut.channels() == cn || lut.channels() == 1) && - lut.rows*lut.cols == 256 && lut.isContinuous() && + lut.total() == 256 && lut.isContinuous() && (src.depth() == CV_8U || src.depth() == CV_8S) ); - dst.create( src.size(), CV_MAKETYPE(lut.depth(), cn)); - - LUTFunc func = 0; - if( esz1 == 1 ) - func = LUT8u; - else if( esz1 == 2 ) - func = LUT8u; - else if( esz1 == 4 ) - func = LUT8u; - else if( esz1 == 8 ) - func = LUT8u; - else - CV_Error(CV_StsUnsupportedFormat, ""); - func( src, dst, lut ); + _dst.create( src.dims, src.size, CV_MAKETYPE(lut.depth(), cn)); + Mat dst = _dst.getMat(); + + LUTFunc func = lutTab[src.depth()]; + CV_Assert( func != 0 ); + + const Mat* arrays[] = {&src, &dst, 0}; + uchar* ptrs[2]; + NAryMatIterator it(arrays, ptrs); + int len = (int)it.size; + + for( size_t i = 0; i < it.nplanes; i++, ++it ) + func(ptrs[0], lut.data, ptrs[1], len, cn); } -void normalize( const Mat& src, Mat& dst, double a, double b, - int norm_type, int rtype, const Mat& mask ) +void cv::normalize( const InputArray& _src, OutputArray _dst, double a, double b, + int norm_type, int rtype, const InputArray& _mask ) { + Mat src = _src.getMat(), mask = _mask.getMat(); + double scale = 1, shift = 0; if( norm_type == CV_MINMAX ) { double smin = 0, smax = 0; double dmin = MIN( a, b ), dmax = MAX( a, b ); - minMaxLoc( src, &smin, &smax, 0, 0, mask ); + minMaxLoc( _src, &smin, &smax, 0, 0, mask ); scale = (dmax - dmin)*(smax - smin > DBL_EPSILON ? 1./(smax - smin) : 0); shift = dmin - smin*scale; } @@ -935,6 +1038,12 @@ void normalize( const Mat& src, Mat& dst, double a, double b, else CV_Error( CV_StsBadArg, "Unknown/unsupported norm type" ); + if( rtype < 0 ) + rtype = _dst.fixedType() ? _dst.depth() : src.depth(); + + _dst.create(src.dims, src.size, CV_MAKETYPE(rtype, src.channels())); + Mat dst = _dst.getMat(); + if( !mask.data ) src.convertTo( dst, rtype, scale, shift ); else @@ -945,8 +1054,6 @@ void normalize( const Mat& src, Mat& dst, double a, double b, } } -} - CV_IMPL void cvSplit( const void* srcarr, void* dstarr0, void* dstarr1, void* dstarr2, void* dstarr3 ) { diff --git a/modules/core/src/copy.cpp b/modules/core/src/copy.cpp index e3e567298b..e2ab4f12e6 100644 --- a/modules/core/src/copy.cpp +++ b/modules/core/src/copy.cpp @@ -11,7 +11,7 @@ // For Open Source Computer Vision Library // // Copyright (C) 2000-2008, Intel Corporation, all rights reserved. -// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2009-2011, Willow Garage Inc., all rights reserved. // Third party copyrights are property of their respective owners. // // Redistribution and use in source and binary forms, with or without modification, @@ -52,18 +52,12 @@ namespace cv { template static void -copyMask_(const Mat& srcmat, Mat& dstmat, const Mat& maskmat) +copyMask_(const uchar* _src, size_t sstep, const uchar* mask, size_t mstep, uchar* _dst, size_t dstep, Size size) { - const uchar* mask = maskmat.data; - size_t sstep = srcmat.step; - size_t dstep = dstmat.step; - size_t mstep = maskmat.step; - Size size = getContinuousSize(srcmat, dstmat, maskmat); - - for( int y = 0; y < size.height; y++, mask += mstep ) + for( ; size.height--; mask += mstep, _src += sstep, _dst += dstep ) { - const T* src = (const T*)(srcmat.data + sstep*y); - T* dst = (T*)(dstmat.data + dstep*y); + const T* src = (const T*)_src; + T* dst = (T*)_dst; int x = 0; for( ; x <= size.width - 4; x += 4 ) { @@ -82,389 +76,397 @@ copyMask_(const Mat& srcmat, Mat& dstmat, const Mat& maskmat) } } -template static void -setMask_(const void* _scalar, Mat& dstmat, const Mat& maskmat) +static void +copyMaskGeneric(const uchar* _src, size_t sstep, const uchar* mask, size_t mstep, uchar* _dst, size_t dstep, Size size, void* _esz) { - T scalar = *(T*)_scalar; - const uchar* mask = maskmat.data; - size_t dstep = dstmat.step; - size_t mstep = maskmat.step; - Size size = dstmat.size(); - - if( dstmat.isContinuous() && maskmat.isContinuous() ) + size_t k, esz = *(size_t*)_esz; + for( ; size.height--; mask += mstep, _src += sstep, _dst += dstep ) { - size.width *= size.height; - size.height = 1; + const uchar* src = _src; + uchar* dst = _dst; + int x = 0; + for( ; x < size.width; x++, src += esz, dst += esz ) + { + if( !mask[x] ) + continue; + for( k = 0; k < esz; k++ ) + dst[k] = src[k]; + } } - - for( int y = 0; y < size.height; y++, mask += mstep ) +} + +template static void +setMask_(T value, const uchar* mask, size_t mstep, uchar* _dst, size_t dstep, Size size) +{ + for( ; size.height--; mask += mstep, _dst += dstep ) { - T* dst = (T*)(dstmat.data + dstep*y); + T* dst = (T*)_dst; int x = 0; for( ; x <= size.width - 4; x += 4 ) { if( mask[x] ) - dst[x] = scalar; + dst[x] = value; if( mask[x+1] ) - dst[x+1] = scalar; + dst[x+1] = value; if( mask[x+2] ) - dst[x+2] = scalar; + dst[x+2] = value; if( mask[x+3] ) - dst[x+3] = scalar; + dst[x+3] = value; } for( ; x < size.width; x++ ) if( mask[x] ) - dst[x] = scalar; + dst[x] = value; } } -typedef void (*SetMaskFunc)(const void* scalar, Mat& dst, const Mat& mask); - -CopyMaskFunc g_copyMaskFuncTab[] = +static void +setMaskGeneric(const uchar* value, size_t, const uchar* mask, size_t mstep, uchar* _dst, size_t dstep, Size size, void* _esz) +{ + size_t k, esz = *(size_t*)_esz; + for( ; size.height--; mask += mstep, _dst += dstep ) + { + uchar* dst = _dst; + int x = 0; + for( ; x < size.width; x++, dst += esz ) + { + if( !mask[x] ) + continue; + for( k = 0; k < esz; k++ ) + dst[k] = value[k]; + } + } +} + +#define DEF_COPY_SET_MASK(suffix, type) \ +static void copyMask##suffix(const uchar* src, size_t sstep, const uchar* mask, size_t mstep, \ + uchar* dst, size_t dstep, Size size, void*) \ +{ \ + copyMask_(src, sstep, mask, mstep, dst, dstep, size); \ +} \ +static void setMask##suffix( const uchar* src, size_t, const uchar* mask, size_t mstep, \ + uchar* dst, size_t dstep, Size size, void*) \ +{ \ + setMask_(*(const type*)src, mask, mstep, dst, dstep, size); \ +} + + +DEF_COPY_SET_MASK(8u, uchar); +DEF_COPY_SET_MASK(16u, ushort); +DEF_COPY_SET_MASK(8uC3, Vec3b); +DEF_COPY_SET_MASK(32s, int); +DEF_COPY_SET_MASK(16uC3, Vec3s); +DEF_COPY_SET_MASK(32sC2, Vec2i); +DEF_COPY_SET_MASK(32sC3, Vec3i); +DEF_COPY_SET_MASK(32sC4, Vec4i); +DEF_COPY_SET_MASK(32sC6, Vec6i); +DEF_COPY_SET_MASK(32sC8, Vec8i); + +BinaryFunc copyMaskTab[] = { 0, - copyMask_, // 1 - copyMask_, // 2 - copyMask_ >, // 3 - copyMask_, // 4 + copyMask8u, + copyMask16u, + copyMask8uC3, + copyMask32s, 0, - copyMask_ >, // 6 + copyMask16uC3, 0, - copyMask_ >, // 8 + copyMask32sC2, 0, 0, 0, - copyMask_ >, // 12 + copyMask32sC3, 0, 0, 0, - copyMask_ >, // 16 + copyMask32sC4, 0, 0, 0, 0, 0, 0, 0, - copyMask_ >, // 24 + copyMask32sC6, 0, 0, 0, 0, 0, 0, 0, - copyMask_ > // 32 + copyMask32sC8 }; -static SetMaskFunc setMaskFuncTab[] = +BinaryFunc setMaskTab[] = { 0, - setMask_, // 1 - setMask_, // 2 - setMask_ >, // 3 - setMask_, // 4 + setMask8u, + setMask16u, + setMask8uC3, + setMask32s, 0, - setMask_ >, // 6 + setMask16uC3, 0, - setMask_ >, // 8 + setMask32sC2, 0, 0, 0, - setMask_ >, // 12 + setMask32sC3, 0, 0, 0, - setMask_ >, // 16 + setMask32sC4, 0, 0, 0, 0, 0, 0, 0, - setMask_ >, // 24 + setMask32sC6, 0, 0, 0, 0, 0, 0, 0, - setMask_ > // 32 -}; - + setMask32sC8 +}; + +BinaryFunc getCopyMaskFunc(size_t esz) +{ + return esz <= 32 && copyMaskTab[esz] ? copyMaskTab[esz] : copyMaskGeneric; +} /* dst = src */ -void Mat::copyTo( Mat& dst ) const +void Mat::copyTo( OutputArray _dst ) const { - if( data == dst.data && data != 0 ) + int dtype = _dst.type(); + if( _dst.fixedType() && dtype != type() ) + { + convertTo( _dst, dtype ); + return; + } + + if( empty() ) + { + _dst.release(); return; + } - if( dims > 2 ) + if( dims <= 2 ) { - dst.create( dims, size, type() ); - if( total() != 0 ) - { - const Mat* arrays[] = { this, &dst, 0 }; - Mat planes[2]; - NAryMatIterator it(arrays, planes); - CV_DbgAssert(it.planes[0].isContinuous() && - it.planes[1].isContinuous()); - size_t planeSize = it.planes[0].elemSize()*it.planes[0].rows*it.planes[0].cols; + _dst.create( rows, cols, type() ); + Mat dst = _dst.getMat(); + if( data == dst.data ) + return; - for( int i = 0; i < it.nplanes; i++, ++it ) - memcpy(it.planes[1].data, it.planes[0].data, planeSize); + if( rows > 0 && cols > 0 ) + { + const uchar* sptr = data; + uchar* dptr = dst.data; + + Size sz = getContinuousSize(*this, dst, (int)elemSize()); + for( ; sz.height--; sptr += step, dptr += dst.step ) + memcpy( dptr, sptr, sz.width ); } return; } - dst.create( rows, cols, type() ); - Size sz = size(); + _dst.create( dims, size, type() ); + Mat dst = _dst.getMat(); + if( data == dst.data ) + return; - if( rows > 0 && cols > 0 ) + if( total() != 0 ) { - const uchar* sptr = data; - uchar* dptr = dst.data; - - size_t width = sz.width*elemSize(); - if( isContinuous() && dst.isContinuous() ) - { - width *= sz.height; - sz.height = 1; - } - - for( ; sz.height--; sptr += step, dptr += dst.step ) - memcpy( dptr, sptr, width ); + const Mat* arrays[] = { this, &dst }; + uchar* ptrs[2]; + NAryMatIterator it(arrays, ptrs, 2); + size_t size = it.size*elemSize(); + + for( size_t i = 0; i < it.nplanes; i++, ++it ) + memcpy(ptrs[1], ptrs[0], size); } } -void Mat::copyTo( Mat& dst, const Mat& mask ) const +void Mat::copyTo( OutputArray _dst, const InputArray& _mask ) const { + Mat mask = _mask.getMat(); if( !mask.data ) { - copyTo(dst); + copyTo(_dst); return; } - if( dims > 2 ) + CV_Assert( mask.type() == CV_8U ); + + size_t esz = elemSize(); + BinaryFunc copymask = getCopyMaskFunc(esz); + + uchar* data0 = _dst.getMat().data; + _dst.create( dims, size, type() ); + Mat dst = _dst.getMat(); + + if( dst.data != data0 ) // do not leave dst uninitialized + dst = Scalar(0); + + if( dims <= 2 ) { - dst.create( dims, size, type() ); - const Mat* arrays[] = { this, &dst, &mask, 0 }; - Mat planes[3]; - NAryMatIterator it(arrays, planes); - - for( int i = 0; i < it.nplanes; i++, ++it ) - it.planes[0].copyTo(it.planes[1], it.planes[2]); + Size sz = getContinuousSize(*this, dst, mask); + copymask(data, step, mask.data, mask.step, dst.data, dst.step, sz, &esz); return; } - - uchar* data0 = dst.data; - dst.create( size(), type() ); - if( dst.data != data0 ) // do not leave dst uninitialized - dst = Scalar(0); - getCopyMaskFunc((int)elemSize())(*this, dst, mask); + + const Mat* arrays[] = { this, &dst, &mask, 0 }; + uchar* ptrs[3]; + NAryMatIterator it(arrays, ptrs); + Size sz((int)it.size, 1); + + for( size_t i = 0; i < it.nplanes; i++, ++it ) + copymask(ptrs[0], 0, ptrs[2], 0, ptrs[1], 0, sz, &esz); } Mat& Mat::operator = (const Scalar& s) { - if( dims > 2 ) - { - const Mat* arrays[] = { this, 0 }; - Mat planes[1]; - NAryMatIterator it(arrays, planes); - - for( int i = 0; i < it.nplanes; i++, ++it ) - it.planes[0] = s; - return *this; - } - - Size sz = size(); - uchar* dst = data; - - sz.width *= (int)elemSize(); - if( isContinuous() ) - { - sz.width *= sz.height; - sz.height = 1; - } + const Mat* arrays[] = { this }; + uchar* ptr; + NAryMatIterator it(arrays, &ptr, 1); + size_t size = it.size*elemSize(); if( s[0] == 0 && s[1] == 0 && s[2] == 0 && s[3] == 0 ) { - for( ; sz.height--; dst += step ) - memset( dst, 0, sz.width ); + for( size_t i = 0; i < it.nplanes; i++, ++it ) + memset( ptr, 0, size ); } else { - int t = type(), esz1 = (int)elemSize1(); - double scalar[12]; - scalarToRawData(s, scalar, t, 12); - int copy_len = 12*esz1; - uchar* dst_limit = dst + sz.width; - - if( sz.height-- ) + if( it.nplanes > 0 ) { - while( dst + copy_len <= dst_limit ) + double scalar[12]; + scalarToRawData(s, scalar, type(), 12); + size_t blockSize = 12*elemSize1(); + + for( size_t j = 0; j < size; j += blockSize ) { - memcpy( dst, scalar, copy_len ); - dst += copy_len; + size_t sz = std::min(blockSize, size - j); + memcpy( ptr + j, scalar, sz ); } - memcpy( dst, scalar, dst_limit - dst ); } - - if( sz.height > 0 ) + + for( size_t i = 1; i < it.nplanes; i++ ) { - dst = dst_limit - sz.width + step; - for( ; sz.height--; dst += step ) - memcpy( dst, data, sz.width ); + ++it; + memcpy( ptr, data, size ); } } return *this; } -Mat& Mat::setTo(const Scalar& s, const Mat& mask) +Mat& Mat::setTo(const Scalar& s, const InputArray& _mask) { + Mat mask = _mask.getMat(); if( !mask.data ) *this = s; else { - CV_Assert( channels() <= 4 ); - SetMaskFunc func = setMaskFuncTab[elemSize()]; - CV_Assert( func != 0 ); + CV_Assert( channels() <= 4 && mask.type() == CV_8U ); + size_t esz = elemSize(); + BinaryFunc func = esz <= 32 ? setMaskTab[esz] : setMaskGeneric; double buf[4]; scalarToRawData(s, buf, type(), 0); - if( dims > 2 ) - { - const Mat* arrays[] = { this, &mask, 0 }; - Mat planes[2]; - NAryMatIterator it(arrays, planes); - - for( int i = 0; i < it.nplanes; i++, ++it ) - func(buf, it.planes[0], it.planes[1]); - } - else - func(buf, *this, mask); + const Mat* arrays[] = { this, &mask, 0 }; + uchar* ptrs[2]; + NAryMatIterator it(arrays, ptrs); + Size sz((int)it.size, 1); + + for( size_t i = 0; i < it.nplanes; i++, ++it ) + func((const uchar*)buf, 0, ptrs[1], 0, ptrs[0], 0, sz, &esz); } return *this; } -template static void -flipHoriz_( const Mat& srcmat, Mat& dstmat, bool flipv ) +static void +flipHoriz( const uchar* src, size_t sstep, uchar* dst, size_t dstep, Size size, size_t esz ) { - uchar* dst0 = dstmat.data; - size_t srcstep = srcmat.step; - int dststep = (int)dstmat.step; - Size size = srcmat.size(); - - if( flipv ) - { - dst0 += (size.height - 1)*dststep; - dststep = -dststep; - } + int i, j, limit = ((size.width + 1)/2)*esz; + AutoBuffer _tab(size.width*esz); + int* tab = _tab; + + for( i = 0; i < size.width; i++ ) + for( size_t k = 0; k < esz; k++ ) + tab[i*esz + k] = (size.width - i - 1)*esz + k; - for( int y = 0; y < size.height; y++ ) + for( ; size.height--; src += sstep, dst += dstep ) { - const T* src = (const T*)(srcmat.data + srcstep*y); - T* dst = (T*)(dst0 + dststep*y); - - for( int i = 0; i < (size.width + 1)/2; i++ ) + for( i = 0; i < limit; i++ ) { - T t0 = src[i], t1 = src[size.width - i - 1]; - dst[i] = t1; dst[size.width - i - 1] = t0; + j = tab[i]; + uchar t0 = src[i], t1 = src[j]; + dst[i] = t1; dst[j] = t0; } } } -typedef void (*FlipHorizFunc)( const Mat& src, Mat& dst, bool flipv ); - static void -flipVert( const Mat& srcmat, Mat& dstmat ) +flipVert( const uchar* src0, size_t sstep, uchar* dst0, size_t dstep, Size size, size_t esz ) { - const uchar* src = srcmat.data; - uchar* dst = dstmat.data; - size_t srcstep = srcmat.step, dststep = dstmat.step; - Size size = srcmat.size(); - const uchar* src1 = src + (size.height - 1)*srcstep; - uchar* dst1 = dst + (size.height - 1)*dststep; - size.width *= (int)srcmat.elemSize(); - - for( int y = 0; y < (size.height + 1)/2; y++, src += srcstep, src1 -= srcstep, - dst += dststep, dst1 -= dststep ) + const uchar* src1 = src0 + (size.height - 1)*sstep; + uchar* dst1 = dst0 + (size.height - 1)*dstep; + size.width *= (int)esz; + + for( int y = 0; y < (size.height + 1)/2; y++, src0 += sstep, src1 -= sstep, + dst0 += dstep, dst1 -= dstep ) { int i = 0; - if( ((size_t)(src)|(size_t)(dst)|(size_t)src1|(size_t)dst1) % sizeof(int) == 0 ) + if( ((size_t)src0|(size_t)dst0|(size_t)src1|(size_t)dst1) % sizeof(int) == 0 ) { for( ; i <= size.width - 16; i += 16 ) { - int t0 = ((int*)(src + i))[0]; + int t0 = ((int*)(src0 + i))[0]; int t1 = ((int*)(src1 + i))[0]; - ((int*)(dst + i))[0] = t1; + ((int*)(dst0 + i))[0] = t1; ((int*)(dst1 + i))[0] = t0; - t0 = ((int*)(src + i))[1]; + t0 = ((int*)(src0 + i))[1]; t1 = ((int*)(src1 + i))[1]; - ((int*)(dst + i))[1] = t1; + ((int*)(dst0 + i))[1] = t1; ((int*)(dst1 + i))[1] = t0; - t0 = ((int*)(src + i))[2]; + t0 = ((int*)(src0 + i))[2]; t1 = ((int*)(src1 + i))[2]; - ((int*)(dst + i))[2] = t1; + ((int*)(dst0 + i))[2] = t1; ((int*)(dst1 + i))[2] = t0; - t0 = ((int*)(src + i))[3]; + t0 = ((int*)(src0 + i))[3]; t1 = ((int*)(src1 + i))[3]; - ((int*)(dst + i))[3] = t1; + ((int*)(dst0 + i))[3] = t1; ((int*)(dst1 + i))[3] = t0; } for( ; i <= size.width - 4; i += 4 ) { - int t0 = ((int*)(src + i))[0]; + int t0 = ((int*)(src0 + i))[0]; int t1 = ((int*)(src1 + i))[0]; - ((int*)(dst + i))[0] = t1; + ((int*)(dst0 + i))[0] = t1; ((int*)(dst1 + i))[0] = t0; } } for( ; i < size.width; i++ ) { - uchar t0 = src[i]; + uchar t0 = src0[i]; uchar t1 = src1[i]; - dst[i] = t1; + dst0[i] = t1; dst1[i] = t0; } } } -void flip( const Mat& src, Mat& dst, int flip_mode ) +void flip( const InputArray& _src, OutputArray _dst, int flip_mode ) { - static FlipHorizFunc tab[] = - { - 0, - flipHoriz_, // 1 - flipHoriz_, // 2 - flipHoriz_ >, // 3 - flipHoriz_, // 4 - 0, - flipHoriz_ >, // 6 - 0, - flipHoriz_ >, // 8 - 0, 0, 0, - flipHoriz_ >, // 12 - 0, 0, 0, - flipHoriz_ >, // 16 - 0, 0, 0, 0, 0, 0, 0, - flipHoriz_ >, // 24 - 0, 0, 0, 0, 0, 0, 0, - flipHoriz_ > // 32 - }; + Mat src = _src.getMat(); CV_Assert( src.dims <= 2 ); - dst.create( src.size(), src.type() ); + _dst.create( src.size(), src.type() ); + Mat dst = _dst.getMat(); + size_t esz = src.elemSize(); - if( flip_mode == 0 ) - flipVert( src, dst ); + if( flip_mode <= 0 ) + flipVert( src.data, src.step, dst.data, dst.step, src.size(), esz ); else - { - int esz = (int)src.elemSize(); - CV_Assert( esz <= 32 ); - FlipHorizFunc func = tab[esz]; - CV_Assert( func != 0 ); - - if( flip_mode > 0 ) - func( src, dst, false ); - else if( src.data != dst.data ) - func( src, dst, true ); - else - { - func( dst, dst, false ); - flipVert( dst, dst ); - } - } + flipHoriz( src.data, src.step, dst.data, dst.step, src.size(), esz ); + + if( flip_mode < 0 ) + flipHoriz( dst.data, dst.step, dst.data, dst.step, dst.size(), esz ); } -void repeat(const Mat& src, int ny, int nx, Mat& dst) +void repeat(const InputArray& _src, int ny, int nx, OutputArray _dst) { + Mat src = _src.getMat(); CV_Assert( src.dims <= 2 ); - dst.create(src.rows*ny, src.cols*nx, src.type()); + _dst.create(src.rows*ny, src.cols*nx, src.type()); + Mat dst = _dst.getMat(); Size ssize = src.size(), dsize = dst.size(); int esz = (int)src.elemSize(); int x, y; @@ -524,7 +526,7 @@ cvCopy( const void* srcarr, void* dstarr, const void* maskarr ) { CvSparseNode* node_copy = (CvSparseNode*)cvSetNew( dst1->heap ); int tabidx = node->hashval & (dst1->hashsize - 1); - CV_MEMCPY_AUTO( node_copy, node, dst1->heap->elem_size ); + memcpy( node_copy, node, dst1->heap->elem_size ); node_copy->next = (CvSparseNode*)dst1->hashtable[tabidx]; dst1->hashtable[tabidx] = node_copy; } diff --git a/modules/core/src/datastructs.cpp b/modules/core/src/datastructs.cpp index 535c9a30a0..330e400f84 100644 --- a/modules/core/src/datastructs.cpp +++ b/modules/core/src/datastructs.cpp @@ -1146,7 +1146,7 @@ cvSeqPush( CvSeq *seq, const void *element ) } if( element ) - CV_MEMCPY_AUTO( ptr, element, elem_size ); + memcpy( ptr, element, elem_size ); seq->first->prev->count++; seq->total++; seq->ptr = ptr + elem_size; @@ -1171,7 +1171,7 @@ cvSeqPop( CvSeq *seq, void *element ) seq->ptr = ptr = seq->ptr - elem_size; if( element ) - CV_MEMCPY_AUTO( element, ptr, elem_size ); + memcpy( element, ptr, elem_size ); seq->ptr = ptr; seq->total--; @@ -1208,7 +1208,7 @@ cvSeqPushFront( CvSeq *seq, const void *element ) ptr = block->data -= elem_size; if( element ) - CV_MEMCPY_AUTO( ptr, element, elem_size ); + memcpy( ptr, element, elem_size ); block->count++; block->start_index--; seq->total++; @@ -1233,7 +1233,7 @@ cvSeqPopFront( CvSeq *seq, void *element ) block = seq->first; if( element ) - CV_MEMCPY_AUTO( element, block->data, elem_size ); + memcpy( element, block->data, elem_size ); block->data += elem_size; block->start_index++; seq->total--; @@ -1708,7 +1708,7 @@ cvSeqRemoveSlice( CvSeq* seq, CvSlice slice ) for( i = 0; i < count; i++ ) { - CV_MEMCPY_AUTO( reader_to.ptr, reader_from.ptr, elem_size ); + memcpy( reader_to.ptr, reader_from.ptr, elem_size ); CV_NEXT_SEQ_ELEM( elem_size, reader_to ); CV_NEXT_SEQ_ELEM( elem_size, reader_from ); } @@ -1726,7 +1726,7 @@ cvSeqRemoveSlice( CvSeq* seq, CvSlice slice ) CV_PREV_SEQ_ELEM( elem_size, reader_to ); CV_PREV_SEQ_ELEM( elem_size, reader_from ); - CV_MEMCPY_AUTO( reader_to.ptr, reader_from.ptr, elem_size ); + memcpy( reader_to.ptr, reader_from.ptr, elem_size ); } cvSeqPopMulti( seq, 0, slice.end_index - slice.start_index, 1 ); @@ -1796,7 +1796,7 @@ cvSeqInsertSlice( CvSeq* seq, int index, const CvArr* from_arr ) for( i = 0; i < index; i++ ) { - CV_MEMCPY_AUTO( reader_to.ptr, reader_from.ptr, elem_size ); + memcpy( reader_to.ptr, reader_from.ptr, elem_size ); CV_NEXT_SEQ_ELEM( elem_size, reader_to ); CV_NEXT_SEQ_ELEM( elem_size, reader_from ); } @@ -1814,7 +1814,7 @@ cvSeqInsertSlice( CvSeq* seq, int index, const CvArr* from_arr ) { CV_PREV_SEQ_ELEM( elem_size, reader_to ); CV_PREV_SEQ_ELEM( elem_size, reader_from ); - CV_MEMCPY_AUTO( reader_to.ptr, reader_from.ptr, elem_size ); + memcpy( reader_to.ptr, reader_from.ptr, elem_size ); } } @@ -1823,7 +1823,7 @@ cvSeqInsertSlice( CvSeq* seq, int index, const CvArr* from_arr ) for( i = 0; i < from_total; i++ ) { - CV_MEMCPY_AUTO( reader_to.ptr, reader_from.ptr, elem_size ); + memcpy( reader_to.ptr, reader_from.ptr, elem_size ); CV_NEXT_SEQ_ELEM( elem_size, reader_to ); CV_NEXT_SEQ_ELEM( elem_size, reader_from ); } @@ -2525,7 +2525,7 @@ cvSetAdd( CvSet* set, CvSetElem* element, CvSetElem** inserted_element ) id = free_elem->flags & CV_SET_ELEM_IDX_MASK; if( element ) - CV_MEMCPY_INT( free_elem, element, (size_t)set->elem_size/sizeof(int) ); + memcpy( free_elem, element, set->elem_size ); free_elem->flags = id; set->active_count++; @@ -2616,8 +2616,7 @@ cvGraphAddVtx( CvGraph* graph, const CvGraphVtx* _vertex, CvGraphVtx** _inserted if( vertex ) { if( _vertex ) - CV_MEMCPY_INT( vertex + 1, _vertex + 1, - (size_t)(graph->elem_size - sizeof(CvGraphVtx))/sizeof(int) ); + memcpy( vertex + 1, _vertex + 1, graph->elem_size - sizeof(CvGraphVtx) ); vertex->first = 0; index = vertex->flags; } @@ -2784,17 +2783,17 @@ cvGraphAddEdgeByPtr( CvGraph* graph, edge->next[1] = end_vtx->first; start_vtx->first = end_vtx->first = edge; - delta = (graph->edges->elem_size - sizeof(*edge))/sizeof(int); + delta = graph->edges->elem_size - sizeof(*edge); if( _edge ) { if( delta > 0 ) - CV_MEMCPY_INT( edge + 1, _edge + 1, delta ); + memcpy( edge + 1, _edge + 1, delta ); edge->weight = _edge->weight; } else { if( delta > 0 ) - CV_ZERO_INT( edge + 1, delta ); + memset( edge + 1, 0, delta ); edge->weight = 1.f; } @@ -3548,14 +3547,14 @@ KDTree::KDTree() normType = NORM_L2; } -KDTree::KDTree(const Mat& _points, bool _copyData) +KDTree::KDTree(const InputArray& _points, bool _copyData) { maxDepth = -1; normType = NORM_L2; build(_points, _copyData); } -KDTree::KDTree(const Mat& _points, const Mat& _labels, bool _copyData) +KDTree::KDTree(const InputArray& _points, const InputArray& _labels, bool _copyData) { maxDepth = -1; normType = NORM_L2; @@ -3638,14 +3637,15 @@ computeSums( const Mat& points, const size_t* ofs, int a, int b, double* sums ) } -void KDTree::build(const Mat& _points, bool _copyData) +void KDTree::build(const InputArray& _points, bool _copyData) { - build(_points, Mat(), _copyData); + build(_points, InputArray(), _copyData); } -void KDTree::build(const Mat& _points, const Mat& _labels, bool _copyData) +void KDTree::build(const InputArray& __points, const InputArray& __labels, bool _copyData) { + Mat _points = __points.getMat(), _labels = __labels.getMat(); CV_Assert(_points.type() == CV_32F && !_points.empty()); vector().swap(nodes); @@ -3744,57 +3744,6 @@ void KDTree::build(const Mat& _points, const Mat& _labels, bool _copyData) } -int KDTree::findNearest(const float* vec, int K, int emax, - vector* neighborsIdx, - Mat* neighbors, - vector* dist, - vector* labels) const -{ - K = std::min(K, points.rows); - CV_Assert(K > 0); - if(neighborsIdx) - neighborsIdx->resize(K); - if(dist) - dist->resize(K); - if(labels) - labels->resize(K); - K = findNearest(vec, K, emax, neighborsIdx ? &(*neighborsIdx)[0] : 0, - neighbors, dist ? &(*dist)[0] : 0, labels ? &(*labels)[0] : 0); - if(neighborsIdx) - neighborsIdx->resize(K); - if(dist) - dist->resize(K); - if(labels) - labels->resize(K); - return K; -} - -int KDTree::findNearest(const vector& vec, int K, int emax, - vector* neighborsIdx, - Mat* neighbors, - vector* dist, - vector* labels) const -{ - CV_Assert((int)vec.size() == points.cols); - K = std::min(K, points.rows); - CV_Assert(K > 0); - if(neighborsIdx) - neighborsIdx->resize(K); - if(dist) - dist->resize(K); - if(labels) - labels->resize(K); - K = findNearest(&vec[0], K, emax, neighborsIdx ? &(*neighborsIdx)[0] : 0, - neighbors, dist ? &(*dist)[0] : 0, labels ? &(*labels)[0] : 0); - if(neighborsIdx) - neighborsIdx->resize(K); - if(dist) - dist->resize(K); - if(labels) - labels->resize(K); - return K; -} - struct PQueueElem { PQueueElem() : dist(0), idx(0) {} @@ -3804,11 +3753,14 @@ struct PQueueElem }; -int KDTree::findNearest(const float* vec, int K, int emax, - int* _neighborsIdx, Mat* _neighbors, - float* _dist, int* _labels) const +int KDTree::findNearest(const InputArray& _vec, int K, int emax, + OutputArray _neighborsIdx, OutputArray _neighbors, + OutputArray _dist, OutputArray _labels) const { + Mat vecmat = _vec.getMat(); + CV_Assert( vecmat.isContinuous() && vecmat.type() == CV_32F && vecmat.total() == (size_t)points.cols ); + const float* vec = vecmat.ptr(); K = std::min(K, points.rows); int dims = points.cols; @@ -3929,42 +3881,43 @@ int KDTree::findNearest(const float* vec, int K, int emax, } K = std::min(K, ncount); - if( _neighborsIdx ) - { - for( i = 0; i < K; i++ ) - _neighborsIdx[i] = idx[i]; - } - if( _dist ) - { - for( i = 0; i < K; i++ ) - _dist[i] = std::sqrt(dist[i]); - } - if( _labels ) + if( _neighborsIdx.needed() ) { - for( i = 0; i < K; i++ ) - _labels[i] = labels[idx[i]]; + _neighborsIdx.create(K, 1, CV_32S, -1, true); + Mat nidx = _neighborsIdx.getMat(); + Mat(nidx.size(), CV_32S, &idx[0]).copyTo(nidx); } + if( _dist.needed() ) + sqrt(Mat(K, 1, CV_32F, dist), _dist); - if( _neighbors ) - getPoints(idx, K, *_neighbors); + if( _neighbors.needed() || _labels.needed() ) + getPoints(Mat(K, 1, CV_32S, idx), _neighbors, _labels); return K; } -void KDTree::findOrthoRange(const float* L, const float* R, - vector* neighborsIdx, - Mat* neighbors, vector* _labels) const +void KDTree::findOrthoRange(const InputArray& _lowerBound, + const InputArray& _upperBound, + OutputArray _neighborsIdx, + OutputArray _neighbors, + OutputArray _labels ) const { int dims = points.cols; + Mat lowerBound = _lowerBound.getMat(), upperBound = _upperBound.getMat(); + CV_Assert( lowerBound.size == upperBound.size && + lowerBound.isContinuous() && + upperBound.isContinuous() && + lowerBound.type() == upperBound.type() && + lowerBound.type() == CV_32F && + lowerBound.total() == (size_t)dims ); + const float* L = lowerBound.ptr(); + const float* R = upperBound.ptr(); - CV_Assert( L && R ); - - vector _idx, *idx = neighborsIdx ? neighborsIdx : &_idx; + vector idx; AutoBuffer _stack(MAX_TREE_DEPTH*2 + 1); int* stack = _stack; int top = 0; - idx->clear(); stack[top++] = 0; while( --top >= 0 ) @@ -3981,7 +3934,7 @@ void KDTree::findOrthoRange(const float* L, const float* R, if( row[j] < L[j] || row[j] >= R[j] ) break; if( j == dims ) - idx->push_back(i); + idx.push_back(i); continue; } if( L[n.idx] <= n.boundary ) @@ -3990,55 +3943,57 @@ void KDTree::findOrthoRange(const float* L, const float* R, stack[top++] = n.right; } - if( neighbors ) - getPoints( &(*idx)[0], idx->size(), *neighbors, _labels ); + if( _neighborsIdx.needed() ) + { + _neighborsIdx.create(idx.size(), 1, CV_32S, -1, true); + Mat nidx = _neighborsIdx.getMat(); + Mat(nidx.size(), CV_32S, &idx[0]).copyTo(nidx); + } + getPoints( idx, _neighbors, _labels ); } -void KDTree::findOrthoRange(const vector& L, const vector& R, - vector* neighborsIdx, Mat* neighbors, vector* _labels) const +void KDTree::getPoints(const InputArray& _idx, OutputArray _pts, OutputArray _labels) const { - size_t dims = points.cols; - CV_Assert(L.size() == dims && R.size() == dims); - findOrthoRange(&L[0], &R[0], neighborsIdx, neighbors, _labels); -} - + Mat idxmat = _idx.getMat(), pts, labelsmat; + CV_Assert( idxmat.isContinuous() && idxmat.type() == CV_32S && + (idxmat.cols == 1 || idxmat.rows == 1) ); + const int* idx = idxmat.ptr(); + int* dstlabels = 0; -void KDTree::getPoints(const int* idx, size_t nidx, Mat& pts, vector* _labels) const -{ - int dims = points.cols, n = (int)nidx; - pts.create( n, dims, points.type()); - if(_labels) - _labels->resize(nidx); - - for( int i = 0; i < n; i++ ) + int dims = points.cols; + int i, nidx = (int)idxmat.total(); + if( nidx == 0 ) { - int k = idx[i]; - CV_Assert( (unsigned)k < (unsigned)points.rows ); - const float* src = points.ptr(k); - std::copy(src, src + dims, pts.ptr(i)); - if(_labels) - (*_labels)[i] = labels[k]; + _pts.release(); + _labels.release(); + return; } -} - - -void KDTree::getPoints(const vector& idx, Mat& pts, vector* _labels) const -{ - int dims = points.cols; - int i, nidx = (int)idx.size(); - pts.create( nidx, dims, points.type()); - if(_labels) - _labels->resize(nidx); + if( _pts.needed() ) + { + _pts.create( nidx, dims, points.type()); + pts = _pts.getMat(); + } + + if(_labels.needed()) + { + _labels.create(nidx, 1, CV_32S, -1, true); + labelsmat = _labels.getMat(); + CV_Assert( labelsmat.isContinuous() ); + dstlabels = labelsmat.ptr(); + } + const int* srclabels = !labels.empty() ? &labels[0] : 0; for( i = 0; i < nidx; i++ ) { int k = idx[i]; CV_Assert( (unsigned)k < (unsigned)points.rows ); const float* src = points.ptr(k); - std::copy(src, src + dims, pts.ptr(i)); - if(_labels) (*_labels)[i] = labels[k]; + if( pts.data ) + std::copy(src, src + dims, pts.ptr(i)); + if( dstlabels ) + dstlabels[i] = srclabels ? srclabels[k] : k; } } @@ -4047,7 +4002,7 @@ const float* KDTree::getPoint(int ptidx, int* label) const { CV_Assert( (unsigned)ptidx < (unsigned)points.rows); if(label) - *label = label[ptidx]; + *label = labels[ptidx]; return points.ptr(ptidx); } diff --git a/modules/core/src/drawing.cpp b/modules/core/src/drawing.cpp index ada9e7ad90..d8101fd8d0 100644 --- a/modules/core/src/drawing.cpp +++ b/modules/core/src/drawing.cpp @@ -235,7 +235,7 @@ LineIterator::LineIterator(const Mat& img, Point pt1, Point pt2, static void Line( Mat& img, Point pt1, Point pt2, - const void* color, int connectivity = 8 ) + const void* _color, int connectivity = 8 ) { if( connectivity == 0 ) connectivity = 8; @@ -245,10 +245,21 @@ Line( Mat& img, Point pt1, Point pt2, LineIterator iterator(img, pt1, pt2, connectivity, true); int i, count = iterator.count; int pix_size = (int)img.elemSize(); + const uchar* color = (const uchar*)_color; for( i = 0; i < count; i++, ++iterator ) { - CV_MEMCPY_AUTO( *iterator, color, pix_size ); + uchar* ptr = *iterator; + if( pix_size == 1 ) + ptr[0] = color[0]; + else if( pix_size == 3 ) + { + ptr[0] = color[0]; + ptr[1] = color[1]; + ptr[2] = color[2]; + } + else + memcpy( *iterator, color, pix_size ); } } @@ -1317,7 +1328,7 @@ Circle( Mat& img, Point center, int radius, const void* color, int fill ) center.y >= radius && center.y < size.height - radius; #define ICV_PUT_POINT( ptr, x ) \ - CV_MEMCPY_CHAR( ptr + (x)*pix_size, color, pix_size ); + memcpy( ptr + (x)*pix_size, color, pix_size ); while( dx >= dy ) { diff --git a/modules/core/src/dxt.cpp b/modules/core/src/dxt.cpp index 470b2bc9d1..cb7e4b8728 100644 --- a/modules/core/src/dxt.cpp +++ b/modules/core/src/dxt.cpp @@ -1449,27 +1449,25 @@ static void CCSIDFT_64f( const double* src, double* dst, int n, int nf, int* fac CCSIDFT( src, dst, n, nf, factors, itab, wave, tab_size, spec, buf, flags, scale); } +} + -void dft( const Mat& src0, Mat& dst, int flags, int nonzero_rows ) +void cv::dft( const InputArray& _src0, OutputArray _dst, int flags, int nonzero_rows ) { - static DFTFunc dft_tbl[6]; - static int inittab = 0; - - if( !inittab ) + static DFTFunc dft_tbl[6] = { - dft_tbl[0] = (DFTFunc)DFT_32f; - dft_tbl[1] = (DFTFunc)RealDFT_32f; - dft_tbl[2] = (DFTFunc)CCSIDFT_32f; - dft_tbl[3] = (DFTFunc)DFT_64f; - dft_tbl[4] = (DFTFunc)RealDFT_64f; - dft_tbl[5] = (DFTFunc)CCSIDFT_64f; - inittab = 1; - } + (DFTFunc)DFT_32f, + (DFTFunc)RealDFT_32f, + (DFTFunc)CCSIDFT_32f, + (DFTFunc)DFT_64f, + (DFTFunc)RealDFT_64f, + (DFTFunc)CCSIDFT_64f + }; AutoBuffer buf; void *spec = 0; - Mat src = src0; + Mat src0 = _src0.getMat(), src = src0; int prev_len = 0, stage = 0; bool inv = (flags & DFT_INVERSE) != 0; int nf = 0, real_transform = src.channels() == 1 || (inv && (flags & DFT_REAL_OUTPUT)!=0); @@ -1485,11 +1483,13 @@ void dft( const Mat& src0, Mat& dst, int flags, int nonzero_rows ) CV_Assert( type == CV_32FC1 || type == CV_32FC2 || type == CV_64FC1 || type == CV_64FC2 ); if( !inv && src.channels() == 1 && (flags & DFT_COMPLEX_OUTPUT) ) - dst.create( src.size(), CV_MAKETYPE(depth, 2) ); + _dst.create( src.size(), CV_MAKETYPE(depth, 2) ); else if( inv && src.channels() == 2 && (flags & DFT_REAL_OUTPUT) ) - dst.create( src.size(), depth ); + _dst.create( src.size(), depth ); else - dst.create( src.size(), type ); + _dst.create( src.size(), type ); + + Mat dst = _dst.getMat(); if( !real_transform ) elem_size = complex_elem_size; @@ -1840,14 +1840,15 @@ void dft( const Mat& src0, Mat& dst, int flags, int nonzero_rows ) } -void idft( const Mat& src, Mat& dst, int flags, int nonzero_rows ) +void cv::idft( const InputArray& src, OutputArray dst, int flags, int nonzero_rows ) { dft( src, dst, flags | DFT_INVERSE, nonzero_rows ); } -void mulSpectrums( const Mat& srcA, const Mat& srcB, - Mat& dst, int flags, bool conjB ) +void cv::mulSpectrums( const InputArray& _srcA, const InputArray& _srcB, + OutputArray _dst, int flags, bool conjB ) { + Mat srcA = _srcA.getMat(), srcB = _srcB.getMat(); int depth = srcA.depth(), cn = srcA.channels(), type = srcA.type(); int rows = srcA.rows, cols = srcA.cols; int j, k; @@ -1855,7 +1856,8 @@ void mulSpectrums( const Mat& srcA, const Mat& srcB, CV_Assert( type == srcB.type() && srcA.size() == srcB.size() ); CV_Assert( type == CV_32FC1 || type == CV_32FC2 || type == CV_64FC1 || type == CV_64FC2 ); - dst.create( srcA.rows, srcA.cols, type ); + _dst.create( srcA.rows, srcA.cols, type ); + Mat dst = _dst.getMat(); bool is_1d = (flags & DFT_ROWS) || (rows == 1 || (cols == 1 && srcA.isContinuous() && srcB.isContinuous() && dst.isContinuous())); @@ -2008,6 +2010,9 @@ void mulSpectrums( const Mat& srcA, const Mat& srcB, Discrete Cosine Transform \****************************************************************************************/ +namespace cv +{ + /* DCT is calculated using DFT, as described here: http://www.ece.utexas.edu/~bevans/courses/ee381k/lectures/09_DCT/lecture9/: */ @@ -2210,23 +2215,21 @@ static void IDCT_64f(const double* src, int src_step, double* dft_src, double* d IDCT(src, src_step, dft_src, dft_dst, dst, dst_step, n, nf, factors, itab, dft_wave, dct_wave, spec, buf); } + +} -void dct( const Mat& src0, Mat& dst, int flags ) +void cv::dct( const InputArray& _src0, OutputArray _dst, int flags ) { - static DCTFunc dct_tbl[4]; - static int inittab = 0; - - if( !inittab ) + static DCTFunc dct_tbl[4] = { - dct_tbl[0] = (DCTFunc)DCT_32f; - dct_tbl[1] = (DCTFunc)IDCT_32f; - dct_tbl[2] = (DCTFunc)DCT_64f; - dct_tbl[3] = (DCTFunc)IDCT_64f; - inittab = 1; - } + (DCTFunc)DCT_32f, + (DCTFunc)IDCT_32f, + (DCTFunc)DCT_64f, + (DCTFunc)IDCT_64f + }; bool inv = (flags & DCT_INVERSE) != 0; - Mat src = src0; + Mat src0 = _src0.getMat(), src = src0; int type = src.type(), depth = src.depth(); void /* *spec_dft = 0, */ *spec = 0; @@ -2242,7 +2245,8 @@ void dct( const Mat& src0, Mat& dst, int flags ) AutoBuffer buf; CV_Assert( type == CV_32FC1 || type == CV_64FC1 ); - dst.create( src.rows, src.cols, type ); + _dst.create( src.rows, src.cols, type ); + Mat dst = _dst.getMat(); DCTFunc dct_func = dct_tbl[inv + (depth == CV_64F)*2]; @@ -2369,11 +2373,14 @@ void dct( const Mat& src0, Mat& dst, int flags ) } -void idct( const Mat& src, Mat& dst, int flags ) +void cv::idct( const InputArray& src, OutputArray dst, int flags ) { dct( src, dst, flags | DCT_INVERSE ); } +namespace cv +{ + static const int optimalDFTSizeTab[] = { 1, 2, 3, 4, 5, 6, 8, 9, 10, 12, 15, 16, 18, 20, 24, 25, 27, 30, 32, 36, 40, 45, 48, 50, 54, 60, 64, 72, 75, 80, 81, 90, 96, 100, 108, 120, 125, 128, 135, 144, 150, 160, @@ -2555,8 +2562,9 @@ static const int optimalDFTSizeTab[] = { 2097152000, 2099520000, 2109375000, 2123366400, 2125764000 }; -int -getOptimalDFTSize( int size0 ) +} + +int cv::getOptimalDFTSize( int size0 ) { int a = 0, b = sizeof(optimalDFTSizeTab)/sizeof(optimalDFTSizeTab[0]) - 1; if( (unsigned)size0 >= (unsigned)optimalDFTSizeTab[b] ) @@ -2574,8 +2582,6 @@ getOptimalDFTSize( int size0 ) return optimalDFTSizeTab[b]; } -} - CV_IMPL void cvDFT( const CvArr* srcarr, CvArr* dstarr, int flags, int nonzero_rows ) { diff --git a/modules/core/src/lapack.cpp b/modules/core/src/lapack.cpp index 6df9454943..97f78b9e96 100644 --- a/modules/core/src/lapack.cpp +++ b/modules/core/src/lapack.cpp @@ -212,6 +212,8 @@ bool Cholesky(double* A, int m, double* b, int n) { return CholImpl(A, m, b, n); } + +} /****************************************************************************************\ * Determinant of the matrix * @@ -222,8 +224,9 @@ bool Cholesky(double* A, int m, double* b, int n) m(0,1)*((double)m(1,0)*m(2,2) - (double)m(1,2)*m(2,0)) + \ m(0,2)*((double)m(1,0)*m(2,1) - (double)m(1,1)*m(2,0))) -double determinant( const Mat& mat ) +double cv::determinant( const InputArray& _mat ) { + Mat mat = _mat.getMat(); double result = 0; int type = mat.type(), rows = mat.rows; size_t step = mat.step; @@ -325,13 +328,16 @@ double determinant( const Mat& mat ) #define Df( y, x ) ((float*)(dstdata + y*dststep))[x] #define Dd( y, x ) ((double*)(dstdata + y*dststep))[x] -double invert( const Mat& src, Mat& dst, int method ) +double cv::invert( const InputArray& _src, OutputArray _dst, int method ) { double result = 0; + Mat src = _src.getMat(); int type = src.type(); CV_Assert( method == DECOMP_LU || method == DECOMP_CHOLESKY || method == DECOMP_SVD ); - + _dst.create( src.cols, src.rows, type ); + Mat dst = _dst.getMat(); + if( method == DECOMP_SVD ) { int n = std::min(src.rows, src.cols); @@ -346,8 +352,7 @@ double invert( const Mat& src, Mat& dst, int method ) } CV_Assert( src.rows == src.cols && (type == CV_32F || type == CV_64F)); - dst.create( src.rows, src.cols, type ); - + if( src.rows <= 3 ) { uchar* srcdata = src.data; @@ -572,9 +577,10 @@ double invert( const Mat& src, Mat& dst, int method ) * Solving a linear system * \****************************************************************************************/ -bool solve( const Mat& src, const Mat& _src2, Mat& dst, int method ) +bool cv::solve( const InputArray& _src, const InputArray& _src2arg, OutputArray _dst, int method ) { bool result = true; + Mat src = _src.getMat(), _src2 = _src2arg.getMat(); int type = src.type(); bool is_normal = (method & DECOMP_NORMAL) != 0; @@ -588,7 +594,8 @@ bool solve( const Mat& src, const Mat& _src2, Mat& dst, int method ) if( (method == DECOMP_LU || method == DECOMP_CHOLESKY) && src.rows <= 3 && src.rows == src.cols && _src2.cols == 1 ) { - dst.create( src.cols, _src2.cols, src.type() ); + _dst.create( src.cols, _src2.cols, src.type() ); + Mat dst = _dst.getMat(); #define bf(y) ((float*)(bdata + y*src2step))[0] #define bd(y) ((double*)(bdata + y*src2step))[0] @@ -729,7 +736,8 @@ bool solve( const Mat& src, const Mat& _src2, Mat& dst, int method ) char N[] = {'N', '\0'}, L[] = {'L', '\0'}; Mat src2 = _src2; - dst.create( src.cols, src2.cols, src.type() ); + _dst.create( src.cols, src2.cols, src.type() ); + Mat dst = _dst.getMat(); if( m <= n ) is_normal = false; @@ -905,6 +913,9 @@ bool solve( const Mat& src, const Mat& _src2, Mat& dst, int method ) /////////////////// finding eigenvalues and eigenvectors of a symmetric matrix /////////////// +namespace cv +{ + template static inline Real hypot(Real a, Real b) { a = std::abs(a); @@ -1077,9 +1088,10 @@ template bool jacobi(const Mat& _S0, Mat& _e, Mat& matE, bool com } -static bool eigen( const Mat& src, Mat& evals, Mat& evects, bool computeEvects, +static bool eigen( const InputArray& _src, OutputArray _evals, OutputArray _evects, bool computeEvects, int lowindex, int highindex ) { + Mat src = _src.getMat(); int type = src.type(); integer n = src.rows; @@ -1094,9 +1106,14 @@ static bool eigen( const Mat& src, Mat& evals, Mat& evects, bool computeEvects, CV_Assert( src.rows == src.cols ); CV_Assert (type == CV_32F || type == CV_64F); - // allow for 1xn eigenvalue matrix too - if( !(evals.rows == 1 && evals.cols == n && evals.type() == type) ) - evals.create(n, 1, type); + _evals.create(n, 1, type, -1, true); + Mat evals = _evals.getMat(), evects; + + if( computeEvects ) + { + _evects.create(n, n, type); + evects = _evects.getMat(); + } if( n <= 20 ) { @@ -1122,10 +1139,7 @@ static bool eigen( const Mat& src, Mat& evals, Mat& evects, bool computeEvects, lda = (int)(src.step/elem_size); if( computeEvects ) - { - evects.create(n, n, type); ldv = (int)(evects.step/elem_size); - } bool copy_evals = !evals.isContinuous(); @@ -1211,19 +1225,21 @@ static bool eigen( const Mat& src, Mat& evals, Mat& evects, bool computeEvects, return result; } -bool eigen( const Mat& src, Mat& evals, int lowindex, int highindex ) +} + +bool cv::eigen( const InputArray& src, OutputArray evals, int lowindex, int highindex ) { - Mat evects; - return eigen(src, evals, evects, false, lowindex, highindex); + return eigen(src, evals, OutputArray(), false, lowindex, highindex); } -bool eigen( const Mat& src, Mat& evals, Mat& evects, int lowindex, - int highindex ) +bool cv::eigen( const InputArray& src, OutputArray evals, OutputArray evects, + int lowindex, int highindex ) { return eigen(src, evals, evects, true, lowindex, highindex); } - +namespace cv +{ /* y[0:m,0:n] += diag(a[0:1,0:m]) * x[0:m,0:n] */ template static void @@ -1316,29 +1332,33 @@ SVBkSb( int m, int n, const T* w, int incw, } -static void _SVDcompute( const Mat& a, Mat& w, Mat* u, Mat* vt, int flags ) +static void _SVDcompute( const InputArray& _aarr, OutputArray _w, + OutputArray _u, OutputArray _vt, int flags ) { + Mat a = _aarr.getMat(), u, vt; integer m = a.rows, n = a.cols, mn = std::max(m, n), nm = std::min(m, n); int type = a.type(), elem_size = (int)a.elemSize(); - bool compute_uv = u && vt; + bool compute_uv = _u.needed() || _vt.needed(); if( flags & SVD::NO_UV ) { - if(u) u->release(); - if(vt) vt->release(); - u = vt = 0; + _u.release(); + _vt.release(); compute_uv = false; } if( compute_uv ) { - u->create( (int)m, (int)((flags & SVD::FULL_UV) ? m : nm), type ); - vt->create( (int)((flags & SVD::FULL_UV) ? n : nm), n, type ); + _u.create( (int)m, (int)((flags & SVD::FULL_UV) ? m : nm), type ); + _vt.create( (int)((flags & SVD::FULL_UV) ? n : nm), n, type ); + u = _u.getMat(); + vt = _vt.getMat(); } - w.create(nm, 1, type); + _w.create(nm, 1, type, -1, true); - Mat _a = a; + Mat _a = a, w = _w.getMat(); + CV_Assert( w.isContinuous() ); int a_ofs = 0, work_ofs=0, iwork_ofs=0, buf_size = 0; bool temp_a = false; double u1=0, v1=0, work1=0; @@ -1353,7 +1373,7 @@ static void _SVDcompute( const Mat& a, Mat& w, Mat* u, Mat* vt, int flags ) { if( mode[0] == 'N' || mode[0] == 'A' ) temp_a = true; - else if( compute_uv && (a.size() == vt->size() || a.size() == u->size()) && mode[0] == 'S' ) + else if( compute_uv && (a.size() == vt.size() || a.size() == u.size()) && mode[0] == 'S' ) mode[0] = 'O'; } @@ -1396,59 +1416,67 @@ static void _SVDcompute( const Mat& a, Mat& w, Mat* u, Mat* vt, int flags ) if( !(flags & SVD::MODIFY_A) && !temp_a ) { - if( compute_uv && a.size() == vt->size() ) + if( compute_uv && a.size() == vt.size() ) { - a.copyTo(*vt); - _a = *vt; + a.copyTo(vt); + _a = vt; } - else if( compute_uv && a.size() == u->size() ) + else if( compute_uv && a.size() == u.size() ) { - a.copyTo(*u); - _a = *u; + a.copyTo(u); + _a = u; } } if( compute_uv ) { - ldv = (int)(vt->step ? vt->step/elem_size : vt->cols); - ldu = (int)(u->step ? u->step/elem_size : u->cols); + ldv = (int)(vt.step ? vt.step/elem_size : vt.cols); + ldu = (int)(u.step ? u.step/elem_size : u.cols); } lda = (int)(_a.step ? _a.step/elem_size : _a.cols); if( type == CV_32F ) { - sgesdd_(mode, &n, &m, (float*)_a.data, &lda, (float*)w.data, - vt ? (float*)vt->data : (float*)&v1, &ldv, u ? (float*)u->data : (float*)&u1, &ldu, - (float*)(buffer + work_ofs), &lwork, (integer*)(buffer + iwork_ofs), &info ); + sgesdd_(mode, &n, &m, _a.ptr(), &lda, w.ptr(), + vt.data ? vt.ptr() : (float*)&v1, &ldv, + u.data ? u.ptr() : (float*)&u1, &ldu, + (float*)(buffer + work_ofs), &lwork, + (integer*)(buffer + iwork_ofs), &info ); } else { - dgesdd_(mode, &n, &m, (double*)_a.data, &lda, (double*)w.data, - vt ? (double*)vt->data : &v1, &ldv, u ? (double*)u->data : &u1, &ldu, - (double*)(buffer + work_ofs), &lwork, (integer*)(buffer + iwork_ofs), &info ); + dgesdd_(mode, &n, &m, _a.ptr(), &lda, w.ptr(), + vt.data ? vt.ptr() : &v1, &ldv, + u.data ? u.ptr() : &u1, &ldu, + (double*)(buffer + work_ofs), &lwork, + (integer*)(buffer + iwork_ofs), &info ); } CV_Assert(info >= 0); if(info != 0) { - *u = Scalar(0.); - *vt = Scalar(0.); + if( u.data ) + u = Scalar(0.); + if( vt.data ) + vt = Scalar(0.); w = Scalar(0.); } } -void SVD::compute( const Mat& a, Mat& w, Mat& u, Mat& vt, int flags ) +void SVD::compute( const InputArray& a, OutputArray w, OutputArray u, OutputArray vt, int flags ) { - _SVDcompute(a, w, &u, &vt, flags); + _SVDcompute(a, w, u, vt, flags); } -void SVD::compute( const Mat& a, Mat& w, int flags ) +void SVD::compute( const InputArray& a, OutputArray w, int flags ) { - _SVDcompute(a, w, 0, 0, flags); + _SVDcompute(a, w, OutputArray(), OutputArray(), flags); } -void SVD::backSubst( const Mat& w, const Mat& u, const Mat& vt, const Mat& rhs, Mat& dst ) +void SVD::backSubst( const InputArray& _w, const InputArray& _u, const InputArray& _vt, + const InputArray& _rhs, OutputArray _dst ) { + Mat w = _w.getMat(), u = _u.getMat(), vt = _vt.getMat(), rhs = _rhs.getMat(); int type = w.type(), esz = (int)w.elemSize(); int m = u.rows, n = vt.cols, nb = rhs.data ? rhs.cols : m; AutoBuffer buffer(nb); @@ -1456,7 +1484,8 @@ void SVD::backSubst( const Mat& w, const Mat& u, const Mat& vt, const Mat& rhs, CV_Assert( rhs.data == 0 || (rhs.type() == type && rhs.rows == m) ); - dst.create( n, nb, type ); + _dst.create( n, nb, type ); + Mat dst = _dst.getMat(); if( type == CV_32F ) SVBkSb(m, n, (float*)w.data, 1, (float*)u.data, (int)(u.step/esz), false, (float*)vt.data, (int)(vt.step/esz), true, (float*)rhs.data, (int)(rhs.step/esz), @@ -1470,14 +1499,14 @@ void SVD::backSubst( const Mat& w, const Mat& u, const Mat& vt, const Mat& rhs, } -SVD& SVD::operator ()(const Mat& a, int flags) +SVD& SVD::operator ()(const InputArray& a, int flags) { - _SVDcompute(a, w, &u, &vt, flags); + _SVDcompute(a, w, u, vt, flags); return *this; } -void SVD::backSubst( const Mat& rhs, Mat& dst ) const +void SVD::backSubst( const InputArray& rhs, OutputArray dst ) const { backSubst( w, u, vt, rhs, dst ); } diff --git a/modules/core/src/mathfuncs.cpp b/modules/core/src/mathfuncs.cpp index 7bd55f43d6..f28bb0cf13 100644 --- a/modules/core/src/mathfuncs.cpp +++ b/modules/core/src/mathfuncs.cpp @@ -11,7 +11,7 @@ // For Open Source Computer Vision Library // // Copyright (C) 2000-2008, Intel Corporation, all rights reserved. -// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2009-2011, Willow Garage Inc., all rights reserved. // Third party copyrights are property of their respective owners. // // Redistribution and use in source and binary forms, with or without modification, @@ -47,7 +47,7 @@ namespace cv { static const int MAX_BLOCK_SIZE = 1024; -typedef CvStatus (CV_STDCALL * MathFunc)(const void* src, void* dst, int len); +typedef void (*MathFunc)(const void* src, void* dst, int len); float fastAtan2( float y, float x ) { @@ -61,16 +61,13 @@ float fastAtan2( float y, float x ) return (float)(y >= 0 ? 90 - a : 270 - a); } -static CvStatus CV_STDCALL FastAtan2_32f(const float *Y, const float *X, float *angle, int len, bool angleInDegrees=true ) +static void FastAtan2_32f(const float *Y, const float *X, float *angle, int len, bool angleInDegrees=true ) { - if( !Y || !X || !angle || len < 0 ) - return CV_BADFACTOR_ERR; - int i = 0; float scale = angleInDegrees ? (float)(180/CV_PI) : 1.f; #if CV_SSE2 - if( checkHardwareSupport(CV_CPU_SSE) ) + if( USE_SSE2 ) { Cv32suf iabsmask; iabsmask.i = 0x7fffffff; __m128 eps = _mm_set1_ps((float)DBL_EPSILON), absmask = _mm_set1_ps(iabsmask.f); @@ -120,8 +117,6 @@ static CvStatus CV_STDCALL FastAtan2_32f(const float *Y, const float *X, float * } angle[i] = a*scale; } - - return CV_OK; } @@ -166,13 +161,12 @@ float cubeRoot( float value ) return v.f; } -static CvStatus CV_STDCALL -Magnitude_32f(const float* x, const float* y, float* mag, int len) +static void Magnitude_32f(const float* x, const float* y, float* mag, int len) { int i = 0; #if CV_SSE - if( checkHardwareSupport(CV_CPU_SSE) ) + if( USE_SSE2 ) { for( ; i <= len - 8; i += 8 ) { @@ -191,17 +185,14 @@ Magnitude_32f(const float* x, const float* y, float* mag, int len) float x0 = x[i], y0 = y[i]; mag[i] = std::sqrt(x0*x0 + y0*y0); } - - return CV_OK; } -static CvStatus CV_STDCALL -Magnitude_64f(const double* x, const double* y, double* mag, int len) +static void Magnitude_64f(const double* x, const double* y, double* mag, int len) { int i = 0; #if CV_SSE2 - if( checkHardwareSupport(CV_CPU_SSE2) ) + if( USE_SSE2 ) { for( ; i <= len - 4; i += 4 ) { @@ -220,17 +211,15 @@ Magnitude_64f(const double* x, const double* y, double* mag, int len) double x0 = x[i], y0 = y[i]; mag[i] = std::sqrt(x0*x0 + y0*y0); } - - return CV_OK; } -static CvStatus CV_STDCALL InvSqrt_32f(const float* src, float* dst, int len) +static void InvSqrt_32f(const float* src, float* dst, int len) { int i = 0; #if CV_SSE - if( checkHardwareSupport(CV_CPU_SSE) ) + if( USE_SSE2 ) { __m128 _0_5 = _mm_set1_ps(0.5f), _1_5 = _mm_set1_ps(1.5f); if( (((size_t)src|(size_t)dst) & 15) == 0 ) @@ -258,24 +247,22 @@ static CvStatus CV_STDCALL InvSqrt_32f(const float* src, float* dst, int len) for( ; i < len; i++ ) dst[i] = 1/std::sqrt(src[i]); - return CV_OK; } -static CvStatus CV_STDCALL InvSqrt_64f(const double* src, double* dst, int len) +static void InvSqrt_64f(const double* src, double* dst, int len) { for( int i = 0; i < len; i++ ) dst[i] = 1/std::sqrt(src[i]); - return CV_OK; } -static CvStatus CV_STDCALL Sqrt_32f(const float* src, float* dst, int len) +static void Sqrt_32f(const float* src, float* dst, int len) { int i = 0; #if CV_SSE - if( checkHardwareSupport(CV_CPU_SSE) ) + if( USE_SSE2 ) { if( (((size_t)src|(size_t)dst) & 15) == 0 ) for( ; i <= len - 8; i += 8 ) @@ -296,17 +283,15 @@ static CvStatus CV_STDCALL Sqrt_32f(const float* src, float* dst, int len) for( ; i < len; i++ ) dst[i] = std::sqrt(src[i]); - - return CV_OK; } -static CvStatus CV_STDCALL Sqrt_64f(const double* src, double* dst, int len) +static void Sqrt_64f(const double* src, double* dst, int len) { int i = 0; #if CV_SSE2 - if( checkHardwareSupport(CV_CPU_SSE2) ) + if( USE_SSE2 ) { if( (((size_t)src|(size_t)dst) & 15) == 0 ) for( ; i <= len - 4; i += 4 ) @@ -327,7 +312,6 @@ static CvStatus CV_STDCALL Sqrt_64f(const double* src, double* dst, int len) for( ; i < len; i++ ) dst[i] = std::sqrt(src[i]); - return CV_OK; } @@ -335,172 +319,151 @@ static CvStatus CV_STDCALL Sqrt_64f(const double* src, double* dst, int len) * Cartezian -> Polar * \****************************************************************************************/ -void magnitude( const Mat& X, const Mat& Y, Mat& Mag ) +void magnitude( const InputArray& src1, const InputArray& src2, OutputArray dst ) { - if( X.dims > 2 ) - { - Mag.create(X.dims, X.size, X.type()); - const Mat* arrays[] = {&X, &Y, &Mag, 0}; - Mat planes[3]; - NAryMatIterator it(arrays, planes); - - for( int i = 0; i < it.nplanes; i++, ++it ) - magnitude( it.planes[0], it.planes[1], it.planes[2] ); - return; - } - + Mat X = src1.getMat(), Y = src2.getMat(); int type = X.type(), depth = X.depth(), cn = X.channels(); - CV_Assert( X.size() == Y.size() && type == Y.type() && (depth == CV_32F || depth == CV_64F)); - Mag.create( X.size(), type ); - - Size size = getContinuousSize( X, Y, Mag, cn ); - - if( depth == CV_32F ) - { - const float *x = (const float*)X.data, *y = (const float*)Y.data; - float *mag = (float*)Mag.data; - size_t xstep = X.step/sizeof(x[0]), ystep = Y.step/sizeof(y[0]); - size_t mstep = Mag.step/sizeof(mag[0]); - - for( ; size.height--; x += xstep, y += ystep, mag += mstep ) - Magnitude_32f( x, y, mag, size.width ); - } - else + CV_Assert( X.size == Y.size && type == Y.type() && (depth == CV_32F || depth == CV_64F)); + dst.create(X.dims, X.size, X.type()); + Mat Mag = dst.getMat(); + + const Mat* arrays[] = {&X, &Y, &Mag, 0}; + uchar* ptrs[3]; + NAryMatIterator it(arrays, ptrs); + int len = (int)it.size*cn; + + for( size_t i = 0; i < it.nplanes; i++, ++it ) { - const double *x = (const double*)X.data, *y = (const double*)Y.data; - double *mag = (double*)Mag.data; - size_t xstep = X.step/sizeof(x[0]), ystep = Y.step/sizeof(y[0]); - size_t mstep = Mag.step/sizeof(mag[0]); - - for( ; size.height--; x += xstep, y += ystep, mag += mstep ) - Magnitude_64f( x, y, mag, size.width ); + if( depth == CV_32F ) + { + const float *x = (const float*)ptrs[0], *y = (const float*)ptrs[1]; + float *mag = (float*)ptrs[2]; + Magnitude_32f( x, y, mag, len ); + } + else + { + const double *x = (const double*)ptrs[0], *y = (const double*)ptrs[1]; + double *mag = (double*)ptrs[2]; + Magnitude_64f( x, y, mag, len ); + } } } -void phase( const Mat& X, const Mat& Y, Mat& Angle, bool angleInDegrees ) + +void phase( const InputArray& src1, const InputArray& src2, OutputArray dst, bool angleInDegrees ) { - if( X.dims > 2 ) - { - Angle.create(X.dims, X.size, X.type()); - const Mat* arrays[] = {&X, &Y, &Angle, 0}; - Mat planes[3]; - NAryMatIterator it(arrays, planes); - - for( int i = 0; i < it.nplanes; i++, ++it ) - phase( it.planes[0], it.planes[1], it.planes[2], angleInDegrees ); - return; - } + Mat X = src1.getMat(), Y = src2.getMat(); + int type = X.type(), depth = X.depth(), cn = X.channels(); + CV_Assert( X.size == Y.size && type == Y.type() && (depth == CV_32F || depth == CV_64F)); + dst.create( X.dims, X.size, type ); + Mat Angle = dst.getMat(); - float buf[2][MAX_BLOCK_SIZE]; - int i, j, type = X.type(), depth = X.depth(), cn = X.channels(); - - CV_Assert( X.size() == Y.size() && type == Y.type() && (depth == CV_32F || depth == CV_64F)); - Angle.create( X.size(), type ); - - Size size = getContinuousSize( X, Y, Angle, cn ); - - if( depth == CV_32F ) + const Mat* arrays[] = {&X, &Y, &Angle, 0}; + uchar* ptrs[3]; + NAryMatIterator it(arrays, ptrs); + cv::AutoBuffer _buf; + float* buf[2] = {0, 0}; + int j, k, total = (int)(it.size*cn), blockSize = total; + size_t esz1 = X.elemSize1(); + + if( depth == CV_64F ) { - const float *x = (const float*)X.data, *y = (const float*)Y.data; - float *angle = (float*)Angle.data; - size_t xstep = X.step/sizeof(x[0]), ystep = Y.step/sizeof(y[0]); - size_t astep = Angle.step/sizeof(angle[0]); - - for( ; size.height--; x += xstep, y += ystep, angle += astep ) - FastAtan2_32f( y, x, angle, size.width, angleInDegrees ); + blockSize = std::min(blockSize, ((BLOCK_SIZE+cn-1)/cn)*cn); + _buf.allocate(blockSize*2); + buf[0] = _buf; + buf[1] = buf[0] + blockSize; } - else + + for( size_t i = 0; i < it.nplanes; i++, ++it ) { - const double *x = (const double*)X.data, *y = (const double*)Y.data; - double *angle = (double*)Angle.data; - size_t xstep = X.step/sizeof(x[0]), ystep = Y.step/sizeof(y[0]); - size_t astep = Angle.step/sizeof(angle[0]); - - for( ; size.height--; x += xstep, y += ystep, angle += astep ) + for( j = 0; j < total; j += blockSize ) { - for( i = 0; i < size.width; i += MAX_BLOCK_SIZE ) + int len = std::min(total - j, blockSize); + if( depth == CV_32F ) { - int block_size = std::min(MAX_BLOCK_SIZE, size.width - i); - for( j = 0; j < block_size; j++ ) + const float *x = (const float*)ptrs[0], *y = (const float*)ptrs[1]; + float *angle = (float*)ptrs[2]; + FastAtan2_32f( y, x, angle, len, angleInDegrees ); + } + else + { + const double *x = (const double*)ptrs[0], *y = (const double*)ptrs[1]; + double *angle = (double*)ptrs[2]; + for( k = 0; k < len; k++ ) { - buf[0][j] = (float)x[i + j]; - buf[1][j] = (float)y[i + j]; + buf[0][k] = (float)x[k]; + buf[1][k] = (float)y[k]; } - FastAtan2_32f( buf[1], buf[0], buf[0], block_size, angleInDegrees ); - for( j = 0; j < block_size; j++ ) - angle[i + j] = buf[0][j]; + + FastAtan2_32f( buf[1], buf[0], buf[0], len, angleInDegrees ); + for( k = 0; k < len; k++ ) + angle[k] = buf[0][k]; } + ptrs[0] += len*esz1; + ptrs[1] += len*esz1; + ptrs[2] += len*esz1; } } } - -void cartToPolar( const Mat& X, const Mat& Y, Mat& Mag, Mat& Angle, bool angleInDegrees ) + + +void cartToPolar( const InputArray& src1, const InputArray& src2, + OutputArray dst1, OutputArray dst2, bool angleInDegrees ) { - if( X.dims > 2 ) + Mat X = src1.getMat(), Y = src2.getMat(); + int type = X.type(), depth = X.depth(), cn = X.channels(); + CV_Assert( X.size == Y.size && type == Y.type() && (depth == CV_32F || depth == CV_64F)); + dst1.create( X.dims, X.size, type ); + dst2.create( X.dims, X.size, type ); + Mat Mag = dst1.getMat(), Angle = dst2.getMat(); + + const Mat* arrays[] = {&X, &Y, &Mag, &Angle, 0}; + uchar* ptrs[4]; + NAryMatIterator it(arrays, ptrs); + cv::AutoBuffer _buf; + float* buf[2] = {0, 0}; + int j, k, total = (int)(it.size*cn), blockSize = std::min(total, ((BLOCK_SIZE+cn-1)/cn)*cn); + size_t esz1 = X.elemSize1(); + + if( depth == CV_64F ) { - Mag.create(X.dims, X.size, X.type()); - Angle.create(X.dims, X.size, X.type()); - const Mat* arrays[] = {&X, &Y, &Mag, &Angle, 0}; - Mat planes[4]; - NAryMatIterator it(arrays, planes); - - for( int i = 0; i < it.nplanes; i++, ++it ) - cartToPolar( it.planes[0], it.planes[1], it.planes[2], it.planes[3], angleInDegrees ); - return; + _buf.allocate(blockSize*2); + buf[0] = _buf; + buf[1] = buf[0] + blockSize; } - float buf[2][MAX_BLOCK_SIZE]; - int i, j, type = X.type(), depth = X.depth(), cn = X.channels(); - - CV_Assert( X.size() == Y.size() && type == Y.type() && (depth == CV_32F || depth == CV_64F)); - Mag.create( X.size(), type ); - Angle.create( X.size(), type ); - - Size size = getContinuousSize( X, Y, Mag, Angle, cn ); - bool inplace = Mag.data == X.data || Mag.data == Y.data; - - if( depth == CV_32F ) + for( size_t i = 0; i < it.nplanes; i++, ++it ) { - const float *x = (const float*)X.data, *y = (const float*)Y.data; - float *mag = (float*)Mag.data, *angle = (float*)Angle.data; - size_t xstep = X.step/sizeof(x[0]), ystep = Y.step/sizeof(y[0]); - size_t mstep = Mag.step/sizeof(mag[0]), astep = Angle.step/sizeof(angle[0]); - - for( ; size.height--; x += xstep, y += ystep, mag += mstep, angle += astep ) + for( j = 0; j < total; j += blockSize ) { - for( i = 0; i < size.width; i += MAX_BLOCK_SIZE ) + int len = std::min(total - j, blockSize); + if( depth == CV_32F ) { - int block_size = std::min(MAX_BLOCK_SIZE, size.width - i); - Magnitude_32f( x + i, y + i, inplace ? buf[0] : mag + i, block_size ); - FastAtan2_32f( y + i, x + i, angle + i, block_size, angleInDegrees ); - if( inplace ) - for( j = 0; j < block_size; j++ ) - mag[i + j] = buf[0][j]; + const float *x = (const float*)ptrs[0], *y = (const float*)ptrs[1]; + float *mag = (float*)ptrs[2], *angle = (float*)ptrs[3]; + Magnitude_32f( x, y, mag, len ); + FastAtan2_32f( y, x, angle, len, angleInDegrees ); } - } - } - else - { - const double *x = (const double*)X.data, *y = (const double*)Y.data; - double *mag = (double*)Mag.data, *angle = (double*)Angle.data; - size_t xstep = X.step/sizeof(x[0]), ystep = Y.step/sizeof(y[0]); - size_t mstep = Mag.step/sizeof(mag[0]), astep = Angle.step/sizeof(angle[0]); - - for( ; size.height--; x += xstep, y += ystep, mag += mstep, angle += astep ) - { - for( i = 0; i < size.width; i += MAX_BLOCK_SIZE ) + else { - int block_size = std::min(MAX_BLOCK_SIZE, size.width - i); - for( j = 0; j < block_size; j++ ) + const double *x = (const double*)ptrs[0], *y = (const double*)ptrs[1]; + double *angle = (double*)ptrs[3]; + + Magnitude_64f(x, y, (double*)ptrs[2], len); + for( k = 0; k < len; k++ ) { - buf[0][j] = (float)x[i + j]; - buf[1][j] = (float)y[i + j]; + buf[0][k] = (float)x[k]; + buf[1][k] = (float)y[k]; } - FastAtan2_32f( buf[1], buf[0], buf[0], block_size, angleInDegrees ); - Magnitude_64f( x + i, y + i, mag + i, block_size ); - for( j = 0; j < block_size; j++ ) - angle[i + j] = buf[0][j]; + + FastAtan2_32f( buf[1], buf[0], buf[0], len, angleInDegrees ); + for( k = 0; k < len; k++ ) + angle[k] = buf[0][k]; } + ptrs[0] += len*esz1; + ptrs[1] += len*esz1; + ptrs[2] += len*esz1; + ptrs[3] += len*esz1; } } } @@ -510,9 +473,8 @@ void cartToPolar( const Mat& X, const Mat& Y, Mat& Mag, Mat& Angle, bool angleIn * Polar -> Cartezian * \****************************************************************************************/ -static CvStatus CV_STDCALL -SinCos_32f( const float *angle,float *sinval, float* cosval, - int len, int angle_in_degrees ) +static void SinCos_32f( const float *angle, float *sinval, float* cosval, + int len, int angle_in_degrees ) { const int N = 64; @@ -588,81 +550,80 @@ SinCos_32f( const float *angle,float *sinval, float* cosval, sinval[i] = (float)sin_val; cosval[i] = (float)cos_val; } - - return CV_OK; } -void polarToCart( const Mat& Mag, const Mat& Angle, Mat& X, Mat& Y, bool angleInDegrees ) +void polarToCart( const InputArray& src1, const InputArray& src2, + OutputArray dst1, OutputArray dst2, bool angleInDegrees ) { - if( Mag.dims > 2 ) - { - X.create(Mag.dims, Mag.size, Mag.type()); - Y.create(Mag.dims, Mag.size, Mag.type()); - const Mat* arrays[] = {&Mag, &Angle, &X, &Y, 0}; - Mat planes[4]; - NAryMatIterator it(arrays, planes); - - for( int i = 0; i < it.nplanes; i++, ++it ) - polarToCart( it.planes[0], it.planes[1], it.planes[2], it.planes[3], angleInDegrees ); - return; - } + Mat Mag = src1.getMat(), Angle = src2.getMat(); + int type = Angle.type(), depth = Angle.depth(), cn = Angle.channels(); + if( !Mag.empty() ) + CV_Assert( Angle.size == Mag.size && type == Mag.type() && (depth == CV_32F || depth == CV_64F)); + dst1.create( Angle.dims, Angle.size, type ); + dst2.create( Angle.dims, Angle.size, type ); + Mat X = dst1.getMat(), Y = dst2.getMat(); - int i, j, type = Angle.type(), depth = Angle.depth(); - Size size; - - CV_Assert( depth == CV_32F || depth == CV_64F ); - X.create( Angle.size(), type ); - Y.create( Angle.size(), type ); - - if( Mag.data ) + const Mat* arrays[] = {&Mag, &Angle, &X, &Y, 0}; + uchar* ptrs[4]; + NAryMatIterator it(arrays, ptrs); + cv::AutoBuffer _buf; + float* buf[2] = {0, 0}; + int j, k, total = (int)(it.size*cn), blockSize = std::min(total, ((BLOCK_SIZE+cn-1)/cn)*cn); + size_t esz1 = Angle.elemSize1(); + + if( depth == CV_64F ) { - CV_Assert( Mag.size() == Angle.size() && Mag.type() == Angle.type() ); - size = getContinuousSize( Mag, Angle, X, Y, Angle.channels() ); + _buf.allocate(blockSize*2); + buf[0] = _buf; + buf[1] = buf[0] + blockSize; } - else - size = getContinuousSize( Angle, X, Y, Angle.channels() ); - - if( depth == CV_32F ) + + for( size_t i = 0; i < it.nplanes; i++, ++it ) { - float *x = (float*)X.data, *y = (float*)Y.data; - const float *mag = (const float*)Mag.data, *angle = (const float*)Angle.data; - size_t xstep = X.step/sizeof(x[0]), ystep = Y.step/sizeof(y[0]); - size_t mstep = Mag.step/sizeof(mag[0]), astep = Angle.step/sizeof(angle[0]); - float x_tmp[MAX_BLOCK_SIZE]; - float y_tmp[MAX_BLOCK_SIZE]; - - for( ; size.height--; x += xstep, y += ystep, mag += mstep, angle += astep ) + for( j = 0; j < total; j += blockSize ) { - for( i = 0; i < size.width; i += MAX_BLOCK_SIZE ) + int len = std::min(total - j, blockSize); + if( depth == CV_32F ) { - int block_size = std::min(MAX_BLOCK_SIZE, size.width - i); - SinCos_32f( angle + i, y_tmp, x_tmp, block_size, angleInDegrees ); - for( j = 0; j < block_size; j++ ) - { - float m = mag ? mag[i + j] : 1.f; - float t0 = x_tmp[j]*m, t1 = y_tmp[j]*m; - x[i + j] = t0; y[i + j] = t1; - } + const float *mag = (const float*)ptrs[0], *angle = (const float*)ptrs[1]; + float *x = (float*)ptrs[2], *y = (float*)ptrs[3]; + + SinCos_32f( angle, y, x, len, angleInDegrees ); + if( mag ) + for( k = 0; k < len; k++ ) + { + float m = mag[k]; + x[k] *= m; y[k] *= m; + } } - } - } - else - { - double *x = (double*)X.data, *y = (double*)Y.data; - const double *mag = (const double*)Mag.data, *angle = (const double*)Angle.data; - size_t xstep = X.step/sizeof(x[0]), ystep = Y.step/sizeof(y[0]); - size_t mstep = Mag.step/sizeof(mag[0]), astep = Angle.step/sizeof(angle[0]); - double ascale = angleInDegrees ? CV_PI/180. : 1; - - for( ; size.height--; x += xstep, y += ystep, mag += mstep, angle += astep ) - { - for( j = 0; j < size.width; j++ ) + else { - double alpha = angle[j]*ascale, m = mag ? mag[j] : 1.; - double a = cos(alpha), b = sin(alpha); - x[j] = m*a; y[j] = m*b; + const double *mag = (const double*)ptrs[0], *angle = (const double*)ptrs[1]; + double *x = (double*)ptrs[2], *y = (double*)ptrs[3]; + + for( k = 0; k < len; k++ ) + buf[0][k] = (float)angle[k]; + + SinCos_32f( buf[0], buf[1], buf[0], len, angleInDegrees ); + if( mag ) + for( k = 0; k < len; k++ ) + { + double m = mag[k]; + x[k] = buf[0][k]*m; y[k] = buf[1][k]*m; + } + else + for( k = 0; k < len; k++ ) + { + x[k] = buf[0][k]; y[k] = buf[1][k]; + } } + + if( ptrs[0] ) + ptrs[0] += len*esz1; + ptrs[1] += len*esz1; + ptrs[2] += len*esz1; + ptrs[3] += len*esz1; } } } @@ -772,7 +733,7 @@ static const double exp_prescale = 1.4426950408889634073599246810019 * (1 << EXP static const double exp_postscale = 1./(1 << EXPTAB_SCALE); static const double exp_max_val = 3000.*(1 << EXPTAB_SCALE); // log10(DBL_MAX) < 3000 -static CvStatus CV_STDCALL Exp_32f( const float *_x, float *y, int n ) +static void Exp_32f( const float *_x, float *y, int n ) { static const float A4 = (float)(1.000000000000002438532970795181890933776 / EXPPOLY_32F_A0), @@ -789,7 +750,7 @@ static CvStatus CV_STDCALL Exp_32f( const float *_x, float *y, int n ) Cv32suf buf[4]; #if CV_SSE2 - if( n >= 8 && checkHardwareSupport(CV_CPU_SSE) ) + if( n >= 8 && USE_SSE2 ) { static const __m128d prescale2 = _mm_set1_pd(exp_prescale); static const __m128 postscale4 = _mm_set1_ps((float)exp_postscale); @@ -969,12 +930,10 @@ static CvStatus CV_STDCALL Exp_32f( const float *_x, float *y, int n ) y[i] = (float)(buf[0].f * expTab[val0 & EXPTAB_MASK] * EXPPOLY(x0)); } - - return CV_OK; } -static CvStatus CV_STDCALL Exp_64f( const double *_x, double *y, int n ) +static void Exp_64f( const double *_x, double *y, int n ) { static const double A5 = .99999999999999999998285227504999 / EXPPOLY_32F_A0, @@ -992,7 +951,7 @@ static CvStatus CV_STDCALL Exp_64f( const double *_x, double *y, int n ) const Cv64suf* x = (const Cv64suf*)_x; #if CV_SSE2 - if( checkHardwareSupport(CV_CPU_SSE) ) + if( USE_SSE2 ) { static const __m128d prescale2 = _mm_set1_pd(exp_prescale); static const __m128d postscale2 = _mm_set1_pd(exp_postscale); @@ -1145,8 +1104,6 @@ static CvStatus CV_STDCALL Exp_64f( const double *_x, double *y, int n ) y[i] = buf[0].f * expTab[val0 & EXPTAB_MASK] * EXPPOLY( x0 ); } - - return CV_OK; } #undef EXPTAB_SCALE @@ -1160,32 +1117,28 @@ static CvStatus CV_STDCALL Exp_64f( const double *_x, double *y, int n ) #endif -void exp( const Mat& src, Mat& dst ) +void exp( const InputArray& _src, OutputArray _dst ) { - if( src.dims > 2 ) + Mat src = _src.getMat(); + int type = src.type(), depth = src.depth(), cn = src.channels(); + + _dst.create( src.dims, src.size, type ); + Mat dst = _dst.getMat(); + + CV_Assert( depth == CV_32F || depth == CV_64F ); + + const Mat* arrays[] = {&src, &dst, 0}; + uchar* ptrs[2]; + NAryMatIterator it(arrays, ptrs); + int len = (int)(it.size*cn); + + for( size_t i = 0; i < it.nplanes; i++, ++it ) { - dst.create(src.dims, src.size, src.type()); - const Mat* arrays[] = {&src, &dst, 0}; - Mat planes[2]; - NAryMatIterator it(arrays, planes); - - for( int i = 0; i < it.nplanes; i++, ++it ) - exp( it.planes[0], it.planes[1] ); - return; + if( depth == CV_32F ) + Exp_32f( (const float*)ptrs[0], (float*)ptrs[1], len ); + else + Exp_64f( (const double*)ptrs[0], (double*)ptrs[1], len ); } - - int depth = src.depth(); - dst.create( src.size(), src.type() ); - Size size = getContinuousSize( src, dst, src.channels() ); - - if( depth == CV_32F ) - for( int y = 0; y < size.height; y++ ) - Exp_32f( src.ptr(y), dst.ptr(y), size.width ); - else if( depth == CV_64F ) - for( int y = 0; y < size.height; y++ ) - Exp_64f( src.ptr(y), dst.ptr(y), size.width ); - else - CV_Error( CV_StsUnsupportedFormat, "" ); } @@ -1464,7 +1417,7 @@ static const double CV_DECL_ALIGNED(16) icvLogTab[] = { #define LOGTAB_TRANSLATE(x,h) (((x) - 1.)*icvLogTab[(h)+1]) static const double ln_2 = 0.69314718055994530941723212145818; -static CvStatus CV_STDCALL Log_32f( const float *_x, float *y, int n ) +static void Log_32f( const float *_x, float *y, int n ) { static const float shift[] = { 0, -1.f/512 }; static const float @@ -1480,7 +1433,7 @@ static CvStatus CV_STDCALL Log_32f( const float *_x, float *y, int n ) const int* x = (const int*)_x; #if CV_SSE2 - if( checkHardwareSupport(CV_CPU_SSE) ) + if( USE_SSE2 ) { static const __m128d ln2_2 = _mm_set1_pd(ln_2); static const __m128 _1_4 = _mm_set1_ps(1.f); @@ -1610,12 +1563,10 @@ static CvStatus CV_STDCALL Log_32f( const float *_x, float *y, int n ) y[i] = (float)y0; } - - return CV_OK; } -static CvStatus CV_STDCALL Log_64f( const double *x, double *y, int n ) +static void Log_64f( const double *x, double *y, int n ) { static const double shift[] = { 0, -1./512 }; static const double @@ -1638,7 +1589,7 @@ static CvStatus CV_STDCALL Log_64f( const double *x, double *y, int n ) DBLINT *X = (DBLINT *) x; #if CV_SSE2 - if( checkHardwareSupport(CV_CPU_SSE) ) + if( USE_SSE2 ) { static const __m128d ln2_2 = _mm_set1_pd(ln_2); static const __m128d _1_2 = _mm_set1_pd(1.); @@ -1802,8 +1753,6 @@ static CvStatus CV_STDCALL Log_64f( const double *x, double *y, int n ) y0 += LOGPOLY( x0, h0 == 510 ); y[i] = y0; } - - return CV_OK; } #else @@ -1813,46 +1762,39 @@ static CvStatus CV_STDCALL Log_64f( const double *x, double *y, int n ) #endif -void log( const Mat& src, Mat& dst ) +void log( const InputArray& _src, OutputArray _dst ) { - if( src.dims > 2 ) + Mat src = _src.getMat(); + int type = src.type(), depth = src.depth(), cn = src.channels(); + + _dst.create( src.dims, src.size, type ); + Mat dst = _dst.getMat(); + + CV_Assert( depth == CV_32F || depth == CV_64F ); + + const Mat* arrays[] = {&src, &dst, 0}; + uchar* ptrs[2]; + NAryMatIterator it(arrays, ptrs); + int len = (int)(it.size*cn); + + for( size_t i = 0; i < it.nplanes; i++, ++it ) { - dst.create(src.dims, src.size, src.type()); - const Mat* arrays[] = {&src, &dst, 0}; - Mat planes[2]; - NAryMatIterator it(arrays, planes); - - for( int i = 0; i < it.nplanes; i++, ++it ) - log( it.planes[0], it.planes[1] ); - return; + if( depth == CV_32F ) + Log_32f( (const float*)ptrs[0], (float*)ptrs[1], len ); + else + Log_64f( (const double*)ptrs[0], (double*)ptrs[1], len ); } - - int depth = src.depth(); - dst.create( src.size(), src.type() ); - Size size = getContinuousSize( src, dst, src.channels() ); - - if( depth == CV_32F ) - for( int y = 0; y < size.height; y++ ) - Log_32f( src.ptr(y), dst.ptr(y), size.width ); - else if( depth == CV_64F ) - for( int y = 0; y < size.height; y++ ) - Log_64f( src.ptr(y), dst.ptr(y), size.width ); - else - CV_Error( CV_StsUnsupportedFormat, "" ); -} - +} /****************************************************************************************\ * P O W E R * \****************************************************************************************/ template -static CvStatus CV_STDCALL -IPow( const void* _src, void* _dst, int len, int power ) +static void +iPow_( const T* src, T* dst, int len, int power ) { int i; - const T* src = (const T*)_src; - T* dst = (T*)_dst; for( i = 0; i < len; i++ ) { WT a = 1, b = src[i]; @@ -1868,53 +1810,86 @@ IPow( const void* _src, void* _dst, int len, int power ) a *= b; dst[i] = saturate_cast(a); } - return CV_OK; } -typedef CvStatus (CV_STDCALL * IPowFunc)( const void* src, void* dst, int len, int power ); + +void iPow8u(const uchar* src, uchar* dst, int len, int power) +{ + iPow_(src, dst, len, power); +} -void pow( const Mat& _src, double power, Mat& dst ) +void iPow8s(const schar* src, schar* dst, int len, int power) { - if( _src.dims > 2 ) - { - dst.create(_src.dims, _src.size, _src.type()); - const Mat* arrays[] = {&_src, &dst, 0}; - Mat planes[2]; - NAryMatIterator it(arrays, planes); - - for( int i = 0; i < it.nplanes; i++, ++it ) - pow( it.planes[0], power, it.planes[1] ); - return; - } + iPow_(src, dst, len, power); +} + +void iPow16u(const ushort* src, ushort* dst, int len, int power) +{ + iPow_(src, dst, len, power); +} + +void iPow16s(const short* src, short* dst, int len, int power) +{ + iPow_(src, dst, len, power); +} - int ipower = cvRound( power ), i, j; - bool is_ipower = 0; - int depth = _src.depth(); - const Mat* src = &_src; +void iPow32s(const int* src, int* dst, int len, int power) +{ + iPow_(src, dst, len, power); +} + +void iPow32f(const float* src, float* dst, int len, int power) +{ + iPow_(src, dst, len, power); +} + +void iPow64f(const double* src, double* dst, int len, int power) +{ + iPow_(src, dst, len, power); +} - dst.create( _src.size(), _src.type() ); + +typedef void (*IPowFunc)( const uchar* src, uchar* dst, int len, int power ); + +static IPowFunc ipowTab[] = +{ + (IPowFunc)iPow8u, (IPowFunc)iPow8s, (IPowFunc)iPow16u, (IPowFunc)iPow16s, + (IPowFunc)iPow32s, (IPowFunc)iPow32f, (IPowFunc)iPow64f, 0 +}; + +void pow( const InputArray& _src, double power, OutputArray _dst ) +{ + Mat src = _src.getMat(); + int type = src.type(), depth = src.depth(), cn = src.channels(); + + _dst.create( src.dims, src.size, type ); + Mat dst = _dst.getMat(); + + int ipower = cvRound(power); + bool is_ipower = false; + if( fabs(ipower - power) < DBL_EPSILON ) { if( ipower < 0 ) { - divide( 1., _src, dst ); + divide( 1., src, dst ); if( ipower == -1 ) return; ipower = -ipower; - src = &dst; + src = dst; } - + switch( ipower ) { case 0: dst = Scalar::all(1); return; case 1: - src->copyTo(dst); + src.copyTo(dst); return; case 2: - multiply(*src, *src, dst); + multiply(src, src, dst); return; default: is_ipower = true; @@ -1922,87 +1897,84 @@ void pow( const Mat& _src, double power, Mat& dst ) } else CV_Assert( depth == CV_32F || depth == CV_64F ); - - Size size = getContinuousSize( *src, dst, src->channels() ); - + + const Mat* arrays[] = {&src, &dst, 0}; + uchar* ptrs[2]; + NAryMatIterator it(arrays, ptrs); + int len = (int)(it.size*cn); + if( is_ipower ) { - static IPowFunc tab[] = - { - IPow, 0, IPow, IPow, IPow, - IPow, IPow, 0 - }; - - IPowFunc func = tab[depth]; + IPowFunc func = ipowTab[depth]; CV_Assert( func != 0 ); - for( i = 0; i < size.height; i++ ) - func( src->data + src->step*i, dst.data + dst.step*i, size.width, ipower ); + + for( size_t i = 0; i < it.nplanes; i++, ++it ) + func( ptrs[0], ptrs[1], len, ipower ); } else if( fabs(fabs(power) - 0.5) < DBL_EPSILON ) { MathFunc func = power < 0 ? (depth == CV_32F ? (MathFunc)InvSqrt_32f : (MathFunc)InvSqrt_64f) : (depth == CV_32F ? (MathFunc)Sqrt_32f : (MathFunc)Sqrt_64f); - - for( i = 0; i < size.height; i++ ) - func( src->data + src->step*i, dst.data + dst.step*i, size.width ); - } - else if( depth == CV_32F ) - { - const float *x = (const float*)src->data; - float *y = (float*)dst.data; - size_t xstep = src->step/sizeof(x[0]), ystep = dst.step/sizeof(y[0]); - float p = (float)power; - - for( ; size.height--; x += xstep, y += ystep ) - { - for( i = 0; i < size.width; i += MAX_BLOCK_SIZE ) - { - int block_size = std::min(MAX_BLOCK_SIZE, size.width - i); - Log_32f(x + i, y + i, block_size); - for( j = 0; j < block_size; j++ ) - y[i + j] *= p; - Exp_32f(y + i, y + i, block_size); - } - } + + for( size_t i = 0; i < it.nplanes; i++, ++it ) + func( ptrs[0], ptrs[1], len ); } else { - const double *x = (const double*)src->data; - double *y = (double*)dst.data; - size_t xstep = src->step/sizeof(x[0]), ystep = dst.step/sizeof(y[0]); - - for( ; size.height--; x += xstep, y += ystep ) + int j, k, blockSize = std::min(len, ((BLOCK_SIZE + cn-1)/cn)*cn); + size_t esz1 = src.elemSize1(); + + for( size_t i = 0; i < it.nplanes; i++, ++it ) { - for( i = 0; i < size.width; i += MAX_BLOCK_SIZE ) + for( j = 0; j < len; j += blockSize ) { - int block_size = std::min(MAX_BLOCK_SIZE, size.width - i); - Log_64f(x + i, y + i, block_size); - for( j = 0; j < block_size; j++ ) - y[i + j] *= power; - Exp_64f(y + i, y + i, block_size); + int bsz = std::min(len - j, blockSize); + if( depth == CV_32F ) + { + const float* x = (const float*)ptrs[0]; + float* y = (float*)ptrs[1]; + + Log_32f(x, y, bsz); + for( k = 0; k < bsz; k++ ) + y[k] = (float)(y[k]*power); + Exp_32f(y, y, bsz); + } + else + { + const double* x = (const double*)ptrs[0]; + double* y = (double*)ptrs[1]; + + Log_64f(x, y, bsz); + for( k = 0; k < bsz; k++ ) + y[k] *= power; + Exp_64f(y, y, bsz); + } + ptrs[0] += bsz*esz1; + ptrs[1] += bsz*esz1; } } } } -void sqrt(const Mat& a, Mat& b) +void sqrt(const InputArray& a, OutputArray b) { pow(a, 0.5, b); } /************************** CheckArray for NaN's, Inf's *********************************/ -bool checkRange(const Mat& src, bool quiet, Point* pt, +bool checkRange(const InputArray& _src, bool quiet, Point* pt, double minVal, double maxVal) { + Mat src = _src.getMat(); if( src.dims > 2 ) { const Mat* arrays[] = {&src, 0}; Mat planes[1]; NAryMatIterator it(arrays, planes); - for( int i = 0; i < it.nplanes; i++, ++it ) + for( size_t i = 0; i < it.nplanes; i++, ++it ) { if( !checkRange( it.planes[0], quiet, pt, minVal, maxVal )) { @@ -2218,61 +2190,46 @@ CV_IMPL int cvCheckArr( const CvArr* arr, int flags, this copyright notice and the above warranty information. ----------------------------------------------------------------------- */ -CV_IMPL int -cvSolveCubic( const CvMat* coeffs, CvMat* roots ) -{ - int n = 0; +int cv::solveCubic( const InputArray& _coeffs, OutputArray _roots ) +{ + const int n0 = 3; + Mat coeffs = _coeffs.getMat(); + int ctype = coeffs.type(); + + CV_Assert( ctype == CV_32F || ctype == CV_64F ); + CV_Assert( (coeffs.size() == Size(n0, 1) || + coeffs.size() == Size(n0+1, 1) || + coeffs.size() == Size(1, n0) || + coeffs.size() == Size(1, n0+1)) ); + + _roots.create(n0, 1, ctype, -1, true, DEPTH_MASK_FLT); + Mat roots = _roots.getMat(); + + int i = -1, n = 0; double a0 = 1., a1, a2, a3; double x0 = 0., x1 = 0., x2 = 0.; - size_t step = 1; - int coeff_count; - - if( !CV_IS_MAT(coeffs) ) - CV_Error( !coeffs ? CV_StsNullPtr : CV_StsBadArg, "Input parameter is not a valid matrix" ); - - if( !CV_IS_MAT(roots) ) - CV_Error( !roots ? CV_StsNullPtr : CV_StsBadArg, "Output parameter is not a valid matrix" ); - - if( (CV_MAT_TYPE(coeffs->type) != CV_32FC1 && CV_MAT_TYPE(coeffs->type) != CV_64FC1) || - (CV_MAT_TYPE(roots->type) != CV_32FC1 && CV_MAT_TYPE(roots->type) != CV_64FC1) ) - CV_Error( CV_StsUnsupportedFormat, - "Both matrices should be floating-point (single or double precision)" ); - - coeff_count = coeffs->rows + coeffs->cols - 1; - - if( (coeffs->rows != 1 && coeffs->cols != 1) || (coeff_count != 3 && coeff_count != 4) ) - CV_Error( CV_StsBadSize, - "The matrix of coefficients must be 1-dimensional vector of 3 or 4 elements" ); - - if( (roots->rows != 1 && roots->cols != 1) || - roots->rows + roots->cols - 1 != 3 ) - CV_Error( CV_StsBadSize, - "The matrix of roots must be 1-dimensional vector of 3 elements" ); - - if( CV_MAT_TYPE(coeffs->type) == CV_32FC1 ) + int ncoeffs = coeffs.rows + coeffs.cols - 1; + + if( ctype == CV_32FC1 ) { - const float* c = coeffs->data.fl; - if( coeffs->rows > 1 ) - step = coeffs->step/sizeof(c[0]); - if( coeff_count == 4 ) - a0 = c[0], c += step; - a1 = c[0]; - a2 = c[step]; - a3 = c[step*2]; + if( ncoeffs == 4 ) + a0 = coeffs.at(++i); + + a1 = coeffs.at(i+1); + a2 = coeffs.at(i+2); + a3 = coeffs.at(i+3); } else { - const double* c = coeffs->data.db; - if( coeffs->rows > 1 ) - step = coeffs->step/sizeof(c[0]); - if( coeff_count == 4 ) - a0 = c[0], c += step; - a1 = c[0]; - a2 = c[step]; - a3 = c[step*2]; + if( ncoeffs == 4 ) + a0 = coeffs.at(++i); + + a1 = coeffs.at(i+1); + a2 = coeffs.at(i+2); + a3 = coeffs.at(i+3); } - + if( a0 == 0 ) { if( a1 == 0 ) @@ -2315,12 +2272,12 @@ cvSolveCubic( const CvMat* coeffs, CvMat* roots ) a1 *= a0; a2 *= a0; a3 *= a0; - + double Q = (a1 * a1 - 3 * a2) * (1./9); double R = (2 * a1 * a1 * a1 - 9 * a1 * a2 + 27 * a3) * (1./54); double Qcubed = Q * Q * Q; double d = Qcubed - R * R; - + if( d >= 0 ) { double theta = acos(R / sqrt(Qcubed)); @@ -2344,72 +2301,43 @@ cvSolveCubic( const CvMat* coeffs, CvMat* roots ) n = 1; } } - - step = 1; - - if( CV_MAT_TYPE(roots->type) == CV_32FC1 ) + + if( roots.type() == CV_32FC1 ) { - float* r = roots->data.fl; - if( roots->rows > 1 ) - step = roots->step/sizeof(r[0]); - r[0] = (float)x0; - r[step] = (float)x1; - r[step*2] = (float)x2; + roots.at(0) = (float)x0; + roots.at(1) = (float)x1; + roots.at(2) = (float)x2; } else { - double* r = roots->data.db; - if( roots->rows > 1 ) - step = roots->step/sizeof(r[0]); - r[0] = x0; - r[step] = x1; - r[step*2] = x2; + roots.at(0) = x0; + roots.at(1) = x1; + roots.at(2) = x2; } - + return n; } - -int cv::solveCubic( const Mat& coeffs, Mat& roots ) -{ - CV_Assert( coeffs.dims <= 2 ); - const int n = 3; - if( ((roots.rows != 1 || roots.cols != n) && - (roots.rows != n || roots.cols != 1)) || - (roots.type() != CV_32F && roots.type() != CV_64F) ) - roots.create(n, 1, CV_64F); - - CvMat _coeffs = coeffs, _roots = roots; - int nroots = cvSolveCubic( &_coeffs, &_roots); - if( nroots == 0 ) - roots = Mat(); - else if( roots.rows > 1 ) - roots = roots.rowRange(0, nroots); - else - roots = roots.colRange(0, nroots); - return nroots; -} - /* finds complex roots of a polynomial using Durand-Kerner method: http://en.wikipedia.org/wiki/Durand%E2%80%93Kerner_method */ -double cv::solvePoly( const Mat& coeffs0, Mat& roots0, int maxIters ) +double cv::solvePoly( const InputArray& _coeffs0, OutputArray _roots0, int maxIters ) { typedef Complex C; double maxDiff = 0; - int iter, i, j, n; - - CV_Assert( coeffs0.dims <= 2 && - (coeffs0.cols == 1 || coeffs0.rows == 1) && - (coeffs0.depth() == CV_32F || coeffs0.depth() == CV_64F) && - coeffs0.channels() <= 2 ); - n = coeffs0.cols + coeffs0.rows - 2; - - if( ((roots0.rows != 1 || roots0.cols != n) && - (roots0.rows != n || roots0.cols != 1)) || - (roots0.type() != CV_32FC2 && roots0.type() != CV_64FC2) ) - roots0.create( n, 1, CV_64FC2 ); + int iter, i, j; + Mat coeffs0 = _coeffs0.getMat(); + int ctype = _coeffs0.type(); + int cdepth = CV_MAT_DEPTH(ctype); + + CV_Assert( CV_MAT_DEPTH(ctype) >= CV_32F && CV_MAT_CN(ctype) <= 2 ); + CV_Assert( coeffs0.rows == 1 || coeffs0.cols == 1 ); + + int n = coeffs0.cols + coeffs0.rows - 2; + _roots0.create(n, 1, CV_MAKETYPE(cdepth, 2), -1, true, DEPTH_MASK_FLT); + Mat roots0 = _roots0.getMat(); + AutoBuffer buf(n*2+2); C *coeffs = buf, *roots = coeffs + n + 1; Mat coeffs1(coeffs0.size(), CV_MAKETYPE(CV_64F, coeffs0.channels()), coeffs0.channels() == 2 ? coeffs : roots); @@ -2463,6 +2391,16 @@ double cv::solvePoly( const Mat& coeffs0, Mat& roots0, int maxIters ) } +CV_IMPL int +cvSolveCubic( const CvMat* coeffs, CvMat* roots ) +{ + cv::Mat _coeffs = cv::cvarrToMat(coeffs), _roots = cv::cvarrToMat(roots), _roots0 = _roots; + int nroots = cv::solveCubic(_coeffs, _roots); + CV_Assert( _roots.data == _roots0.data ); // check that the array of roots was not reallocated + return nroots; +} + + void cvSolvePoly(const CvMat* a, CvMat *r, int maxiter, int) { cv::Mat _a = cv::cvarrToMat(a), _r = cv::cvarrToMat(r), _r0 = r; diff --git a/modules/core/src/matmul.cpp b/modules/core/src/matmul.cpp index 2c2aa26399..20bb513347 100644 --- a/modules/core/src/matmul.cpp +++ b/modules/core/src/matmul.cpp @@ -11,7 +11,7 @@ // For Open Source Computer Vision Library // // Copyright (C) 2000-2008, Intel Corporation, all rights reserved. -// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2009-2011, Willow Garage Inc., all rights reserved. // Third party copyrights are property of their respective owners. // // Redistribution and use in source and binary forms, with or without modification, @@ -683,9 +683,10 @@ static void GEMMStore_64fc( const Complexd* c_data, size_t c_step, GEMMStore(c_data, c_step, d_buf, d_buf_step, d_data, d_step, d_size, alpha, beta, flags); } +} -void gemm( const Mat& matA, const Mat& matB, double alpha, - const Mat& matC, double beta, Mat& D, int flags ) +void cv::gemm( const InputArray& matA, const InputArray& matB, double alpha, + const InputArray& matC, double beta, OutputArray matD, int flags ) { const int block_lin_size = 128; const int block_size = block_lin_size * block_lin_size; @@ -693,8 +694,7 @@ void gemm( const Mat& matA, const Mat& matB, double alpha, static double zero[] = {0,0,0,0}; static float zerof[] = {0,0,0,0}; - Mat A = matA, B = matB; - const Mat* C = matC.data && beta != 0 ? &matC : 0; + Mat A = matA.getMat(), B = matB.getMat(), C = beta != 0 ? matC.getMat() : Mat(); Size a_size = A.size(), d_size; int i, len = 0, type = A.type(); @@ -724,19 +724,20 @@ void gemm( const Mat& matA, const Mat& matB, double alpha, break; } - if( C ) + if( C.data ) { - CV_Assert( C->type() == type && - (((flags&GEMM_3_T) == 0 && C->rows == d_size.height && C->cols == d_size.width) || - ((flags&GEMM_3_T) != 0 && C->rows == d_size.width && C->cols == d_size.height))); - if( (flags & GEMM_3_T) != 0 && C->data == D.data ) - { - transpose( D, D ); - flags &= ~GEMM_3_T; - } + CV_Assert( C.type() == type && + (((flags&GEMM_3_T) == 0 && C.rows == d_size.height && C.cols == d_size.width) || + ((flags&GEMM_3_T) != 0 && C.rows == d_size.width && C.cols == d_size.height))); } - D.create( d_size.height, d_size.width, type ); + matD.create( d_size.height, d_size.width, type ); + Mat D = matD.getMat(); + if( (flags & GEMM_3_T) != 0 && C.data == D.data ) + { + transpose( C, C ); + flags &= ~GEMM_3_T; + } if( flags == 0 && 2 <= len && len <= 4 && (len == d_size.width || len == d_size.height) ) { @@ -745,11 +746,11 @@ void gemm( const Mat& matA, const Mat& matB, double alpha, float* d = (float*)D.data; const float *a = (const float*)A.data, *b = (const float*)B.data, - *c = (const float*)(C ? C->data : 0); + *c = (const float*)C.data; size_t d_step = D.step/sizeof(d[0]), a_step = A.step/sizeof(a[0]), b_step = B.step/sizeof(b[0]), - c_step = C ? C->step/sizeof(c[0]) : 0; + c_step = C.data ? C.step/sizeof(c[0]) : 0; if( !c ) c = zerof; @@ -873,11 +874,11 @@ void gemm( const Mat& matA, const Mat& matB, double alpha, double* d = (double*)D.data; const double *a = (const double*)A.data, *b = (const double*)B.data, - *c = (const double*)(C ? C->data : 0); + *c = (const double*)C.data; size_t d_step = D.step/sizeof(d[0]), a_step = A.step/sizeof(a[0]), b_step = B.step/sizeof(b[0]), - c_step = C ? C->step/sizeof(c[0]) : 0; + c_step = C.data ? C.step/sizeof(c[0]) : 0; if( !c ) c = zero; @@ -1002,8 +1003,8 @@ void gemm( const Mat& matA, const Mat& matB, double alpha, GEMMBlockMulFunc blockMulFunc; GEMMStoreFunc storeFunc; Mat *matD = &D, tmat; - const uchar* Cdata = C ? C->data : 0; - size_t Cstep = C ? (size_t)C->step : 0; + const uchar* Cdata = C.data; + size_t Cstep = C.data ? (size_t)C.step : 0; AutoBuffer buf; if( type == CV_32FC1 ) @@ -1140,15 +1141,15 @@ void gemm( const Mat& matA, const Mat& matB, double alpha, else b_step0 = elem_size, b_step1 = b_step; - if( !C ) + if( !C.data ) { c_step0 = c_step1 = 0; flags &= ~GEMM_3_T; } else if( !(flags & GEMM_3_T) ) - c_step0 = C->step, c_step1 = elem_size; + c_step0 = C.step, c_step1 = elem_size; else - c_step0 = elem_size, c_step1 = C->step; + c_step0 = elem_size, c_step1 = C.step; dm0 = std::min( block_lin_size, d_size.height ); dn0 = std::min( block_lin_size, d_size.width ); @@ -1265,131 +1266,70 @@ void gemm( const Mat& matA, const Mat& matB, double alpha, * Transform * \****************************************************************************************/ -template static void -transformC1_( const Mat& srcmat, Mat& dstmat, Mat& tmat ) +namespace cv { - Size size = getContinuousSize( srcmat, dstmat ); - const WT* m = (const WT*)tmat.data; - int dst_cn = dstmat.channels(); - int x, y, k; - - for( y = 0; y < size.height; y++ ) - { - const T* src = (const T*)(srcmat.data + srcmat.step*y); - T* dst = (T*)(dstmat.data + dstmat.step*y); - const WT* _m = m; - - for( k = 0; k < dst_cn; k++, dst++, _m += 2 ) - for( x = 0; x < size.width; x++ ) - dst[x*dst_cn] = saturate_cast(_m[0]*src[x] + _m[1]); - } -} template static void -transformC2_( const Mat& srcmat, Mat& dstmat, Mat& tmat ) +transform_( const T* src, T* dst, const WT* m, int len, int scn, int dcn ) { - Size size = getContinuousSize( srcmat, dstmat ); - const WT* m = (const WT*)tmat.data; - int dst_cn = dstmat.channels(); - int x, y, k; - - for( y = 0; y < size.height; y++ ) + int x; + + if( scn == 2 && dcn == 2 ) { - const T* src = (const T*)(srcmat.data + srcmat.step*y); - T* dst = (T*)(dstmat.data + dstmat.step*y); - - if( dst_cn == 2 ) - for( x = 0; x < size.width*2; x += 2 ) - { - WT v0 = src[x], v1 = src[x+1]; - T t0 = saturate_cast(m[0]*v0 + m[1]*v1 + m[2]); - T t1 = saturate_cast(m[3]*v0 + m[4]*v1 + m[5]); - dst[x] = t0; dst[x+1] = t1; - } - else + for( x = 0; x < len*2; x += 2 ) { - const WT* _m = m; - for( k = 0; k < dst_cn; k++, dst++, _m += 3 ) - for( x = 0; x < size.width; x++ ) - dst[x*dst_cn] = saturate_cast(_m[0]*src[x*2] + - _m[1]*src[x*2+1] + _m[2]); + WT v0 = src[x], v1 = src[x+1]; + T t0 = saturate_cast(m[0]*v0 + m[1]*v1 + m[2]); + T t1 = saturate_cast(m[3]*v0 + m[4]*v1 + m[5]); + dst[x] = t0; dst[x+1] = t1; } } -} - -template static void -transformC3_( const Mat& srcmat, Mat& dstmat, Mat& tmat ) -{ - Size size = getContinuousSize( srcmat, dstmat ); - const WT* m = (const WT*)tmat.data; - int dst_cn = dstmat.channels(); - int x, y, k; - - for( y = 0; y < size.height; y++ ) + else if( scn == 3 && dcn == 3 ) { - const T* src = (const T*)(srcmat.data + srcmat.step*y); - T* dst = (T*)(dstmat.data + dstmat.step*y); - - if( dst_cn == 3 ) - for( x = 0; x < size.width*3; x += 3 ) - { - WT v0 = src[x], v1 = src[x+1], v2 = src[x+2]; - T t0 = saturate_cast(m[0]*v0 + m[1]*v1 + m[2]*v2 + m[3]); - T t1 = saturate_cast(m[4]*v0 + m[5]*v1 + m[6]*v2 + m[7]); - T t2 = saturate_cast(m[8]*v0 + m[9]*v1 + m[10]*v2 + m[11]); - dst[x] = t0; dst[x+1] = t1; dst[x+2] = t2; - } - else if( dst_cn == 1 ) - for( x = 0; x < size.width; x++, src += 3 ) - dst[x] = saturate_cast(m[0]*src[0] + m[1]*src[1] + m[2]*src[2] + m[3]); - else + for( x = 0; x < len*3; x += 3 ) { - const WT* _m = m; - for( k = 0; k < dst_cn; k++, dst++, _m += 4 ) - for( x = 0; x < size.width; x++ ) - dst[x*dst_cn] = saturate_cast(_m[0]*src[x*3] + - _m[1]*src[x*3+1] + _m[2]*src[x*3+2] + _m[3]); + WT v0 = src[x], v1 = src[x+1], v2 = src[x+2]; + T t0 = saturate_cast(m[0]*v0 + m[1]*v1 + m[2]*v2 + m[3]); + T t1 = saturate_cast(m[4]*v0 + m[5]*v1 + m[6]*v2 + m[7]); + T t2 = saturate_cast(m[8]*v0 + m[9]*v1 + m[10]*v2 + m[11]); + dst[x] = t0; dst[x+1] = t1; dst[x+2] = t2; } } -} - - -template static void -transformC4_( const Mat& srcmat, Mat& dstmat, Mat& tmat ) -{ - Size size = getContinuousSize( srcmat, dstmat ); - const WT* m = (const WT*)tmat.data; - int dst_cn = dstmat.channels(); - int x, y, k; - - for( y = 0; y < size.height; y++ ) + else if( scn == 3 && dcn == 1 ) { - const T* src = (const T*)(srcmat.data + srcmat.step*y); - T* dst = (T*)(dstmat.data + dstmat.step*y); - - if( dst_cn == 4 ) - for( x = 0; x < size.width*4; x += 4 ) - { - WT v0 = src[x], v1 = src[x+1], v2 = src[x+2], v3 = src[x+3]; - T t0 = saturate_cast(m[0]*v0 + m[1]*v1 + m[2]*v2 + m[3]*v3 + m[4]); - T t1 = saturate_cast(m[5]*v0 + m[6]*v1 + m[7]*v2 + m[8]*v3 + m[9]); - dst[x] = t0; dst[x+1] = t1; - t0 = saturate_cast(m[10]*v0 + m[11]*v1 + m[12]*v2 + m[13]*v3 + m[14]); - t1 = saturate_cast(m[15]*v0 + m[16]*v1 + m[17]*v2 + m[18]*v3 + m[19]); - dst[x+2] = t0; dst[x+3] = t1; - } - else + for( x = 0; x < len; x++, src += 3 ) + dst[x] = saturate_cast(m[0]*src[0] + m[1]*src[1] + m[2]*src[2] + m[3]); + } + else if( scn == 4 && dcn == 4 ) + { + for( x = 0; x < len*4; x += 4 ) + { + WT v0 = src[x], v1 = src[x+1], v2 = src[x+2], v3 = src[x+3]; + T t0 = saturate_cast(m[0]*v0 + m[1]*v1 + m[2]*v2 + m[3]*v3 + m[4]); + T t1 = saturate_cast(m[5]*v0 + m[6]*v1 + m[7]*v2 + m[8]*v3 + m[9]); + dst[x] = t0; dst[x+1] = t1; + t0 = saturate_cast(m[10]*v0 + m[11]*v1 + m[12]*v2 + m[13]*v3 + m[14]); + t1 = saturate_cast(m[15]*v0 + m[16]*v1 + m[17]*v2 + m[18]*v3 + m[19]); + dst[x+2] = t0; dst[x+3] = t1; + } + } + else + { + for( x = 0; x < len; x++, src += scn, dst += dcn ) { const WT* _m = m; - for( k = 0; k < dst_cn; k++, dst++, _m += 5 ) - for( x = 0; x < size.width; x++ ) - dst[x*dst_cn] = saturate_cast(_m[0]*src[x*4] + _m[1]*src[x*4+1] + - _m[2]*src[x*4+2] + _m[3]*src[x*4+3] + _m[4]); + int j, k; + for( j = 0; j < dcn; j++, _m += scn + 1 ) + { + WT s = _m[scn]; + for( k = 0; k < scn; k++ ) + s += _m[k]*src[k]; + dst[j] = saturate_cast(s); + } } } } - #if CV_SSE2 static inline void @@ -1411,19 +1351,16 @@ load4x4Matrix( const float* m, __m128& m0, __m128& m1, __m128& m2, __m128& m3, _ m4 = _mm_setr_ps(m[4], m[9], m[14], m[19]); } -template<> void -transformC3_( const Mat& srcmat, Mat& dstmat, Mat& tmat ) +#endif + +static void +transform_8u( const uchar* src, uchar* dst, const float* m, int len, int scn, int dcn ) { - typedef uchar T; - typedef float WT; +#if CV_SSE2 const int BITS = 10, SCALE = 1 << BITS; const float MAX_M = (float)(1 << (15 - BITS)); - Size size = getContinuousSize( srcmat, dstmat ); - const float* m = (const float*)tmat.data; - int dst_cn = dstmat.channels(); - int x, y, k; - if( checkHardwareSupport(CV_CPU_SSE2) && dst_cn == 3 && + if( USE_SSE2 && scn == 3 && dcn == 3 && std::abs(m[0]) < MAX_M && std::abs(m[1]) < MAX_M && std::abs(m[2]) < MAX_M && std::abs(m[3]) < MAX_M*256 && std::abs(m[4]) < MAX_M && std::abs(m[5]) < MAX_M && std::abs(m[6]) < MAX_M && std::abs(m[7]) < MAX_M*256 && std::abs(m[8]) < MAX_M && std::abs(m[9]) < MAX_M && std::abs(m[10]) < MAX_M && std::abs(m[11]) < MAX_M*256 ) @@ -1441,238 +1378,182 @@ transformC3_( const Mat& srcmat, Mat& dstmat, Mat& tmat ) __m128i m1 = _mm_setr_epi16(0, m10, m11, m12, m10, m11, m12, 0); __m128i m2 = _mm_setr_epi16(0, m20, m21, m22, m20, m21, m22, 0); __m128i m3 = _mm_setr_epi32(m03, m13, m23, 0); - - for( y = 0; y < size.height; y++ ) - { - const T* src = (const T*)(srcmat.data + srcmat.step*y); - T* dst = (T*)(dstmat.data + dstmat.step*y); - int x = 0; - - for( ; x <= (size.width - 8)*3; x += 8*3 ) - { - __m128i z = _mm_setzero_si128(), t0, t1, t2, r0, r1; - __m128i v0 = _mm_loadl_epi64((const __m128i*)(src + x)); - __m128i v1 = _mm_loadl_epi64((const __m128i*)(src + x + 8)); - __m128i v2 = _mm_loadl_epi64((const __m128i*)(src + x + 16)), v3; - v0 = _mm_unpacklo_epi8(v0, z); // b0 g0 r0 b1 g1 r1 b2 g2 - v1 = _mm_unpacklo_epi8(v1, z); // r2 b3 g3 r3 b4 g4 r4 b5 - v2 = _mm_unpacklo_epi8(v2, z); // g5 r5 b6 g6 r6 b7 g7 r7 - - v3 = _mm_srli_si128(v2, 2); // ? b6 g6 r6 b7 g7 r7 0 - v2 = _mm_or_si128(_mm_slli_si128(v2, 10), _mm_srli_si128(v1, 6)); // ? b4 g4 r4 b5 g5 r5 ? - v1 = _mm_or_si128(_mm_slli_si128(v1, 6), _mm_srli_si128(v0, 10)); // ? b2 g2 r2 b3 g3 r3 ? - v0 = _mm_slli_si128(v0, 2); // 0 b0 g0 r0 b1 g1 r1 ? - - // process pixels 0 & 1 - t0 = _mm_madd_epi16(v0, m0); // a0 b0 a1 b1 - t1 = _mm_madd_epi16(v0, m1); // c0 d0 c1 d1 - t2 = _mm_madd_epi16(v0, m2); // e0 f0 e1 f1 - v0 = _mm_unpacklo_epi32(t0, t1); // a0 c0 b0 d0 - t0 = _mm_unpackhi_epi32(t0, t1); // a1 b1 c1 d1 - t1 = _mm_unpacklo_epi32(t2, z); // e0 0 f0 0 - t2 = _mm_unpackhi_epi32(t2, z); // e1 0 f1 0 - r0 = _mm_add_epi32(_mm_add_epi32(_mm_unpacklo_epi64(v0, t1), _mm_unpackhi_epi64(v0,t1)), m3); // B0 G0 R0 0 - r1 = _mm_add_epi32(_mm_add_epi32(_mm_unpacklo_epi64(t0, t2), _mm_unpackhi_epi64(t0,t2)), m3); // B1 G1 R1 0 - r0 = _mm_srai_epi32(r0, BITS); - r1 = _mm_srai_epi32(r1, BITS); - v0 = _mm_packus_epi16(_mm_packs_epi32(_mm_slli_si128(r0, 4), r1), z); // 0 B0 G0 R0 B1 G1 R1 0 - - // process pixels 2 & 3 - t0 = _mm_madd_epi16(v1, m0); // a0 b0 a1 b1 - t1 = _mm_madd_epi16(v1, m1); // c0 d0 c1 d1 - t2 = _mm_madd_epi16(v1, m2); // e0 f0 e1 f1 - v1 = _mm_unpacklo_epi32(t0, t1); // a0 c0 b0 d0 - t0 = _mm_unpackhi_epi32(t0, t1); // a1 b1 c1 d1 - t1 = _mm_unpacklo_epi32(t2, z); // e0 0 f0 0 - t2 = _mm_unpackhi_epi32(t2, z); // e1 0 f1 0 - r0 = _mm_add_epi32(_mm_add_epi32(_mm_unpacklo_epi64(v1, t1), _mm_unpackhi_epi64(v1,t1)), m3); // B2 G2 R2 0 - r1 = _mm_add_epi32(_mm_add_epi32(_mm_unpacklo_epi64(t0, t2), _mm_unpackhi_epi64(t0,t2)), m3); // B3 G3 R3 0 - r0 = _mm_srai_epi32(r0, BITS); - r1 = _mm_srai_epi32(r1, BITS); - v1 = _mm_packus_epi16(_mm_packs_epi32(_mm_slli_si128(r0, 4), r1), z); // 0 B2 G2 R2 B3 G3 R3 0 - - // process pixels 4 & 5 - t0 = _mm_madd_epi16(v2, m0); // a0 b0 a1 b1 - t1 = _mm_madd_epi16(v2, m1); // c0 d0 c1 d1 - t2 = _mm_madd_epi16(v2, m2); // e0 f0 e1 f1 - v2 = _mm_unpacklo_epi32(t0, t1); // a0 c0 b0 d0 - t0 = _mm_unpackhi_epi32(t0, t1); // a1 b1 c1 d1 - t1 = _mm_unpacklo_epi32(t2, z); // e0 0 f0 0 - t2 = _mm_unpackhi_epi32(t2, z); // e1 0 f1 0 - r0 = _mm_add_epi32(_mm_add_epi32(_mm_unpacklo_epi64(v2, t1), _mm_unpackhi_epi64(v2,t1)), m3); // B4 G4 R4 0 - r1 = _mm_add_epi32(_mm_add_epi32(_mm_unpacklo_epi64(t0, t2), _mm_unpackhi_epi64(t0,t2)), m3); // B5 G5 R5 0 - r0 = _mm_srai_epi32(r0, BITS); - r1 = _mm_srai_epi32(r1, BITS); - v2 = _mm_packus_epi16(_mm_packs_epi32(_mm_slli_si128(r0, 4), r1), z); // 0 B4 G4 R4 B5 G5 R5 0 - - // process pixels 6 & 7 - t0 = _mm_madd_epi16(v3, m0); // a0 b0 a1 b1 - t1 = _mm_madd_epi16(v3, m1); // c0 d0 c1 d1 - t2 = _mm_madd_epi16(v3, m2); // e0 f0 e1 f1 - v3 = _mm_unpacklo_epi32(t0, t1); // a0 c0 b0 d0 - t0 = _mm_unpackhi_epi32(t0, t1); // a1 b1 c1 d1 - t1 = _mm_unpacklo_epi32(t2, z); // e0 0 f0 0 - t2 = _mm_unpackhi_epi32(t2, z); // e1 0 f1 0 - r0 = _mm_add_epi32(_mm_add_epi32(_mm_unpacklo_epi64(v3, t1), _mm_unpackhi_epi64(v3,t1)), m3); // B6 G6 R6 0 - r1 = _mm_add_epi32(_mm_add_epi32(_mm_unpacklo_epi64(t0, t2), _mm_unpackhi_epi64(t0,t2)), m3); // B7 G7 R7 0 - r0 = _mm_srai_epi32(r0, BITS); - r1 = _mm_srai_epi32(r1, BITS); - v3 = _mm_packus_epi16(_mm_packs_epi32(_mm_slli_si128(r0, 4), r1), z); // 0 B6 G6 R6 B7 G7 R7 0 - - v0 = _mm_or_si128(_mm_srli_si128(v0, 1), _mm_slli_si128(v1, 5)); - v1 = _mm_or_si128(_mm_srli_si128(v1, 3), _mm_slli_si128(v2, 3)); - v2 = _mm_or_si128(_mm_srli_si128(v2, 5), _mm_slli_si128(v3, 1)); - _mm_storel_epi64((__m128i*)(dst + x), v0); - _mm_storel_epi64((__m128i*)(dst + x + 8), v1); - _mm_storel_epi64((__m128i*)(dst + x + 16), v2); - } - - for( ; x < size.width*3; x += 3 ) - { - int v0 = src[x], v1 = src[x+1], v2 = src[x+2]; - uchar t0 = saturate_cast((m00*v0 + m01*v1 + m02*v2 + m03)>>BITS); - uchar t1 = saturate_cast((m10*v0 + m11*v1 + m12*v2 + m13)>>BITS); - uchar t2 = saturate_cast((m20*v0 + m21*v1 + m22*v2 + m23)>>BITS); - dst[x] = t0; dst[x+1] = t1; dst[x+2] = t2; - } + int x = 0; + + for( ; x <= (len - 8)*3; x += 8*3 ) + { + __m128i z = _mm_setzero_si128(), t0, t1, t2, r0, r1; + __m128i v0 = _mm_loadl_epi64((const __m128i*)(src + x)); + __m128i v1 = _mm_loadl_epi64((const __m128i*)(src + x + 8)); + __m128i v2 = _mm_loadl_epi64((const __m128i*)(src + x + 16)), v3; + v0 = _mm_unpacklo_epi8(v0, z); // b0 g0 r0 b1 g1 r1 b2 g2 + v1 = _mm_unpacklo_epi8(v1, z); // r2 b3 g3 r3 b4 g4 r4 b5 + v2 = _mm_unpacklo_epi8(v2, z); // g5 r5 b6 g6 r6 b7 g7 r7 + + v3 = _mm_srli_si128(v2, 2); // ? b6 g6 r6 b7 g7 r7 0 + v2 = _mm_or_si128(_mm_slli_si128(v2, 10), _mm_srli_si128(v1, 6)); // ? b4 g4 r4 b5 g5 r5 ? + v1 = _mm_or_si128(_mm_slli_si128(v1, 6), _mm_srli_si128(v0, 10)); // ? b2 g2 r2 b3 g3 r3 ? + v0 = _mm_slli_si128(v0, 2); // 0 b0 g0 r0 b1 g1 r1 ? + + // process pixels 0 & 1 + t0 = _mm_madd_epi16(v0, m0); // a0 b0 a1 b1 + t1 = _mm_madd_epi16(v0, m1); // c0 d0 c1 d1 + t2 = _mm_madd_epi16(v0, m2); // e0 f0 e1 f1 + v0 = _mm_unpacklo_epi32(t0, t1); // a0 c0 b0 d0 + t0 = _mm_unpackhi_epi32(t0, t1); // a1 b1 c1 d1 + t1 = _mm_unpacklo_epi32(t2, z); // e0 0 f0 0 + t2 = _mm_unpackhi_epi32(t2, z); // e1 0 f1 0 + r0 = _mm_add_epi32(_mm_add_epi32(_mm_unpacklo_epi64(v0, t1), _mm_unpackhi_epi64(v0,t1)), m3); // B0 G0 R0 0 + r1 = _mm_add_epi32(_mm_add_epi32(_mm_unpacklo_epi64(t0, t2), _mm_unpackhi_epi64(t0,t2)), m3); // B1 G1 R1 0 + r0 = _mm_srai_epi32(r0, BITS); + r1 = _mm_srai_epi32(r1, BITS); + v0 = _mm_packus_epi16(_mm_packs_epi32(_mm_slli_si128(r0, 4), r1), z); // 0 B0 G0 R0 B1 G1 R1 0 + + // process pixels 2 & 3 + t0 = _mm_madd_epi16(v1, m0); // a0 b0 a1 b1 + t1 = _mm_madd_epi16(v1, m1); // c0 d0 c1 d1 + t2 = _mm_madd_epi16(v1, m2); // e0 f0 e1 f1 + v1 = _mm_unpacklo_epi32(t0, t1); // a0 c0 b0 d0 + t0 = _mm_unpackhi_epi32(t0, t1); // a1 b1 c1 d1 + t1 = _mm_unpacklo_epi32(t2, z); // e0 0 f0 0 + t2 = _mm_unpackhi_epi32(t2, z); // e1 0 f1 0 + r0 = _mm_add_epi32(_mm_add_epi32(_mm_unpacklo_epi64(v1, t1), _mm_unpackhi_epi64(v1,t1)), m3); // B2 G2 R2 0 + r1 = _mm_add_epi32(_mm_add_epi32(_mm_unpacklo_epi64(t0, t2), _mm_unpackhi_epi64(t0,t2)), m3); // B3 G3 R3 0 + r0 = _mm_srai_epi32(r0, BITS); + r1 = _mm_srai_epi32(r1, BITS); + v1 = _mm_packus_epi16(_mm_packs_epi32(_mm_slli_si128(r0, 4), r1), z); // 0 B2 G2 R2 B3 G3 R3 0 + + // process pixels 4 & 5 + t0 = _mm_madd_epi16(v2, m0); // a0 b0 a1 b1 + t1 = _mm_madd_epi16(v2, m1); // c0 d0 c1 d1 + t2 = _mm_madd_epi16(v2, m2); // e0 f0 e1 f1 + v2 = _mm_unpacklo_epi32(t0, t1); // a0 c0 b0 d0 + t0 = _mm_unpackhi_epi32(t0, t1); // a1 b1 c1 d1 + t1 = _mm_unpacklo_epi32(t2, z); // e0 0 f0 0 + t2 = _mm_unpackhi_epi32(t2, z); // e1 0 f1 0 + r0 = _mm_add_epi32(_mm_add_epi32(_mm_unpacklo_epi64(v2, t1), _mm_unpackhi_epi64(v2,t1)), m3); // B4 G4 R4 0 + r1 = _mm_add_epi32(_mm_add_epi32(_mm_unpacklo_epi64(t0, t2), _mm_unpackhi_epi64(t0,t2)), m3); // B5 G5 R5 0 + r0 = _mm_srai_epi32(r0, BITS); + r1 = _mm_srai_epi32(r1, BITS); + v2 = _mm_packus_epi16(_mm_packs_epi32(_mm_slli_si128(r0, 4), r1), z); // 0 B4 G4 R4 B5 G5 R5 0 + + // process pixels 6 & 7 + t0 = _mm_madd_epi16(v3, m0); // a0 b0 a1 b1 + t1 = _mm_madd_epi16(v3, m1); // c0 d0 c1 d1 + t2 = _mm_madd_epi16(v3, m2); // e0 f0 e1 f1 + v3 = _mm_unpacklo_epi32(t0, t1); // a0 c0 b0 d0 + t0 = _mm_unpackhi_epi32(t0, t1); // a1 b1 c1 d1 + t1 = _mm_unpacklo_epi32(t2, z); // e0 0 f0 0 + t2 = _mm_unpackhi_epi32(t2, z); // e1 0 f1 0 + r0 = _mm_add_epi32(_mm_add_epi32(_mm_unpacklo_epi64(v3, t1), _mm_unpackhi_epi64(v3,t1)), m3); // B6 G6 R6 0 + r1 = _mm_add_epi32(_mm_add_epi32(_mm_unpacklo_epi64(t0, t2), _mm_unpackhi_epi64(t0,t2)), m3); // B7 G7 R7 0 + r0 = _mm_srai_epi32(r0, BITS); + r1 = _mm_srai_epi32(r1, BITS); + v3 = _mm_packus_epi16(_mm_packs_epi32(_mm_slli_si128(r0, 4), r1), z); // 0 B6 G6 R6 B7 G7 R7 0 + + v0 = _mm_or_si128(_mm_srli_si128(v0, 1), _mm_slli_si128(v1, 5)); + v1 = _mm_or_si128(_mm_srli_si128(v1, 3), _mm_slli_si128(v2, 3)); + v2 = _mm_or_si128(_mm_srli_si128(v2, 5), _mm_slli_si128(v3, 1)); + _mm_storel_epi64((__m128i*)(dst + x), v0); + _mm_storel_epi64((__m128i*)(dst + x + 8), v1); + _mm_storel_epi64((__m128i*)(dst + x + 16), v2); + } + + for( ; x < len*3; x += 3 ) + { + int v0 = src[x], v1 = src[x+1], v2 = src[x+2]; + uchar t0 = saturate_cast((m00*v0 + m01*v1 + m02*v2 + m03)>>BITS); + uchar t1 = saturate_cast((m10*v0 + m11*v1 + m12*v2 + m13)>>BITS); + uchar t2 = saturate_cast((m20*v0 + m21*v1 + m22*v2 + m23)>>BITS); + dst[x] = t0; dst[x+1] = t1; dst[x+2] = t2; } return; } - - for( y = 0; y < size.height; y++ ) - { - const T* src = (const T*)(srcmat.data + srcmat.step*y); - T* dst = (T*)(dstmat.data + dstmat.step*y); - - if( dst_cn == 1 ) - for( x = 0; x < size.width; x++, src += 3 ) - dst[x] = saturate_cast(m[0]*CV_8TO32F(src[0]) + - m[1]*CV_8TO32F(src[1]) + m[2]*CV_8TO32F(src[2]) + m[3]); - else - { - const WT* _m = m; - for( k = 0; k < dst_cn; k++, dst++, _m += 4 ) - for( x = 0; x < size.width; x++ ) - dst[x*dst_cn] = saturate_cast(_m[0]*CV_8TO32F(src[x*3]) + - _m[1]*CV_8TO32F(src[x*3+1]) + _m[2]*CV_8TO32F(src[x*3+2]) + _m[3]); - } - } +#endif + + transform_(src, dst, m, len, scn, dcn); } -template<> void -transformC3_( const Mat& srcmat, Mat& dstmat, Mat& tmat ) +static void +transform_16u( const ushort* src, ushort* dst, const float* m, int len, int scn, int dcn ) { - typedef ushort T; - typedef float WT; - Size size = getContinuousSize( srcmat, dstmat ); - const float* m = (const float*)tmat.data; - int dst_cn = dstmat.channels(); - int x, y, k; - - if( checkHardwareSupport(CV_CPU_SSE2) && dst_cn == 3 ) +#if CV_SSE2 + if( USE_SSE2 && scn == 3 && dcn == 3 ) { __m128 m0, m1, m2, m3; __m128i delta = _mm_setr_epi16(0,-32768,-32768,-32768,-32768,-32768,-32768,0); load3x3Matrix(m, m0, m1, m2, m3); m3 = _mm_sub_ps(m3, _mm_setr_ps(32768.f, 32768.f, 32768.f, 0.f)); - for( y = 0; y < size.height; y++ ) - { - const T* src = (const T*)(srcmat.data + srcmat.step*y); - T* dst = (T*)(dstmat.data + dstmat.step*y); - int x = 0; - - for( ; x <= (size.width - 4)*3; x += 4*3 ) - { - __m128i z = _mm_setzero_si128(); - __m128i v0 = _mm_loadu_si128((const __m128i*)(src + x)), v1; - __m128i v2 = _mm_loadl_epi64((const __m128i*)(src + x + 8)), v3; - v1 = _mm_unpacklo_epi16(_mm_srli_si128(v0, 6), z); // b1 g1 r1 - v3 = _mm_unpacklo_epi16(_mm_srli_si128(v2, 2), z); // b3 g3 r3 - v2 = _mm_or_si128(_mm_srli_si128(v0, 12), _mm_slli_si128(v2, 4)); - v0 = _mm_unpacklo_epi16(v0, z); // b0 g0 r0 - v2 = _mm_unpacklo_epi16(v2, z); // b2 g2 r2 - __m128 x0 = _mm_cvtepi32_ps(v0), x1 = _mm_cvtepi32_ps(v1); - __m128 x2 = _mm_cvtepi32_ps(v2), x3 = _mm_cvtepi32_ps(v3); - __m128 y0 = _mm_add_ps(_mm_add_ps(_mm_add_ps( - _mm_mul_ps(m0, _mm_shuffle_ps(x0,x0,_MM_SHUFFLE(0,0,0,0))), - _mm_mul_ps(m1, _mm_shuffle_ps(x0,x0,_MM_SHUFFLE(1,1,1,1)))), - _mm_mul_ps(m2, _mm_shuffle_ps(x0,x0,_MM_SHUFFLE(2,2,2,2)))), m3); - __m128 y1 = _mm_add_ps(_mm_add_ps(_mm_add_ps( - _mm_mul_ps(m0, _mm_shuffle_ps(x1,x1,_MM_SHUFFLE(0,0,0,0))), - _mm_mul_ps(m1, _mm_shuffle_ps(x1,x1,_MM_SHUFFLE(1,1,1,1)))), - _mm_mul_ps(m2, _mm_shuffle_ps(x1,x1,_MM_SHUFFLE(2,2,2,2)))), m3); - __m128 y2 = _mm_add_ps(_mm_add_ps(_mm_add_ps( - _mm_mul_ps(m0, _mm_shuffle_ps(x2,x2,_MM_SHUFFLE(0,0,0,0))), - _mm_mul_ps(m1, _mm_shuffle_ps(x2,x2,_MM_SHUFFLE(1,1,1,1)))), - _mm_mul_ps(m2, _mm_shuffle_ps(x2,x2,_MM_SHUFFLE(2,2,2,2)))), m3); - __m128 y3 = _mm_add_ps(_mm_add_ps(_mm_add_ps( - _mm_mul_ps(m0, _mm_shuffle_ps(x3,x3,_MM_SHUFFLE(0,0,0,0))), - _mm_mul_ps(m1, _mm_shuffle_ps(x3,x3,_MM_SHUFFLE(1,1,1,1)))), - _mm_mul_ps(m2, _mm_shuffle_ps(x3,x3,_MM_SHUFFLE(2,2,2,2)))), m3); - v0 = _mm_cvtps_epi32(y0); v1 = _mm_cvtps_epi32(y1); - v2 = _mm_cvtps_epi32(y2); v3 = _mm_cvtps_epi32(y3); - - v0 = _mm_add_epi16(_mm_packs_epi32(_mm_slli_si128(v0,4), v1), delta); // 0 b0 g0 r0 b1 g1 r1 0 - v2 = _mm_add_epi16(_mm_packs_epi32(_mm_slli_si128(v2,4), v3), delta); // 0 b2 g2 r2 b3 g3 r3 0 - v1 = _mm_or_si128(_mm_srli_si128(v0,2), _mm_slli_si128(v2,10)); // b0 g0 r0 b1 g1 r1 b2 g2 - v2 = _mm_srli_si128(v2, 6); // r2 b3 g3 r3 0 0 0 0 - _mm_storeu_si128((__m128i*)(dst + x), v1); - _mm_storel_epi64((__m128i*)(dst + x + 8), v2); - } - - for( ; x < size.width*3; x += 3 ) - { - WT v0 = src[x], v1 = src[x+1], v2 = src[x+2]; - T t0 = saturate_cast(m[0]*v0 + m[1]*v1 + m[2]*v2 + m[3]); - T t1 = saturate_cast(m[4]*v0 + m[5]*v1 + m[6]*v2 + m[7]); - T t2 = saturate_cast(m[8]*v0 + m[9]*v1 + m[10]*v2 + m[11]); - dst[x] = t0; dst[x+1] = t1; dst[x+2] = t2; - } + int x = 0; + for( ; x <= (len - 4)*3; x += 4*3 ) + { + __m128i z = _mm_setzero_si128(); + __m128i v0 = _mm_loadu_si128((const __m128i*)(src + x)), v1; + __m128i v2 = _mm_loadl_epi64((const __m128i*)(src + x + 8)), v3; + v1 = _mm_unpacklo_epi16(_mm_srli_si128(v0, 6), z); // b1 g1 r1 + v3 = _mm_unpacklo_epi16(_mm_srli_si128(v2, 2), z); // b3 g3 r3 + v2 = _mm_or_si128(_mm_srli_si128(v0, 12), _mm_slli_si128(v2, 4)); + v0 = _mm_unpacklo_epi16(v0, z); // b0 g0 r0 + v2 = _mm_unpacklo_epi16(v2, z); // b2 g2 r2 + __m128 x0 = _mm_cvtepi32_ps(v0), x1 = _mm_cvtepi32_ps(v1); + __m128 x2 = _mm_cvtepi32_ps(v2), x3 = _mm_cvtepi32_ps(v3); + __m128 y0 = _mm_add_ps(_mm_add_ps(_mm_add_ps( + _mm_mul_ps(m0, _mm_shuffle_ps(x0,x0,_MM_SHUFFLE(0,0,0,0))), + _mm_mul_ps(m1, _mm_shuffle_ps(x0,x0,_MM_SHUFFLE(1,1,1,1)))), + _mm_mul_ps(m2, _mm_shuffle_ps(x0,x0,_MM_SHUFFLE(2,2,2,2)))), m3); + __m128 y1 = _mm_add_ps(_mm_add_ps(_mm_add_ps( + _mm_mul_ps(m0, _mm_shuffle_ps(x1,x1,_MM_SHUFFLE(0,0,0,0))), + _mm_mul_ps(m1, _mm_shuffle_ps(x1,x1,_MM_SHUFFLE(1,1,1,1)))), + _mm_mul_ps(m2, _mm_shuffle_ps(x1,x1,_MM_SHUFFLE(2,2,2,2)))), m3); + __m128 y2 = _mm_add_ps(_mm_add_ps(_mm_add_ps( + _mm_mul_ps(m0, _mm_shuffle_ps(x2,x2,_MM_SHUFFLE(0,0,0,0))), + _mm_mul_ps(m1, _mm_shuffle_ps(x2,x2,_MM_SHUFFLE(1,1,1,1)))), + _mm_mul_ps(m2, _mm_shuffle_ps(x2,x2,_MM_SHUFFLE(2,2,2,2)))), m3); + __m128 y3 = _mm_add_ps(_mm_add_ps(_mm_add_ps( + _mm_mul_ps(m0, _mm_shuffle_ps(x3,x3,_MM_SHUFFLE(0,0,0,0))), + _mm_mul_ps(m1, _mm_shuffle_ps(x3,x3,_MM_SHUFFLE(1,1,1,1)))), + _mm_mul_ps(m2, _mm_shuffle_ps(x3,x3,_MM_SHUFFLE(2,2,2,2)))), m3); + v0 = _mm_cvtps_epi32(y0); v1 = _mm_cvtps_epi32(y1); + v2 = _mm_cvtps_epi32(y2); v3 = _mm_cvtps_epi32(y3); + + v0 = _mm_add_epi16(_mm_packs_epi32(_mm_slli_si128(v0,4), v1), delta); // 0 b0 g0 r0 b1 g1 r1 0 + v2 = _mm_add_epi16(_mm_packs_epi32(_mm_slli_si128(v2,4), v3), delta); // 0 b2 g2 r2 b3 g3 r3 0 + v1 = _mm_or_si128(_mm_srli_si128(v0,2), _mm_slli_si128(v2,10)); // b0 g0 r0 b1 g1 r1 b2 g2 + v2 = _mm_srli_si128(v2, 6); // r2 b3 g3 r3 0 0 0 0 + _mm_storeu_si128((__m128i*)(dst + x), v1); + _mm_storel_epi64((__m128i*)(dst + x + 8), v2); + } + + for( ; x < len*3; x += 3 ) + { + float v0 = src[x], v1 = src[x+1], v2 = src[x+2]; + ushort t0 = saturate_cast(m[0]*v0 + m[1]*v1 + m[2]*v2 + m[3]); + ushort t1 = saturate_cast(m[4]*v0 + m[5]*v1 + m[6]*v2 + m[7]); + ushort t2 = saturate_cast(m[8]*v0 + m[9]*v1 + m[10]*v2 + m[11]); + dst[x] = t0; dst[x+1] = t1; dst[x+2] = t2; } return; } - - for( y = 0; y < size.height; y++ ) - { - const T* src = (const T*)(srcmat.data + srcmat.step*y); - T* dst = (T*)(dstmat.data + dstmat.step*y); - - if( dst_cn == 1 ) - for( x = 0; x < size.width; x++, src += 3 ) - dst[x] = saturate_cast(m[0]*src[0] + m[1]*src[1] + m[2]*src[2] + m[3]); - else - { - const WT* _m = m; - for( k = 0; k < dst_cn; k++, dst++, _m += 4 ) - for( x = 0; x < size.width; x++ ) - dst[x*dst_cn] = saturate_cast(_m[0]*src[x*3] + _m[1]*src[x*3+1] + _m[2]*src[x*3+2] + _m[3]); - } - } +#endif + + transform_(src, dst, m, len, scn, dcn); } - -template<> void -transformC3_( const Mat& srcmat, Mat& dstmat, Mat& tmat ) + + +static void +transform_32f( const float* src, float* dst, const float* m, int len, int scn, int dcn ) { - typedef float T; - typedef float WT; - Size size = getContinuousSize( srcmat, dstmat ); - const float* m = (const float*)tmat.data; - int dst_cn = dstmat.channels(); - int x, y, k; - - if( checkHardwareSupport(CV_CPU_SSE2) && dst_cn == 3 ) +#if CV_SSE2 + if( USE_SSE2 ) { - __m128 m0, m1, m2, m3; - load3x3Matrix(m, m0, m1, m2, m3); - - for( y = 0; y < size.height; y++ ) + int x = 0; + if( scn == 3 && dcn == 3 ) { - const T* src = (const T*)(srcmat.data + srcmat.step*y); - T* dst = (T*)(dstmat.data + dstmat.step*y); - int x = 0; + __m128 m0, m1, m2, m3; + load3x3Matrix(m, m0, m1, m2, m3); - for( ; x < (size.width - 1)*3; x += 3 ) + for( ; x < (len - 1)*3; x += 3 ) { __m128 x0 = _mm_loadu_ps(src + x); __m128 y0 = _mm_add_ps(_mm_add_ps(_mm_add_ps( @@ -1683,119 +1564,82 @@ transformC3_( const Mat& srcmat, Mat& dstmat, Mat& tmat ) _mm_store_ss(dst + x + 2, _mm_movehl_ps(y0,y0)); } - for( ; x < size.width*3; x += 3 ) + for( ; x < len*3; x += 3 ) { - WT v0 = src[x], v1 = src[x+1], v2 = src[x+2]; - T t0 = saturate_cast(m[0]*v0 + m[1]*v1 + m[2]*v2 + m[3]); - T t1 = saturate_cast(m[4]*v0 + m[5]*v1 + m[6]*v2 + m[7]); - T t2 = saturate_cast(m[8]*v0 + m[9]*v1 + m[10]*v2 + m[11]); + float v0 = src[x], v1 = src[x+1], v2 = src[x+2]; + float t0 = saturate_cast(m[0]*v0 + m[1]*v1 + m[2]*v2 + m[3]); + float t1 = saturate_cast(m[4]*v0 + m[5]*v1 + m[6]*v2 + m[7]); + float t2 = saturate_cast(m[8]*v0 + m[9]*v1 + m[10]*v2 + m[11]); dst[x] = t0; dst[x+1] = t1; dst[x+2] = t2; } + return; } - return; - } - - for( y = 0; y < size.height; y++ ) - { - const T* src = (const T*)(srcmat.data + srcmat.step*y); - T* dst = (T*)(dstmat.data + dstmat.step*y); - - if( dst_cn == 1 ) - for( x = 0; x < size.width; x++, src += 3 ) - dst[x] = saturate_cast(m[0]*src[0] + m[1]*src[1] + m[2]*src[2] + m[3]); - else - { - const WT* _m = m; - for( k = 0; k < dst_cn; k++, dst++, _m += 4 ) - for( x = 0; x < size.width; x++ ) - dst[x*dst_cn] = saturate_cast(_m[0]*src[x*3] + _m[1]*src[x*3+1] + _m[2]*src[x*3+2] + _m[3]); - } - } -} - - -template<> void -transformC4_( const Mat& srcmat, Mat& dstmat, Mat& tmat ) -{ - typedef float T; - typedef float WT; - Size size = getContinuousSize( srcmat, dstmat ); - const WT* m = (const WT*)tmat.data; - int dst_cn = dstmat.channels(); - int x, y, k; - - if( checkHardwareSupport(CV_CPU_SSE2) && dst_cn == 4 ) - { - __m128 m0, m1, m2, m3, m4; - load4x4Matrix(m, m0, m1, m2, m3, m4); - - for( y = 0; y < size.height; y++ ) + + if( scn == 4 && dcn == 4 ) { - const T* src = (const T*)(srcmat.data + srcmat.step*y); - T* dst = (T*)(dstmat.data + dstmat.step*y); - for( x = 0; x < size.width*4; x += 4 ) + __m128 m0, m1, m2, m3, m4; + load4x4Matrix(m, m0, m1, m2, m3, m4); + + for( ; x < len*4; x += 4 ) { __m128 x0 = _mm_loadu_ps(src + x); __m128 y0 = _mm_add_ps(_mm_add_ps(_mm_add_ps(_mm_add_ps( - _mm_mul_ps(m0, _mm_shuffle_ps(x0,x0,_MM_SHUFFLE(0,0,0,0))), - _mm_mul_ps(m1, _mm_shuffle_ps(x0,x0,_MM_SHUFFLE(1,1,1,1)))), - _mm_mul_ps(m2, _mm_shuffle_ps(x0,x0,_MM_SHUFFLE(2,2,2,2)))), - _mm_mul_ps(m3, _mm_shuffle_ps(x0,x0,_MM_SHUFFLE(3,3,3,3)))), m4); + _mm_mul_ps(m0, _mm_shuffle_ps(x0,x0,_MM_SHUFFLE(0,0,0,0))), + _mm_mul_ps(m1, _mm_shuffle_ps(x0,x0,_MM_SHUFFLE(1,1,1,1)))), + _mm_mul_ps(m2, _mm_shuffle_ps(x0,x0,_MM_SHUFFLE(2,2,2,2)))), + _mm_mul_ps(m3, _mm_shuffle_ps(x0,x0,_MM_SHUFFLE(3,3,3,3)))), m4); _mm_storeu_ps(dst + x, y0); } + return; } - return; } +#endif - for( y = 0; y < size.height; y++ ) - { - const T* src = (const T*)(srcmat.data + srcmat.step*y); - T* dst = (T*)(dstmat.data + dstmat.step*y); - const WT* _m = m; - for( k = 0; k < dst_cn; k++, dst++, _m += 5 ) - for( x = 0; x < size.width; x++ ) - dst[x*dst_cn] = saturate_cast(_m[0]*src[x*4] + _m[1]*src[x*4+1] + - _m[2]*src[x*4+2] + _m[3]*src[x*4+3] + _m[4]); - } + transform_(src, dst, m, len, scn, dcn); } -#endif +static void +transform_8s(const schar* src, schar* dst, const float* m, int len, int scn, int dcn) +{ + transform_(src, dst, m, len, scn, dcn); +} -template static void -diagtransC2_( const Mat& srcmat, Mat& dstmat, Mat& tmat ) +static void +transform_16s(const short* src, short* dst, const float* m, int len, int scn, int dcn) { - Size size = getContinuousSize( srcmat, dstmat ); - const WT* m = (const WT*)tmat.data; - int x, y; + transform_(src, dst, m, len, scn, dcn); +} - for( y = 0; y < size.height; y++ ) +static void +transform_32s(const int* src, int* dst, const double* m, int len, int scn, int dcn) +{ + transform_(src, dst, m, len, scn, dcn); +} + +static void +transform_64f(const double* src, double* dst, const double* m, int len, int scn, int dcn) +{ + transform_(src, dst, m, len, scn, dcn); +} + +template static void +diagtransform_( const T* src, T* dst, const WT* m, int len, int cn, int ) +{ + int x; + + if( cn == 2 ) { - const T* src = (const T*)(srcmat.data + srcmat.step*y); - T* dst = (T*)(dstmat.data + dstmat.step*y); - - for( x = 0; x < size.width*2; x += 2 ) + for( x = 0; x < len*2; x += 2 ) { T t0 = saturate_cast(m[0]*src[x] + m[2]); T t1 = saturate_cast(m[4]*src[x+1] + m[5]); dst[x] = t0; dst[x+1] = t1; } } -} - -template static void -diagtransC3_( const Mat& srcmat, Mat& dstmat, Mat& tmat ) -{ - Size size = getContinuousSize( srcmat, dstmat ); - const WT* m = (const WT*)tmat.data; - int x, y; - - for( y = 0; y < size.height; y++ ) + else if( cn == 3 ) { - const T* src = (const T*)(srcmat.data + srcmat.step*y); - T* dst = (T*)(dstmat.data + dstmat.step*y); - - for( x = 0; x < size.width*3; x += 3 ) + for( x = 0; x < len*3; x += 3 ) { T t0 = saturate_cast(m[0]*src[x] + m[3]); T t1 = saturate_cast(m[5]*src[x+1] + m[7]); @@ -1803,21 +1647,9 @@ diagtransC3_( const Mat& srcmat, Mat& dstmat, Mat& tmat ) dst[x] = t0; dst[x+1] = t1; dst[x+2] = t2; } } -} - -template static void -diagtransC4_( const Mat& srcmat, Mat& dstmat, Mat& tmat ) -{ - Size size = getContinuousSize( srcmat, dstmat ); - const WT* m = (const WT*)tmat.data; - int x, y; - - for( y = 0; y < size.height; y++ ) + else if( cn == 4 ) { - const T* src = (const T*)(srcmat.data + srcmat.step*y); - T* dst = (T*)(dstmat.data + dstmat.step*y); - - for( x = 0; x < size.width*4; x += 4 ) + for( x = 0; x < len*4; x += 4 ) { T t0 = saturate_cast(m[0]*src[x] + m[4]); T t1 = saturate_cast(m[6]*src[x+1] + m[9]); @@ -1827,49 +1659,108 @@ diagtransC4_( const Mat& srcmat, Mat& dstmat, Mat& tmat ) dst[x+2] = t0; dst[x+3] = t1; } } + else + { + for( x = 0; x < len; x++, src += cn, dst += cn ) + { + const WT* _m = m; + for( int j = 0; j < cn; j++, _m += cn + 1 ) + dst[j] = src[j]*_m[j] + _m[cn]; + } + } } -typedef void (*TransformFunc)( const Mat &src, Mat& dst, Mat& M ); - -void transform( const Mat& src, Mat& dst, const Mat& _m ) +static void +diagtransform_8u(const uchar* src, uchar* dst, const float* m, int len, int scn, int dcn) { - static TransformFunc tab[2][32] = - { - {transformC1_, 0, transformC1_, transformC1_, - transformC1_, transformC1_, transformC1_, 0, - transformC2_, 0, transformC2_, transformC2_, - transformC2_, transformC2_, transformC2_, 0, - transformC3_, 0, transformC3_, transformC3_, - transformC3_, transformC3_, transformC3_, 0, - transformC4_, 0, transformC4_, transformC4_, - transformC4_, transformC4_, transformC4_, 0}, + diagtransform_(src, dst, m, len, scn, dcn); +} + +static void +diagtransform_8s(const schar* src, schar* dst, const float* m, int len, int scn, int dcn) +{ + diagtransform_(src, dst, m, len, scn, dcn); +} - {0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, diagtransC2_, diagtransC2_, - diagtransC2_, diagtransC2_, diagtransC2_, 0, - 0, 0, diagtransC3_, diagtransC3_, - diagtransC3_, diagtransC3_, diagtransC3_, 0, - 0, 0, diagtransC4_, diagtransC4_, - diagtransC4_, diagtransC4_, diagtransC4_, 0} - }; +static void +diagtransform_16u(const ushort* src, ushort* dst, const float* m, int len, int scn, int dcn) +{ + diagtransform_(src, dst, m, len, scn, dcn); +} + +static void +diagtransform_16s(const short* src, short* dst, const float* m, int len, int scn, int dcn) +{ + diagtransform_(src, dst, m, len, scn, dcn); +} - int type = src.type(), depth = src.depth(), scn = src.channels(), dcn = _m.rows; - bool isDiag = false; - CV_Assert( (scn == _m.cols || scn + 1 == _m.cols) && scn <= 4 && dcn <= 4 ); +static void +diagtransform_32s(const int* src, int* dst, const double* m, int len, int scn, int dcn) +{ + diagtransform_(src, dst, m, len, scn, dcn); +} - double mbuf[20] = {0}; - Mat m = _m; +static void +diagtransform_32f(const float* src, float* dst, const float* m, int len, int scn, int dcn) +{ + diagtransform_(src, dst, m, len, scn, dcn); +} + +static void +diagtransform_64f(const double* src, double* dst, const double* m, int len, int scn, int dcn) +{ + diagtransform_(src, dst, m, len, scn, dcn); +} + + +typedef void (*TransformFunc)( const uchar* src, uchar* dst, const uchar* m, int, int, int ); + +static TransformFunc transformTab[] = +{ + (TransformFunc)transform_8u, (TransformFunc)transform_8s, (TransformFunc)transform_16u, + (TransformFunc)transform_16s, (TransformFunc)transform_32s, (TransformFunc)transform_32f, + (TransformFunc)transform_64f, 0 +}; - dst.create( src.size(), CV_MAKETYPE(depth, dcn) ); - Size size = getContinuousSize( src, dst ); +static TransformFunc diagTransformTab[] = +{ + (TransformFunc)diagtransform_8u, (TransformFunc)diagtransform_8s, (TransformFunc)diagtransform_16u, + (TransformFunc)diagtransform_16s, (TransformFunc)diagtransform_32s, (TransformFunc)diagtransform_32f, + (TransformFunc)diagtransform_64f, 0 +}; + +} + +void cv::transform( const InputArray& _src, OutputArray _dst, const InputArray& _mtx ) +{ + Mat src = _src.getMat(), m = _mtx.getMat(); + int depth = src.depth(), scn = src.channels(), dcn = m.rows; + CV_Assert( scn == m.cols || scn + 1 == m.cols ); + bool isDiag = false; + + _dst.create( src.size(), CV_MAKETYPE(depth, dcn) ); + Mat dst = _dst.getMat(); int mtype = depth == CV_32S || depth == CV_64F ? CV_64F : CV_32F; - if( !_m.isContinuous() || _m.type() != mtype || _m.cols != scn + 1 ) + AutoBuffer _mbuf; + double* mbuf = _mbuf; + + if( !m.isContinuous() || m.type() != mtype || m.cols != scn + 1 ) { - m = Mat(dcn, scn + 1, mtype, mbuf); - Mat tmat_part = m.colRange(0, _m.cols); - _m.convertTo(tmat_part, mtype); + _mbuf.allocate(dcn*(scn+1)); + Mat tmp(dcn, scn+1, mtype, (double*)_mbuf); + memset(tmp.data, 0, tmp.total()*tmp.elemSize()); + if( m.cols == scn+1 ) + m.convertTo(tmp, mtype); + else + { + Mat tmppart = tmp.colRange(0, m.cols); + m.convertTo(tmppart, mtype); + } + m = tmp; } + else + mbuf = (double*)m.data; if( scn == dcn ) { @@ -1880,10 +1771,10 @@ void transform( const Mat& src, Mat& dst, const Mat& _m ) { double alpha, beta; if( mtype == CV_32F ) - alpha = ((float*)m.data)[0], beta = ((float*)m.data)[1]; + alpha = m.at(0), beta = m.at(1); else - alpha = ((double*)m.data)[0], beta = ((double*)m.data)[1]; - src.convertTo( dst, dst.type(), alpha, beta ); + alpha = m.at(0), beta = m.at(1); + src.convertTo(dst, dst.type(), alpha, beta); return; } @@ -1891,279 +1782,306 @@ void transform( const Mat& src, Mat& dst, const Mat& _m ) { for( j = 0; isDiag && j < scn; j++ ) { - double v = mtype == CV_32F ? ((float*)m.data)[i*(scn+1)+j] : - ((double*)m.data)[i*(scn+1)+j]; + double v = mtype == CV_32F ? m.at(i, j) : m.at(i, j); if( i != j && fabs(v) > eps ) isDiag = false; } } - - if( isDiag && depth == CV_8U ) - { - Mat lut(1, 256, CV_8UC(scn)); - for( i = 0; i < scn; i++ ) - { - uchar* data = lut.data + i; - double val, delta; - if( mtype == CV_32F ) - { - val = ((float*)m.data)[i*(scn+1) + scn]; - delta = ((float*)m.data)[i*(scn+1) + i]; - } - else - { - val = ((double*)m.data)[i*(scn+1) + scn]; - delta = ((double*)m.data)[i*(scn+1) + i]; - } - for( j = 0; j < 256; j++, val += delta ) - { - int ival = cvRound(val); - data[j*scn] = CV_CAST_8U(ival); - } - } - LUT( src, lut, dst ); - return; - } } - TransformFunc func = tab[isDiag][type]; + TransformFunc func = isDiag ? diagTransformTab[depth] : transformTab[depth]; CV_Assert( func != 0 ); - func( src, dst, m ); + + const Mat* arrays[] = {&src, &dst, 0}; + uchar* ptrs[2]; + NAryMatIterator it(arrays, ptrs); + size_t i, total = it.size; + + for( i = 0; i < it.nplanes; i++, ++it ) + func( ptrs[0], ptrs[1], (uchar*)mbuf, (int)total, scn, dcn ); } - /****************************************************************************************\ * Perspective Transform * \****************************************************************************************/ -template static void -perspectiveTransform2_( const Mat& srcmat, Mat& dstmat, const double* mat ) +namespace cv { - Size size = getContinuousSize( srcmat, dstmat, srcmat.channels() ); - for( int i = 0; i < size.height; i++ ) +template static void +perspectiveTransform_( const T* src, T* dst, const double* m, int len, int scn, int dcn ) +{ + const double eps = FLT_EPSILON; + int i; + + if( scn == 2 && dcn == 2 ) { - const T* src = (const T*)(srcmat.data + srcmat.step*i); - T* dst = (T*)(dstmat.data + dstmat.step*i); - - for( int j = 0; j < size.width; j += 2 ) + for( i = 0; i < len*2; i += 2 ) { - T x = src[j], y = src[j + 1]; - double w = x*mat[6] + y*mat[7] + mat[8]; + T x = src[i], y = src[i + 1]; + double w = x*m[6] + y*m[7] + m[8]; - if( fabs(w) > FLT_EPSILON ) + if( fabs(w) > eps ) { w = 1./w; - dst[j] = (T)((x*mat[0] + y*mat[1] + mat[2])*w); - dst[j+1] = (T)((x*mat[3] + y*mat[4] + mat[5])*w); + dst[i] = (T)((x*m[0] + y*m[1] + m[2])*w); + dst[i+1] = (T)((x*m[3] + y*m[4] + m[5])*w); } else - dst[j] = dst[j+1] = (T)0; + dst[i] = dst[i+1] = (T)0; } } -} - -template static void -perspectiveTransform3_( const Mat& srcmat, Mat& dstmat, const double* mat ) -{ - Size size = getContinuousSize( srcmat, dstmat, srcmat.channels() ); - - for( int i = 0; i < size.height; i++ ) + else if( scn == 3 && dcn == 3 ) { - const T* src = (const T*)(srcmat.data + srcmat.step*i); - T* dst = (T*)(dstmat.data + dstmat.step*i); - - for( int j = 0; j < size.width; j += 3 ) + for( i = 0; i < len*3; i += 3 ) { - T x = src[j], y = src[j + 1], z = src[j + 2]; - double w = x*mat[12] + y*mat[13] + z*mat[14] + mat[15]; - - if( fabs(w) > FLT_EPSILON ) + T x = src[i], y = src[i + 1], z = src[i + 2]; + double w = x*m[12] + y*m[13] + z*m[14] + m[15]; + + if( fabs(w) > eps ) { w = 1./w; - dst[j] = (T)((x*mat[0] + y*mat[1] + z*mat[2] + mat[3]) * w); - dst[j+1] = (T)((x*mat[4] + y*mat[5] + z*mat[6] + mat[7]) * w); - dst[j+2] = (T)((x*mat[8] + y*mat[9] + z*mat[10] + mat[11]) * w); + dst[i] = (T)((x*m[0] + y*m[1] + z*m[2] + m[3]) * w); + dst[i+1] = (T)((x*m[4] + y*m[5] + z*m[6] + m[7]) * w); + dst[i+2] = (T)((x*m[8] + y*m[9] + z*m[10] + m[11]) * w); } else - dst[j] = dst[j+1] = dst[j+2] = (T)0; + dst[i] = dst[i+1] = dst[i+2] = (T)0; } } -} - -template static void -perspectiveTransform23_( const Mat& srcmat, Mat& dstmat, const double* mat ) -{ - Size size = getContinuousSize( srcmat, dstmat, srcmat.channels() ); - - for( int i = 0; i < size.height; i++ ) + else if( scn == 3 && dcn == 2 ) { - const T* src = (const T*)(srcmat.data + srcmat.step*i); - T* dst = (T*)(dstmat.data + dstmat.step*i); - - for( int j = 0; j < size.width; j++, src += 3, dst += 2 ) + for( i = 0; i < len; i++, src += 3, dst += 2 ) { T x = src[0], y = src[1], z = src[2]; - double w = x*mat[8] + y*mat[9] + z*mat[10] + mat[11]; - - if( fabs(w) > FLT_EPSILON ) + double w = x*m[8] + y*m[9] + z*m[10] + m[11]; + + if( fabs(w) > eps ) { w = 1./w; - dst[0] = (T)((x*mat[0] + y*mat[1] + z*mat[2] + mat[3])*w); - dst[1] = (T)((x*mat[4] + y*mat[5] + z*mat[6] + mat[7])*w); + dst[0] = (T)((x*m[0] + y*m[1] + z*m[2] + m[3])*w); + dst[1] = (T)((x*m[4] + y*m[5] + z*m[6] + m[7])*w); } else dst[0] = dst[1] = (T)0; } } + else + { + for( i = 0; i < len; i++, src += scn, dst += dcn ) + { + const double* _m = m + dcn*(scn + 1); + double w = _m[scn]; + int j, k; + for( k = 0; k < scn; k++ ) + w += _m[k]*src[k]; + if( fabs(w) > eps ) + { + _m = m; + for( j = 0; j < dcn; j++, _m += scn + 1 ) + { + double s = _m[scn]; + for( k = 0; k < scn; k++ ) + s += _m[k]*src[k]; + dst[j] = (T)(s*w); + } + } + else + for( j = 0; j < dcn; j++ ) + dst[j] = 0; + } + } } -typedef void (*PerspectiveTransformFunc)(const Mat& src, Mat& dst, const double* mat ); - -void perspectiveTransform( const Mat& src, Mat& dst, const Mat& _m ) + +static void +perspectiveTransform_32f(const float* src, float* dst, const double* m, int len, int scn, int dcn) { - int depth = src.depth(), scn = src.channels(), dcn = _m.rows-1; - CV_Assert( (depth == CV_32F || depth == CV_64F) && scn+1 == _m.cols && scn <= 4 && - ((scn == 2 && dcn == 2) || (scn == 3 && dcn == 3) || (scn == 2 && dcn == 3))); - - double mbuf[16] = {0}; - Mat tmat; - const double* m = (const double*)_m.data; - - dst.create( src.size(), CV_MAKETYPE(depth, dcn) ); - - if( !_m.isContinuous() || _m.type() != CV_64F ) - { - tmat = Mat(dcn + 1, scn + 1, CV_64F, mbuf); - _m.convertTo(tmat, CV_64F); - m = (const double*)tmat.data; - } + perspectiveTransform_(src, dst, m, len, scn, dcn); +} - PerspectiveTransformFunc func = 0; - if( scn == 2 && dcn == 2 ) - { - if(depth == CV_32F) - func = perspectiveTransform2_; - else - func = perspectiveTransform2_; - } - else if( scn == 2 && dcn == 3 ) - { - if(depth == CV_32F) - func = perspectiveTransform23_; - else - func = perspectiveTransform23_; - } - else if( scn == 3 && dcn == 3 ) +static void +perspectiveTransform_64f(const double* src, double* dst, const double* m, int len, int scn, int dcn) +{ + perspectiveTransform_(src, dst, m, len, scn, dcn); +} + +} + +void cv::perspectiveTransform( const InputArray& _src, OutputArray _dst, const InputArray& _mtx ) +{ + Mat src = _src.getMat(), m = _mtx.getMat(); + int depth = src.depth(), scn = src.channels(), dcn = m.rows-1; + CV_Assert( scn + 1 == m.cols && (depth == CV_32F || depth == CV_64F)); + + _dst.create( src.size(), CV_MAKETYPE(depth, dcn) ); + Mat dst = _dst.getMat(); + + const int mtype = CV_64F; + AutoBuffer _mbuf; + double* mbuf = _mbuf; + + if( !m.isContinuous() || m.type() != mtype ) { - if(depth == CV_32F) - func = perspectiveTransform3_; - else - func = perspectiveTransform3_; + _mbuf.allocate((dcn+1)*(scn+1)); + Mat tmp(dcn+1, scn+1, mtype, (double*)_mbuf); + m.convertTo(tmp, mtype); + m = tmp; } else - CV_Error( CV_StsNotImplemented, "Only 2->2, 2->3 and 3->3 perspective transformation is implemented" ); - func( src, dst, m ); -} + mbuf = (double*)m.data; + + TransformFunc func = depth == CV_32F ? + (TransformFunc)perspectiveTransform_32f : + (TransformFunc)perspectiveTransform_64f; + CV_Assert( func != 0 ); + + const Mat* arrays[] = {&src, &dst, 0}; + uchar* ptrs[2]; + NAryMatIterator it(arrays, ptrs); + size_t i, total = it.size; + + for( i = 0; i < it.nplanes; i++, ++it ) + func( ptrs[0], ptrs[1], (uchar*)mbuf, (int)total, scn, dcn ); +} /****************************************************************************************\ * ScaleAdd * \****************************************************************************************/ -void scaleAdd( const Mat& src1, double alpha, const Mat& src2, Mat& dst ) +namespace cv { - if( src1.dims > 2 || src2.dims > 2 ) - { - dst.create(src1.dims, src1.size, src1.type()); - const Mat* arrays[] = {&src1, &src2, &dst, 0}; - Mat planes[3]; - NAryMatIterator it(arrays, planes); - - for( int i = 0; i < it.nplanes; i++, ++it ) - scaleAdd( it.planes[0], alpha, it.planes[1], it.planes[2] ); - return; - } - - int type = src1.type(), depth = CV_MAT_DEPTH(type); - CV_Assert( src1.size() == src2.size() && type == src2.type() ); - dst.create( src1.size(), type ); - Size size = getContinuousSize( src1, src2, dst, src1.channels() ); - if( depth == CV_32F ) +static void scaleAdd_32f(const float* src1, const float* src2, float* dst, + int len, float* _alpha) +{ + float alpha = *_alpha; + int i = 0; +#if CV_SSE2 + if( USE_SSE2 ) { - const float *s1 = (const float*)src1.data, *s2 = (const float*)src2.data; - float* d = (float*)dst.data; - size_t step1 = src1.step/sizeof(s1[0]), step2 = src2.step/sizeof(s2[0]); - size_t step = dst.step/sizeof(d[0]); - - if( size.width == 1 ) - { - for( ; size.height--; s1 += step1, s2 += step2, d += step ) - d[0] = (float)(s1[0]*alpha + s2[0]); - return; - } - - for( ; size.height--; s1 += step1, s2 += step2, d += step ) - { - int i; - for( i = 0; i <= size.width - 4; i += 4 ) + __m128 a4 = _mm_set1_ps(alpha); + if( (((size_t)src1|(size_t)src2|(size_t)dst) & 15) == 0 ) + for( ; i <= len - 8; i += 8 ) { - float t0 = (float)(s1[i]*alpha + s2[i]); - float t1 = (float)(s1[i+1]*alpha + s2[i+1]); - d[i] = t0; - d[i+1] = t1; - t0 = (float)(s1[i+2]*alpha + s2[i+2]); - t1 = (float)(s1[i+3]*alpha + s2[i+3]); - d[i+2] = t0; - d[i+3] = t1; + __m128 x0, x1, y0, y1, t0, t1; + x0 = _mm_load_ps(src1 + i); x1 = _mm_load_ps(src1 + i + 4); + y0 = _mm_load_ps(src2 + i); y1 = _mm_load_ps(src2 + i + 4); + t0 = _mm_add_ps(_mm_mul_ps(x0, a4), y0); + t1 = _mm_add_ps(_mm_mul_ps(x1, a4), y1); + _mm_store_ps(dst + i, t0); + _mm_store_ps(dst + i + 4, t1); + } + else + for( ; i <= len - 8; i += 8 ) + { + __m128 x0, x1, y0, y1, t0, t1; + x0 = _mm_loadu_ps(src1 + i); x1 = _mm_loadu_ps(src1 + i + 4); + y0 = _mm_loadu_ps(src2 + i); y1 = _mm_loadu_ps(src2 + i + 4); + t0 = _mm_add_ps(_mm_mul_ps(x0, a4), y0); + t1 = _mm_add_ps(_mm_mul_ps(x1, a4), y1); + _mm_storeu_ps(dst + i, t0); + _mm_storeu_ps(dst + i + 4, t1); } - - for( ; i < size.width; i++ ) - d[i] = (float)(s1[i]*alpha + s2[i]); - } } - else if( depth == CV_64F ) - { - const double *s1 = (const double*)src1.data, *s2 = (const double*)src2.data; - double* d = (double*)dst.data; - size_t step1 = src1.step/sizeof(s1[0]), step2 = src2.step/sizeof(s2[0]); - size_t step = dst.step/sizeof(d[0]); + else +#endif + for( ; i <= len - 4; i += 4 ) + { + float t0, t1; + t0 = src1[i]*alpha + src2[i]; + t1 = src1[i+1]*alpha + src2[i+1]; + dst[i] = t0; dst[i+1] = t1; + t0 = src1[i+2]*alpha + src2[i+2]; + t1 = src1[i+3]*alpha + src2[i+3]; + dst[i+2] = t0; dst[i+3] = t1; + } + for( ; i < len; i++ ) + dst[i] = src1[i]*alpha + src2[i]; +} - if( size.width == 1 ) + +static void scaleAdd_64f(const double* src1, const double* src2, double* dst, + int len, double* _alpha) +{ + double alpha = *_alpha; + int i = 0; +#if CV_SSE2 + if( USE_SSE2 && (((size_t)src1|(size_t)src2|(size_t)dst) & 15) == 0 ) + { + __m128d a2 = _mm_set1_pd(alpha); + for( ; i <= len - 4; i += 4 ) { - for( ; size.height--; s1 += step1, s2 += step2, d += step ) - d[0] = s1[0]*alpha + s2[0]; - return; + __m128d x0, x1, y0, y1, t0, t1; + x0 = _mm_load_pd(src1 + i); x1 = _mm_load_pd(src1 + i + 2); + y0 = _mm_load_pd(src2 + i); y1 = _mm_load_pd(src2 + i + 2); + t0 = _mm_add_pd(_mm_mul_pd(x0, a2), y0); + t1 = _mm_add_pd(_mm_mul_pd(x1, a2), y1); + _mm_store_pd(dst + i, t0); + _mm_store_pd(dst + i + 2, t1); } + } + else +#endif + for( ; i <= len - 4; i += 4 ) + { + double t0, t1; + t0 = src1[i]*alpha + src2[i]; + t1 = src1[i+1]*alpha + src2[i+1]; + dst[i] = t0; dst[i+1] = t1; + t0 = src1[i+2]*alpha + src2[i+2]; + t1 = src1[i+3]*alpha + src2[i+3]; + dst[i+2] = t0; dst[i+3] = t1; + } + for( ; i < len; i++ ) + dst[i] = src1[i]*alpha + src2[i]; +} - for( ; size.height--; s1 += step1, s2 += step2, d += step ) - { - int i; - for( i = 0; i <= size.width - 4; i += 4 ) - { - double t0 = s1[i]*alpha + s2[i]; - double t1 = s1[i+1]*alpha + s2[i+1]; - d[i] = t0; - d[i+1] = t1; - t0 = s1[i+2]*alpha + s2[i+2]; - t1 = s1[i+3]*alpha + s2[i+3]; - d[i+2] = t0; - d[i+3] = t1; - } +typedef void (*ScaleAddFunc)(const uchar* src1, const uchar* src2, uchar* dst, int len, const void* alpha); - for( ; i < size.width; i++ ) - d[i] = s1[i]*alpha + s2[i]; - } +} + +void cv::scaleAdd( const InputArray& _src1, double alpha, const InputArray& _src2, OutputArray _dst ) +{ + Mat src1 = _src1.getMat(), src2 = _src2.getMat(); + int depth = src1.depth(), cn = src1.channels(); + + CV_Assert( src1.type() == src2.type() ); + if( depth < CV_32F ) + { + addWeighted(_src1, alpha, _src2, 1, 0, _dst, depth); + return; } - else - addWeighted(src1, alpha, src2, 1, 0, dst); + + _dst.create(src1.dims, src1.size, src1.type()); + Mat dst = _dst.getMat(); + + float falpha = (float)alpha; + void* palpha = depth == CV_32F ? (void*)&falpha : (void*)α + + ScaleAddFunc func = depth == CV_32F ? (ScaleAddFunc)scaleAdd_32f : (ScaleAddFunc)scaleAdd_64f; + + if( src1.isContinuous() && src2.isContinuous() && dst.isContinuous() ) + { + size_t len = src1.total()*cn; + func(src1.data, src2.data, dst.data, (int)len, palpha); + return; + } + + const Mat* arrays[] = {&src1, &src2, &dst, 0}; + uchar* ptrs[3]; + NAryMatIterator it(arrays, ptrs); + size_t i, len = it.size*cn; + + for( i = 0; i < it.nplanes; i++, ++it ) + func( ptrs[0], ptrs[1], ptrs[2], (int)len, palpha ); } /****************************************************************************************\ * Covariation Matrix * \****************************************************************************************/ -void calcCovarMatrix( const Mat* data, int nsamples, Mat& covar, Mat& _mean, int flags, int ctype ) +void cv::calcCovarMatrix( const Mat* data, int nsamples, Mat& covar, Mat& _mean, int flags, int ctype ) { CV_Assert( data && nsamples > 0 ); Size size = data[0].size(); @@ -2202,30 +2120,37 @@ void calcCovarMatrix( const Mat* data, int nsamples, Mat& covar, Mat& _mean, int _mean = mean.reshape(1, size.height); } -void calcCovarMatrix( const Mat& data, Mat& covar, Mat& _mean, int flags, int ctype ) +void cv::calcCovarMatrix( const InputArray& _data, OutputArray _covar, InputOutputArray _mean, int flags, int ctype ) { + Mat data = _data.getMat(), mean; CV_Assert( ((flags & CV_COVAR_ROWS) != 0) ^ ((flags & CV_COVAR_COLS) != 0) ); bool takeRows = (flags & CV_COVAR_ROWS) != 0; int type = data.type(); int nsamples = takeRows ? data.rows : data.cols; CV_Assert( nsamples > 0 ); Size size = takeRows ? Size(data.cols, 1) : Size(1, data.rows); - Mat mean = _mean; - ctype = std::max(std::max(CV_MAT_DEPTH(ctype >= 0 ? ctype : type), _mean.depth()), CV_32F); if( (flags & CV_COVAR_USE_AVG) != 0 ) { + mean = _mean.getMat(); + ctype = std::max(std::max(CV_MAT_DEPTH(ctype >= 0 ? ctype : type), mean.depth()), CV_32F); CV_Assert( mean.size() == size ); if( mean.type() != ctype ) - _mean.convertTo(mean, ctype); + { + _mean.create(mean.size(), ctype); + Mat tmp = _mean.getMat(); + mean.convertTo(tmp, ctype); + mean = tmp; + } } else { - reduce( data, _mean, takeRows ? 0 : 1, CV_REDUCE_AVG, ctype ); - mean = _mean; + ctype = std::max(CV_MAT_DEPTH(ctype >= 0 ? ctype : type), CV_32F); + reduce( _data, _mean, takeRows ? 0 : 1, CV_REDUCE_AVG, ctype ); + mean = _mean.getMat(); } - mulTransposed( data, covar, ((flags & CV_COVAR_NORMAL) == 0) ^ takeRows, + mulTransposed( data, _covar, ((flags & CV_COVAR_NORMAL) == 0) ^ takeRows, mean, (flags & CV_COVAR_SCALE) != 0 ? 1./nsamples : 1, ctype ); } @@ -2233,8 +2158,9 @@ void calcCovarMatrix( const Mat& data, Mat& covar, Mat& _mean, int flags, int ct * Mahalanobis * \****************************************************************************************/ -double Mahalanobis( const Mat& v1, const Mat& v2, const Mat& icovar ) +double cv::Mahalanobis( const InputArray& _v1, const InputArray& _v2, const InputArray& _icovar ) { + Mat v1 = _v1.getMat(), v2 = _v2.getMat(), icovar = _icovar.getMat(); int type = v1.type(), depth = v1.depth(); Size sz = v1.size(); int i, j, len = sz.width*sz.height*v1.channels(); @@ -2313,15 +2239,18 @@ double Mahalanobis( const Mat& v1, const Mat& v2, const Mat& icovar ) return std::sqrt(result); } -double Mahalonobis(const Mat& v1, const Mat& v2, const Mat& icovar) +double cv::Mahalonobis( const InputArray& _v1, const InputArray& _v2, const InputArray& _icovar ) { - return Mahalanobis(v1, v2, icovar); + return Mahalanobis(_v1, _v2, _icovar); } /****************************************************************************************\ -* cvMulTransposed * +* MulTransposed * \****************************************************************************************/ +namespace cv +{ + template static void MulTransposedR( const Mat& srcmat, Mat& dstmat, const Mat& deltamat, double scale ) { @@ -2515,12 +2444,14 @@ MulTransposedL( const Mat& srcmat, Mat& dstmat, const Mat& deltamat, double scal typedef void (*MulTransposedFunc)(const Mat& src, Mat& dst, const Mat& delta, double scale); -void mulTransposed( const Mat& src, Mat& dst, bool ata, - const Mat& _delta, double scale, int dtype ) +} + +void cv::mulTransposed( const InputArray& _src, OutputArray _dst, bool ata, + const InputArray& _delta, double scale, int dtype ) { + Mat src = _src.getMat(), delta = _delta.getMat(); const int gemm_level = 100; // boundary above which GEMM is faster. int stype = src.type(); - Mat delta = _delta; dtype = std::max(std::max(CV_MAT_DEPTH(dtype >= 0 ? dtype : stype), delta.depth()), CV_32F); CV_Assert( src.channels() == 1 ); @@ -2530,11 +2461,12 @@ void mulTransposed( const Mat& src, Mat& dst, bool ata, (delta.rows == src.rows || delta.rows == 1) && (delta.cols == src.cols || delta.cols == 1)); if( delta.type() != dtype ) - _delta.convertTo(delta, dtype); + delta.convertTo(delta, dtype); } int dsize = ata ? src.cols : src.rows; - dst.create( dsize, dsize, dtype ); + _dst.create( dsize, dsize, dtype ); + Mat dst = _dst.getMat(); if( src.data == dst.data || (stype == dtype && (dst.cols >= gemm_level && dst.rows >= gemm_level && @@ -2633,260 +2565,165 @@ void mulTransposed( const Mat& src, Mat& dst, bool ata, * Dot Product * \****************************************************************************************/ -#if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7) - -static double ippDotProd8u(const Mat& srcmat1, const Mat& srcmat2) +namespace cv { - int nchan = srcmat1.channels(); - Ipp64f sum[4] = { 0.0 }; - IppiSize roi = { srcmat1.cols, srcmat1.rows }; - - switch(nchan) - { - case 1: - ippiDotProd_8u64f_C1R((const Ipp8u*)srcmat1.data, (int)srcmat1.step, - (const Ipp8u*)srcmat2.data, (int)srcmat2.step, roi, sum); - break; - - case 3: - ippiDotProd_8u64f_C3R((const Ipp8u*)srcmat1.data, (int)srcmat1.step, - (const Ipp8u*)srcmat2.data, (int)srcmat2.step, roi, sum); - break; - - case 4: - ippiDotProd_8u64f_C4R((const Ipp8u*)srcmat1.data, (int)srcmat1.step, - (const Ipp8u*)srcmat2.data, (int)srcmat2.step, roi, sum); - break; - } - - for(int c = 1; c < nchan; c++) - { - sum[0] += sum[c]; - } - - return sum[0]; -} // ippDotProd8u() - -static double ippDotProd16u(const Mat& srcmat1, const Mat& srcmat2) +template double +dotProd_(const T* src1, const T* src2, int len) { - int nchan = srcmat1.channels(); - Ipp64f sum[4] = { 0.0 }; - IppiSize roi = { srcmat1.cols, srcmat1.rows }; - - switch(nchan) - { - case 1: - ippiDotProd_16u64f_C1R((const Ipp16u*)srcmat1.data, (int)srcmat1.step, - (const Ipp16u*)srcmat2.data, (int)srcmat2.step, roi, sum); - break; - - case 3: - ippiDotProd_16u64f_C3R((const Ipp16u*)srcmat1.data, (int)srcmat1.step, - (const Ipp16u*)srcmat2.data, (int)srcmat2.step, roi, sum); - break; - - case 4: - ippiDotProd_16u64f_C4R((const Ipp16u*)srcmat1.data, (int)srcmat1.step, - (const Ipp16u*)srcmat2.data, (int)srcmat2.step, roi, sum); - break; - } - - for(int c = 1; c < nchan; c++) - { - sum[0] += sum[c]; - } - - return sum[0]; -} // ippDotProd16u() + int i = 0; + double result = 0; + for( ; i <= len - 4; i += 4 ) + result += (double)src1[i]*src2[i] + (double)src1[i+1]*src2[i+1] + + (double)src1[i+2]*src2[i+2] + (double)src1[i+3]*src2[i+3]; + for( ; i < len; i++ ) + result += (double)src1[i]*src2[i]; + + return result; +} -static double ippDotProd16s(const Mat& srcmat1, const Mat& srcmat2) +static double dotProd_8u(const uchar* src1, const uchar* src2, int len) { - int nchan = srcmat1.channels(); - Ipp64f sum[4] = { 0.0 }; - IppiSize roi = { srcmat1.cols, srcmat1.rows }; - - switch(nchan) - { - case 1: - ippiDotProd_16s64f_C1R((const Ipp16s*)srcmat1.data, (int)srcmat1.step, - (const Ipp16s*)srcmat2.data, (int)srcmat2.step, roi, sum); - break; - - case 3: - ippiDotProd_16s64f_C3R((const Ipp16s*)srcmat1.data, (int)srcmat1.step, - (const Ipp16s*)srcmat2.data, (int)srcmat2.step, roi, sum); - break; - - case 4: - ippiDotProd_16s64f_C4R((const Ipp16s*)srcmat1.data, (int)srcmat1.step, - (const Ipp16s*)srcmat2.data, (int)srcmat2.step, roi, sum); - break; - } - - for(int c = 1; c < nchan; c++) + double r = 0; +#if ARITHM_USE_IPP + ippiDotProd_8u64f_C1R(src1, (int)(len*sizeof(src1[0])), + src2, (int)(len*sizeof(src2[0])), + ippiSize(len, 1), &r); +#else + int i = 0; + +#if CV_SSE2 + if( USE_SSE2 ) { - sum[0] += sum[c]; + int j, len0 = len & -4, blockSize0 = (1 << 15), blockSize; + __m128i z = _mm_setzero_si128(); + while( i < len0 ) + { + blockSize = std::min(len0 - j, blockSize0); + __m128i s = _mm_setzero_si128(); + for( j = 0; j <= blockSize - 16; j += 16 ) + { + __m128i b0 = _mm_loadu_si128((const __m128i*)(src1 + j)); + __m128i b1 = _mm_loadu_si128((const __m128i*)(src2 + j)); + __m128i s0, s1, s2, s3; + s0 = _mm_unpacklo_epi8(b0, z); + s2 = _mm_unpackhi_epi8(b0, z); + s1 = _mm_unpacklo_epi8(b1, z); + s3 = _mm_unpackhi_epi8(b1, z); + s0 = _mm_madd_epi16(s0, s1); + s1 = _mm_madd_epi16(s2, s3); + s = _mm_add_epi32(s, s0); + s = _mm_add_epi32(s, s2); + } + + for( ; j < blockSize; j += 4 ) + { + __m128i s0 = _mm_unpacklo_epi8(_mm_cvtsi32_si128(*(const int*)(src1 + j)), z); + __m128i s1 = _mm_unpacklo_epi8(_mm_cvtsi32_si128(*(const int*)(src2 + j)), z); + s0 = _mm_madd_epi16(s0, s1); + s = _mm_add_epi32(s, s0); + } + CV_DECL_ALIGNED(16) int buf[4]; + _mm_store_si128((__m128i*)buf, s); + r += buf[0] + buf[1] + buf[2] + buf[3]; + + src1 += blockSize; + src2 += blockSize; + i += blockSize; + } } - - return sum[0]; -} // ippDotProd16s() +#endif + return r + dotProd_(src1, src2, len - i); +#endif +} -static double ippDotProd32s(const Mat& srcmat1, const Mat& srcmat2) +static double dotProd_8s(const schar* src1, const schar* src2, int len) { - int nchan = srcmat1.channels(); - Ipp64f sum[4] = { 0.0 }; - IppiSize roi = { srcmat1.cols, srcmat1.rows }; - - switch(nchan) - { - case 1: - ippiDotProd_32s64f_C1R((const Ipp32s*)srcmat1.data, (int)srcmat1.step, - (const Ipp32s*)srcmat2.data, (int)srcmat2.step, roi, sum); - break; - - case 3: - ippiDotProd_32s64f_C3R((const Ipp32s*)srcmat1.data, (int)srcmat1.step, - (const Ipp32s*)srcmat2.data, (int)srcmat2.step, roi, sum); - break; - - case 4: - ippiDotProd_32s64f_C4R((const Ipp32s*)srcmat1.data, (int)srcmat1.step, - (const Ipp32s*)srcmat2.data, (int)srcmat2.step, roi, sum); - break; - } - - for(int c = 1; c < nchan; c++) - { - sum[0] += sum[c]; - } - - return sum[0]; -} // ippDotProd32s() - + return dotProd_(src1, src2, len); +} -static double ippDotProd32f(const Mat& srcmat1, const Mat& srcmat2) +static double dotProd_16u(const ushort* src1, const ushort* src2, int len) { - int nchan = srcmat1.channels(); - Ipp64f sum[4] = { 0.0 }; - IppiSize roi = { srcmat1.cols, srcmat1.rows }; - - switch(nchan) - { - case 1: - ippiDotProd_32f64f_C1R((const Ipp32f*)srcmat1.data, (int)srcmat1.step, - (const Ipp32f*)srcmat2.data, (int)srcmat2.step, roi, sum, ippAlgHintAccurate); - break; - - case 3: - ippiDotProd_32f64f_C3R((const Ipp32f*)srcmat1.data, (int)srcmat1.step, - (const Ipp32f*)srcmat2.data, (int)srcmat2.step, roi, sum, ippAlgHintAccurate); - break; - - case 4: - ippiDotProd_32f64f_C4R((const Ipp32f*)srcmat1.data, (int)srcmat1.step, - (const Ipp32f*)srcmat2.data, (int)srcmat2.step, roi, sum, ippAlgHintAccurate); - break; - } - - for(int c = 1; c < nchan; c++) - { - sum[0] += sum[c]; - } - - return sum[0]; -} // ippDotProd32f() - -#endif + double r = 0; + IF_IPP(ippiDotProd_16u64f_C1R(src1, (int)(len*sizeof(src1[0])), + src2, (int)(len*sizeof(src2[0])), + ippiSize(len, 1), &r), + r = dotProd_(src1, src2, len)); + return r; +} -template static double -dotprod_( const Mat& srcmat1, const Mat& srcmat2 ) +static double dotProd_16s(const short* src1, const short* src2, int len) { - const T* src1 = (const T*)srcmat1.data; - const T* src2 = (const T*)srcmat2.data; - - size_t step1 = srcmat1.step/sizeof(src1[0]); - size_t step2 = srcmat2.step/sizeof(src2[0]); - - ST sum = 0; - Size size = getContinuousSize( srcmat1, srcmat2, srcmat1.channels() ); - - if( size.width == 1 ) - { - WT t = 0; - for( ; size.height--; src1 += step1, src2 += step2 ) - t += (WT)src1[0]*src2[0]; - - sum += t; - } - else - { - for( ; size.height--; src1 += step1, src2 += step2 ) - { - int i; - WT t = 0; - for( i = 0; i <= size.width - 4; i += 4 ) - { - sum += (WT)src1[i ]*src2[i ] + - (WT)src1[i+1]*src2[i+1] + - (WT)src1[i+2]*src2[i+2] + - (WT)src1[i+3]*src2[i+3]; - } + double r = 0; + IF_IPP(ippiDotProd_16s64f_C1R(src1, (int)(len*sizeof(src1[0])), + src2, (int)(len*sizeof(src2[0])), + ippiSize(len, 1), &r), + r = dotProd_(src1, src2, len)); + return r; +} - for( ; i < size.width; i++ ) - t += (WT)src1[i]*src2[i]; +static double dotProd_32s(const int* src1, const int* src2, int len) +{ + double r = 0; + IF_IPP(ippiDotProd_32s64f_C1R(src1, (int)(len*sizeof(src1[0])), + src2, (int)(len*sizeof(src2[0])), + ippiSize(len, 1), &r), + r = dotProd_(src1, src2, len)); + return r; +} - sum += t; - } - } +static double dotProd_32f(const float* src1, const float* src2, int len) +{ + double r = 0; + IF_IPP(ippsDotProd_32f64f(src1, src2, len, &r), + r = dotProd_(src1, src2, len)); + return r; +} - return (double)sum; +static double dotProd_64f(const double* src1, const double* src2, int len) +{ + double r = 0; + IF_IPP(ippsDotProd_64f(src1, src2, len, &r), + r = dotProd_(src1, src2, len)); + return r; } -typedef double (*DotProductFunc)(const Mat& src1, const Mat& src2); -double Mat::dot(const Mat& mat) const +typedef double (*DotProdFunc)(const uchar* src1, const uchar* src2, int len); + +static DotProdFunc dotProdTab[] = { -#if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7) - static DotProductFunc ipptab[] = - { - dotprod_, - 0, - dotprod_, - dotprod_, - dotprod_, - ippDotProd32f, - dotprod_, - 0 - }; -#endif - - static DotProductFunc tab[] = - { - dotprod_, - 0, - dotprod_, - dotprod_, - dotprod_, - dotprod_, - dotprod_, - 0 - }; + (DotProdFunc)dotProd_8u, (DotProdFunc)dotProd_8s, (DotProdFunc)dotProd_16u, + (DotProdFunc)dotProd_16s, (DotProdFunc)dotProd_32s, (DotProdFunc)dotProd_32f, + (DotProdFunc)dotProd_64f, 0 +}; - DotProductFunc func = tab[depth()]; +double Mat::dot(const InputArray& _mat) const +{ + Mat mat = _mat.getMat(); + int cn = channels(); + DotProdFunc func = dotProdTab[depth()]; + CV_Assert( mat.type() == type() && mat.size == size && func != 0 ); -#if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7) - if((*this).channels() != 2) + if( isContinuous() && mat.isContinuous() ) { - func = ipptab[depth()]; + size_t len = total()*cn; + if( len == (size_t)(int)len ) + return func(data, mat.data, len); } -#endif - - CV_Assert( mat.type() == type() && mat.size() == size() && func != 0 ); - - return func( *this, mat ); + + const Mat* arrays[] = {this, &mat, 0}; + uchar* ptrs[2]; + NAryMatIterator it(arrays, ptrs); + int len = (int)(it.size*cn); + double r = 0; + + for( size_t i = 0; i < it.nplanes; i++, ++it ) + r += func( ptrs[0], ptrs[1], len ); + + return r; } /****************************************************************************************\ @@ -2895,13 +2732,14 @@ double Mat::dot(const Mat& mat) const PCA::PCA() {} -PCA::PCA(const Mat& data, const Mat& mean, int flags, int maxComponents) +PCA::PCA(const InputArray& data, const InputArray& mean, int flags, int maxComponents) { operator()(data, mean, flags, maxComponents); } -PCA& PCA::operator()(const Mat& data, const Mat& _mean, int flags, int maxComponents) +PCA& PCA::operator()(const InputArray& _data, const InputArray& __mean, int flags, int maxComponents) { + Mat data = _data.getMat(), _mean = __mean.getMat(); int covar_flags = CV_COVAR_SCALE; int i, len, in_count; Size mean_sz; @@ -2984,8 +2822,9 @@ PCA& PCA::operator()(const Mat& data, const Mat& _mean, int flags, int maxCompon } -void PCA::project(const Mat& data, Mat& result) const +void PCA::project(const InputArray& _data, OutputArray result) const { + Mat data = _data.getMat(); CV_Assert( mean.data && eigenvectors.data && ((mean.rows == 1 && mean.cols == data.cols) || (mean.cols == 1 && mean.rows == data.rows))); Mat tmp_data, tmp_mean = repeat(mean, data.rows/mean.rows, data.cols/mean.cols); @@ -3006,15 +2845,16 @@ void PCA::project(const Mat& data, Mat& result) const gemm( eigenvectors, tmp_data, 1, Mat(), 0, result, 0 ); } -Mat PCA::project(const Mat& data) const +Mat PCA::project(const InputArray& data) const { Mat result; project(data, result); return result; } -void PCA::backProject(const Mat& data, Mat& result) const +void PCA::backProject(const InputArray& _data, OutputArray result) const { + Mat data = _data.getMat(); CV_Assert( mean.data && eigenvectors.data && ((mean.rows == 1 && eigenvectors.rows == data.cols) || (mean.cols == 1 && eigenvectors.rows == data.rows))); @@ -3033,7 +2873,7 @@ void PCA::backProject(const Mat& data, Mat& result) const } } -Mat PCA::backProject(const Mat& data) const +Mat PCA::backProject(const InputArray& data) const { Mat result; backProject(data, result); diff --git a/modules/core/src/matop.cpp b/modules/core/src/matop.cpp index 6406ebafc4..959c8878d5 100644 --- a/modules/core/src/matop.cpp +++ b/modules/core/src/matop.cpp @@ -208,9 +208,11 @@ static inline bool isIdentity(const MatExpr& e) { return e.op == &g_MatOp_Identi static inline bool isAddEx(const MatExpr& e) { return e.op == &g_MatOp_AddEx; } static inline bool isScaled(const MatExpr& e) { return isAddEx(e) && (!e.b.data || e.beta == 0) && e.s == Scalar(); } static inline bool isBin(const MatExpr& e, char c) { return e.op == &g_MatOp_Bin && e.flags == c; } +static inline bool isCmp(const MatExpr& e) { return e.op == &g_MatOp_Cmp; } static inline bool isReciprocal(const MatExpr& e) { return isBin(e,'/') && (!e.b.data || e.beta == 0); } static inline bool isT(const MatExpr& e) { return e.op == &g_MatOp_T; } static inline bool isInv(const MatExpr& e) { return e.op == &g_MatOp_Invert; } +static inline bool isSolve(const MatExpr& e) { return e.op == &g_MatOp_Solve; } static inline bool isGEMM(const MatExpr& e) { return e.op == &g_MatOp_GEMM; } static inline bool isMatProd(const MatExpr& e) { return e.op == &g_MatOp_GEMM && (!e.c.data || e.beta == 0); } static inline bool isInitializer(const MatExpr& e) { return e.op == &g_MatOp_Initializer; } @@ -571,7 +573,18 @@ void MatOp::invert(const MatExpr& expr, int method, MatExpr& res) const expr.op->assign(expr, m); MatOp_Invert::makeExpr(res, method, m); } + + +Size MatOp::size(const MatExpr& expr) const +{ + return !expr.a.empty() ? expr.a.size() : expr.b.empty() ? expr.b.size() : expr.c.size(); +} +int MatOp::type(const MatExpr& expr) const +{ + return !expr.a.empty() ? expr.a.type() : expr.b.empty() ? expr.b.type() : expr.c.type(); +} + ////////////////////////////////////////////////////////////////////////////////////////////////// MatExpr::MatExpr(const Mat& m) : op(&g_MatOp_Identity), flags(0), a(m), b(Mat()), c(Mat()), alpha(1), beta(0), s(Scalar()) @@ -1142,6 +1155,30 @@ MatExpr abs(const MatExpr& e) } +Size MatExpr::size() const +{ + if( isT(*this) || isInv(*this) ) + return Size(a.rows, a.cols); + if( isGEMM(*this) ) + return Size(b.cols, a.rows); + if( isSolve(*this) ) + return Size(b.cols, a.cols); + if( isInitializer(*this) ) + return a.size(); + return op ? op->size(*this) : Size(); +} + + +int MatExpr::type() const +{ + if( isInitializer(*this) ) + return a.type(); + if( isCmp(*this) ) + return CV_8U; + return op ? op->type(*this) : -1; +} + + ///////////////////////////////////////////////////////////////////////////////////////////////////// void MatOp_Identity::assign(const MatExpr& e, Mat& m, int type) const @@ -1552,10 +1589,10 @@ MatExpr Mat::inv(int method) const } -MatExpr Mat::mul(const Mat& m, double scale) const +MatExpr Mat::mul(const InputArray& m, double scale) const { MatExpr e; - MatOp_Bin::makeExpr(e, '*', *this, m, scale); + MatOp_Bin::makeExpr(e, '*', *this, m.getMat(), scale); return e; } diff --git a/modules/core/src/matrix.cpp b/modules/core/src/matrix.cpp index e574d80af9..c6c8003230 100644 --- a/modules/core/src/matrix.cpp +++ b/modules/core/src/matrix.cpp @@ -50,11 +50,6 @@ namespace cv { void swap( Mat& a, Mat& b ) { - /*int *ap = (int*)&a, *bp = (int*)&b; - size_t i, n = sizeof(Mat)/sizeof(ap[0]); - - for( i = 0; i < n; i++ ) - std::swap(ap[i], bp[i]);*/ std::swap(a.flags, b.flags); std::swap(a.dims, b.dims); std::swap(a.rows, b.rows); @@ -681,11 +676,14 @@ Mat& Mat::adjustROI( int dtop, int dbottom, int dleft, int dright ) flags &= ~CONTINUOUS_FLAG; return *this; } + +} -void extractImageCOI(const CvArr* arr, Mat& ch, int coi) +void cv::extractImageCOI(const CvArr* arr, OutputArray _ch, int coi) { Mat mat = cvarrToMat(arr, false, true, 1); - ch.create(mat.dims, mat.size, mat.depth()); + _ch.create(mat.dims, mat.size, mat.depth()); + Mat ch = _ch.getMat(); if(coi < 0) { CV_Assert( CV_IS_IMAGE(arr) ); @@ -696,9 +694,9 @@ void extractImageCOI(const CvArr* arr, Mat& ch, int coi) mixChannels( &mat, 1, &ch, 1, _pairs, 1 ); } -void insertImageCOI(const Mat& ch, CvArr* arr, int coi) +void cv::insertImageCOI(const InputArray& _ch, CvArr* arr, int coi) { - Mat mat = cvarrToMat(arr, false, true, 1); + Mat ch = _ch.getMat(), mat = cvarrToMat(arr, false, true, 1); if(coi < 0) { CV_Assert( CV_IS_IMAGE(arr) ); @@ -709,6 +707,8 @@ void insertImageCOI(const Mat& ch, CvArr* arr, int coi) mixChannels( &ch, 1, &mat, 1, _pairs, 1 ); } +namespace cv +{ Mat Mat::reshape(int new_cn, int new_rows) const { @@ -850,16 +850,553 @@ void scalarToRawData(const Scalar& s, void* _buf, int type, int unroll_to) CV_Error(CV_StsUnsupportedFormat,""); } } + + +/*************************************************************************************************\ + Input/Output Array +\*************************************************************************************************/ + +InputArray::InputArray() : flags(0), obj(0) {} +InputArray::InputArray(const Mat& m) : flags(MAT), obj((void*)&m) {} +InputArray::InputArray(const vector& vec) : flags(STD_VECTOR_MAT), obj((void*)&vec) {} +InputArray::InputArray(const double& val) : flags(MATX+CV_64F), obj((void*)&val), sz(Size(1,1)) {} +InputArray::InputArray(const MatExpr& expr) : flags(EXPR), obj((void*)&expr) {} + +Mat InputArray::getMat(int i) const +{ + int k = kind(); + + if( k == MAT ) + { + CV_Assert( i < 0 ); + return *(const Mat*)obj; + } + + if( k == EXPR ) + { + CV_Assert( i < 0 ); + return (Mat)*((const MatExpr*)obj); + } + + if( k == MATX ) + { + CV_Assert( i < 0 ); + return Mat(sz, flags, obj); + } + + if( k == STD_VECTOR ) + { + CV_Assert( i < 0 ); + int t = CV_MAT_TYPE(flags); + const vector& v = *(const vector*)obj; + + return !v.empty() ? Mat(size(), t, (void*)&v[0]) : Mat(); + } + + if( k == NONE ) + return Mat(); + + if( k == STD_VECTOR_VECTOR ) + { + int t = type(i); + const vector >& vv = *(const vector >*)obj; + CV_Assert( 0 <= i && i < (int)vv.size() ); + const vector& v = vv[i]; + + return !v.empty() ? Mat(size(i), t, (void*)&v[0]) : Mat(); + } + + CV_Assert( k == STD_VECTOR_MAT ); + //if( k == STD_VECTOR_MAT ) + { + const vector& v = *(const vector*)obj; + CV_Assert( 0 <= i && i < (int)v.size() ); + + return v[i]; + } +} + + +void InputArray::getMatVector(vector& mv) const +{ + int k = kind(); + + if( k == MAT ) + { + const Mat& m = *(const Mat*)obj; + size_t i, n = m.size[0]; + mv.resize(n); + + for( i = 0; i < n; i++ ) + mv[i] = m.dims == 2 ? Mat(1, m.cols, m.type(), (void*)m.ptr(i)) : + Mat(m.dims-1, &m.size[1], m.type(), (void*)m.ptr(i), &m.step[1]); + return; + } + + if( k == EXPR ) + { + Mat m = *(const MatExpr*)obj; + size_t i, n = m.size[0]; + mv.resize(n); + + for( i = 0; i < n; i++ ) + mv[i] = m.row(i); + return; + } + + if( k == MATX ) + { + size_t i, n = sz.height, esz = CV_ELEM_SIZE(flags); + mv.resize(n); + + for( i = 0; i < n; i++ ) + mv[i] = Mat(1, sz.width, CV_MAT_TYPE(flags), (uchar*)obj + esz*sz.width*i); + return; + } + + if( k == STD_VECTOR ) + { + const vector& v = *(const vector*)obj; + + size_t i, n = v.size(), esz = CV_ELEM_SIZE(flags); + int t = CV_MAT_DEPTH(flags), cn = CV_MAT_CN(flags); + mv.resize(n); + + for( i = 0; i < n; i++ ) + mv[i] = Mat(1, cn, t, (void*)(&v[0] + esz*i)); + return; + } + + if( k == NONE ) + { + mv.clear(); + return; + } + + if( k == STD_VECTOR_VECTOR ) + { + const vector >& vv = *(const vector >*)obj; + size_t i, n = vv.size(); + int t = CV_MAT_TYPE(flags); + mv.resize(n); + + for( i = 0; i < n; i++ ) + { + const vector& v = vv[i]; + mv[i] = Mat(size(i), t, (void*)&v[0]); + } + return; + } + + CV_Assert( k == STD_VECTOR_MAT ); + //if( k == STD_VECTOR_MAT ) + { + const vector& v = *(const vector*)obj; + mv.resize(v.size()); + std::copy(v.begin(), v.end(), mv.begin()); + return; + } +} + +int InputArray::kind() const +{ + return flags & -(1 << KIND_SHIFT); +} + +Size InputArray::size(int i) const +{ + int k = kind(); + + if( k == MAT ) + { + CV_Assert( i < 0 ); + return ((const Mat*)obj)->size(); + } + + if( k == EXPR ) + { + CV_Assert( i < 0 ); + return ((const MatExpr*)obj)->size(); + } + + if( k == MATX ) + { + CV_Assert( i < 0 ); + return sz; + } + + if( k == STD_VECTOR ) + { + CV_Assert( i < 0 ); + const vector& v = *(const vector*)obj; + const vector& iv = *(const vector*)obj; + size_t szb = v.size(), szi = iv.size(); + return szb == szi ? Size((int)szb, 1) : Size((int)(szb/CV_ELEM_SIZE(flags)), 1); + } + + if( k == NONE ) + return Size(); + + if( k == STD_VECTOR_VECTOR ) + { + const vector >& vv = *(const vector >*)obj; + if( i < 0 ) + return vv.empty() ? Size() : Size((int)vv.size(), 1); + CV_Assert( i < (int)vv.size() ); + const vector >& ivv = *(const vector >*)obj; + + size_t szb = vv[i].size(), szi = ivv[i].size(); + return szb == szi ? Size((int)szb, 1) : Size((int)(szb/CV_ELEM_SIZE(flags)), 1); + } + + CV_Assert( k == STD_VECTOR_MAT ); + //if( k == STD_VECTOR_MAT ) + { + const vector& vv = *(const vector*)obj; + if( i < 0 ) + return vv.empty() ? Size() : Size((int)vv.size(), 1); + CV_Assert( i < (int)vv.size() ); + + return vv[i].size(); + } +} + +size_t InputArray::total(int i) const +{ + return size(i).area(); +} + +int InputArray::type(int i) const +{ + int k = kind(); + + if( k == MAT ) + return ((const Mat*)obj)->type(); + + if( k == EXPR ) + return ((const MatExpr*)obj)->type(); + + if( k == MATX || k == STD_VECTOR || k == STD_VECTOR_VECTOR ) + return CV_MAT_TYPE(flags); + + if( k == NONE ) + return -1; + + CV_Assert( k == STD_VECTOR_MAT ); + //if( k == STD_VECTOR_MAT ) + { + const vector& vv = *(const vector*)obj; + CV_Assert( i < (int)vv.size() ); + + return vv[i >= 0 ? i : 0].type(); + } +} + +int InputArray::depth(int i) const +{ + return CV_MAT_DEPTH(type(i)); +} + +int InputArray::channels(int i) const +{ + return CV_MAT_CN(type(i)); +} + +bool InputArray::empty() const +{ + int k = kind(); + + if( k == MAT ) + return ((const Mat*)obj)->empty(); + + if( k == EXPR ) + return false; + + if( k == MATX ) + return false; + + if( k == STD_VECTOR ) + { + const vector& v = *(const vector*)obj; + return v.empty(); + } + + if( k == NONE ) + return true; + + if( k == STD_VECTOR_VECTOR ) + { + const vector >& vv = *(const vector >*)obj; + return vv.empty(); + } + + CV_Assert( k == STD_VECTOR_MAT ); + //if( k == STD_VECTOR_MAT ) + { + const vector& vv = *(const vector*)obj; + return vv.empty(); + } +} + + +OutputArray::OutputArray() {} +OutputArray::OutputArray(Mat& m) : InputArray(m) {} +OutputArray::OutputArray(vector& vec) : InputArray(vec) {} + +bool OutputArray::fixedSize() const +{ + int k = kind(); + return k == MATX; +} + +bool OutputArray::fixedType() const +{ + int k = kind(); + return k != MAT && k != STD_VECTOR_MAT; +} + +void OutputArray::create(Size _sz, int type, int i, bool allowTransposed, int fixedDepthMask) +{ + int k = kind(); + if( k == MAT && i < 0 && !allowTransposed && fixedDepthMask == 0 ) + { + ((Mat*)obj)->create(_sz, type); + return; + } + int sz[] = {_sz.height, _sz.width}; + create(2, sz, type, i, allowTransposed, fixedDepthMask); +} + +void OutputArray::create(int rows, int cols, int type, int i, bool allowTransposed, int fixedDepthMask) +{ + int k = kind(); + if( k == MAT && i < 0 && !allowTransposed && fixedDepthMask == 0 ) + { + ((Mat*)obj)->create(rows, cols, type); + return; + } + int sz[] = {rows, cols}; + create(2, sz, type, i, allowTransposed, fixedDepthMask); +} + +void OutputArray::create(int dims, const int* size, int type, int i, bool allocateVector, int fixedDepthMask) +{ + int k = kind(); + type = CV_MAT_TYPE(type); + + if( k == MAT ) + { + CV_Assert( i < 0 ); + Mat& m = *(Mat*)obj; + if( allocateVector && dims == 2 && m.dims == 2 && + m.type() == type && m.rows == size[1] && m.cols == size[0] && m.isContinuous()) + return; + if( !m.isContinuous() ) + m.release(); + m.create(dims, size, type); + return; + } + + if( k == MATX ) + { + CV_Assert( i < 0 ); + int type0 = CV_MAT_TYPE(flags); + CV_Assert( type == type0 || (CV_MAT_CN(type) == 1 && ((1 << type0) & fixedDepthMask) != 0) ); + CV_Assert( dims == 2 && ((size[0] == sz.height && size[1] == sz.width) || + (allocateVector && size[0] == sz.width && size[1] == sz.height))); + return; + } + + if( k == STD_VECTOR || k == STD_VECTOR_VECTOR ) + { + CV_Assert( dims == 2 && (size[0] == 1 || size[1] == 1 || size[0]*size[1] == 0) ); + size_t len = size[0]*size[1] > 0 ? size[0] + size[1] - 1 : 0; + vector* v = (vector*)obj; + + if( k == STD_VECTOR_VECTOR ) + { + vector >& vv = *(vector >*)obj; + if( i < 0 ) + { + vv.resize(len); + return; + } + CV_Assert( i < (int)vv.size() ); + v = &vv[i]; + } + else + CV_Assert( i < 0 ); + + int type0 = CV_MAT_TYPE(flags); + CV_Assert( type == type0 || (CV_MAT_CN(type) == CV_MAT_CN(type0) && ((1 << type0) & fixedDepthMask) != 0) ); + + int esz = CV_ELEM_SIZE(type0); + switch( esz ) + { + case 1: + ((vector*)v)->resize(len); + break; + case 2: + ((vector*)v)->resize(len); + break; + case 3: + ((vector*)v)->resize(len); + break; + case 4: + ((vector*)v)->resize(len); + break; + case 6: + ((vector*)v)->resize(len); + break; + case 8: + ((vector*)v)->resize(len); + break; + case 12: + ((vector*)v)->resize(len); + break; + case 16: + ((vector*)v)->resize(len); + break; + case 24: + ((vector*)v)->resize(len); + break; + case 32: + ((vector*)v)->resize(len); + break; + case 36: + ((vector >*)v)->resize(len); + break; + case 48: + ((vector >*)v)->resize(len); + break; + case 64: + ((vector >*)v)->resize(len); + break; + case 128: + ((vector >*)v)->resize(len); + break; + case 256: + ((vector >*)v)->resize(len); + break; + case 512: + ((vector >*)v)->resize(len); + break; + default: + CV_Error_(CV_StsBadArg, ("Vectors with element size %d are not supported. Please, modify OutputArray::create()\n", esz)); + } + return; + } + + if( k == NONE ) + { + CV_Error(CV_StsNullPtr, "create() called for the missing output array" ); + return; + } + + CV_Assert( k == STD_VECTOR_MAT ); + //if( k == STD_VECTOR_MAT ) + { + vector& v = *(vector*)obj; + + if( i < 0 ) + { + CV_Assert( dims == 2 && (size[0] == 1 || size[1] == 1 || size[0]*size[1] == 0) ); + size_t len = size[0]*size[1] > 0 ? size[0] + size[1] - 1 : 0; + + v.resize(len); + return; + } + + CV_Assert( i < (int)v.size() ); + Mat& m = v[i]; + + if( allocateVector && dims == 2 && m.dims == 2 && + m.type() == type && m.rows == size[1] && m.cols == size[0] && m.isContinuous()) + return; + if(!m.isContinuous()) + m.release(); + m.create(dims, size, type); + } +} + +void OutputArray::release() +{ + int k = kind(); + + if( k == MAT ) + { + ((Mat*)obj)->release(); + return; + } + + if( k == NONE ) + return; + + if( k == STD_VECTOR ) + { + create(Size(), CV_MAT_TYPE(flags)); + return; + } + + if( k == STD_VECTOR_VECTOR ) + { + ((vector >*)obj)->clear(); + return; + } + + CV_Assert( k == STD_VECTOR_MAT ); + //if( k == STD_VECTOR_MAT ) + { + ((vector*)obj)->clear(); + } +} + +void OutputArray::clear() +{ + int k = kind(); + + if( k == MAT ) + { + ((Mat*)obj)->resize(0); + return; + } + + release(); +} + +bool OutputArray::needed() const +{ + return kind() != NONE; +} + +Mat& OutputArray::getMatRef(int i) +{ + int k = kind(); + if( i < 0 ) + { + CV_Assert( k == MAT ); + return *(Mat*)obj; + } + else + { + CV_Assert( k == STD_VECTOR_MAT ); + vector& v = *(vector*)obj; + CV_Assert( i < (int)v.size() ); + return v[i]; + } +} +} + /*************************************************************************************************\ Matrix Operations \*************************************************************************************************/ -void hconcat(const Mat* src, size_t nsrc, Mat& dst) +void cv::hconcat(const Mat* src, size_t nsrc, OutputArray _dst) { if( nsrc == 0 || !src ) { - dst.release(); + _dst.release(); return; } @@ -872,31 +1409,34 @@ void hconcat(const Mat* src, size_t nsrc, Mat& dst) src[i].type() == src[0].type()); totalCols += src[i].cols; } - dst.create( src[0].rows, totalCols, src[0].type()); + _dst.create( src[0].rows, totalCols, src[0].type()); + Mat dst = _dst.getMat(); for( i = 0; i < nsrc; i++ ) { - Mat dpart(dst, Rect(cols, 0, src[i].cols, src[i].rows)); + Mat dpart = dst(Rect(cols, 0, src[i].cols, src[i].rows)); src[i].copyTo(dpart); cols += src[i].cols; } } -void hconcat(const Mat& src1, const Mat& src2, Mat& dst) +void cv::hconcat(const InputArray& src1, const InputArray& src2, OutputArray dst) { - Mat src[] = {src1, src2}; + Mat src[] = {src1.getMat(), src2.getMat()}; hconcat(src, 2, dst); } -void hconcat(const vector& src, CV_OUT Mat& dst) +void cv::hconcat(const InputArray& _src, OutputArray dst) { + vector src; + _src.getMatVector(src); hconcat(!src.empty() ? &src[0] : 0, src.size(), dst); } -void vconcat(const Mat* src, size_t nsrc, Mat& dst) +void cv::vconcat(const Mat* src, size_t nsrc, OutputArray _dst) { if( nsrc == 0 || !src ) { - dst.release(); + _dst.release(); return; } @@ -909,7 +1449,8 @@ void vconcat(const Mat* src, size_t nsrc, Mat& dst) src[i].type() == src[0].type()); totalRows += src[i].rows; } - dst.create( totalRows, src[0].cols, src[0].type()); + _dst.create( totalRows, src[0].cols, src[0].type()); + Mat dst = _dst.getMat(); for( i = 0; i < nsrc; i++ ) { Mat dpart(dst, Rect(0, rows, src[i].cols, src[i].rows)); @@ -918,20 +1459,23 @@ void vconcat(const Mat* src, size_t nsrc, Mat& dst) } } -void vconcat(const Mat& src1, const Mat& src2, Mat& dst) +void cv::vconcat(const InputArray& src1, const InputArray& src2, OutputArray dst) { - Mat src[] = {src1, src2}; + Mat src[] = {src1.getMat(), src2.getMat()}; vconcat(src, 2, dst); } -void vconcat(const vector& src, CV_OUT Mat& dst) +void cv::vconcat(const InputArray& _src, OutputArray dst) { + vector src; + _src.getMatVector(src); vconcat(!src.empty() ? &src[0] : 0, src.size(), dst); } //////////////////////////////////////// set identity //////////////////////////////////////////// -void setIdentity( Mat& m, const Scalar& s ) +void cv::setIdentity( InputOutputArray _m, const Scalar& s ) { + Mat m = _m.getMat(); CV_Assert( m.dims <= 2 ); int i, j, rows = m.rows, cols = m.cols, type = m.type(); @@ -970,8 +1514,9 @@ void setIdentity( Mat& m, const Scalar& s ) //////////////////////////////////////////// trace /////////////////////////////////////////// -Scalar trace( const Mat& m ) +cv::Scalar cv::trace( const InputArray& _m ) { + Mat m = _m.getMat(); CV_Assert( m.dims <= 2 ); int i, type = m.type(); int nm = std::min(m.rows, m.cols); @@ -1000,107 +1545,141 @@ Scalar trace( const Mat& m ) } ////////////////////////////////////// transpose ///////////////////////////////////////// - + +namespace cv +{ + template static void -transposeI_( Mat& mat ) +transpose_( const uchar* src, size_t sstep, uchar* dst, size_t dstep, Size sz ) { - int rows = mat.rows, cols = mat.cols; - uchar* data = mat.data; - size_t step = mat.step; + int i, j, m = sz.width, n = sz.height; + + for( i = 0; i <= m - 4; i += 4 ) + { + T* d0 = (T*)(dst + dstep*i); + T* d1 = (T*)(dst + dstep*(i+1)); + T* d2 = (T*)(dst + dstep*(i+2)); + T* d3 = (T*)(dst + dstep*(i+3)); + + for( j = 0; j <= n - 4; j += 4 ) + { + const T* s0 = (const T*)(src + i*sizeof(T) + sstep*j); + const T* s1 = (const T*)(src + i*sizeof(T) + sstep*(j+1)); + const T* s2 = (const T*)(src + i*sizeof(T) + sstep*(j+2)); + const T* s3 = (const T*)(src + i*sizeof(T) + sstep*(j+3)); + + d0[j] = s0[0]; d0[j+1] = s1[0]; d0[j+2] = s2[0]; d0[j+3] = s3[0]; + d1[j] = s0[1]; d1[j+1] = s1[1]; d1[j+2] = s2[1]; d1[j+3] = s3[1]; + d2[j] = s0[2]; d2[j+1] = s1[2]; d2[j+2] = s2[2]; d2[j+3] = s3[2]; + d3[j] = s0[3]; d3[j+1] = s1[3]; d3[j+2] = s2[3]; d3[j+3] = s3[3]; + } + + for( ; j < n; j++ ) + { + const T* s0 = (const T*)(src + i*sizeof(T) + j*sstep); + d0[j] = s0[0]; d1[j] = s0[1]; d2[j] = s0[2]; d3[j] = s0[3]; + } + } + + for( ; i < m; i++ ) + { + T* d0 = (T*)(dst + dstep*i); + + for( j = 0; j <= n - 4; j += 4 ) + { + const T* s0 = (const T*)(src + i*sizeof(T) + sstep*j); + const T* s1 = (const T*)(src + i*sizeof(T) + sstep*(j+1)); + const T* s2 = (const T*)(src + i*sizeof(T) + sstep*(j+2)); + const T* s3 = (const T*)(src + i*sizeof(T) + sstep*(j+3)); + + d0[j] = s0[0]; d0[j+1] = s1[0]; d0[j+2] = s2[0]; d0[j+3] = s3[0]; + } + + for( ; j < n; j++ ) + { + const T* s0 = (const T*)(src + i*sizeof(T) + j*sstep); + d0[j] = s0[0]; + } + } +} - for( int i = 0; i < rows; i++ ) +template static void +transposeI_( uchar* data, size_t step, int n ) +{ + int i, j; + for( i = 0; i < n; i++ ) { T* row = (T*)(data + step*i); uchar* data1 = data + i*sizeof(T); - for( int j = i+1; j < cols; j++ ) + for( j = i+1; j < n; j++ ) std::swap( row[j], *(T*)(data1 + step*j) ); } } + +typedef void (*TransposeFunc)( const uchar* src, size_t sstep, uchar* dst, size_t dstep, Size sz ); +typedef void (*TransposeInplaceFunc)( uchar* data, size_t step, int n ); + +#define DEF_TRANSPOSE_FUNC(suffix, type) \ +static void transpose_##suffix( const uchar* src, size_t sstep, uchar* dst, size_t dstep, Size sz ) \ +{ transpose_(src, sstep, dst, dstep, sz); } \ +\ +static void transposeI_##suffix( uchar* data, size_t step, int n ) \ +{ transposeI_(data, step, n); } -template static void -transpose_( const Mat& src, Mat& dst ) -{ - int rows = dst.rows, cols = dst.cols; - uchar* data = src.data; - size_t step = src.step; +DEF_TRANSPOSE_FUNC(8u, uchar) +DEF_TRANSPOSE_FUNC(16u, ushort) +DEF_TRANSPOSE_FUNC(8uC3, Vec3b) +DEF_TRANSPOSE_FUNC(32s, int) +DEF_TRANSPOSE_FUNC(16uC3, Vec3s) +DEF_TRANSPOSE_FUNC(32sC2, Vec2i) +DEF_TRANSPOSE_FUNC(32sC3, Vec3i) +DEF_TRANSPOSE_FUNC(32sC4, Vec4i) +DEF_TRANSPOSE_FUNC(32sC6, Vec6i) +DEF_TRANSPOSE_FUNC(32sC8, Vec8i) - for( int i = 0; i < rows; i++ ) - { - T* row = (T*)(dst.data + dst.step*i); - uchar* data1 = data + i*sizeof(T); - for( int j = 0; j < cols; j++ ) - row[j] = *(T*)(data1 + step*j); - } -} - -typedef void (*TransposeInplaceFunc)( Mat& mat ); -typedef void (*TransposeFunc)( const Mat& src, Mat& dst ); - -void transpose( const Mat& src, Mat& dst ) -{ - TransposeInplaceFunc itab[] = - { - 0, - transposeI_, // 1 - transposeI_, // 2 - transposeI_ >, // 3 - transposeI_, // 4 - 0, - transposeI_ >, // 6 - 0, - transposeI_ >, // 8 - 0, 0, 0, - transposeI_ >, // 12 - 0, 0, 0, - transposeI_ >, // 16 - 0, 0, 0, 0, 0, 0, 0, - transposeI_ >, // 24 - 0, 0, 0, 0, 0, 0, 0, - transposeI_ > // 32 - }; +static TransposeFunc transposeTab[] = +{ + 0, transpose_8u, transpose_16u, transpose_8uC3, transpose_32s, 0, transpose_16uC3, 0, + transpose_32sC2, 0, 0, 0, transpose_32sC3, 0, 0, 0, transpose_32sC4, + 0, 0, 0, 0, 0, 0, 0, transpose_32sC6, 0, 0, 0, 0, 0, 0, 0, transpose_32sC8 +}; - TransposeFunc tab[] = - { - 0, - transpose_, // 1 - transpose_, // 2 - transpose_ >, // 3 - transpose_, // 4 - 0, - transpose_ >, // 6 - 0, - transpose_ >, // 8 - 0, 0, 0, - transpose_ >, // 12 - 0, 0, 0, - transpose_ >, // 16 - 0, 0, 0, 0, 0, 0, 0, - transpose_ >, // 24 - 0, 0, 0, 0, 0, 0, 0, - transpose_ > // 32 - }; +static TransposeInplaceFunc transposeInplaceTab[] = +{ + 0, transposeI_8u, transposeI_16u, transposeI_8uC3, transposeI_32s, 0, transposeI_16uC3, 0, + transposeI_32sC2, 0, 0, 0, transposeI_32sC3, 0, 0, 0, transposeI_32sC4, + 0, 0, 0, 0, 0, 0, 0, transposeI_32sC6, 0, 0, 0, 0, 0, 0, 0, transposeI_32sC8 +}; +} + +void cv::transpose( const InputArray& _src, OutputArray _dst ) +{ + Mat src = _src.getMat(); size_t esz = src.elemSize(); CV_Assert( src.dims <= 2 && esz <= (size_t)32 ); - if( dst.data == src.data && dst.cols == dst.rows ) + _dst.create(src.cols, src.rows, src.type()); + Mat dst = _dst.getMat(); + + if( dst.data == src.data ) { - TransposeInplaceFunc func = itab[esz]; + TransposeInplaceFunc func = transposeInplaceTab[esz]; CV_Assert( func != 0 ); - func( dst ); + func( dst.data, dst.step, dst.rows ); } else { - dst.create( src.cols, src.rows, src.type() ); - TransposeFunc func = tab[esz]; + TransposeFunc func = transposeTab[esz]; CV_Assert( func != 0 ); - func( src, dst ); + func( src.data, src.step, dst.data, dst.step, src.size() ); } } -void completeSymm( Mat& m, bool LtoR ) +void cv::completeSymm( InputOutputArray _m, bool LtoR ) { + Mat m = _m.getMat(); CV_Assert( m.dims <= 2 ); int i, j, nrows = m.rows, type = m.type(); @@ -1134,8 +1713,9 @@ void completeSymm( Mat& m, bool LtoR ) } -Mat Mat::cross(const Mat& m) const +cv::Mat cv::Mat::cross(const InputArray& _m) const { + Mat m = _m.getMat(); int t = type(), d = CV_MAT_DEPTH(t); CV_Assert( dims <= 2 && m.dims <= 2 && size() == m.size() && t == m.type() && ((rows == 3 && cols == 1) || (cols*channels() == 3 && rows == 1))); @@ -1170,6 +1750,9 @@ Mat Mat::cross(const Mat& m) const ////////////////////////////////////////// reduce //////////////////////////////////////////// +namespace cv +{ + template static void reduceR_( const Mat& srcmat, Mat& dstmat ) { @@ -1253,17 +1836,21 @@ reduceC_( const Mat& srcmat, Mat& dstmat ) typedef void (*ReduceFunc)( const Mat& src, Mat& dst ); -void reduce(const Mat& src, Mat& dst, int dim, int op, int dtype) +} + +void cv::reduce(const InputArray& _src, OutputArray _dst, int dim, int op, int dtype) { + Mat src = _src.getMat(); CV_Assert( src.dims <= 2 ); int op0 = op; - int stype = src.type(), sdepth = src.depth(); + int stype = src.type(), sdepth = src.depth(), cn = src.channels(); if( dtype < 0 ) - dtype = stype; + dtype = _dst.fixedType() ? _dst.type() : stype; int ddepth = CV_MAT_DEPTH(dtype); - dst.create(dim == 0 ? 1 : src.rows, dim == 0 ? src.cols : 1, dtype >= 0 ? dtype : stype); - Mat temp = dst; + _dst.create(dim == 0 ? 1 : src.rows, dim == 0 ? src.cols : 1, + CV_MAKETYPE(dtype >= 0 ? dtype : stype, cn)); + Mat dst = _dst.getMat(), temp = dst; CV_Assert( op == CV_REDUCE_SUM || op == CV_REDUCE_MAX || op == CV_REDUCE_MIN || op == CV_REDUCE_AVG ); @@ -1273,7 +1860,7 @@ void reduce(const Mat& src, Mat& dst, int dim, int op, int dtype) { op = CV_REDUCE_SUM; if( sdepth < CV_32S && ddepth < CV_32S ) - temp.create(dst.rows, dst.cols, CV_32SC(src.channels())); + temp.create(dst.rows, dst.cols, CV_32SC(cn)); } ReduceFunc func = 0; @@ -1379,6 +1966,9 @@ void reduce(const Mat& src, Mat& dst, int dim, int op, int dtype) //////////////////////////////////////// sort /////////////////////////////////////////// +namespace cv +{ + template static void sort_( const Mat& src, Mat& dst, int flags ) { AutoBuffer buf; @@ -1479,38 +2069,48 @@ template static void sortIdx_( const Mat& src, Mat& dst, int flags ) typedef void (*SortFunc)(const Mat& src, Mat& dst, int flags); -void sort( const Mat& src, Mat& dst, int flags ) +} + +void cv::sort( const InputArray& _src, OutputArray _dst, int flags ) { static SortFunc tab[] = { sort_, sort_, sort_, sort_, sort_, sort_, sort_, 0 }; + Mat src = _src.getMat(); SortFunc func = tab[src.depth()]; CV_Assert( src.dims <= 2 && src.channels() == 1 && func != 0 ); - dst.create( src.size(), src.type() ); + _dst.create( src.size(), src.type() ); + Mat dst = _dst.getMat(); func( src, dst, flags ); } -void sortIdx( const Mat& src, Mat& dst, int flags ) +void cv::sortIdx( const InputArray& _src, OutputArray _dst, int flags ) { static SortFunc tab[] = { sortIdx_, sortIdx_, sortIdx_, sortIdx_, sortIdx_, sortIdx_, sortIdx_, 0 }; + Mat src = _src.getMat(); SortFunc func = tab[src.depth()]; CV_Assert( src.dims <= 2 && src.channels() == 1 && func != 0 ); + + Mat dst = _dst.getMat(); if( dst.data == src.data ) - dst.release(); - dst.create( src.size(), CV_32S ); + _dst.release(); + _dst.create( src.size(), CV_32S ); + dst = _dst.getMat(); func( src, dst, flags ); } - ////////////////////////////////////////// kmeans //////////////////////////////////////////// - + +namespace cv +{ + static void generateRandomCenter(const vector& box, float* center, RNG& rng) { size_t j, dims = box.size(); @@ -1520,11 +2120,11 @@ static void generateRandomCenter(const vector& box, float* center, RNG& r } -static inline float distance(const float* a, const float* b, int n, bool simd) +static inline float distance(const float* a, const float* b, int n) { int j = 0; float d = 0.f; #if CV_SSE - if( simd ) + if( USE_SSE2 ) { float CV_DECL_ALIGNED(16) buf[4]; __m128 d0 = _mm_setzero_ps(), d1 = _mm_setzero_ps(); @@ -1572,13 +2172,12 @@ static void generateCentersPP(const Mat& _data, Mat& _out_centers, vector _dist(N*3); float* dist = &_dist[0], *tdist = dist + N, *tdist2 = tdist + N; double sum0 = 0; - bool simd = checkHardwareSupport(CV_CPU_SSE); centers[0] = (unsigned)rng % N; for( i = 0; i < N; i++ ) { - dist[i] = distance(data + step*i, data + step*centers[0], dims, simd); + dist[i] = distance(data + step*i, data + step*centers[0], dims); sum0 += dist[i]; } @@ -1596,7 +2195,7 @@ static void generateCentersPP(const Mat& _data, Mat& _out_centers, int ci = i; for( i = 0; i < N; i++ ) { - tdist2[i] = std::min(distance(data + step*i, data + step*ci, dims, simd), dist[i]); + tdist2[i] = std::min(distance(data + step*i, data + step*ci, dims), dist[i]); s += tdist2[i]; } @@ -1621,20 +2220,25 @@ static void generateCentersPP(const Mat& _data, Mat& _out_centers, } } -double kmeans( const Mat& data, int K, Mat& best_labels, - TermCriteria criteria, int attempts, - int flags, Mat* _centers ) +} + +double cv::kmeans( const InputArray& _data, int K, + InputOutputArray _bestLabels, + TermCriteria criteria, int attempts, + int flags, OutputArray _centers ) { const int SPP_TRIALS = 3; + Mat data = _data.getMat(); int N = data.rows > 1 ? data.rows : data.cols; int dims = (data.rows > 1 ? data.cols : 1)*data.channels(); int type = data.depth(); - bool simd = checkHardwareSupport(CV_CPU_SSE); attempts = std::max(attempts, 1); CV_Assert( data.dims <= 2 && type == CV_32F && K > 0 ); - Mat _labels; + _bestLabels.create(N, 1, CV_32S, -1, true); + + Mat _labels, best_labels = _bestLabels.getMat(); if( flags & CV_KMEANS_USE_INITIAL_LABELS ) { CV_Assert( (best_labels.cols == 1 || best_labels.rows == 1) && @@ -1789,7 +2393,7 @@ double kmeans( const Mat& data, int K, Mat& best_labels, for( k = 0; k < K; k++ ) { const float* center = centers.ptr(k); - double dist = distance(sample, center, dims, simd); + double dist = distance(sample, center, dims); if( min_dist > dist ) { @@ -1806,8 +2410,8 @@ double kmeans( const Mat& data, int K, Mat& best_labels, if( compactness < best_compactness ) { best_compactness = compactness; - if( _centers ) - centers.copyTo(*_centers); + if( _centers.needed() ) + centers.copyTo(_centers); _labels.copyTo(best_labels); } } @@ -1815,8 +2419,6 @@ double kmeans( const Mat& data, int K, Mat& best_labels, return best_compactness; } -} - CV_IMPL void cvSetIdentity( CvArr* arr, CvScalar value ) { @@ -1975,8 +2577,9 @@ cvKMeans2( const CvArr* _samples, int cluster_count, CvArr* _labels, CV_Assert( labels.isContinuous() && labels.type() == CV_32S && (labels.cols == 1 || labels.rows == 1) && labels.cols + labels.rows - 1 == data.rows ); + double compactness = cv::kmeans(data, cluster_count, labels, termcrit, attempts, - flags, _centers ? ¢ers : 0 ); + flags, _centers ? cv::OutputArray(centers) : cv::OutputArray() ); if( _compactness ) *_compactness = compactness; return 1; @@ -2006,25 +2609,33 @@ Mat::operator CvMatND() const } NAryMatIterator::NAryMatIterator() - : arrays(0), planes(0), narrays(0), nplanes(0), iterdepth(0), idx(0) + : arrays(0), planes(0), ptrs(0), narrays(0), nplanes(0), size(0), iterdepth(0), idx(0) { } - + NAryMatIterator::NAryMatIterator(const Mat** _arrays, Mat* _planes, int _narrays) - : arrays(0), planes(0), narrays(0), nplanes(0), iterdepth(0), idx(0) +: arrays(0), planes(0), ptrs(0), narrays(0), nplanes(0), size(0), iterdepth(0), idx(0) +{ + init(_arrays, _planes, 0, _narrays); +} + +NAryMatIterator::NAryMatIterator(const Mat** _arrays, uchar** _ptrs, int _narrays) + : arrays(0), planes(0), ptrs(0), narrays(0), nplanes(0), size(0), iterdepth(0), idx(0) { - init(_arrays, _planes, _narrays); + init(_arrays, 0, _ptrs, _narrays); } -void NAryMatIterator::init(const Mat** _arrays, Mat* _planes, int _narrays) +void NAryMatIterator::init(const Mat** _arrays, Mat* _planes, uchar** _ptrs, int _narrays) { - CV_Assert( _arrays && _planes ); - int i, j, d1=0, i0 = -1, d = -1, total = 0; + CV_Assert( _arrays && (_ptrs || _planes) ); + int i, j, d1=0, i0 = -1, d = -1; arrays = _arrays; + ptrs = _ptrs; planes = _planes; narrays = _narrays; nplanes = 0; + size = 0; if( narrays < 0 ) { @@ -2039,9 +2650,12 @@ void NAryMatIterator::init(const Mat** _arrays, Mat* _planes, int _narrays) for( i = 0; i < narrays; i++ ) { CV_Assert(arrays[i] != 0); - if( !arrays[i]->data ) - continue; const Mat& A = *arrays[i]; + if( ptrs ) + ptrs[i] = A.data; + + if( !A.data ) + continue; if( i0 < 0 ) { @@ -2069,13 +2683,13 @@ void NAryMatIterator::init(const Mat** _arrays, Mat* _planes, int _narrays) if( i0 >= 0 ) { - total = arrays[i0]->size[d-1]; + size = arrays[i0]->size[d-1]; for( j = d-1; j > iterdepth; j-- ) { - int64 total1 = (int64)total*arrays[i0]->size[j-1]; + int64 total1 = (int64)size*arrays[i0]->size[j-1]; if( total1 != (int)total1 ) break; - total = (int)total1; + size = (int)total1; } iterdepth = j; @@ -2087,21 +2701,26 @@ void NAryMatIterator::init(const Mat** _arrays, Mat* _planes, int _narrays) nplanes *= arrays[i0]->size[j]; } else - iterdepth = nplanes = 0; + iterdepth = 0; + + idx = 0; + + if( !planes ) + return; for( i = 0; i < narrays; i++ ) { - if( !arrays[i]->data ) + CV_Assert(arrays[i] != 0); + const Mat& A = *arrays[i]; + + if( !A.data ) { planes[i] = Mat(); continue; } - planes[i] = Mat( 1, total, arrays[i]->type(), arrays[i]->data ); - planes[i].datastart = arrays[i]->datastart; - planes[i].dataend = arrays[i]->dataend; + + planes[i] = Mat(1, (int)size, A.type(), A.data); } - - idx = 0; } @@ -2110,22 +2729,48 @@ NAryMatIterator& NAryMatIterator::operator ++() if( idx >= nplanes-1 ) return *this; ++idx; - - for( int i = 0; i < narrays; i++ ) + + if( iterdepth == 1 ) { - const Mat& A = *arrays[i]; - Mat& M = planes[i]; - if( !A.data ) - continue; - int _idx = idx; - uchar* data = A.data; - for( int j = iterdepth-1; j >= 0 && _idx > 0; j-- ) + if( ptrs ) { - int szi = A.size[j], t = _idx/szi; - data += (_idx - t * szi)*A.step[j]; - _idx = t; + for( int i = 0; i < narrays; i++ ) + { + if( !ptrs[i] ) + continue; + ptrs[i] = arrays[i]->data + arrays[i]->step[0]*idx; + } + } + if( planes ) + { + for( int i = 0; i < narrays; i++ ) + { + if( !planes[i].data ) + continue; + planes[i].data = arrays[i]->data + arrays[i]->step[0]*idx; + } + } + } + else + { + for( int i = 0; i < narrays; i++ ) + { + const Mat& A = *arrays[i]; + if( !A.data ) + continue; + int _idx = idx; + uchar* data = A.data; + for( int j = iterdepth-1; j >= 0 && _idx > 0; j-- ) + { + int szi = A.size[j], t = _idx/szi; + data += (_idx - t * szi)*A.step[j]; + _idx = t; + } + if( ptrs ) + ptrs[i] = data; + if( planes ) + planes[i].data = data; } - M.data = data; } return *this; diff --git a/modules/core/src/precomp.hpp b/modules/core/src/precomp.hpp index ed96556572..09711b69a1 100644 --- a/modules/core/src/precomp.hpp +++ b/modules/core/src/precomp.hpp @@ -65,74 +65,6 @@ #include #include -#define CV_MEMCPY_CHAR( dst, src, len ) \ -{ \ - size_t _icv_memcpy_i_, _icv_memcpy_len_ = (len); \ - char* _icv_memcpy_dst_ = (char*)(dst); \ - const char* _icv_memcpy_src_ = (const char*)(src); \ - \ - for( _icv_memcpy_i_ = 0; _icv_memcpy_i_ < _icv_memcpy_len_; _icv_memcpy_i_++ ) \ - _icv_memcpy_dst_[_icv_memcpy_i_] = _icv_memcpy_src_[_icv_memcpy_i_]; \ -} - - -#define CV_MEMCPY_INT( dst, src, len ) \ -{ \ - size_t _icv_memcpy_i_, _icv_memcpy_len_ = (len); \ - int* _icv_memcpy_dst_ = (int*)(dst); \ - const int* _icv_memcpy_src_ = (const int*)(src); \ - assert( ((size_t)_icv_memcpy_src_&(sizeof(int)-1)) == 0 && \ - ((size_t)_icv_memcpy_dst_&(sizeof(int)-1)) == 0 ); \ - \ - for(_icv_memcpy_i_=0;_icv_memcpy_i_<_icv_memcpy_len_;_icv_memcpy_i_++) \ - _icv_memcpy_dst_[_icv_memcpy_i_] = _icv_memcpy_src_[_icv_memcpy_i_];\ -} - - -#define CV_MEMCPY_AUTO( dst, src, len ) \ -{ \ - size_t _icv_memcpy_i_, _icv_memcpy_len_ = (len); \ - char* _icv_memcpy_dst_ = (char*)(dst); \ - const char* _icv_memcpy_src_ = (const char*)(src); \ - if( (_icv_memcpy_len_ & (sizeof(int)-1)) == 0 ) \ - { \ - assert( ((size_t)_icv_memcpy_src_&(sizeof(int)-1)) == 0 && \ - ((size_t)_icv_memcpy_dst_&(sizeof(int)-1)) == 0 ); \ - for( _icv_memcpy_i_ = 0; _icv_memcpy_i_ < _icv_memcpy_len_; \ - _icv_memcpy_i_+=sizeof(int) ) \ - { \ - *(int*)(_icv_memcpy_dst_+_icv_memcpy_i_) = \ - *(const int*)(_icv_memcpy_src_+_icv_memcpy_i_); \ - } \ - } \ - else \ - { \ - for(_icv_memcpy_i_ = 0; _icv_memcpy_i_ < _icv_memcpy_len_; _icv_memcpy_i_++)\ - _icv_memcpy_dst_[_icv_memcpy_i_] = _icv_memcpy_src_[_icv_memcpy_i_]; \ - } \ -} - - -#define CV_ZERO_CHAR( dst, len ) \ -{ \ - size_t _icv_memcpy_i_, _icv_memcpy_len_ = (len); \ - char* _icv_memcpy_dst_ = (char*)(dst); \ - \ - for( _icv_memcpy_i_ = 0; _icv_memcpy_i_ < _icv_memcpy_len_; _icv_memcpy_i_++ ) \ - _icv_memcpy_dst_[_icv_memcpy_i_] = '\0'; \ -} - - -#define CV_ZERO_INT( dst, len ) \ -{ \ - size_t _icv_memcpy_i_, _icv_memcpy_len_ = (len); \ - int* _icv_memcpy_dst_ = (int*)(dst); \ - assert( ((size_t)_icv_memcpy_dst_&(sizeof(int)-1)) == 0 ); \ - \ - for(_icv_memcpy_i_=0;_icv_memcpy_i_<_icv_memcpy_len_;_icv_memcpy_i_++) \ - _icv_memcpy_dst_[_icv_memcpy_i_] = 0; \ -} - namespace cv { @@ -150,23 +82,11 @@ extern const uchar g_Saturate8u[]; #define CV_MIN_8U(a,b) ((a) - CV_FAST_CAST_8U((a) - (b))) #define CV_MAX_8U(a,b) ((a) + CV_FAST_CAST_8U((b) - (a))) -typedef void (*CopyMaskFunc)(const Mat& src, Mat& dst, const Mat& mask); - -extern CopyMaskFunc g_copyMaskFuncTab[]; - -static inline CopyMaskFunc getCopyMaskFunc(int esz) -{ - CV_Assert( (unsigned)esz <= 32U ); - CopyMaskFunc func = g_copyMaskFuncTab[esz]; - CV_Assert( func != 0 ); - return func; -} #if defined WIN32 || defined _WIN32 void deleteThreadAllocData(); void deleteThreadRNGData(); #endif - template struct OpAdd { @@ -192,22 +112,6 @@ template struct OpRSub T3 operator ()(T1 a, T2 b) const { return saturate_cast(b - a); } }; -template struct OpMul -{ - typedef T1 type1; - typedef T2 type2; - typedef T3 rtype; - T3 operator ()(T1 a, T2 b) const { return saturate_cast(a * b); } -}; - -template struct OpDiv -{ - typedef T1 type1; - typedef T2 type2; - typedef T3 rtype; - T3 operator ()(T1 a, T2 b) const { return saturate_cast(a / b); } -}; - template struct OpMin { typedef T type1; @@ -261,155 +165,35 @@ inline Size getContinuousSize( const Mat& m1, const Mat& m2, struct NoVec { - int operator()(const void*, const void*, void*, int) const { return 0; } + size_t operator()(const void*, const void*, void*, size_t) const { return 0; } }; - - -template static void -binaryOpC1_( const Mat& srcmat1, const Mat& srcmat2, Mat& dstmat ) -{ - Op op; VecOp vecOp; - typedef typename Op::type1 T1; - typedef typename Op::type2 T2; - typedef typename Op::rtype DT; - - const T1* src1 = (const T1*)srcmat1.data; - const T2* src2 = (const T2*)srcmat2.data; - DT* dst = (DT*)dstmat.data; - size_t step1 = srcmat1.step/sizeof(src1[0]); - size_t step2 = srcmat2.step/sizeof(src2[0]); - size_t step = dstmat.step/sizeof(dst[0]); - Size size = getContinuousSize( srcmat1, srcmat2, dstmat, dstmat.channels() ); - - if( size.width == 1 ) - { - for( ; size.height--; src1 += step1, src2 += step2, dst += step ) - dst[0] = op( src1[0], src2[0] ); - return; - } - - for( ; size.height--; src1 += step1, src2 += step2, dst += step ) - { - int x; - x = vecOp(src1, src2, dst, size.width); - for( ; x <= size.width - 4; x += 4 ) - { - DT f0, f1; - f0 = op( src1[x], src2[x] ); - f1 = op( src1[x+1], src2[x+1] ); - dst[x] = f0; - dst[x+1] = f1; - f0 = op(src1[x+2], src2[x+2]); - f1 = op(src1[x+3], src2[x+3]); - dst[x+2] = f0; - dst[x+3] = f1; - } - - for( ; x < size.width; x++ ) - dst[x] = op( src1[x], src2[x] ); - } -} - -typedef void (*BinaryFunc)(const Mat& src1, const Mat& src2, Mat& dst); - -template static void -binarySOpCn_( const Mat& srcmat, Mat& dstmat, const Scalar& _scalar ) -{ - Op op; - typedef typename Op::type1 T; - typedef typename Op::type2 WT; - typedef typename Op::rtype DT; - const T* src0 = (const T*)srcmat.data; - DT* dst0 = (DT*)dstmat.data; - size_t step1 = srcmat.step/sizeof(src0[0]); - size_t step = dstmat.step/sizeof(dst0[0]); - int cn = dstmat.channels(); - Size size = getContinuousSize( srcmat, dstmat, cn ); - WT scalar[12]; - scalarToRawData(_scalar, scalar, CV_MAKETYPE(DataType::depth,cn), 12); - - for( ; size.height--; src0 += step1, dst0 += step ) - { - int i, len = size.width; - const T* src = src0; - T* dst = dst0; - for( ; (len -= 12) >= 0; dst += 12, src += 12 ) - { - DT t0 = op(src[0], scalar[0]); - DT t1 = op(src[1], scalar[1]); - dst[0] = t0; dst[1] = t1; +extern volatile bool USE_SSE2; - t0 = op(src[2], scalar[2]); - t1 = op(src[3], scalar[3]); - dst[2] = t0; dst[3] = t1; +typedef void (*BinaryFunc)(const uchar* src1, size_t step1, + const uchar* src2, size_t step2, + uchar* dst, size_t step, Size sz, + void*); - t0 = op(src[4], scalar[4]); - t1 = op(src[5], scalar[5]); - dst[4] = t0; dst[5] = t1; +BinaryFunc getConvertFunc(int sdepth, int ddepth); +BinaryFunc getConvertScaleFunc(int sdepth, int ddepth); +BinaryFunc getCopyMaskFunc(size_t esz); - t0 = op(src[6], scalar[6]); - t1 = op(src[7], scalar[7]); - dst[6] = t0; dst[7] = t1; - - t0 = op(src[8], scalar[8]); - t1 = op(src[9], scalar[9]); - dst[8] = t0; dst[9] = t1; - - t0 = op(src[10], scalar[10]); - t1 = op(src[11], scalar[11]); - dst[10] = t0; dst[11] = t1; - } - - for( (len) += 12, i = 0; i < (len); i++ ) - dst[i] = op((WT)src[i], scalar[i]); - } -} - -template static void -binarySOpC1_( const Mat& srcmat, Mat& dstmat, double _scalar ) -{ - Op op; - typedef typename Op::type1 T; - typedef typename Op::type2 WT; - typedef typename Op::rtype DT; - WT scalar = saturate_cast(_scalar); - const T* src = (const T*)srcmat.data; - DT* dst = (DT*)dstmat.data; - size_t step1 = srcmat.step/sizeof(src[0]); - size_t step = dstmat.step/sizeof(dst[0]); - Size size = srcmat.size(); - - size.width *= srcmat.channels(); - if( srcmat.isContinuous() && dstmat.isContinuous() ) - { - size.width *= size.height; - size.height = 1; - } - - for( ; size.height--; src += step1, dst += step ) - { - int x; - for( x = 0; x <= size.width - 4; x += 4 ) - { - DT f0 = op( src[x], scalar ); - DT f1 = op( src[x+1], scalar ); - dst[x] = f0; - dst[x+1] = f1; - f0 = op( src[x+2], scalar ); - f1 = op( src[x+3], scalar ); - dst[x+2] = f0; - dst[x+3] = f1; - } - - for( ; x < size.width; x++ ) - dst[x] = op( src[x], scalar ); - } -} - -typedef void (*BinarySFuncCn)(const Mat& src1, Mat& dst, const Scalar& scalar); -typedef void (*BinarySFuncC1)(const Mat& src1, Mat& dst, double scalar); +enum { BLOCK_SIZE = 1024 }; +#ifdef HAVE_IPP +static inline IppiSize ippiSize(int width, int height) { IppiSize sz={width, height}; return sz; } +static inline IppiSize ippiSize(Size _sz) { reIppiSize sz={_sz.width, _sz.height}; return sz; } +#endif + +#if defined HAVE_IPP && (IPP_VERSION_MAJOR >= 7) +#define ARITHM_USE_IPP 1 +#define IF_IPP(then_call, else_call) then_call +#else +#define ARITHM_USE_IPP 0 +#define IF_IPP(then_call, else_call) else_call +#endif + } #endif /*_CXCORE_INTERNAL_H_*/ diff --git a/modules/core/src/rand.cpp b/modules/core/src/rand.cpp index 69b5b85c77..f0701e82e5 100644 --- a/modules/core/src/rand.cpp +++ b/modules/core/src/rand.cpp @@ -67,82 +67,60 @@ namespace cv \***************************************************************************************/ template static void -RandBits_( Mat& _arr, uint64* state, const void* _param ) +randBits_( T* arr, int len, uint64* state, const Vec2i* p, bool small_flag ) { uint64 temp = *state; - const int* param = (const int*)_param; - int small_flag = (param[12]|param[13]|param[14]|param[15]) <= 255; - Size size = getContinuousSize(_arr,_arr.channels()); + int i; - for( int y = 0; y < size.height; y++ ) + if( !small_flag ) { - T* arr = (T*)(_arr.data + _arr.step*y); - int i, k = 3; - const int* p = param; - - if( !small_flag ) - { - for( i = 0; i <= size.width - 4; i += 4 ) - { - int t0, t1; - - temp = RNG_NEXT(temp); - t0 = ((int)temp & p[i + 12]) + p[i]; - temp = RNG_NEXT(temp); - t1 = ((int)temp & p[i + 13]) + p[i+1]; - arr[i] = saturate_cast(t0); - arr[i+1] = saturate_cast(t1); - - temp = RNG_NEXT(temp); - t0 = ((int)temp & p[i + 14]) + p[i+2]; - temp = RNG_NEXT(temp); - t1 = ((int)temp & p[i + 15]) + p[i+3]; - arr[i+2] = saturate_cast(t0); - arr[i+3] = saturate_cast(t1); - - if( !--k ) - { - k = 3; - p -= 12; - } - } - } - else + for( i = 0; i <= len - 4; i += 4 ) { - for( i = 0; i <= size.width - 4; i += 4 ) - { - int t0, t1, t; - - temp = RNG_NEXT(temp); - t = (int)temp; - t0 = (t & p[i + 12]) + p[i]; - t1 = ((t >> 8) & p[i + 13]) + p[i+1]; - arr[i] = saturate_cast(t0); - arr[i+1] = saturate_cast(t1); + int t0, t1; - t0 = ((t >> 16) & p[i + 14]) + p[i + 2]; - t1 = ((t >> 24) & p[i + 15]) + p[i + 3]; - arr[i+2] = saturate_cast(t0); - arr[i+3] = saturate_cast(t1); + temp = RNG_NEXT(temp); + t0 = ((int)temp & p[i][0]) + p[i][1]; + temp = RNG_NEXT(temp); + t1 = ((int)temp & p[i+1][0]) + p[i+1][1]; + arr[i] = saturate_cast(t0); + arr[i+1] = saturate_cast(t1); - if( !--k ) - { - k = 3; - p -= 12; - } - } + temp = RNG_NEXT(temp); + t0 = ((int)temp & p[i+2][0]) + p[i+2][1]; + temp = RNG_NEXT(temp); + t1 = ((int)temp & p[i+3][0]) + p[i+3][1]; + arr[i+2] = saturate_cast(t0); + arr[i+3] = saturate_cast(t1); } - - for( ; i < size.width; i++ ) + } + else + { + for( i = 0; i <= len - 4; i += 4 ) { - int t0; + int t0, t1, t; temp = RNG_NEXT(temp); - - t0 = ((int)temp & p[i + 12]) + p[i]; + t = (int)temp; + t0 = (t & p[i][0]) + p[i][1]; + t1 = ((t >> 8) & p[i+1][0]) + p[i+1][1]; arr[i] = saturate_cast(t0); + arr[i+1] = saturate_cast(t1); + + t0 = ((t >> 16) & p[i+2][0]) + p[i+2][1]; + t1 = ((t >> 24) & p[i+3][0]) + p[i+3][1]; + arr[i+2] = saturate_cast(t0); + arr[i+3] = saturate_cast(t1); } } + for( ; i < len; i++ ) + { + int t0; + temp = RNG_NEXT(temp); + + t0 = ((int)temp & p[i][0]) + p[i][1]; + arr[i] = saturate_cast(t0); + } + *state = temp; } @@ -155,124 +133,96 @@ struct DivStruct }; template static void -Randi_( Mat& _arr, uint64* state, const void* _param ) +randi_( T* arr, int len, uint64* state, const DivStruct* p ) { uint64 temp = *state; - const int* param = (const int*)_param; - Size size = getContinuousSize(_arr,_arr.channels()); - int i, k, cn = _arr.channels(); - DivStruct ds[12]; - - for( k = 0; k < cn; k++ ) + int i = 0; + unsigned t0, t1, v0, v1; + + for( i = 0; i <= len - 4; i += 4 ) { - ds[k].delta = param[k]; - ds[k].d = (unsigned)(param[k+12] - param[k]); - int l = 0; - while(((uint64)1 << l) < ds[k].d) - l++; - ds[k].M = (unsigned)(((uint64)1 << 32)*(((uint64)1 << l) - ds[k].d)/ds[k].d) + 1; - ds[k].sh1 = min(l, 1); - ds[k].sh2 = max(l - 1, 0); + temp = RNG_NEXT(temp); + t0 = (unsigned)temp; + temp = RNG_NEXT(temp); + t1 = (unsigned)temp; + v0 = (unsigned)(((uint64)t0 * p[i].M) >> 32); + v1 = (unsigned)(((uint64)t1 * p[i+1].M) >> 32); + v0 = (v0 + ((t0 - v0) >> p[i].sh1)) >> p[i].sh2; + v1 = (v1 + ((t1 - v1) >> p[i+1].sh1)) >> p[i+1].sh2; + v0 = t0 - v0*p[i].d + p[i].delta; + v1 = t1 - v1*p[i+1].d + p[i+1].delta; + arr[i] = saturate_cast((int)v0); + arr[i+1] = saturate_cast((int)v1); + + temp = RNG_NEXT(temp); + t0 = (unsigned)temp; + temp = RNG_NEXT(temp); + t1 = (unsigned)temp; + v0 = (unsigned)(((uint64)t0 * p[i+2].M) >> 32); + v1 = (unsigned)(((uint64)t1 * p[i+3].M) >> 32); + v0 = (v0 + ((t0 - v0) >> p[i+2].sh1)) >> p[i+2].sh2; + v1 = (v1 + ((t1 - v1) >> p[i+3].sh1)) >> p[i+3].sh2; + v0 = t0 - v0*p[i+2].d + p[i+2].delta; + v1 = t1 - v1*p[i+3].d + p[i+3].delta; + arr[i+2] = saturate_cast((int)v0); + arr[i+3] = saturate_cast((int)v1); } - - for( ; k < 12; k++ ) - ds[k] = ds[k - cn]; - for( int y = 0; y < size.height; y++ ) + for( ; i < len; i++ ) { - T* arr = (T*)(_arr.data + _arr.step*y); - const DivStruct* p = ds; - unsigned t0, t1, v0, v1; - - for( i = 0, k = 3; i <= size.width - 4; i += 4 ) - { - temp = RNG_NEXT(temp); - t0 = (unsigned)temp; - temp = RNG_NEXT(temp); - t1 = (unsigned)temp; - v0 = (unsigned)(((uint64)t0 * p[i].M) >> 32); - v1 = (unsigned)(((uint64)t1 * p[i+1].M) >> 32); - v0 = (v0 + ((t0 - v0) >> p[i].sh1)) >> p[i].sh2; - v1 = (v1 + ((t1 - v1) >> p[i+1].sh1)) >> p[i+1].sh2; - v0 = t0 - v0*p[i].d + p[i].delta; - v1 = t1 - v1*p[i+1].d + p[i+1].delta; - arr[i] = saturate_cast((int)v0); - arr[i+1] = saturate_cast((int)v1); - - temp = RNG_NEXT(temp); - t0 = (unsigned)temp; - temp = RNG_NEXT(temp); - t1 = (unsigned)temp; - v0 = (unsigned)(((uint64)t0 * p[i+2].M) >> 32); - v1 = (unsigned)(((uint64)t1 * p[i+3].M) >> 32); - v0 = (v0 + ((t0 - v0) >> p[i+2].sh1)) >> p[i+2].sh2; - v1 = (v1 + ((t1 - v1) >> p[i+3].sh1)) >> p[i+3].sh2; - v0 = t0 - v0*p[i+2].d + p[i+2].delta; - v1 = t1 - v1*p[i+3].d + p[i+3].delta; - arr[i+2] = saturate_cast((int)v0); - arr[i+3] = saturate_cast((int)v1); - - if( !--k ) - { - k = 3; - p -= 12; - } - } - - for( ; i < size.width; i++ ) - { - temp = RNG_NEXT(temp); - t0 = (unsigned)temp; - v0 = (unsigned)(((uint64)t0 * p[i].M) >> 32); - v0 = (v0 + ((t0 - v0) >> p[i].sh1)) >> p[i].sh2; - v0 = t0 - v0*p[i].d + p[i].delta; - arr[i] = saturate_cast((int)v0); - } + temp = RNG_NEXT(temp); + t0 = (unsigned)temp; + v0 = (unsigned)(((uint64)t0 * p[i].M) >> 32); + v0 = (v0 + ((t0 - v0) >> p[i].sh1)) >> p[i].sh2; + v0 = t0 - v0*p[i].d + p[i].delta; + arr[i] = saturate_cast((int)v0); } *state = temp; } - -static void Randf_( Mat& _arr, uint64* state, const void* _param ) + +#define DEF_RANDI_FUNC(suffix, type) \ +static void randBits_##suffix(type* arr, int len, uint64* state, \ + const Vec2i* p, bool small_flag) \ +{ randBits_(arr, len, state, p, small_flag); } \ +\ +static void randi_##suffix(type* arr, int len, uint64* state, \ + const DivStruct* p, bool ) \ +{ randi_(arr, len, state, p); } + +DEF_RANDI_FUNC(8u, uchar) +DEF_RANDI_FUNC(8s, schar) +DEF_RANDI_FUNC(16u, ushort) +DEF_RANDI_FUNC(16s, short) +DEF_RANDI_FUNC(32s, int) + +static void randf_32f( float* arr, int len, uint64* state, const Vec2f* p, bool ) { uint64 temp = *state; - const float* param = (const float*)_param; - Size size = getContinuousSize(_arr,_arr.channels()); + int i; - for( int y = 0; y < size.height; y++ ) + for( i = 0; i <= len - 4; i += 4 ) { - float* arr = (float*)(_arr.data + _arr.step*y); - int i, k = 3; - const float* p = param; - for( i = 0; i <= size.width - 4; i += 4 ) - { - float f0, f1; - - temp = RNG_NEXT(temp); - f0 = (int)temp*p[i+12] + p[i]; - temp = RNG_NEXT(temp); - f1 = (int)temp*p[i+13] + p[i+1]; - arr[i] = f0; arr[i+1] = f1; - - temp = RNG_NEXT(temp); - f0 = (int)temp*p[i+14] + p[i+2]; - temp = RNG_NEXT(temp); - f1 = (int)temp*p[i+15] + p[i+3]; - arr[i+2] = f0; arr[i+3] = f1; - - if( !--k ) - { - k = 3; - p -= 12; - } - } + float f0, f1; + + temp = RNG_NEXT(temp); + f0 = (int)temp*p[i][0] + p[i][1]; + temp = RNG_NEXT(temp); + f1 = (int)temp*p[i+1][0] + p[i+1][1]; + arr[i] = f0; arr[i+1] = f1; + + temp = RNG_NEXT(temp); + f0 = (int)temp*p[i+2][0] + p[i+2][1]; + temp = RNG_NEXT(temp); + f1 = (int)temp*p[i+3][0] + p[i+3][1]; + arr[i+2] = f0; arr[i+3] = f1; + } - for( ; i < size.width; i++ ) - { - temp = RNG_NEXT(temp); - arr[i] = (int)temp*p[i+12] + p[i]; - } + for( ; i < len; i++ ) + { + temp = RNG_NEXT(temp); + arr[i] = (int)temp*p[i][0] + p[i][1]; } *state = temp; @@ -280,65 +230,65 @@ static void Randf_( Mat& _arr, uint64* state, const void* _param ) static void -Randd_( Mat& _arr, uint64* state, const void* _param ) +randf_64f( double* arr, int len, uint64* state, const Vec2d* p, bool ) { uint64 temp = *state; - const double* param = (const double*)_param; - Size size = getContinuousSize(_arr,_arr.channels()); int64 v = 0; + int i; - for( int y = 0; y < size.height; y++ ) + for( i = 0; i <= len - 4; i += 4 ) { - double* arr = (double*)(_arr.data + _arr.step*y); - int i, k = 3; - const double* p = param; - - for( i = 0; i <= size.width - 4; i += 4 ) - { - double f0, f1; - - temp = RNG_NEXT(temp); - v = (temp >> 32)|(temp << 32); - f0 = v*p[i+12] + p[i]; - temp = RNG_NEXT(temp); - v = (temp >> 32)|(temp << 32); - f1 = v*p[i+13] + p[i+1]; - arr[i] = f0; arr[i+1] = f1; - - temp = RNG_NEXT(temp); - v = (temp >> 32)|(temp << 32); - f0 = v*p[i+14] + p[i+2]; - temp = RNG_NEXT(temp); - v = (temp >> 32)|(temp << 32); - f1 = v*p[i+15] + p[i+3]; - arr[i+2] = f0; arr[i+3] = f1; - - if( !--k ) - { - k = 3; - p -= 12; - } - } + double f0, f1; + + temp = RNG_NEXT(temp); + v = (temp >> 32)|(temp << 32); + f0 = v*p[i][0] + p[i][1]; + temp = RNG_NEXT(temp); + v = (temp >> 32)|(temp << 32); + f1 = v*p[i+1][0] + p[i+1][1]; + arr[i] = f0; arr[i+1] = f1; + + temp = RNG_NEXT(temp); + v = (temp >> 32)|(temp << 32); + f0 = v*p[i+2][0] + p[i+2][1]; + temp = RNG_NEXT(temp); + v = (temp >> 32)|(temp << 32); + f1 = v*p[i+3][0] + p[i+3][1]; + arr[i+2] = f0; arr[i+3] = f1; + } - for( ; i < size.width; i++ ) - { - temp = RNG_NEXT(temp); - v = (temp >> 32)|(temp << 32); - arr[i] = v*p[i+12] + p[i]; - } + for( ; i < len; i++ ) + { + temp = RNG_NEXT(temp); + v = (temp >> 32)|(temp << 32); + arr[i] = v*p[i][0] + p[i][1]; } *state = temp; } - +typedef void (*RandFunc)(uchar* arr, int len, uint64* state, const void* p, bool small_flag); + + +static RandFunc randTab[][8] = +{ + { + (RandFunc)randi_8u, (RandFunc)randi_8s, (RandFunc)randi_16u, (RandFunc)randi_16s, + (RandFunc)randi_32s, (RandFunc)randf_32f, (RandFunc)randf_64f, 0 + }, + { + (RandFunc)randBits_8u, (RandFunc)randBits_8s, (RandFunc)randBits_16u, (RandFunc)randBits_16s, + (RandFunc)randBits_32s, 0, 0, 0 + } +}; + /* The code below implements the algorithm described in "The Ziggurat Method for Generating Random Variables" by Marsaglia and Tsang, Journal of Statistical Software. */ static void -Randn_0_1_32f_C1R( float* arr, int len, uint64* state ) +randn_0_1_32f( float* arr, int len, uint64* state ) { const float r = 3.442620f; // The start of the right tail const float rng_flt = 2.3283064365386962890625e-10f; // 2^-32 @@ -416,115 +366,163 @@ Randn_0_1_32f_C1R( float* arr, int len, uint64* state ) double RNG::gaussian(double sigma) { float temp; - Randn_0_1_32f_C1R( &temp, 1, &state ); + randn_0_1_32f( &temp, 1, &state ); return temp*sigma; } - + template static void -Randn_( Mat& _arr, uint64* state, const void* _param ) +randnScale_( const float* src, T* dst, int len, int cn, const PT* mean, const PT* stddev, bool stdmtx ) { - const int RAND_BUF_SIZE = 96; - float buffer[RAND_BUF_SIZE]; - int pidx[RAND_BUF_SIZE]; - const PT* param = (const PT*)_param; - Size size = getContinuousSize(_arr, _arr.channels()); - - int i, n = std::min(size.width, RAND_BUF_SIZE); - for( i = 0; i < 12; i++ ) - pidx[i] = i; - for( ; i < n; i++ ) - pidx[i] = pidx[i - 12]; - - for( int y = 0; y < size.height; y++ ) + int i, j, k; + if( !stdmtx ) { - T* arr = (T*)(_arr.data + _arr.step*y); - int len = RAND_BUF_SIZE; - for( i = 0; i < size.width; i += RAND_BUF_SIZE ) + if( cn == 1 ) { - if( i + len > size.width ) - len = size.width - i; - - Randn_0_1_32f_C1R( buffer, len, state ); - - for( int j = 0; j < len; j++ ) - arr[i+j] = saturate_cast(buffer[j]*param[pidx[j]+12] + param[pidx[j]]); + PT b = mean[0], a = stddev[0]; + for( i = 0; i < len; i++ ) + dst[i] = saturate_cast(src[i]*a + b); + } + else + { + for( i = 0; i < len; i++, src += cn, dst += cn ) + for( k = 0; k < cn; k++ ) + dst[k] = saturate_cast(src[k]*stddev[k] + mean[k]); + } + } + else + { + for( i = 0; i < len; i++, src += cn, dst += cn ) + { + for( j = 0; j < cn; j++ ) + { + PT s = mean[j]; + for( k = 0; k < cn; k++ ) + s += src[k]*stddev[j*cn + k]; + dst[j] = saturate_cast(s); + } } } } + +static void randnScale_8u( const float* src, uchar* dst, int len, int cn, + const float* mean, const float* stddev, bool stdmtx ) +{ randnScale_(src, dst, len, cn, mean, stddev, stdmtx); } + +static void randnScale_8s( const float* src, schar* dst, int len, int cn, + const float* mean, const float* stddev, bool stdmtx ) +{ randnScale_(src, dst, len, cn, mean, stddev, stdmtx); } +static void randnScale_16u( const float* src, ushort* dst, int len, int cn, + const float* mean, const float* stddev, bool stdmtx ) +{ randnScale_(src, dst, len, cn, mean, stddev, stdmtx); } -typedef void (*RandFunc)(Mat& dst, uint64* state, const void* param); +static void randnScale_16s( const float* src, short* dst, int len, int cn, + const float* mean, const float* stddev, bool stdmtx ) +{ randnScale_(src, dst, len, cn, mean, stddev, stdmtx); } -void RNG::fill( Mat& mat, int disttype, const Scalar& param1, const Scalar& param2 ) +static void randnScale_32s( const float* src, int* dst, int len, int cn, + const float* mean, const float* stddev, bool stdmtx ) +{ randnScale_(src, dst, len, cn, mean, stddev, stdmtx); } + +static void randnScale_32f( const float* src, float* dst, int len, int cn, + const float* mean, const float* stddev, bool stdmtx ) +{ randnScale_(src, dst, len, cn, mean, stddev, stdmtx); } + +static void randnScale_64f( const float* src, double* dst, int len, int cn, + const double* mean, const double* stddev, bool stdmtx ) +{ randnScale_(src, dst, len, cn, mean, stddev, stdmtx); } + +typedef void (*RandnScaleFunc)(const float* src, uchar* dst, int len, int cn, + const uchar*, const uchar*, bool); + +static RandnScaleFunc randnScaleTab[] = { - static RandFunc rngtab[3][8] = - { - { - RandBits_, - RandBits_, - RandBits_, - RandBits_, - RandBits_, 0, 0, 0}, - - {Randi_, - Randi_, - Randi_, - Randi_, - Randi_, - Randf_, Randd_, 0}, - - {Randn_, - Randn_, - Randn_, - Randn_, - Randn_, - Randn_, - Randn_, 0} - }; + (RandnScaleFunc)randnScale_8u, (RandnScaleFunc)randnScale_8s, (RandnScaleFunc)randnScale_16u, + (RandnScaleFunc)randnScale_16s, (RandnScaleFunc)randnScale_32s, (RandnScaleFunc)randnScale_32f, + (RandnScaleFunc)randnScale_64f, 0 +}; - int depth = mat.depth(), channels = mat.channels(); - double dparam[2][12]; - float fparam[2][12]; - int iparam[2][12]; - void* param = dparam; - int i, fast_int_mode = 0; +void RNG::fill( InputOutputArray _mat, int disttype, const InputArray& _param1arg, const InputArray& _param2arg ) +{ + Mat mat = _mat.getMat(), _param1 = _param1arg.getMat(), _param2 = _param2arg.getMat(); + int depth = mat.depth(), cn = mat.channels(); + AutoBuffer _parambuf; + int j, k, fast_int_mode = 0, smallFlag = 1; RandFunc func = 0; - - CV_Assert( channels <= 4 ); + RandnScaleFunc scaleFunc = 0; + + CV_Assert(_param1.channels() == 1 && (_param1.rows == 1 || _param1.cols == 1) && + (_param1.rows + _param1.cols - 1 == cn || + (_param1.size() == Size(1, 4) && _param1.type() == CV_64F && cn <= 4))); + CV_Assert( _param2.channels() == 1 && + (((_param2.rows == 1 || _param2.cols == 1) && + (_param2.rows + _param2.cols - 1 == cn || + (_param1.size() == Size(1, 4) && _param1.type() == CV_64F && cn <= 4))) || + (_param2.rows == cn && _param2.cols == cn && disttype == NORMAL))); + + Vec2i* ip = 0; + Vec2d* dp = 0; + Vec2f* fp = 0; + DivStruct* ds = 0; + uchar* mean = 0; + uchar* stddev = 0; + bool stdmtx = false; if( disttype == UNIFORM ) { + _parambuf.allocate(cn*8); + double* parambuf = _parambuf; + const double* p1 = (const double*)_param1.data; + const double* p2 = (const double*)_param2.data; + + if( !_param1.isContinuous() || _param1.type() != CV_64F ) + { + Mat tmp(_param1.size(), CV_64F, parambuf); + _param1.convertTo(tmp, CV_64F); + p1 = parambuf; + } + + if( !_param2.isContinuous() || _param2.type() != CV_64F ) + { + Mat tmp(_param2.size(), CV_64F, parambuf + cn); + _param2.convertTo(tmp, CV_64F); + p2 = parambuf + cn; + } + if( depth <= CV_32S ) { - for( i = 0, fast_int_mode = 1; i < channels; i++ ) + ip = (Vec2i*)(parambuf + cn*2); + for( j = 0, fast_int_mode = 1; j < cn; j++ ) { - double a = min(param1.val[i], param2.val[i]); - double b = max(param1.val[i], param2.val[i]); - int t0 = iparam[0][i] = cvCeil(a); - int t1 = iparam[1][i] = cvFloor(b); + double a = min(p1[j], p2[j]); + double b = max(p1[j], p2[j]); + ip[j][1] = cvCeil(a); + int idiff = ip[j][0] = cvFloor(b) - ip[j][1] - 1; double diff = b - a; - fast_int_mode &= diff <= 4294967296. && ((t1-t0) & (t1-t0-1)) == 0; + fast_int_mode &= diff <= 4294967296. && (idiff & (idiff+1)) == 0; + if( fast_int_mode ) + smallFlag &= idiff <= 255; } - if( fast_int_mode ) - { - for( i = 0; i < channels; i++ ) - iparam[1][i] = iparam[1][i] > iparam[0][i] ? iparam[1][i] - iparam[0][i] - 1 : 0; - } - - for( ; i < 12; i++ ) + if( !fast_int_mode ) { - int t0 = iparam[0][i - channels]; - int t1 = iparam[1][i - channels]; - - iparam[0][i] = t0; - iparam[1][i] = t1; + ds = (DivStruct*)(ip + cn); + for( j = 0; j < cn; j++ ) + { + ds[j].delta = ip[j][1]; + unsigned d = ds[j].d = (unsigned)(ip[j][0]+1); + int l = 0; + while(((uint64)1 << l) < d) + l++; + ds[j].M = (unsigned)(((uint64)1 << 32)*(((uint64)1 << l) - d)/d) + 1; + ds[j].sh1 = min(l, 1); + ds[j].sh2 = max(l - 1, 0); + } } - func = rngtab[!fast_int_mode][depth]; - param = iparam; + func = randTab[fast_int_mode][depth]; } else { @@ -536,70 +534,128 @@ void RNG::fill( Mat& mat, int disttype, const Scalar& param1, const Scalar& para // so that a signed 32/64-bit integer X is transformed to // the range [param1.val[i], param2.val[i]) using // dparam[1][i]*X + dparam[0][i] - for( i = 0; i < channels; i++ ) + if( depth == CV_32F ) { - double t0 = param1.val[i]; - double t1 = param2.val[i]; - dparam[0][i] = (t1 + t0)*0.5; - dparam[1][i] = (t1 - t0)*scale; + fp = (Vec2f*)(parambuf + cn*2); + for( j = 0; j < cn; j++ ) + { + fp[j][0] = (float)((p2[j] - p1[j])*scale); + fp[j][1] = (float)((p2[j] + p1[j])*0.5); + } + } + else + { + dp = (Vec2d*)(parambuf + cn*2); + for( j = 0; j < cn; j++ ) + { + dp[j][0] = ((p2[j] - p1[j])*scale); + dp[j][1] = ((p2[j] + p1[j])*0.5); + } } - func = rngtab[1][depth]; - param = dparam; + func = randTab[0][depth]; } + CV_Assert( func != 0 ); } else if( disttype == CV_RAND_NORMAL ) { - for( i = 0; i < channels; i++ ) + _parambuf.allocate(_param1.total() + _param2.total()); + double* parambuf = _parambuf; + + int ptype = depth == CV_64F ? CV_64F : CV_32F; + if( _param1.isContinuous() && _param1.type() == ptype ) + mean = _param1.data; + else { - double t0 = param1.val[i]; - double t1 = param2.val[i]; - - dparam[0][i] = t0; - dparam[1][i] = t1; + Mat tmp(_param1.size(), ptype, parambuf); + _param1.convertTo(tmp, ptype); + mean = (uchar*)parambuf; } - - func = rngtab[2][depth]; - param = dparam; + + if( _param2.isContinuous() && _param2.type() == ptype ) + stddev = _param2.data; + else + { + Mat tmp(_param2.size(), ptype, parambuf + cn); + _param2.convertTo(tmp, ptype); + stddev = (uchar*)(parambuf + cn); + } + + stdmtx = _param2.rows == cn && _param2.cols == cn; + scaleFunc = randnScaleTab[depth]; + CV_Assert( scaleFunc != 0 ); } else CV_Error( CV_StsBadArg, "Unknown distribution type" ); - if( param == dparam ) + const Mat* arrays[] = {&mat, 0}; + uchar* ptr; + NAryMatIterator it(arrays, &ptr); + int total = (int)it.size, blockSize = std::min((BLOCK_SIZE + cn - 1)/cn, total); + size_t esz = mat.elemSize(); + AutoBuffer buf; + uchar* param = 0; + float* nbuf = 0; + + if( disttype == UNIFORM ) { - for( i = channels; i < 12; i++ ) - { - double t0 = dparam[0][i - channels]; - double t1 = dparam[1][i - channels]; - - dparam[0][i] = t0; - dparam[1][i] = t1; - } - - if( depth != CV_64F ) + buf.allocate(blockSize*cn*4); + param = (uchar*)(double*)buf; + + if( ip ) { - for( i = 0; i < 12; i++ ) + if( ds ) + { + DivStruct* p = (DivStruct*)param; + for( j = 0; j < blockSize*cn; j += cn ) + for( k = 0; k < cn; k++ ) + p[j + k] = ds[k]; + } + else { - fparam[0][i] = (float)dparam[0][i]; - fparam[1][i] = (float)dparam[1][i]; + Vec2i* p = (Vec2i*)param; + for( j = 0; j < blockSize*cn; j += cn ) + for( k = 0; k < cn; k++ ) + p[j + k] = ip[k]; } - param = fparam; + } + else if( fp ) + { + Vec2f* p = (Vec2f*)param; + for( j = 0; j < blockSize*cn; j += cn ) + for( k = 0; k < cn; k++ ) + p[j + k] = fp[k]; + } + else + { + Vec2d* p = (Vec2d*)param; + for( j = 0; j < blockSize*cn; j += cn ) + for( k = 0; k < cn; k++ ) + p[j + k] = dp[k]; } } - - CV_Assert( func != 0); + else + { + buf.allocate((blockSize*cn+1)/2); + nbuf = (float*)(double*)buf; + } - if( mat.dims > 2 ) + for( size_t i = 0; i < it.nplanes; i++, ++it ) { - const Mat* arrays[] = {&mat, 0}; - Mat planes[1]; - NAryMatIterator it(arrays, planes); - - for( int i = 0; i < it.nplanes; i++, ++it ) - func( it.planes[0], &state, param ); + for( j = 0; j < total; j += blockSize ) + { + int len = std::min(total - j, blockSize); + + if( disttype == CV_RAND_UNI ) + func( ptr, len*cn, &state, param, smallFlag != 0 ); + else + { + randn_0_1_32f(nbuf, len*cn, &state); + scaleFunc(nbuf, ptr, len, cn, mean, stddev, stdmtx); + } + ptr += len*esz; + } } - else - func( mat, &state, param ); } #ifdef WIN32 @@ -657,16 +713,21 @@ RNG& theRNG() #endif -void randu(CV_OUT Mat& dst, const Scalar& low, const Scalar& high) +} + +void cv::randu(InputOutputArray dst, const InputArray& low, const InputArray& high) { theRNG().fill(dst, RNG::UNIFORM, low, high); } -void randn(CV_OUT Mat& dst, const Scalar& mean, const Scalar& stddev) +void cv::randn(InputOutputArray dst, const InputArray& mean, const InputArray& stddev) { theRNG().fill(dst, RNG::NORMAL, mean, stddev); } - + +namespace cv +{ + template static void randShuffle_( Mat& _arr, RNG& rng, double iterFactor ) { @@ -697,7 +758,9 @@ randShuffle_( Mat& _arr, RNG& rng, double iterFactor ) typedef void (*RandShuffleFunc)( Mat& dst, RNG& rng, double iterFactor ); -void randShuffle( Mat& dst, double iterFactor, RNG* _rng ) +} + +void cv::randShuffle( InputOutputArray _dst, double iterFactor, RNG* _rng ) { RandShuffleFunc tab[] = { @@ -719,7 +782,8 @@ void randShuffle( Mat& dst, double iterFactor, RNG* _rng ) 0, 0, 0, 0, 0, 0, 0, randShuffle_ > // 32 }; - + + Mat dst = _dst.getMat(); RNG& rng = _rng ? *_rng : theRNG(); CV_Assert( dst.elemSize() <= 32 ); RandShuffleFunc func = tab[dst.elemSize()]; @@ -727,8 +791,6 @@ void randShuffle( Mat& dst, double iterFactor, RNG* _rng ) func( dst, rng, iterFactor ); } -} - CV_IMPL void cvRandArr( CvRNG* _rng, CvArr* arr, int disttype, CvScalar param1, CvScalar param2 ) { @@ -736,7 +798,7 @@ cvRandArr( CvRNG* _rng, CvArr* arr, int disttype, CvScalar param1, CvScalar para // !!! this will only work for current 64-bit MWC RNG !!! cv::RNG& rng = _rng ? (cv::RNG&)*_rng : cv::theRNG(); rng.fill(mat, disttype == CV_RAND_NORMAL ? - cv::RNG::NORMAL : cv::RNG::UNIFORM, param1, param2 ); + cv::RNG::NORMAL : cv::RNG::UNIFORM, (cv::Scalar&)param1, (cv::Scalar&)param2 ); } CV_IMPL void cvRandShuffle( CvArr* arr, CvRNG* _rng, double iter_factor ) diff --git a/modules/core/src/stat.cpp b/modules/core/src/stat.cpp index 44f981a370..b35d1cf08e 100644 --- a/modules/core/src/stat.cpp +++ b/modules/core/src/stat.cpp @@ -11,7 +11,7 @@ // For Open Source Computer Vision Library // // Copyright (C) 2000-2008, Intel Corporation, all rights reserved. -// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Copyright (C) 2009-2011, Willow Garage Inc., all rights reserved. // Third party copyrights are property of their respective owners. // // Redistribution and use in source and binary forms, with or without modification, @@ -59,608 +59,611 @@ template static inline Scalar rawToScalar(const T& v) * sum * \****************************************************************************************/ -template -static Scalar sumBlock_( const Mat& srcmat ) +template +static size_t sum_(const T* src0, const uchar* mask, ST* dst, int len, int cn ) { - assert( DataType::type == srcmat.type() ); - Size size = getContinuousSize( srcmat ); - ST s0 = 0; - WT s = 0; - int y, remaining = BLOCK_SIZE; - - for( y = 0; y < size.height; y++ ) + const T* src = src0; + if( !mask ) { - const T* src = (const T*)(srcmat.data + srcmat.step*y); - int x = 0; - while( x < size.width ) + int i; + int k = cn % 4; + if( k == 1 ) + { + ST s0 = dst[0]; + for( i = 0; i <= len - 4; i += 4, src += cn*4 ) + s0 += src[0] + src[cn] + src[cn*2] + src[cn*3]; + for( ; i < len; i++, src += cn ) + s0 += src[0]; + dst[0] = s0; + } + else if( k == 2 ) { - int limit = std::min( remaining, size.width - x ); - remaining -= limit; - limit += x; - for( ; x <= limit - 4; x += 4 ) + ST s0 = dst[0], s1 = dst[1]; + for( i = 0; i < len; i++, src += cn ) { - s += src[x]; - s += src[x+1]; - s += src[x+2]; - s += src[x+3]; + s0 += src[0]; + s1 += src[1]; } - for( ; x < limit; x++ ) - s += src[x]; - if( remaining == 0 || (x == size.width && y == size.height-1) ) + dst[0] = s0; + dst[1] = s1; + } + else if( k == 3 ) + { + ST s0 = dst[0], s1 = dst[1], s2 = dst[2]; + for( i = 0; i < len; i++, src += cn ) { - s0 += s; - s = 0; - remaining = BLOCK_SIZE; + s0 += src[0]; + s1 += src[1]; + s2 += src[2]; } + dst[0] = s0; + dst[1] = s1; + dst[2] = s2; } - } - return rawToScalar(s0); -} - -template -static Scalar sum_( const Mat& srcmat ) -{ - assert( DataType::type == srcmat.type() ); - Size size = getContinuousSize( srcmat ); - ST s = 0; - - for( int y = 0; y < size.height; y++ ) - { - const T* src = (const T*)(srcmat.data + srcmat.step*y); - int x = 0; - for( ; x <= size.width - 4; x += 4 ) + + for( ; k < cn; k += 4 ) { - s += src[x]; - s += src[x+1]; - s += src[x+2]; - s += src[x+3]; + src = src0 + k; + ST s0 = dst[k], s1 = dst[k+1], s2 = dst[k+2], s3 = dst[k+3]; + for( i = 0; i < len; i++, src += cn ) + { + s0 += src[0]; s1 += src[1]; + s2 += src[2]; s3 += src[3]; + } + dst[k] = s0; + dst[k+1] = s1; + dst[k+2] = s2; + dst[k+3] = s3; } - for( ; x < size.width; x++ ) - s += src[x]; + return len; } - return rawToScalar(s); -} - -typedef Scalar (*SumFunc)(const Mat& src); - -Scalar sum( const Mat& m ) -{ - static SumFunc tab[]= + + int i, nzm = 0; + if( cn == 1 ) { - sumBlock_, - sumBlock_, - sumBlock_, - sumBlock_, - sum_, - sum_, - sum_, 0, - - sumBlock_, Vec, Vec, 1<<23>, - sumBlock_, Vec, Vec, 1<<24>, - sumBlock_, Vec, Vec, 1<<15>, - sumBlock_, Vec, Vec, 1<<16>, - sum_, Vec >, - sum_, Vec >, - sum_, Vec >, 0, - - sumBlock_, Vec, Vec, 1<<23>, - sumBlock_, Vec, Vec, 1<<24>, - sumBlock_, Vec, Vec, 1<<15>, - sumBlock_, Vec, Vec, 1<<16>, - sum_, Vec >, - sum_, Vec >, - sum_, Vec >, 0, - - sumBlock_, Vec, Vec, 1<<23>, - sumBlock_, Vec, Vec, 1<<24>, - sumBlock_, Vec, Vec, 1<<15>, - sumBlock_, Vec, Vec, 1<<16>, - sum_, Vec >, - sum_, Vec >, - sum_, Vec >, 0 - }; - - CV_Assert( m.channels() <= 4 ); - - SumFunc func = tab[m.type()]; - CV_Assert( func != 0 ); - - if( m.dims > 2 ) + ST s = dst[0]; + for( i = 0; i < len; i++ ) + if( mask[i] ) + { + s += src[i]; + nzm++; + } + dst[0] = s; + } + else if( cn == 3 ) { - const Mat* arrays[] = {&m, 0}; - Mat planes[1]; - NAryMatIterator it(arrays, planes); - Scalar s; - - for( int i = 0; i < it.nplanes; i++, ++it ) - s += func(it.planes[0]); - return s; + ST s0 = dst[0], s1 = dst[1], s2 = dst[2]; + for( i = 0; i < len; i++, src += 3 ) + if( mask[i] ) + { + s0 += src[0]; + s1 += src[1]; + s2 += src[2]; + nzm++; + } + dst[0] = s0; + dst[1] = s1; + dst[2] = s2; } - - return func(m); + else + { + for( i = 0; i < len; i++, src += cn ) + if( mask[i] ) + { + int k = 0; + for( ; k <= cn - 4; k += 4 ) + { + ST s0, s1; + s0 = dst[k] + src[k]; + s1 = dst[k+1] + src[k+1]; + dst[k] = s0; dst[k+1] = s1; + s0 = dst[k+2] + src[k+2]; + s1 = dst[k+3] + src[k+3]; + dst[k+2] = s0; dst[k+3] = s1; + } + for( ; k < cn; k++ ) + dst[k] += src[k]; + nzm++; + } + } + return nzm; } -/****************************************************************************************\ -* countNonZero * -\****************************************************************************************/ + +static int sum8u( const uchar* src, const uchar* mask, int* dst, int len, int cn ) +{ return sum_(src, mask, dst, len, cn); } -template -static int countNonZero_( const Mat& srcmat ) -{ - //assert( DataType::type == srcmat.type() ); - const T* src = (const T*)srcmat.data; - size_t step = srcmat.step/sizeof(src[0]); - Size size = getContinuousSize( srcmat ); - int nz = 0; +static int sum8s( const schar* src, const uchar* mask, int* dst, int len, int cn ) +{ return sum_(src, mask, dst, len, cn); } - for( ; size.height--; src += step ) - { - int x = 0; - for( ; x <= size.width - 4; x += 4 ) - nz += (src[x] != 0) + (src[x+1] != 0) + (src[x+2] != 0) + (src[x+3] != 0); - for( ; x < size.width; x++ ) - nz += src[x] != 0; - } - return nz; -} +static int sum16u( const ushort* src, const uchar* mask, int* dst, int len, int cn ) +{ return sum_(src, mask, dst, len, cn); } -typedef int (*CountNonZeroFunc)(const Mat& src); +static int sum16s( const short* src, const uchar* mask, int* dst, int len, int cn ) +{ return sum_(src, mask, dst, len, cn); } -int countNonZero( const Mat& m ) -{ - static CountNonZeroFunc tab[] = - { - countNonZero_, countNonZero_, countNonZero_, - countNonZero_, countNonZero_, countNonZero_, - countNonZero_, 0 - }; - - CountNonZeroFunc func = tab[m.depth()]; - CV_Assert( m.channels() == 1 && func != 0 ); - - if( m.dims > 2 ) - { - const Mat* arrays[] = {&m, 0}; - Mat planes[1]; - NAryMatIterator it(arrays, planes); - int nz = 0; - - for( int i = 0; i < it.nplanes; i++, ++it ) - nz += func(it.planes[0]); - return nz; - } - - return func(m); -} +static int sum32s( const int* src, const uchar* mask, double* dst, int len, int cn ) +{ return sum_(src, mask, dst, len, cn); } +static int sum32f( const float* src, const uchar* mask, double* dst, int len, int cn ) +{ return sum_(src, mask, dst, len, cn); } -/****************************************************************************************\ -* mean * -\****************************************************************************************/ +static int sum64f( const double* src, const uchar* mask, double* dst, int len, int cn ) +{ return sum_(src, mask, dst, len, cn); } -template -static Scalar meanBlock_( const Mat& srcmat, const Mat& maskmat ) +typedef int (*SumFunc)(const uchar*, const uchar* mask, uchar*, int, int); + +static SumFunc sumTab[] = { - assert( DataType::type == srcmat.type() && - CV_8U == maskmat.type() && srcmat.size() == maskmat.size() ); - Size size = getContinuousSize( srcmat, maskmat ); - ST s0 = 0; - WT s = 0; - int y, remaining = BLOCK_SIZE, pix = 0; - - for( y = 0; y < size.height; y++ ) - { - const T* src = (const T*)(srcmat.data + srcmat.step*y); - const uchar* mask = maskmat.data + maskmat.step*y; - int x = 0; - while( x < size.width ) - { - int limit = std::min( remaining, size.width - x ); - remaining -= limit; - limit += x; - for( ; x < limit; x++ ) - if( mask[x] ) - s += src[x], pix++; - if( remaining == 0 || (x == size.width && y == size.height-1) ) - { - s0 += s; - s = 0; - remaining = BLOCK_SIZE; - } - } - } - return rawToScalar(s0)*(1./std::max(pix, 1)); + (SumFunc)sum8u, (SumFunc)sum8s, (SumFunc)sum16u, (SumFunc)sum16s, + (SumFunc)sum32s, (SumFunc)sum32f, (SumFunc)sum64f, 0 +}; + + +template +static int countNonZero_(const T* src, int len ) +{ + int i, nz = 0; + for( i = 0; i <= len - 4; i += 4 ) + nz += (src[i] != 0) + (src[i+1] != 0) + (src[i+2] != 0) + (src[i+3] != 0); + for( ; i < len; i++ ) + nz += src[i] != 0; + return nz; } +static int countNonZero8u( const uchar* src, int len ) +{ return countNonZero_(src, len); } -template -static Scalar mean_( const Mat& srcmat, const Mat& maskmat ) -{ - assert( DataType::type == srcmat.type() && - CV_8U == maskmat.type() && srcmat.size() == maskmat.size() ); - Size size = getContinuousSize( srcmat, maskmat ); - ST s = 0; - int y, pix = 0; +static int countNonZero16u( const ushort* src, int len ) +{ return countNonZero_(src, len); } - for( y = 0; y < size.height; y++ ) - { - const T* src = (const T*)(srcmat.data + srcmat.step*y); - const uchar* mask = maskmat.data + maskmat.step*y; - for( int x = 0; x < size.width; x++ ) - if( mask[x] ) - s += src[x], pix++; - } - return rawToScalar(s)*(1./std::max(pix, 1)); -} +static int countNonZero32s( const int* src, int len ) +{ return countNonZero_(src, len); } + +static int countNonZero32f( const float* src, int len ) +{ return countNonZero_(src, len); } -typedef Scalar (*MeanMaskFunc)(const Mat& src, const Mat& mask); +static int countNonZero64f( const double* src, int len ) +{ return countNonZero_(src, len); } -Scalar mean(const Mat& m) +typedef int (*CountNonZeroFunc)(const uchar*, int); + +static CountNonZeroFunc countNonZeroTab[] = { - return sum(m)*(1./m.total()); -} + (CountNonZeroFunc)countNonZero8u, (CountNonZeroFunc)countNonZero8u, + (CountNonZeroFunc)countNonZero16u, (CountNonZeroFunc)countNonZero16u, + (CountNonZeroFunc)countNonZero32s, (CountNonZeroFunc)countNonZero32f, + (CountNonZeroFunc)countNonZero64f, 0 +}; -Scalar mean( const Mat& m, const Mat& mask ) + +template +static int sumsqr_(const T* src0, const uchar* mask, ST* sum, SQT* sqsum, int len, int cn ) { - static MeanMaskFunc tab[]= - { - meanBlock_, 0, - meanBlock_, - meanBlock_, - mean_, - mean_, - mean_, 0, - - meanBlock_, Vec, Vec, 1<<23>, 0, - meanBlock_, Vec, Vec, 1<<15>, - meanBlock_, Vec, Vec, 1<<16>, - mean_, Vec >, - mean_, Vec >, - mean_, Vec >, 0, - - meanBlock_, Vec, Vec, 1<<23>, 0, - meanBlock_, Vec, Vec, 1<<15>, - meanBlock_, Vec, Vec, 1<<16>, - mean_, Vec >, - mean_, Vec >, - mean_, Vec >, 0, - - meanBlock_, Vec, Vec, 1<<23>, 0, - meanBlock_, Vec, Vec, 1<<15>, - meanBlock_, Vec, Vec, 1<<16>, - mean_, Vec >, - mean_, Vec >, - mean_, Vec >, 0 - }; - - if( !mask.data ) - return mean(m); - - CV_Assert( m.channels() <= 4 && mask.type() == CV_8U ); - - MeanMaskFunc func = tab[m.type()]; - CV_Assert( func != 0 ); + const T* src = src0; - if( m.dims > 2 ) + if( !mask ) { - const Mat* arrays[] = {&m, &mask, 0}; - Mat planes[2]; - NAryMatIterator it(arrays, planes); - double total = 0; - Scalar s; - for( int i = 0; i < it.nplanes; i++, ++it ) + int i; + int k = cn % 4; + + if( k == 1 ) + { + ST s0 = sum[0]; + SQT sq0 = sqsum[0]; + for( i = 0; i < len; i++, src += cn ) + { + T v = src[0]; + s0 += v; sq0 += (SQT)v*v; + } + sum[0] = s0; + sqsum[0] = sq0; + } + else if( k == 2 ) + { + ST s0 = sum[0], s1 = sum[1]; + SQT sq0 = sqsum[0], sq1 = sqsum[1]; + for( i = 0; i < len; i++, src += cn ) + { + T v0 = src[0], v1 = src[1]; + s0 += v0; sq0 += (SQT)v0*v0; + s1 += v1; sq1 += (SQT)v1*v1; + } + sum[0] = s0; sum[1] = s1; + sqsum[0] = sq0; sqsum[1] = sq1; + } + else if( k == 3 ) + { + ST s0 = sum[0], s1 = sum[1], s2 = sum[2]; + SQT sq0 = sqsum[0], sq1 = sqsum[1], sq2 = sqsum[2]; + for( i = 0; i < len; i++, src += cn ) + { + T v0 = src[0], v1 = src[1], v2 = src[2]; + s0 += v0; sq0 += (SQT)v0*v0; + s1 += v1; sq1 += (SQT)v1*v1; + s2 += v2; sq2 += (SQT)v2*v2; + } + sum[0] = s0; sum[1] = s1; sum[2] = s2; + sqsum[0] = sq0; sqsum[1] = sq1; sqsum[2] = sq2; + } + + for( ; k < cn; k += 4 ) { - int n = countNonZero(it.planes[1]); - s += mean(it.planes[0], it.planes[1])*(double)n; - total += n; + src = src0 + k; + ST s0 = sum[k], s1 = sum[k+1], s2 = sum[k+2], s3 = sum[k+3]; + SQT sq0 = sqsum[k], sq1 = sqsum[k+1], sq2 = sqsum[k+2], sq3 = sqsum[k+3]; + for( i = 0; i < len; i++, src += cn ) + { + T v0, v1; + v0 = src[0], v1 = src[1]; + s0 += v0; sq0 += (SQT)v0*v0; + s1 += v1; sq1 += (SQT)v1*v1; + v0 = src[2], v1 = src[3]; + s2 += v0; sq2 += (SQT)v0*v0; + s3 += v1; sq3 += (SQT)v1*v1; + } + sum[k] = s0; sum[k+1] = s1; + sum[k+2] = s2; sum[k+3] = s3; + sqsum[k] = sq0; sqsum[k+1] = sq1; + sqsum[k+2] = sq2; sqsum[k+3] = sq3; } - return (s * 1./std::max(total, 1.)); + return len; } - CV_Assert( m.size() == mask.size() ); - return func( m, mask ); -} + int i, nzm = 0; -/****************************************************************************************\ -* meanStdDev * -\****************************************************************************************/ + if( cn == 1 ) + { + ST s0 = sum[0]; + SQT sq0 = sqsum[0]; + for( i = 0; i < len; i++ ) + if( mask[i] ) + { + T v = src[i]; + s0 += v; sq0 += (SQT)v*v; + nzm++; + } + sum[0] = s0; + sqsum[0] = sq0; + } + else if( cn == 3 ) + { + ST s0 = sum[0], s1 = sum[1], s2 = sum[2]; + SQT sq0 = sqsum[0], sq1 = sqsum[1], sq2 = sqsum[2]; + for( i = 0; i < len; i++, src += 3 ) + if( mask[i] ) + { + T v0 = src[0], v1 = src[1], v2 = src[2]; + s0 += v0; sq0 += (SQT)v0*v0; + s1 += v1; sq1 += (SQT)v1*v1; + s2 += v2; sq2 += (SQT)v2*v2; + nzm++; + } + sum[0] = s0; sum[1] = s1; sum[2] = s2; + sqsum[0] = sq0; sqsum[1] = sq1; sqsum[2] = sq2; + } + else + { + for( i = 0; i < len; i++, src += cn ) + if( mask[i] ) + { + for( int k = 0; k < cn; k++ ) + { + T v = src[k]; + ST s = sum[k] + v; + SQT sq = sqsum[k] + (SQT)v*v; + sum[k] = s; sqsum[k] = sq; + } + nzm++; + } + } + return nzm; +} -template struct SqrC1 -{ - typedef T type1; - typedef SqT rtype; - rtype operator()(type1 x) const { return (SqT)x*x; } -}; -template struct SqrC2 -{ - typedef Vec type1; - typedef Vec rtype; - rtype operator()(const type1& x) const { return rtype((SqT)x[0]*x[0], (SqT)x[1]*x[1]); } -}; +static int sqsum8u( const uchar* src, const uchar* mask, int* sum, int* sqsum, int len, int cn ) +{ return sumsqr_(src, mask, sum, sqsum, len, cn); } -template struct SqrC3 -{ - typedef Vec type1; - typedef Vec rtype; - rtype operator()(const type1& x) const - { return rtype((SqT)x[0]*x[0], (SqT)x[1]*x[1], (SqT)x[2]*x[2]); } -}; +static int sqsum8s( const schar* src, const uchar* mask, int* sum, int* sqsum, int len, int cn ) +{ return sumsqr_(src, mask, sum, sqsum, len, cn); } -template struct SqrC4 -{ - typedef Vec type1; - typedef Vec rtype; - rtype operator()(const type1& x) const - { return rtype((SqT)x[0]*x[0], (SqT)x[1]*x[1], (SqT)x[2]*x[2], (SqT)x[3]*x[3]); } -}; +static int sqsum16u( const ushort* src, const uchar* mask, int* sum, double* sqsum, int len, int cn ) +{ return sumsqr_(src, mask, sum, sqsum, len, cn); } -template<> inline double SqrC1::operator()(uchar x) const -{ return CV_SQR_8U(x); } +static int sqsum16s( const short* src, const uchar* mask, int* sum, double* sqsum, int len, int cn ) +{ return sumsqr_(src, mask, sum, sqsum, len, cn); } -template<> inline Vec SqrC2::operator()(const Vec& x) const -{ return Vec(CV_SQR_8U(x[0]), CV_SQR_8U(x[1])); } +static int sqsum32s( const int* src, const uchar* mask, double* sum, double* sqsum, int len, int cn ) +{ return sumsqr_(src, mask, sum, sqsum, len, cn); } -template<> inline Vec SqrC3::operator() (const Vec& x) const -{ return Vec(CV_SQR_8U(x[0]), CV_SQR_8U(x[1]), CV_SQR_8U(x[2])); } +static int sqsum32f( const float* src, const uchar* mask, double* sum, double* sqsum, int len, int cn ) +{ return sumsqr_(src, mask, sum, sqsum, len, cn); } -template<> inline Vec SqrC4::operator() (const Vec& x) const -{ return Vec(CV_SQR_8U(x[0]), CV_SQR_8U(x[1]), CV_SQR_8U(x[2]), CV_SQR_8U(x[3])); } +static int sqsum64f( const double* src, const uchar* mask, double* sum, double* sqsum, int len, int cn ) +{ return sumsqr_(src, mask, sum, sqsum, len, cn); } +typedef int (*SumSqrFunc)(const uchar*, const uchar* mask, uchar*, uchar*, int, int); -template static void -meanStdDev_( const Mat& srcmat, Scalar& _sum, Scalar& _sqsum ) +static SumSqrFunc sumSqrTab[] = { - SqrOp sqr; - typedef typename SqrOp::type1 T; - typedef typename SqrOp::rtype ST; - typedef typename DataType::channel_type ST1; - - assert( DataType::type == srcmat.type() ); - Size size = getContinuousSize( srcmat ); - ST s = 0, sq = 0; + (SumSqrFunc)sqsum8u, (SumSqrFunc)sqsum8s, (SumSqrFunc)sqsum16u, (SumSqrFunc)sqsum16s, + (SumSqrFunc)sqsum32s, (SumSqrFunc)sqsum32f, (SumSqrFunc)sqsum64f, 0 +}; - for( int y = 0; y < size.height; y++ ) +} + +cv::Scalar cv::sum( const InputArray& _src ) +{ + Mat src = _src.getMat(); + int k, cn = src.channels(), depth = src.depth(); + SumFunc func = sumTab[depth]; + + CV_Assert( cn <= 4 && func != 0 ); + + const Mat* arrays[] = {&src, 0}; + uchar* ptrs[1]; + NAryMatIterator it(arrays, ptrs); + Scalar s; + int total = (int)it.size, blockSize = total, intSumBlockSize = 0; + int j, count = 0; + AutoBuffer _buf; + int* buf = (int*)&s[0]; + size_t esz = 0; + bool blockSum = depth < CV_32S; + + if( blockSum ) { - const T* src = (const T*)(srcmat.data + srcmat.step*y); - for( int x = 0; x < size.width; x++ ) + intSumBlockSize = depth <= CV_8S ? (1 << 23) : (1 << 15); + blockSize = std::min(blockSize, intSumBlockSize); + _buf.allocate(cn); + buf = _buf; + + for( k = 0; k < cn; k++ ) + buf[k] = 0; + esz = src.elemSize(); + } + + for( size_t i = 0; i < it.nplanes; i++, ++it ) + { + for( j = 0; j < total; j += blockSize ) { - T v = src[x]; - s += v; - sq += sqr(v); + int bsz = std::min(total - j, blockSize); + func( ptrs[0], 0, (uchar*)buf, bsz, cn ); + count += bsz; + if( blockSum && (count + blockSize >= intSumBlockSize || (i+1 >= it.nplanes && j+bsz >= total)) ) + { + for( k = 0; k < cn; k++ ) + { + s[k] += buf[k]; + buf[k] = 0; + } + count = 0; + } + ptrs[0] += bsz*esz; } } - _sum = rawToScalar(s); - _sqsum = rawToScalar(sq); + return s; } -template static void -meanStdDevMask_( const Mat& srcmat, const Mat& maskmat, - Scalar& _sum, Scalar& _sqsum, int& _nz ) +int cv::countNonZero( const InputArray& _src ) +{ + Mat src = _src.getMat(); + CountNonZeroFunc func = countNonZeroTab[src.depth()]; + + CV_Assert( src.channels() == 1 && func != 0 ); + + const Mat* arrays[] = {&src, 0}; + uchar* ptrs[1]; + NAryMatIterator it(arrays, ptrs); + int total = (int)it.size, nz = 0; + + for( size_t i = 0; i < it.nplanes; i++, ++it ) + nz += func( ptrs[0], total ); + + return nz; +} + +cv::Scalar cv::mean( const InputArray& _src, const InputArray& _mask ) { - SqrOp sqr; - typedef typename SqrOp::type1 T; - typedef typename SqrOp::rtype ST; - typedef typename DataType::channel_type ST1; - - assert( DataType::type == srcmat.type() && - CV_8U == maskmat.type() && - srcmat.size() == maskmat.size() ); - Size size = getContinuousSize( srcmat, maskmat ); - ST s = 0, sq = 0; - int pix = 0; - - for( int y = 0; y < size.height; y++ ) + Mat src = _src.getMat(), mask = _mask.getMat(); + if( !mask.empty() ) + CV_Assert( mask.type() == CV_8U ); + + int k, cn = src.channels(), depth = src.depth(); + SumFunc func = sumTab[depth]; + + CV_Assert( cn <= 4 && func != 0 ); + + const Mat* arrays[] = {&src, &mask, 0}; + uchar* ptrs[2]; + NAryMatIterator it(arrays, ptrs); + Scalar s; + int total = (int)it.size, blockSize = total, intSumBlockSize = 0; + int j, count = 0; + AutoBuffer _buf; + int* buf = (int*)&s[0]; + bool blockSum = depth <= CV_16S; + size_t esz = 0, nz0 = 0; + + if( blockSum ) + { + intSumBlockSize = depth <= CV_8S ? (1 << 23) : (1 << 15); + blockSize = std::min(blockSize, intSumBlockSize); + _buf.allocate(cn); + buf = _buf; + + for( k = 0; k < cn; k++ ) + buf[k] = 0; + esz = src.elemSize(); + } + + for( size_t i = 0; i < it.nplanes; i++, ++it ) { - const T* src = (const T*)(srcmat.data + srcmat.step*y); - const uchar* mask = maskmat.data + maskmat.step*y; - for( int x = 0; x < size.width; x++ ) - if( mask[x] ) + for( j = 0; j < total; j += blockSize ) + { + int bsz = std::min(total - j, blockSize); + int nz = func( ptrs[0], ptrs[1], (uchar*)buf, bsz, cn ); + count += nz; + nz0 += nz; + if( blockSum && (count + blockSize >= intSumBlockSize || (i+1 >= it.nplanes && j+bsz >= total)) ) { - T v = src[x]; - s += v; - sq += sqr(v); - pix++; + for( k = 0; k < cn; k++ ) + { + s[k] += buf[k]; + buf[k] = 0; + } + count = 0; } + ptrs[0] += bsz*esz; + if( ptrs[1] ) + ptrs[1] += bsz; + } } - _sum = rawToScalar(s); - _sqsum = rawToScalar(sq); - _nz = pix; -} - -typedef void (*MeanStdDevFunc)(const Mat& src, Scalar& s, Scalar& sq); - -typedef void (*MeanStdDevMaskFunc)(const Mat& src, const Mat& mask, - Scalar& s, Scalar& sq, int& nz); + return s*(nz0 ? 1./nz0 : 0); +} -void meanStdDev( const Mat& m, Scalar& mean, Scalar& stddev, const Mat& mask ) + +void cv::meanStdDev( const InputArray& _src, OutputArray _mean, OutputArray _sdv, const InputArray& _mask ) { - static MeanStdDevFunc tab[]= - { - meanStdDev_ >, 0, - meanStdDev_ >, - meanStdDev_ >, - meanStdDev_ >, - meanStdDev_ >, - meanStdDev_ >, 0, - - meanStdDev_ >, 0, - meanStdDev_ >, - meanStdDev_ >, - meanStdDev_ >, - meanStdDev_ >, - meanStdDev_ >, 0, - - meanStdDev_ >, 0, - meanStdDev_ >, - meanStdDev_ >, - meanStdDev_ >, - meanStdDev_ >, - meanStdDev_ >, 0, - - meanStdDev_ >, 0, - meanStdDev_ >, - meanStdDev_ >, - meanStdDev_ >, - meanStdDev_ >, - meanStdDev_ >, 0 - }; - - static MeanStdDevMaskFunc mtab[]= + Mat src = _src.getMat(), mask = _mask.getMat(); + if( !mask.empty() ) + CV_Assert( mask.type() == CV_8U ); + + int k, cn = src.channels(), depth = src.depth(); + SumSqrFunc func = sumSqrTab[depth]; + + CV_Assert( func != 0 ); + + const Mat* arrays[] = {&src, &mask, 0}; + uchar* ptrs[2]; + NAryMatIterator it(arrays, ptrs); + int total = it.size, blockSize = total, intSumBlockSize = 0; + int j, count = 0, nz0 = 0; + AutoBuffer _buf(cn*4); + double *s = (double*)_buf, *sq = s + cn; + int *sbuf = (int*)s, *sqbuf = (int*)sq; + bool blockSum = depth <= CV_16S, blockSqSum = depth <= CV_8S; + size_t esz = 0; + + for( k = 0; k < cn; k++ ) + s[k] = sq[k] = 0; + + if( blockSum ) { - meanStdDevMask_ >, 0, - meanStdDevMask_ >, - meanStdDevMask_ >, - meanStdDevMask_ >, - meanStdDevMask_ >, - meanStdDevMask_ >, 0, - - meanStdDevMask_ >, 0, - meanStdDevMask_ >, - meanStdDevMask_ >, - meanStdDevMask_ >, - meanStdDevMask_ >, - meanStdDevMask_ >, 0, - - meanStdDevMask_ >, 0, - meanStdDevMask_ >, - meanStdDevMask_ >, - meanStdDevMask_ >, - meanStdDevMask_ >, - meanStdDevMask_ >, 0, - - meanStdDevMask_ >, 0, - meanStdDevMask_ >, - meanStdDevMask_ >, - meanStdDevMask_ >, - meanStdDevMask_ >, - meanStdDevMask_ >, 0 - }; - - CV_Assert( m.channels() <= 4 && (mask.empty() || mask.type() == CV_8U) ); - - Scalar sum, sqsum; - int total = 0; - MeanStdDevFunc func = tab[m.type()]; - MeanStdDevMaskFunc mfunc = mtab[m.type()]; - CV_Assert( func != 0 && mfunc != 0 ); - - if( m.dims > 2 ) + intSumBlockSize = 1 << 15; + blockSize = std::min(blockSize, intSumBlockSize); + sbuf = (int*)(sq + cn); + if( blockSqSum ) + sqbuf = sbuf + cn; + for( k = 0; k < cn; k++ ) + sbuf[k] = sqbuf[k] = 0; + esz = src.elemSize(); + } + + for( size_t i = 0; i < it.nplanes; i++, ++it ) { - const Mat* arrays[] = {&m, &mask, 0}; - Mat planes[2]; - NAryMatIterator it(arrays, planes); - int nz = (int)planes[0].total(); - - for( int i = 0; i < it.nplanes; i++, ++it ) + for( j = 0; j < total; j += blockSize ) { - Scalar s, sq; - - if( mask.empty() ) - func(it.planes[0], s, sq); - else - mfunc(it.planes[0], it.planes[1], s, sq, nz); - - total += nz; - sum += s; - sqsum += sq; + int bsz = std::min(total - j, blockSize); + int nz = func( ptrs[0], ptrs[1], (uchar*)sbuf, (uchar*)sqbuf, bsz, cn ); + count += nz; + nz0 += nz; + if( blockSum && (count + blockSize >= intSumBlockSize || (i+1 >= it.nplanes && j+bsz >= total)) ) + { + for( k = 0; k < cn; k++ ) + { + s[k] += sbuf[k]; + sbuf[k] = 0; + } + if( blockSqSum ) + { + for( k = 0; k < cn; k++ ) + { + sq[k] += sqbuf[k]; + sqbuf[k] = 0; + } + } + count = 0; + } + ptrs[0] += bsz*esz; + if( ptrs[1] ) + ptrs[1] += bsz; } } - else + + double scale = nz0 ? 1./nz0 : 0.; + for( int k = 0; k < cn; k++ ) { - if( mask.data ) - { - CV_Assert( mask.size() == m.size() ); - mfunc( m, mask, sum, sqsum, total ); - } - else - { - func( m, sum, sqsum ); - total = (int)m.total(); - } + s[k] *= scale; + sq[k] = std::sqrt(std::max(sq[k]*scale - s[k]*s[k], 0.)); } - double scale = 1./std::max(total, 1); - for( int k = 0; k < 4; k++ ) + for( j = 0; j < 2; j++ ) { - mean[k] = sum[k]*scale; - stddev[k] = std::sqrt(std::max(sqsum[k]*scale - mean[k]*mean[k], 0.)); + const double* sptr = j == 0 ? s : sq; + OutputArray& _dst = j == 0 ? _mean : _sdv; + if( !_dst.needed() ) + continue; + + if( !_dst.fixedSize() ) + _dst.create(cn, 1, CV_64F, -1, true); + Mat dst = _dst.getMat(); + int dcn = (int)dst.total(); + CV_Assert( dst.type() == CV_64F && dst.isContinuous() && + (dst.cols == 1 || dst.rows == 1) && dcn >= cn ); + double* dptr = dst.ptr(); + for( k = 0; k < cn; k++ ) + dptr[k] = sptr[k]; + for( ; k < dcn; k++ ) + dptr[k] = 0; } } - /****************************************************************************************\ * minMaxLoc * \****************************************************************************************/ +namespace cv +{ + template static void -minMaxIndx_( const Mat& srcmat, double* _minVal, double* _maxVal, - size_t startIdx, size_t* _minIdx, size_t* _maxIdx ) +minMaxIdx_( const T* src, const uchar* mask, WT* _minVal, WT* _maxVal, + size_t* _minIdx, size_t* _maxIdx, int len, size_t startIdx ) { - assert( DataType::type == srcmat.type() ); - const T* src = (const T*)srcmat.data; - size_t step = srcmat.step/sizeof(src[0]); - WT minVal = saturate_cast(*_minVal), maxVal = saturate_cast(*_maxVal); + WT minVal = *_minVal, maxVal = *_maxVal; size_t minIdx = *_minIdx, maxIdx = *_maxIdx; - Size size = getContinuousSize( srcmat ); - - for( ; size.height--; src += step, startIdx += size.width ) + + if( !mask ) { - for( int x = 0; x < size.width; x++ ) + for( int i = 0; i < len; i++ ) { - T val = src[x]; + T val = src[i]; if( val < minVal ) { minVal = val; - minIdx = startIdx + x; + minIdx = startIdx + i; } if( val > maxVal ) { maxVal = val; - maxIdx = startIdx + x; + maxIdx = startIdx + i; } } } - - *_minIdx = minIdx; - *_maxIdx = maxIdx; - *_minVal = minVal; - *_maxVal = maxVal; -} - - -template static void -minMaxIndxMask_( const Mat& srcmat, const Mat& maskmat, - double* _minVal, double* _maxVal, - size_t startIdx, size_t* _minIdx, size_t* _maxIdx ) -{ - assert( DataType::type == srcmat.type() && - CV_8U == maskmat.type() && - srcmat.size() == maskmat.size() ); - const T* src = (const T*)srcmat.data; - const uchar* mask = maskmat.data; - size_t step = srcmat.step/sizeof(src[0]); - size_t maskstep = maskmat.step; - WT minVal = saturate_cast(*_minVal), maxVal = saturate_cast(*_maxVal); - size_t minIdx = *_minIdx, maxIdx = *_maxIdx; - Size size = getContinuousSize( srcmat, maskmat ); - - for( ; size.height--; src += step, mask += maskstep, startIdx += size.width ) + else { - for( int x = 0; x < size.width; x++ ) + for( int i = 0; i < len; i++ ) { - T val = src[x]; - int m = mask[x]; - - if( val < minVal && m ) + T val = src[i]; + if( mask[i] && val < minVal ) { minVal = val; - minIdx = startIdx + x; + minIdx = startIdx + i; } - if( val > maxVal && m ) + if( mask[i] && val > maxVal ) { maxVal = val; - maxIdx = startIdx + x; + maxIdx = startIdx + i; } } } @@ -671,79 +674,43 @@ minMaxIndxMask_( const Mat& srcmat, const Mat& maskmat, *_maxVal = maxVal; } -typedef void (*MinMaxIndxFunc)(const Mat&, double*, double*, size_t, size_t*, size_t*); +static void minMaxIdx_8u(const uchar* src, const uchar* mask, int* minval, int* maxval, + size_t* minidx, size_t* maxidx, int len, size_t startidx ) +{ minMaxIdx_(src, mask, minval, maxval, minidx, maxidx, len, startidx ); } -typedef void (*MinMaxIndxMaskFunc)(const Mat&, const Mat&, double*, double*, - size_t, size_t*, size_t*); +static void minMaxIdx_8s(const schar* src, const uchar* mask, int* minval, int* maxval, + size_t* minidx, size_t* maxidx, int len, size_t startidx ) +{ minMaxIdx_(src, mask, minval, maxval, minidx, maxidx, len, startidx ); } -void minMaxLoc( const Mat& img, double* minVal, double* maxVal, - Point* minLoc, Point* maxLoc, const Mat& mask ) -{ - CV_Assert(img.dims <= 2); - - static MinMaxIndxFunc tab[] = - { - minMaxIndx_, 0, minMaxIndx_, minMaxIndx_, - minMaxIndx_, minMaxIndx_, minMaxIndx_, 0 - }; - static MinMaxIndxMaskFunc tabm[] = - { - minMaxIndxMask_, 0, minMaxIndxMask_, minMaxIndxMask_, - minMaxIndxMask_, minMaxIndxMask_, minMaxIndxMask_, 0 - }; +static void minMaxIdx_16u(const ushort* src, const uchar* mask, int* minval, int* maxval, + size_t* minidx, size_t* maxidx, int len, size_t startidx ) +{ minMaxIdx_(src, mask, minval, maxval, minidx, maxidx, len, startidx ); } - int depth = img.depth(); - double minval = depth < CV_32F ? INT_MAX : depth == CV_32F ? FLT_MAX : DBL_MAX; - double maxval = depth < CV_32F ? INT_MIN : depth == CV_32F ? -FLT_MAX : -DBL_MAX; - size_t minidx = 0, maxidx = 0, startidx = 1; +static void minMaxIdx_16s(const short* src, const uchar* mask, int* minval, int* maxval, + size_t* minidx, size_t* maxidx, int len, size_t startidx ) +{ minMaxIdx_(src, mask, minval, maxval, minidx, maxidx, len, startidx ); } - CV_Assert( img.channels() == 1 ); +static void minMaxIdx_32s(const int* src, const uchar* mask, int* minval, int* maxval, + size_t* minidx, size_t* maxidx, int len, size_t startidx ) +{ minMaxIdx_(src, mask, minval, maxval, minidx, maxidx, len, startidx ); } - if( !mask.data ) - { - MinMaxIndxFunc func = tab[depth]; - CV_Assert( func != 0 ); - func( img, &minval, &maxval, startidx, &minidx, &maxidx ); - } - else - { - CV_Assert( img.size() == mask.size() && mask.type() == CV_8U ); - MinMaxIndxMaskFunc func = tabm[depth]; - CV_Assert( func != 0 ); - func( img, mask, &minval, &maxval, startidx, &minidx, &maxidx ); - } +static void minMaxIdx_32f(const float* src, const uchar* mask, float* minval, float* maxval, + size_t* minidx, size_t* maxidx, int len, size_t startidx ) +{ minMaxIdx_(src, mask, minval, maxval, minidx, maxidx, len, startidx ); } - if( minidx == 0 ) - minVal = maxVal = 0; +static void minMaxIdx_64f(const double* src, const uchar* mask, double* minval, double* maxval, + size_t* minidx, size_t* maxidx, int len, size_t startidx ) +{ minMaxIdx_(src, mask, minval, maxval, minidx, maxidx, len, startidx ); } - if( minVal ) - *minVal = minval; - if( maxVal ) - *maxVal = maxval; - if( minLoc ) - { - if( minidx > 0 ) - { - minidx--; - minLoc->y = minidx/img.cols; - minLoc->x = minidx - minLoc->y*img.cols; - } - else - minLoc->x = minLoc->y = -1; - } - if( maxLoc ) - { - if( maxidx > 0 ) - { - maxidx--; - maxLoc->y = maxidx/img.cols; - maxLoc->x = maxidx - maxLoc->y*img.cols; - } - else - maxLoc->x = maxLoc->y = -1; - } -} +typedef void (*MinMaxIdxFunc)(const uchar*, const uchar*, int*, int*, size_t*, size_t*, int, size_t); +static MinMaxIdxFunc minmaxTab[] = +{ + (MinMaxIdxFunc)minMaxIdx_8u, (MinMaxIdxFunc)minMaxIdx_8s, (MinMaxIdxFunc)minMaxIdx_16u, + (MinMaxIdxFunc)minMaxIdx_16s, (MinMaxIdxFunc)minMaxIdx_32s, (MinMaxIdxFunc)minMaxIdx_32f, + (MinMaxIdxFunc)minMaxIdx_64f, 0 +}; + static void ofs2idx(const Mat& a, size_t ofs, int* idx) { int i, d = a.dims; @@ -763,712 +730,482 @@ static void ofs2idx(const Mat& a, size_t ofs, int* idx) idx[i] = -1; } } + +} -void minMaxIdx(const Mat& a, double* minVal, - double* maxVal, int* minIdx, int* maxIdx, - const Mat& mask) +void cv::minMaxIdx(const InputArray& _src, double* minVal, + double* maxVal, int* minIdx, int* maxIdx, + const InputArray& _mask) { - if( a.dims <= 2 ) - { - Point minLoc, maxLoc; - minMaxLoc(a, minVal, maxVal, &minLoc, &maxLoc, mask); - if( minIdx ) - minIdx[0] = minLoc.y, minIdx[1] = minLoc.x; - if( maxIdx ) - maxIdx[0] = maxLoc.y, maxIdx[1] = maxLoc.x; - return; - } - - static MinMaxIndxFunc tab[] = - { - minMaxIndx_, 0, minMaxIndx_, minMaxIndx_, - minMaxIndx_, minMaxIndx_, minMaxIndx_, 0 - }; - static MinMaxIndxMaskFunc tabm[] = - { - minMaxIndxMask_, 0, minMaxIndxMask_, minMaxIndxMask_, - minMaxIndxMask_, minMaxIndxMask_, minMaxIndxMask_, 0 - }; + Mat src = _src.getMat(), mask = _mask.getMat(); + int depth = src.depth(); + + CV_Assert( src.channels() == 1 && (mask.empty() || mask.type() == CV_8U) ); + MinMaxIdxFunc func = minmaxTab[depth]; + CV_Assert( func != 0 ); - const Mat* arrays[] = {&a, &mask, 0}; - Mat planes[2]; - NAryMatIterator it(arrays, planes); + const Mat* arrays[] = {&src, &mask, 0}; + uchar* ptrs[2]; + NAryMatIterator it(arrays, ptrs); - int depth = a.depth(); - double minval = depth < CV_32F ? INT_MAX : depth == CV_32F ? FLT_MAX : DBL_MAX; - double maxval = depth < CV_32F ? INT_MIN : depth == CV_32F ? -FLT_MAX : -DBL_MAX; size_t minidx = 0, maxidx = 0; - size_t startidx = 1, planeSize = planes[0].total(); - MinMaxIndxFunc func = 0; - MinMaxIndxMaskFunc mfunc = 0; + int iminval = INT_MAX, imaxval = INT_MIN; + float fminval = FLT_MAX, fmaxval = -FLT_MAX; + double dminval = DBL_MAX, dmaxval = -DBL_MAX; + size_t startidx = 1; + int *minval = &iminval, *maxval = &imaxval; + int planeSize = (int)it.size; - if( mask.empty() ) - func = tab[depth]; - else - mfunc = tabm[depth]; - CV_Assert( func != 0 || mfunc != 0 ); + if( depth == CV_32F ) + minval = (int*)&fminval, maxval = (int*)&fmaxval; + else if( depth == CV_64F ) + minval = (int*)&dminval, maxval = (int*)&dmaxval; - for( int i = 0; i < it.nplanes; i++, ++it, startidx += planeSize ) - { - if( func ) - func( planes[0], &minval, &maxval, startidx, &minidx, &maxidx ); - else - mfunc( planes[0], planes[1], &minval, &maxval, startidx, &minidx, &maxidx ); - } + for( size_t i = 0; i < it.nplanes; i++, ++it, startidx += planeSize ) + func( ptrs[0], ptrs[1], minval, maxval, &minidx, &maxidx, planeSize, startidx ); if( minidx == 0 ) - minVal = maxVal = 0; + dminval = dmaxval = 0; + else if( depth == CV_32F ) + dminval = fminval, dmaxval = fmaxval; + else if( depth <= CV_32S ) + dminval = iminval, dmaxval = imaxval; if( minVal ) - *minVal = minval; + *minVal = dminval; if( maxVal ) - *maxVal = maxval; + *maxVal = dmaxval; + if( minIdx ) - ofs2idx(a, minidx, minIdx); + ofs2idx(src, minidx, minIdx); if( maxIdx ) - ofs2idx(a, maxidx, maxIdx); + ofs2idx(src, maxidx, maxIdx); } + +void cv::minMaxLoc( const InputArray& _img, double* minVal, double* maxVal, + Point* minLoc, Point* maxLoc, const InputArray& mask ) +{ + Mat img = _img.getMat(); + CV_Assert(img.dims <= 2); + + minMaxIdx(_img, minVal, maxVal, (int*)minLoc, (int*)maxLoc, mask); + if( minLoc ) + std::swap(minLoc->x, minLoc->y); + if( maxLoc ) + std::swap(maxLoc->x, maxLoc->y); +} /****************************************************************************************\ * norm * \****************************************************************************************/ -template struct OpAbs +namespace cv { - typedef T type1; - typedef WT rtype; - rtype operator()(type1 x) const { return (WT)std::abs(x); } -}; - -template<> inline uchar OpAbs::operator()(uchar x) const { return x; } -template<> inline ushort OpAbs::operator()(ushort x) const { return x; } -template -static double normBlock_( const Mat& srcmat ) +template int +normInf_(const T* src, const uchar* mask, ST* _result, int len, int cn) { - ElemFunc f; - UpdateFunc update; - GlobUpdateFunc globUpdate; - typedef typename ElemFunc::type1 T; - typedef typename UpdateFunc::rtype WT; - typedef typename GlobUpdateFunc::rtype ST; - - assert( DataType::depth == srcmat.depth() ); - Size size = getContinuousSize( srcmat, srcmat.channels() ); - ST s0 = 0; // luckily, 0 is the correct starting value for both + and max update operations - WT s = 0; - int y, remaining = BLOCK_SIZE; - - for( y = 0; y < size.height; y++ ) + ST result = *_result; + if( !mask ) { - const T* src = (const T*)(srcmat.data + srcmat.step*y); - int x = 0; - while( x < size.width ) - { - int limit = std::min( remaining, size.width - x ); - remaining -= limit; - limit += x; - for( ; x <= limit - 4; x += 4 ) + len *= cn; + for( int i = 0; i < len; i++ ) + result = std::max(result, std::abs(src[i])); + } + else + { + for( int i = 0; i < len; i++, src += cn ) + if( mask[i] ) { - s = update(s, (WT)f(src[x])); - s = update(s, (WT)f(src[x+1])); - s = update(s, (WT)f(src[x+2])); - s = update(s, (WT)f(src[x+3])); + for( int k = 0; k < cn; k++ ) + result = std::max(result, std::abs(src[k])); } - for( ; x < limit; x++ ) - s = update(s, (WT)f(src[x])); - if( remaining == 0 || (x == size.width && y == size.height-1) ) + } + *_result = result; + return 0; +} + +template int +normL1_(const T* src, const uchar* mask, ST* _result, int len, int cn) +{ + ST result = *_result; + if( !mask ) + { + len *= cn; + for( int i = 0; i < len; i++ ) + result += std::abs(src[i]); + } + else + { + for( int i = 0; i < len; i++, src += cn ) + if( mask[i] ) { - s0 = globUpdate(s0, (ST)s); - s = 0; - remaining = BLOCK_SIZE; + for( int k = 0; k < cn; k++ ) + result += std::abs(src[k]); } - } } - return s0; + *_result = result; + return 0; } -template -static double norm_( const Mat& srcmat ) +template int +normL2_(const T* src, const uchar* mask, ST* _result, int len, int cn) { - ElemFunc f; - UpdateFunc update; - typedef typename ElemFunc::type1 T; - typedef typename UpdateFunc::rtype ST; - - assert( DataType::depth == srcmat.depth() ); - Size size = getContinuousSize( srcmat, srcmat.channels() ); - ST s = 0; - - for( int y = 0; y < size.height; y++ ) + ST result = *_result; + if( !mask ) { - const T* src = (const T*)(srcmat.data + srcmat.step*y); - int x = 0; - for( ; x <= size.width - 4; x += 4 ) + len *= cn; + for( int i = 0; i < len; i++ ) { - s = update(s, (ST)f(src[x])); - s = update(s, (ST)f(src[x+1])); - s = update(s, (ST)f(src[x+2])); - s = update(s, (ST)f(src[x+3])); + T v = src[i]; + result += (ST)v*v; } - for( ; x < size.width; x++ ) - s = update(s, (ST)f(src[x])); } - return s; -} - -template -static double normMaskBlock_( const Mat& srcmat, const Mat& maskmat ) -{ - ElemFunc f; - UpdateFunc update; - GlobUpdateFunc globUpdate; - typedef typename ElemFunc::type1 T; - typedef typename UpdateFunc::rtype WT; - typedef typename GlobUpdateFunc::rtype ST; - - assert( DataType::depth == srcmat.depth() ); - Size size = getContinuousSize( srcmat, maskmat ); - ST s0 = 0; - WT s = 0; - int y, remaining = BLOCK_SIZE; - int cn = srcmat.channels(); - - for( y = 0; y < size.height; y++ ) + else { - const T* src = (const T*)(srcmat.data + srcmat.step*y); - const uchar* mask = maskmat.data + maskmat.step*y; - int x = 0; - while( x < size.width ) - { - int limit = std::min( remaining, size.width - x ); - remaining -= limit; - limit += x; - int x0 = x; - for( int c = 0; c < cn; c++ ) + for( int i = 0; i < len; i++, src += cn ) + if( mask[i] ) { - for( x = x0; x <= limit - 4; x += 4 ) - { - if( mask[x] ) - s = update(s, (WT)f(src[x*cn + c])); - if( mask[x+1] ) - s = update(s, (WT)f(src[(x+1)*cn + c])); - if( mask[x+2] ) - s = update(s, (WT)f(src[(x+2)*cn + c])); - if( mask[x+3] ) - s = update(s, (WT)f(src[(x+3)*cn + c])); - } - for( ; x < limit; x++ ) + for( int k = 0; k < cn; k++ ) { - if( mask[x] ) - s = update(s, (WT)f(src[x*cn + c])); + T v = src[k]; + result += (ST)v*v; } } - if( remaining == 0 || (x == size.width && y == size.height-1) ) - { - s0 = globUpdate(s0, (ST)s); - s = 0; - remaining = BLOCK_SIZE; - } - } } - return s0; -} - -template -static double normMask_( const Mat& srcmat, const Mat& maskmat ) -{ - ElemFunc f; - UpdateFunc update; - typedef typename ElemFunc::type1 T; - typedef typename UpdateFunc::rtype ST; - - assert( DataType::depth == srcmat.depth() ); - Size size = getContinuousSize( srcmat, maskmat ); - ST s = 0; - int cn = srcmat.channels(); + *_result = result; + return 0; +} - for( int y = 0; y < size.height; y++ ) +template int +normDiffInf_(const T* src1, const T* src2, const uchar* mask, ST* _result, int len, int cn) +{ + ST result = *_result; + if( !mask ) { - const T* src = (const T*)(srcmat.data + srcmat.step*y); - const uchar* mask = maskmat.data + maskmat.step*y; - for( int c = 0; c < cn; c++ ) - { - int x = 0; - for( ; x <= size.width - 4; x += 4 ) - { - if( mask[x] ) - s = update(s, (ST)f(src[x*cn + c])); - if( mask[x+1] ) - s = update(s, (ST)f(src[(x+1)*cn + c])); - if( mask[x+2] ) - s = update(s, (ST)f(src[(x+2)*cn + c])); - if( mask[x+3] ) - s = update(s, (ST)f(src[(x+3)*cn + c])); - } - for( ; x < size.width; x++ ) + len *= cn; + for( int i = 0; i < len; i++ ) + result = std::max(result, std::abs(src1[i] - src2[i])); + } + else + { + for( int i = 0; i < len; i++, src1 += cn, src2 += cn ) + if( mask[i] ) { - if( mask[x] ) - s = update(s, (ST)f(src[x*cn + c])); + for( int k = 0; k < cn; k++ ) + result = std::max(result, std::abs(src1[k] - src2[k])); } - } } - return s; + *_result = result; + return 0; } -template -static double normDiffBlock_( const Mat& srcmat1, const Mat& srcmat2 ) +template int +normDiffL1_(const T* src1, const T* src2, const uchar* mask, ST* _result, int len, int cn) { - ElemFunc f; - UpdateFunc update; - GlobUpdateFunc globUpdate; - typedef typename UpdateFunc::rtype WT; - typedef typename GlobUpdateFunc::rtype ST; - - assert( DataType::depth == srcmat1.depth() ); - Size size = getContinuousSize( srcmat1, srcmat2, srcmat1.channels() ); - ST s0 = 0; - WT s = 0; - int y, remaining = BLOCK_SIZE; - - for( y = 0; y < size.height; y++ ) + ST result = *_result; + if( !mask ) { - const T* src1 = (const T*)(srcmat1.data + srcmat1.step*y); - const T* src2 = (const T*)(srcmat2.data + srcmat2.step*y); - int x = 0; - while( x < size.width ) - { - int limit = std::min( remaining, size.width - x ); - remaining -= limit; - limit += x; - for( ; x <= limit - 4; x += 4 ) - { - s = update(s, (WT)f(src1[x] - src2[x])); - s = update(s, (WT)f(src1[x+1] - src2[x+1])); - s = update(s, (WT)f(src1[x+2] - src2[x+2])); - s = update(s, (WT)f(src1[x+3] - src2[x+3])); - } - for( ; x < limit; x++ ) - s = update(s, (WT)f(src1[x] - src2[x])); - if( remaining == 0 || (x == size.width && y == size.height-1) ) + len *= cn; + for( int i = 0; i < len; i++ ) + result += std::abs(src1[i] - src2[i]); + } + else + { + for( int i = 0; i < len; i++, src1 += cn, src2 += cn ) + if( mask[i] ) { - s0 = globUpdate(s0, (ST)s); - s = 0; - remaining = BLOCK_SIZE; + for( int k = 0; k < cn; k++ ) + result += std::abs(src1[k] - src2[k]); } - } } - return s0; + *_result = result; + return 0; } -template -static double normDiff_( const Mat& srcmat1, const Mat& srcmat2 ) +template int +normDiffL2_(const T* src1, const T* src2, const uchar* mask, ST* _result, int len, int cn) { - ElemFunc f; - UpdateFunc update; - typedef typename UpdateFunc::rtype ST; - - assert( DataType::depth == srcmat1.depth() ); - Size size = getContinuousSize( srcmat1, srcmat2, srcmat1.channels() ); - ST s = 0; - - for( int y = 0; y < size.height; y++ ) + ST result = *_result; + if( !mask ) { - const T* src1 = (const T*)(srcmat1.data + srcmat1.step*y); - const T* src2 = (const T*)(srcmat2.data + srcmat2.step*y); - int x = 0; - for( ; x <= size.width - 4; x += 4 ) + len *= cn; + for( int i = 0; i < len; i++ ) { - s = update(s, (ST)f(src1[x] - src2[x])); - s = update(s, (ST)f(src1[x+1] - src2[x+1])); - s = update(s, (ST)f(src1[x+2] - src2[x+2])); - s = update(s, (ST)f(src1[x+3] - src2[x+3])); + ST v = src1[i] - src2[i]; + result += v*v; } - for( ; x < size.width; x++ ) - s = update(s, (ST)f(src1[x] - src2[x])); } - return s; -} - -template -static double normDiffMaskBlock_( const Mat& srcmat1, const Mat& srcmat2, const Mat& maskmat ) -{ - ElemFunc f; - UpdateFunc update; - GlobUpdateFunc globUpdate; - typedef typename UpdateFunc::rtype WT; - typedef typename GlobUpdateFunc::rtype ST; - - assert( DataType::depth == srcmat1.depth() ); - Size size = getContinuousSize( srcmat1, srcmat2, maskmat ); - ST s0 = 0; - WT s = 0; - int y, remaining = BLOCK_SIZE; - int cn = srcmat1.channels(); - - for( y = 0; y < size.height; y++ ) + else { - const T* src1 = (const T*)(srcmat1.data + srcmat1.step*y); - const T* src2 = (const T*)(srcmat2.data + srcmat2.step*y); - const uchar* mask = maskmat.data + maskmat.step*y; - int x = 0; - while( x < size.width ) - { - int limit = std::min( remaining, size.width - x ); - remaining -= limit; - limit += x; - int x0 = x; - for( int c = 0; c < cn; c++ ) + for( int i = 0; i < len; i++, src1 += cn, src2 += cn ) + if( mask[i] ) { - for( x = x0; x <= limit - 4; x += 4 ) + for( int k = 0; k < cn; k++ ) { - if( mask[x] ) - s = update(s, (WT)f(src1[x*cn + c] - src2[x*cn + c])); - if( mask[x+1] ) - s = update(s, (WT)f(src1[(x+1)*cn + c] - src2[(x+1)*cn + c])); - if( mask[x+2] ) - s = update(s, (WT)f(src1[(x+2)*cn + c] - src2[(x+2)*cn + c])); - if( mask[x+3] ) - s = update(s, (WT)f(src1[(x+3)*cn + c] - src2[(x+3)*cn + c])); + ST v = src1[k] - src2[k]; + result += v*v; } - for( ; x < limit; x++ ) - if( mask[x] ) - s = update(s, (WT)f(src1[x*cn + c] - src2[x*cn + c])); } - if( remaining == 0 || (x == size.width && y == size.height-1) ) - { - s0 = globUpdate(s0, (ST)s); - s = 0; - remaining = BLOCK_SIZE; - } - } } - return s0; -} + *_result = result; + return 0; +} -template -static double normDiffMask_( const Mat& srcmat1, const Mat& srcmat2, const Mat& maskmat ) -{ - ElemFunc f; - UpdateFunc update; - typedef typename UpdateFunc::rtype ST; + +#define CV_DEF_NORM_FUNC(L, suffix, type, ntype) \ +static int norm##L##_##suffix(const type* src, const uchar* mask, ntype* r, size_t len, int cn) \ +{ return norm##L##_(src, mask, r, len, cn); } \ +static int normDiff##L##_##suffix(const type* src1, const type* src2, \ + const uchar* mask, ntype* r, size_t len, int cn) \ +{ return normDiff##L##_(src1, src2, mask, r, len, cn); } - assert( DataType::depth == srcmat1.depth() ); - Size size = getContinuousSize( srcmat1, srcmat2, maskmat ); - ST s = 0; - int cn = srcmat1.channels(); +#define CV_DEF_NORM_ALL(suffix, type, inftype, l1type, l2type) \ +CV_DEF_NORM_FUNC(Inf, suffix, type, inftype) \ +CV_DEF_NORM_FUNC(L1, suffix, type, l1type) \ +CV_DEF_NORM_FUNC(L2, suffix, type, l2type) + +CV_DEF_NORM_ALL(8u, uchar, int, int, int) +CV_DEF_NORM_ALL(8s, schar, int, int, int) +CV_DEF_NORM_ALL(16u, ushort, int, int, double) +CV_DEF_NORM_ALL(16s, short, int, int, double) +CV_DEF_NORM_ALL(32s, int, int, double, double) +CV_DEF_NORM_ALL(32f, float, float, double, double) +CV_DEF_NORM_ALL(64f, double, double, double, double) - for( int y = 0; y < size.height; y++ ) + +typedef int (*NormFunc)(const uchar*, const uchar*, uchar*, int, int); +typedef int (*NormDiffFunc)(const uchar*, const uchar*, const uchar*, uchar*, int, int); + +static NormFunc normTab[3][8] = +{ { - const T* src1 = (const T*)(srcmat1.data + srcmat1.step*y); - const T* src2 = (const T*)(srcmat2.data + srcmat2.step*y); - const uchar* mask = maskmat.data + maskmat.step*y; - for( int c = 0; c < cn; c++ ) - { - int x = 0; - for( ; x <= size.width - 4; x += 4 ) - { - if( mask[x] ) - s = update(s, (ST)f(src1[x*cn + c] - src2[x*cn + c])); - if( mask[x+1] ) - s = update(s, (ST)f(src1[(x+1)*cn + c] - src2[(x+1)*cn + c])); - if( mask[x+2] ) - s = update(s, (ST)f(src1[(x+2)*cn + c] - src2[(x+2)*cn + c])); - if( mask[x+3] ) - s = update(s, (ST)f(src1[(x+3)*cn + c] - src2[(x+3)*cn + c])); - } - for( ; x < size.width; x++ ) - if( mask[x] ) - s = update(s, (ST)f(src1[x*cn + c] - src2[x*cn + c])); - } + (NormFunc)normInf_8u, (NormFunc)normInf_8s, (NormFunc)normInf_16u, (NormFunc)normInf_16s, + (NormFunc)normInf_32s, (NormFunc)normInf_32f, (NormFunc)normInf_64f, 0 + }, + { + (NormFunc)normL1_8u, (NormFunc)normL1_8s, (NormFunc)normL1_16u, (NormFunc)normL1_16s, + (NormFunc)normL1_32s, (NormFunc)normL1_32f, (NormFunc)normL1_64f, 0 + }, + { + (NormFunc)normL2_8u, (NormFunc)normL2_8s, (NormFunc)normL2_16u, (NormFunc)normL2_16s, + (NormFunc)normL2_32s, (NormFunc)normL2_32f, (NormFunc)normL2_64f, 0 } - return s; -} - -typedef double (*NormFunc)(const Mat& src); -typedef double (*NormDiffFunc)(const Mat& src1, const Mat& src2); -typedef double (*NormMaskFunc)(const Mat& src1, const Mat& mask); -typedef double (*NormDiffMaskFunc)(const Mat& src1, const Mat& src2, const Mat& mask); +}; -double norm( const Mat& a, int normType ) +static NormDiffFunc normDiffTab[3][8] = { - static NormFunc tab[3][8] = { - { - norm_, OpMax >, - norm_, OpMax >, - norm_, OpMax >, - norm_, OpMax >, - norm_, OpMax >, - norm_, OpMax >, - norm_, OpMax > - }, - - { - normBlock_, OpAdd, OpAdd, 1<<24>, - normBlock_, OpAdd, OpAdd, 1<<24>, - normBlock_, OpAdd, OpAdd, 1<<16>, - normBlock_, OpAdd, OpAdd, 1<<16>, - norm_, OpAdd >, - norm_, OpAdd >, - norm_, OpAdd > - }, - - { - normBlock_, OpAdd, OpAdd, 1<<16>, - normBlock_, OpAdd, OpAdd, 1<<16>, - norm_, OpAdd >, - norm_, OpAdd >, - norm_, OpAdd >, - norm_, OpAdd >, - norm_, OpAdd > - } - }; + (NormDiffFunc)normDiffInf_8u, (NormDiffFunc)normDiffInf_8s, + (NormDiffFunc)normDiffInf_16u, (NormDiffFunc)normDiffInf_16s, + (NormDiffFunc)normDiffInf_32s, (NormDiffFunc)normDiffInf_32f, + (NormDiffFunc)normDiffInf_64f, 0 + }, + { + (NormDiffFunc)normDiffL1_8u, (NormDiffFunc)normDiffL1_8s, + (NormDiffFunc)normDiffL1_16u, (NormDiffFunc)normDiffL1_16s, + (NormDiffFunc)normDiffL1_32s, (NormDiffFunc)normDiffL1_32f, + (NormDiffFunc)normDiffL1_64f, 0 + }, + { + (NormDiffFunc)normDiffL2_8u, (NormDiffFunc)normDiffL2_8s, + (NormDiffFunc)normDiffL2_16u, (NormDiffFunc)normDiffL2_16s, + (NormDiffFunc)normDiffL2_32s, (NormDiffFunc)normDiffL2_32f, + (NormDiffFunc)normDiffL2_64f, 0 + } +}; +} + +double cv::norm( const InputArray& _src, int normType, const InputArray& _mask ) +{ + Mat src = _src.getMat(), mask = _mask.getMat(); + int depth = src.depth(), cn = src.channels(); + normType &= 7; - CV_Assert(normType == NORM_INF || normType == NORM_L1 || normType == NORM_L2); - NormFunc func = tab[normType >> 1][a.depth()]; - CV_Assert(func != 0); + CV_Assert( normType == NORM_INF || normType == NORM_L1 || normType == NORM_L2 ); - double r = 0; - if( a.dims > 2 ) + if( depth == CV_32F && src.isContinuous() && mask.empty() ) { - const Mat* arrays[] = {&a, 0}; - Mat planes[1]; - NAryMatIterator it(arrays, planes); - - for( int i = 0; i < it.nplanes; i++, ++it ) + size_t len = src.total()*cn; + if( len == (size_t)(int)len ) { - double n = func(it.planes[0]); - if( normType == NORM_INF ) - r = std::max(r, n); - else - r += n; + const float* data = src.ptr(); + + if( normType == NORM_L2 ) + { + double result = 0; + normL2_32f(data, 0, &result, (int)len, 1); + return std::sqrt(result); + } + if( normType == NORM_L1 ) + { + double result = 0; + normL1_32f(data, 0, &result, (int)len, 1); + return result; + } + { + float result = 0; + normInf_32f(data, 0, &result, (int)len, 1); + return result; + } } } - else - r = func(a); - return normType == NORM_L2 ? std::sqrt(r) : r; -} - - -double norm( const Mat& a, int normType, const Mat& mask ) -{ - static NormMaskFunc tab[3][8] = + CV_Assert( mask.empty() || mask.type() == CV_8U ); + + NormFunc func = normTab[normType >> 1][depth]; + CV_Assert( func != 0 ); + + const Mat* arrays[] = {&src, &mask, 0}; + uchar* ptrs[2]; + double result = 0; + NAryMatIterator it(arrays, ptrs); + int j, total = (int)it.size, blockSize = total, intSumBlockSize = 0, count = 0; + bool blockSum = (normType == NORM_L1 && depth <= CV_16S) || + (normType == NORM_L2 && depth <= CV_8S); + int isum = 0; + int *ibuf = (int*)&result; + size_t esz = 0; + + if( blockSum ) { - { - normMask_, OpMax >, - normMask_, OpMax >, - normMask_, OpMax >, - normMask_, OpMax >, - normMask_, OpMax >, - normMask_, OpMax >, - normMask_, OpMax > - }, - - { - normMaskBlock_, OpAdd, OpAdd, 1<<24>, - normMaskBlock_, OpAdd, OpAdd, 1<<24>, - normMaskBlock_, OpAdd, OpAdd, 1<<16>, - normMaskBlock_, OpAdd, OpAdd, 1<<16>, - normMask_, OpAdd >, - normMask_, OpAdd >, - normMask_, OpAdd > - }, - - { - normMaskBlock_, OpAdd, OpAdd, 1<<16>, - normMaskBlock_, OpAdd, OpAdd, 1<<16>, - normMask_, OpAdd >, - normMask_, OpAdd >, - normMask_, OpAdd >, - normMask_, OpAdd >, - normMask_, OpAdd > - } - }; - - if( !mask.data ) - return norm(a, normType); - - normType &= 7; - CV_Assert((normType == NORM_INF || normType == NORM_L1 || normType == NORM_L2) && mask.type() == CV_8U); - NormMaskFunc func = tab[normType >> 1][a.depth()]; - CV_Assert(func != 0); + intSumBlockSize = (normType == NORM_L1 && depth <= CV_8S ? (1 << 23) : (1 << 15))/cn; + blockSize = std::min(blockSize, intSumBlockSize); + ibuf = &isum; + esz = src.elemSize(); + } - double r = 0; - if( a.dims > 2 ) + for( size_t i = 0; i < it.nplanes; i++, ++it ) { - const Mat* arrays[] = {&a, &mask, 0}; - Mat planes[2]; - NAryMatIterator it(arrays, planes); - - for( int i = 0; i < it.nplanes; i++, ++it ) + for( j = 0; j < total; j += blockSize ) { - double n = func(it.planes[0], it.planes[1]); - if( normType == NORM_INF ) - r = std::max(r, n); - else - r += n; + int bsz = std::min(total - j, blockSize); + func( ptrs[0], ptrs[1], (uchar*)ibuf, bsz, cn ); + count += bsz; + if( blockSum && (count + blockSize >= intSumBlockSize || (i+1 >= it.nplanes && j+bsz >= total)) ) + { + result += isum; + isum = 0; + count = 0; + } + ptrs[0] += bsz*esz; + if( ptrs[1] ) + ptrs[1] += bsz; } } - else + + if( normType == NORM_INF ) { - CV_Assert( a.size() == mask.size() ); - r = func(a, mask); + if( depth == CV_64F ) + ; + else if( depth == CV_32F ) + result = (float&)result; + else + result = (int&)result; } + else if( normType == NORM_L2 ) + result = std::sqrt(result); - return normType == NORM_L2 ? std::sqrt(r) : r; + return result; } - -double norm( const Mat& a, const Mat& b, int normType ) + +double cv::norm( const InputArray& _src1, const InputArray& _src2, int normType, const InputArray& _mask ) { - static NormDiffFunc tab[3][8] = - { - { - normDiff_, OpMax >, - normDiff_, OpMax >, - normDiff_, OpMax >, - normDiff_, OpMax >, - normDiff_, OpMax >, - normDiff_, OpMax >, - normDiff_, OpMax > - }, - - { - normDiffBlock_, OpAdd, OpAdd, 1<<24>, - normDiffBlock_, OpAdd, OpAdd, 1<<24>, - normDiffBlock_, OpAdd, OpAdd, 1<<16>, - normDiffBlock_, OpAdd, OpAdd, 1<<16>, - normDiff_, OpAdd >, - normDiff_, OpAdd >, - normDiff_, OpAdd > - }, - - { - normDiffBlock_, OpAdd, OpAdd, 1<<16>, - normDiffBlock_, OpAdd, OpAdd, 1<<16>, - normDiff_, OpAdd >, - normDiff_, OpAdd >, - normDiff_, OpAdd >, - normDiff_, OpAdd >, - normDiff_, OpAdd > - } - }; + Mat src1 = _src1.getMat(), src2 = _src2.getMat(), mask = _mask.getMat(); + int depth = src1.depth(), cn = src1.channels(); + + CV_Assert( src1.size == src2.size && src1.type() == src2.type() ); - CV_Assert( a.type() == b.type() ); - bool isRelative = (normType & NORM_RELATIVE) != 0; normType &= 7; - CV_Assert(normType == NORM_INF || normType == NORM_L1 || normType == NORM_L2); - NormDiffFunc func = tab[normType >> 1][a.depth()]; - CV_Assert(func != 0); + CV_Assert( normType == NORM_INF || normType == NORM_L1 || normType == NORM_L2 ); - double r = 0.; - if( a.dims > 2 ) + if( src1.depth() == CV_32F && src1.isContinuous() && src2.isContinuous() && mask.empty() ) { - const Mat* arrays[] = {&a, &b, 0}; - Mat planes[2]; - NAryMatIterator it(arrays, planes); - - for( int i = 0; i < it.nplanes; i++, ++it ) + size_t len = src1.total()*src1.channels(); + if( len == (size_t)(int)len ) { - double n = func(it.planes[0], it.planes[1]); - - if( normType == NORM_INF ) - r = std::max(r, n); - else - r += n; + const float* data1 = src1.ptr(); + const float* data2 = src2.ptr(); + + if( normType == NORM_L2 ) + { + double result = 0; + normDiffL2_32f(data1, data2, 0, &result, (int)len, 1); + return std::sqrt(result); + } + if( normType == NORM_L1 ) + { + double result = 0; + normDiffL1_32f(data1, data2, 0, &result, (int)len, 1); + return result; + } + { + float result = 0; + normDiffInf_32f(data1, data2, 0, &result, (int)len, 1); + return result; + } } } - else + + CV_Assert( mask.empty() || mask.type() == CV_8U ); + + NormDiffFunc func = normDiffTab[normType >> 1][depth]; + CV_Assert( func != 0 ); + + const Mat* arrays[] = {&src1, &src2, &mask, 0}; + uchar* ptrs[3]; + double result = 0; + NAryMatIterator it(arrays, ptrs); + int j, total = (int)it.size, blockSize = total, intSumBlockSize = 0, count = 0; + bool blockSum = (normType == NORM_L1 && depth <= CV_16S) || + (normType == NORM_L2 && depth <= CV_8S); + int isum = 0; + int *ibuf = (int*)&result; + size_t esz = 0; + + if( blockSum ) { - CV_Assert( a.size() == b.size() ); - r = func( a, b ); + intSumBlockSize = normType == NORM_L1 && depth <= CV_8S ? (1 << 23) : (1 << 15); + blockSize = std::min(blockSize, intSumBlockSize); + ibuf = &isum; + esz = src1.elemSize(); } - if( normType == NORM_L2 ) - r = std::sqrt(r); - if( isRelative ) - r /= norm(b, normType); - return r; -} - -double norm( const Mat& a, const Mat& b, int normType, const Mat& mask ) -{ - static NormDiffMaskFunc tab[3][8] = - { - { - normDiffMask_, OpMax >, - normDiffMask_, OpMax >, - normDiffMask_, OpMax >, - normDiffMask_, OpMax >, - normDiffMask_, OpMax >, - normDiffMask_, OpMax >, - normDiffMask_, OpMax > - }, - - { - normDiffMaskBlock_, OpAdd, OpAdd, 1<<24>, - normDiffMaskBlock_, OpAdd, OpAdd, 1<<24>, - normDiffMaskBlock_, OpAdd, OpAdd, 1<<16>, - normDiffMaskBlock_, OpAdd, OpAdd, 1<<16>, - normDiffMask_, OpAdd >, - normDiffMask_, OpAdd >, - normDiffMask_, OpAdd > - }, - - { - normDiffMaskBlock_, OpAdd, OpAdd, 1<<16>, - normDiffMaskBlock_, OpAdd, OpAdd, 1<<16>, - normDiffMask_, OpAdd >, - normDiffMask_, OpAdd >, - normDiffMask_, OpAdd >, - normDiffMask_, OpAdd >, - normDiffMask_, OpAdd > - } - }; - if( !mask.data ) - return norm(a, b, normType); - - CV_Assert( a.type() == b.type() && mask.type() == CV_8U); - bool isRelative = (normType & NORM_RELATIVE) != 0; - normType &= 7; - CV_Assert(normType == NORM_INF || normType == NORM_L1 || normType == NORM_L2); - - NormDiffMaskFunc func = tab[normType >> 1][a.depth()]; - CV_Assert(func != 0); - - double r = 0.; - if( a.dims > 2 ) + for( size_t i = 0; i < it.nplanes; i++, ++it ) { - const Mat* arrays[] = {&a, &b, &mask, 0}; - Mat planes[3]; - NAryMatIterator it(arrays, planes); - - for( int i = 0; i < it.nplanes; i++, ++it ) + for( j = 0; j < total; j += blockSize ) { - double n = func(it.planes[0], it.planes[1], it.planes[2]); - - if( normType == NORM_INF ) - r = std::max(r, n); - else - r += n; + int bsz = std::min(total - j, blockSize); + func( ptrs[0], ptrs[1], ptrs[2], (uchar*)ibuf, bsz, cn ); + count += bsz; + if( blockSum && (count + blockSize >= intSumBlockSize || (i+1 >= it.nplanes && j+bsz >= total)) ) + { + result += isum; + isum = 0; + count = 0; + } + ptrs[0] += bsz*esz; + ptrs[1] += bsz*esz; + if( ptrs[2] ) + ptrs[2] += bsz; } } - else + + if( normType == NORM_INF ) { - CV_Assert( a.size() == b.size() && a.size() == mask.size() ); - r = func( a, b, mask ); + if( depth == CV_64F ) + ; + else if( depth == CV_32F ) + result = (float&)result; + else + result = (int&)result; } + else if( normType == NORM_L2 ) + result = std::sqrt(result); - if( normType == NORM_L2 ) - r = std::sqrt(r); - if( isRelative ) - r /= std::max(norm(b, normType, mask), DBL_EPSILON); - return r; -} - + return result; } diff --git a/modules/core/src/system.cpp b/modules/core/src/system.cpp index 1d1ef192e1..24c5148798 100644 --- a/modules/core/src/system.cpp +++ b/modules/core/src/system.cpp @@ -170,12 +170,14 @@ struct IPPInitializer IPPInitializer ippInitializer; #else volatile bool useOptimizedFlag = false; +volatile bool USE_SSE2 = false; #endif void setUseOptimized( bool flag ) { useOptimizedFlag = flag; currentFeatures = flag ? &featuresEnabled : &featuresDisabled; + USE_SSE2 = currentFeatures->have[CV_CPU_SSE2]; } bool useOptimized(void) diff --git a/modules/core/test/test_arithm.cpp b/modules/core/test/test_arithm.cpp index 258b4bd5b2..aa638cf69b 100644 --- a/modules/core/test/test_arithm.cpp +++ b/modules/core/test/test_arithm.cpp @@ -35,7 +35,7 @@ struct BaseElemWiseOp virtual int getRandomType(RNG& rng) { - return cvtest::randomType(rng, cvtest::TYPE_MASK_ALL_BUT_8S, 1, + return cvtest::randomType(rng, DEPTH_MASK_ALL_BUT_8S, 1, ninputs > 1 ? ARITHM_MAX_CHANNELS : 4); } @@ -172,6 +172,10 @@ struct ScaleAddOp : public BaseAddOp { scaleAdd(src[0], alpha, src[1], dst); } + double getMaxErr(int depth) + { + return depth <= CV_32S ? 2 : depth < CV_64F ? 1e-4 : 1e-12; + } }; @@ -414,7 +418,7 @@ struct CmpOp : public BaseElemWiseOp } int getRandomType(RNG& rng) { - return cvtest::randomType(rng, cvtest::TYPE_MASK_ALL_BUT_8S, 1, 1); + return cvtest::randomType(rng, DEPTH_MASK_ALL_BUT_8S, 1, 1); } double getMaxErr(int) @@ -431,6 +435,8 @@ struct CmpSOp : public BaseElemWiseOp { BaseElemWiseOp::generateScalars(depth, rng); cmpop = rng.uniform(0, 6); + if( depth < CV_32F ) + gamma[0] = cvRound(gamma[0]); } void op(const vector& src, Mat& dst, const Mat&) { @@ -442,7 +448,7 @@ struct CmpSOp : public BaseElemWiseOp } int getRandomType(RNG& rng) { - return cvtest::randomType(rng, cvtest::TYPE_MASK_ALL_BUT_8S, 1, 1); + return cvtest::randomType(rng, DEPTH_MASK_ALL_BUT_8S, 1, 1); } double getMaxErr(int) { @@ -465,7 +471,7 @@ struct CopyOp : public BaseElemWiseOp } int getRandomType(RNG& rng) { - return cvtest::randomType(rng, cvtest::TYPE_MASK_ALL, 1, ARITHM_MAX_CHANNELS); + return cvtest::randomType(rng, DEPTH_MASK_ALL, 1, ARITHM_MAX_CHANNELS); } double getMaxErr(int) { @@ -488,7 +494,7 @@ struct SetOp : public BaseElemWiseOp } int getRandomType(RNG& rng) { - return cvtest::randomType(rng, cvtest::TYPE_MASK_ALL, 1, ARITHM_MAX_CHANNELS); + return cvtest::randomType(rng, DEPTH_MASK_ALL, 1, ARITHM_MAX_CHANNELS); } double getMaxErr(int) { @@ -504,14 +510,14 @@ inRangeS_(const _Tp* src, const _WTp* a, const _WTp* b, uchar* dst, size_t total for( i = 0; i < total; i++ ) { _Tp val = src[i*cn]; - dst[i] = a[0] <= val && val < b[0] ? 255 : 0; + dst[i] = a[0] <= val && val <= b[0] ? 255 : 0; } for( c = 1; c < cn; c++ ) { for( i = 0; i < total; i++ ) { _Tp val = src[i*cn + c]; - dst[i] = a[c] <= val && val < b[c] ? dst[i] : 0; + dst[i] = a[c] <= val && val <= b[c] ? dst[i] : 0; } } } @@ -523,14 +529,14 @@ template static void inRange_(const _Tp* src, const _Tp* a, const for( i = 0; i < total; i++ ) { _Tp val = src[i*cn]; - dst[i] = a[i*cn] <= val && val < b[i*cn] ? 255 : 0; + dst[i] = a[i*cn] <= val && val <= b[i*cn] ? 255 : 0; } for( c = 1; c < cn; c++ ) { for( i = 0; i < total; i++ ) { _Tp val = src[i*cn + c]; - dst[i] = a[i*cn + c] <= val && val < b[i*cn + c] ? dst[i] : 0; + dst[i] = a[i*cn + c] <= val && val <= b[i*cn + c] ? dst[i] : 0; } } } @@ -703,13 +709,13 @@ struct ConvertScaleOp : public BaseElemWiseOp } int getRandomType(RNG& rng) { - int srctype = cvtest::randomType(rng, cvtest::TYPE_MASK_ALL, 1, ARITHM_MAX_CHANNELS); - ddepth = cvtest::randomType(rng, cvtest::TYPE_MASK_ALL, 1, 1); + int srctype = cvtest::randomType(rng, DEPTH_MASK_ALL, 1, ARITHM_MAX_CHANNELS); + ddepth = cvtest::randomType(rng, DEPTH_MASK_ALL, 1, 1); return srctype; } double getMaxErr(int) { - return ddepth <= CV_32S ? 2 : ddepth < CV_64F ? 1e-4 : 1e-12; + return ddepth <= CV_32S ? 2 : ddepth < CV_64F ? 1e-3 : 1e-12; } void generateScalars(int depth, RNG& rng) { @@ -940,7 +946,7 @@ struct ExpOp : public BaseElemWiseOp ExpOp() : BaseElemWiseOp(1, FIX_ALPHA+FIX_BETA+FIX_GAMMA, 1, 1, Scalar::all(0)) {}; int getRandomType(RNG& rng) { - return cvtest::randomType(rng, cvtest::TYPE_MASK_FLT, 1, ARITHM_MAX_CHANNELS); + return cvtest::randomType(rng, DEPTH_MASK_FLT, 1, ARITHM_MAX_CHANNELS); } void getValueRange(int depth, double& minval, double& maxval) { @@ -967,7 +973,7 @@ struct LogOp : public BaseElemWiseOp LogOp() : BaseElemWiseOp(1, FIX_ALPHA+FIX_BETA+FIX_GAMMA, 1, 1, Scalar::all(0)) {}; int getRandomType(RNG& rng) { - return cvtest::randomType(rng, cvtest::TYPE_MASK_FLT, 1, ARITHM_MAX_CHANNELS); + return cvtest::randomType(rng, DEPTH_MASK_FLT, 1, ARITHM_MAX_CHANNELS); } void getValueRange(int depth, double& minval, double& maxval) { @@ -1052,7 +1058,7 @@ struct CartToPolarToCartOp : public BaseElemWiseOp } int getRandomType(RNG& rng) { - return cvtest::randomType(rng, cvtest::TYPE_MASK_FLT, 1, 1); + return cvtest::randomType(rng, DEPTH_MASK_FLT, 1, 1); } void op(const vector& src, Mat& dst, const Mat&) { @@ -1128,7 +1134,7 @@ struct SumOp : public BaseElemWiseOp } double getMaxErr(int) { - return 1e-6; + return 1e-5; } }; @@ -1139,7 +1145,7 @@ struct CountNonZeroOp : public BaseElemWiseOp {} int getRandomType(RNG& rng) { - return cvtest::randomType(rng, cvtest::TYPE_MASK_ALL, 1, 1); + return cvtest::randomType(rng, DEPTH_MASK_ALL, 1, 1); } void op(const vector& src, Mat& dst, const Mat& mask) { @@ -1208,7 +1214,7 @@ struct NormOp : public BaseElemWiseOp }; int getRandomType(RNG& rng) { - return cvtest::randomType(rng, cvtest::TYPE_MASK_ALL_BUT_8S, 1, 4); + return cvtest::randomType(rng, DEPTH_MASK_ALL_BUT_8S, 1, 4); } void op(const vector& src, Mat& dst, const Mat& mask) { @@ -1242,7 +1248,7 @@ struct MinMaxLocOp : public BaseElemWiseOp }; int getRandomType(RNG& rng) { - return cvtest::randomType(rng, cvtest::TYPE_MASK_ALL_BUT_8S, 1, 1); + return cvtest::randomType(rng, DEPTH_MASK_ALL_BUT_8S, 1, 1); } void saveOutput(const vector& minidx, const vector& maxidx, double minval, double maxval, Mat& dst) @@ -1341,6 +1347,8 @@ INSTANTIATE_TEST_CASE_P(Core_SubRS, ElemWiseTest, ::testing::Values(ElemWiseOpPt INSTANTIATE_TEST_CASE_P(Core_ScaleAdd, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new cvtest::ScaleAddOp))); INSTANTIATE_TEST_CASE_P(Core_AddWeighted, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new cvtest::AddWeightedOp))); INSTANTIATE_TEST_CASE_P(Core_AbsDiff, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new cvtest::AbsDiffOp))); + + INSTANTIATE_TEST_CASE_P(Core_AbsDiffS, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new cvtest::AbsDiffSOp))); INSTANTIATE_TEST_CASE_P(Core_And, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new cvtest::LogicOp('&')))); @@ -1380,3 +1388,6 @@ INSTANTIATE_TEST_CASE_P(Core_Sum, ElemWiseTest, ::testing::Values(ElemWiseOpPtr( INSTANTIATE_TEST_CASE_P(Core_Norm, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new cvtest::NormOp))); INSTANTIATE_TEST_CASE_P(Core_MinMaxLoc, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new cvtest::MinMaxLocOp))); INSTANTIATE_TEST_CASE_P(Core_CartToPolarToCart, ElemWiseTest, ::testing::Values(ElemWiseOpPtr(new cvtest::CartToPolarToCartOp))); + + + diff --git a/modules/core/test/test_dxt.cpp b/modules/core/test/test_dxt.cpp index b6f7078b34..be6826e1d9 100644 --- a/modules/core/test/test_dxt.cpp +++ b/modules/core/test/test_dxt.cpp @@ -827,3 +827,4 @@ TEST(Core_DCT, accuracy) { CxCore_DCTTest test; test.safe_run(); } TEST(Core_DFT, accuracy) { CxCore_DFTTest test; test.safe_run(); } TEST(Core_MulSpectrums, accuracy) { CxCore_MulSpectrumsTest test; test.safe_run(); } + diff --git a/modules/core/test/test_mat.cpp b/modules/core/test/test_mat.cpp index ae5f4429ff..19708769c4 100644 --- a/modules/core/test/test_mat.cpp +++ b/modules/core/test/test_mat.cpp @@ -277,8 +277,6 @@ public: protected: void run(int) { - int code = cvtest::TS::OK; - double diffPrjEps, diffBackPrjEps, prjEps, backPrjEps, evalEps, evecEps; @@ -327,26 +325,44 @@ protected: if( err > eigenEps ) { ts->printf( cvtest::TS::LOG, "bad accuracy of eigen(); err = %f\n", err ); - code = cvtest::TS::FAIL_BAD_ACCURACY; - goto exit_func; + ts->set_failed_test_info( cvtest::TS::FAIL_BAD_ACCURACY ); + return; } } // check pca eigenvalues - evalEps = 1e-6, evecEps = 1; + evalEps = 1e-6, evecEps = 1e-3; err = norm( rPCA.eigenvalues, subEval ); if( err > evalEps ) { ts->printf( cvtest::TS::LOG, "pca.eigenvalues is incorrect (CV_PCA_DATA_AS_ROW); err = %f\n", err ); - code = cvtest::TS::FAIL_BAD_ACCURACY; - goto exit_func; + ts->set_failed_test_info( cvtest::TS::FAIL_BAD_ACCURACY ); + return; } // check pca eigenvectors - err = norm( rPCA.eigenvectors, subEvec, CV_RELATIVE_L2 ); - if( err > evecEps ) + for(int i = 0; i < subEvec.rows; i++) { - ts->printf( cvtest::TS::LOG, "pca.eigenvectors is incorrect (CV_PCA_DATA_AS_ROW); err = %f\n", err ); - code = cvtest::TS::FAIL_BAD_ACCURACY; - goto exit_func; + Mat r0 = rPCA.eigenvectors.row(i); + Mat r1 = subEvec.row(i); + err = norm( r0, r1, CV_L2 ); + if( err > evecEps ) + { + r1 *= -1; + double err2 = norm(r0, r1, CV_L2); + if( err2 > evecEps ) + { + Mat tmp; + absdiff(rPCA.eigenvectors, subEvec, tmp); + double mval = 0; Point mloc; + minMaxLoc(tmp, 0, &mval, 0, &mloc); + + ts->printf( cvtest::TS::LOG, "pca.eigenvectors is incorrect (CV_PCA_DATA_AS_ROW); err = %f\n", err ); + ts->printf( cvtest::TS::LOG, "max diff is %g at (i=%d, j=%d) (%g vs %g)\n", + mval, mloc.y, mloc.x, rPCA.eigenvectors.at(mloc.y, mloc.x), + subEvec.at(mloc.y, mloc.x)); + ts->set_failed_test_info( cvtest::TS::FAIL_BAD_ACCURACY ); + return; + } + } } prjEps = 1.265, backPrjEps = 1.265; @@ -359,8 +375,8 @@ protected: if( err > prjEps ) { ts->printf( cvtest::TS::LOG, "bad accuracy of project() (CV_PCA_DATA_AS_ROW); err = %f\n", err ); - code = cvtest::TS::FAIL_BAD_ACCURACY; - goto exit_func; + ts->set_failed_test_info( cvtest::TS::FAIL_BAD_ACCURACY ); + return; } // check pca backProject Mat backPrj = rPrjTestPoints.row(i) * subEvec + avg; @@ -368,27 +384,28 @@ protected: if( err > backPrjEps ) { ts->printf( cvtest::TS::LOG, "bad accuracy of backProject() (CV_PCA_DATA_AS_ROW); err = %f\n", err ); - code = cvtest::TS::FAIL_BAD_ACCURACY; - goto exit_func; + ts->set_failed_test_info( cvtest::TS::FAIL_BAD_ACCURACY ); + return; } } // 2. check C++ PCA & COL cPCA( rPoints.t(), Mat(), CV_PCA_DATA_AS_COL, maxComponents ); diffPrjEps = 1, diffBackPrjEps = 1; - err = norm(cPCA.project(rTestPoints.t()), rPrjTestPoints.t(), CV_RELATIVE_L2 ); + Mat ocvPrjTestPoints = cPCA.project(rTestPoints.t()); + err = norm(cv::abs(ocvPrjTestPoints), cv::abs(rPrjTestPoints.t()), CV_RELATIVE_L2 ); if( err > diffPrjEps ) { ts->printf( cvtest::TS::LOG, "bad accuracy of project() (CV_PCA_DATA_AS_COL); err = %f\n", err ); - code = cvtest::TS::FAIL_BAD_ACCURACY; - goto exit_func; + ts->set_failed_test_info( cvtest::TS::FAIL_BAD_ACCURACY ); + return; } - err = norm(cPCA.backProject(rPrjTestPoints.t()), rBackPrjTestPoints.t(), CV_RELATIVE_L2 ); + err = norm(cPCA.backProject(ocvPrjTestPoints), rBackPrjTestPoints.t(), CV_RELATIVE_L2 ); if( err > diffBackPrjEps ) { ts->printf( cvtest::TS::LOG, "bad accuracy of backProject() (CV_PCA_DATA_AS_COL); err = %f\n", err ); - code = cvtest::TS::FAIL_BAD_ACCURACY; - goto exit_func; + ts->set_failed_test_info( cvtest::TS::FAIL_BAD_ACCURACY ); + return; } #ifdef CHECK_C @@ -411,15 +428,15 @@ protected: if( err > diffPrjEps ) { ts->printf( cvtest::TS::LOG, "bad accuracy of cvProjectPCA() (CV_PCA_DATA_AS_ROW); err = %f\n", err ); - code = cvtest::TS::FAIL_BAD_ACCURACY; - goto exit_func; + ts->set_failed_test_info( cvtest::TS::FAIL_BAD_ACCURACY ); + return; } err = norm(backPrjTestPoints, rBackPrjTestPoints, CV_RELATIVE_L2); if( err > diffBackPrjEps ) { ts->printf( cvtest::TS::LOG, "bad accuracy of cvBackProjectPCA() (CV_PCA_DATA_AS_ROW); err = %f\n", err ); - code = cvtest::TS::FAIL_BAD_ACCURACY; - goto exit_func; + ts->set_failed_test_info( cvtest::TS::FAIL_BAD_ACCURACY ); + return; } // 3. check C PCA & COL @@ -435,27 +452,21 @@ protected: cvProjectPCA( &_testPoints, &_avg, &_evec, &_prjTestPoints ); cvBackProjectPCA( &_prjTestPoints, &_avg, &_evec, &_backPrjTestPoints ); - err = norm(prjTestPoints, rPrjTestPoints.t(), CV_RELATIVE_L2 ); + err = norm(cv::abs(prjTestPoints), cv::abs(rPrjTestPoints.t()), CV_RELATIVE_L2 ); if( err > diffPrjEps ) { ts->printf( cvtest::TS::LOG, "bad accuracy of cvProjectPCA() (CV_PCA_DATA_AS_COL); err = %f\n", err ); - code = cvtest::TS::FAIL_BAD_ACCURACY; - goto exit_func; + ts->set_failed_test_info( cvtest::TS::FAIL_BAD_ACCURACY ); + return; } err = norm(backPrjTestPoints, rBackPrjTestPoints.t(), CV_RELATIVE_L2); if( err > diffBackPrjEps ) { ts->printf( cvtest::TS::LOG, "bad accuracy of cvBackProjectPCA() (CV_PCA_DATA_AS_COL); err = %f\n", err ); - code = cvtest::TS::FAIL_BAD_ACCURACY; - goto exit_func; + ts->set_failed_test_info( cvtest::TS::FAIL_BAD_ACCURACY ); + return; } #endif - - exit_func: - - RNG& _rng = ts->get_rng(); - _rng = rng; - ts->set_failed_test_info( code ); } }; @@ -790,7 +801,7 @@ void Core_ArrayOpTest::run( int /* start_from */) break; } - minMaxLoc(Md, &val1, &val2, idx1, idx2); + minMaxIdx(Md, &val1, &val2, idx1, idx2); s1 = idx2string(idx1, dims), s2 = idx2string(idx2, dims); if( (min_val < 0 && (val1 != min_val || s1 != min_sidx)) || (max_val > 0 && (val2 != max_val || s2 != max_sidx)) ) @@ -809,3 +820,5 @@ void Core_ArrayOpTest::run( int /* start_from */) TEST(Core_PCA, accuracy) { Core_PCATest test; test.safe_run(); } TEST(Core_Reduce, accuracy) { Core_ReduceTest test; test.safe_run(); } TEST(Core_Array, basic_operations) { Core_ArrayOpTest test; test.safe_run(); } + + diff --git a/modules/features2d/src/bagofwords.cpp b/modules/features2d/src/bagofwords.cpp index 92e0d84aa3..384d2bc1ac 100755 --- a/modules/features2d/src/bagofwords.cpp +++ b/modules/features2d/src/bagofwords.cpp @@ -113,7 +113,7 @@ BOWKMeansTrainer::~BOWKMeansTrainer() Mat BOWKMeansTrainer::cluster( const Mat& descriptors ) const { Mat labels, vocabulary; - kmeans( descriptors, clusterCount, labels, termcrit, attempts, flags, &vocabulary ); + kmeans( descriptors, clusterCount, labels, termcrit, attempts, flags, vocabulary ); return vocabulary; } diff --git a/modules/features2d/test/test_nearestneighbors.cpp b/modules/features2d/test/test_nearestneighbors.cpp index 90c8b16013..01d16c8a36 100644 --- a/modules/features2d/test/test_nearestneighbors.cpp +++ b/modules/features2d/test/test_nearestneighbors.cpp @@ -281,7 +281,6 @@ void CV_KDTreeTest_CPP::createModel( const Mat& data ) int CV_KDTreeTest_CPP::checkGetPoins( const Mat& data ) { Mat res1( data.size(), data.type() ), - res2( data.size(), data.type() ), res3( data.size(), data.type() ); Mat idxs( 1, data.rows, CV_32SC1 ); for( int pi = 0; pi < data.rows; pi++ ) @@ -292,14 +291,11 @@ int CV_KDTreeTest_CPP::checkGetPoins( const Mat& data ) for( int di = 0; di < data.cols; di++ ) res1.at(pi, di) = point[di]; } - // 2nd way - tr->getPoints( idxs.ptr(0), data.rows, res2 ); // 3d way tr->getPoints( idxs, res3 ); if( norm( res1, data, NORM_L1) != 0 || - norm( res2, data, NORM_L1) != 0 || norm( res3, data, NORM_L1) != 0) return cvtest::TS::FAIL_BAD_ACCURACY; return cvtest::TS::OK; @@ -309,7 +305,7 @@ int CV_KDTreeTest_CPP::checkFindBoxed() { vector min( dims, minValue), max(dims, maxValue); vector indices; - tr->findOrthoRange( &min[0], &max[0], &indices ); + tr->findOrthoRange( min, max, indices ); // TODO check indices if( (int)indices.size() != featuresCount) return cvtest::TS::FAIL_BAD_ACCURACY; @@ -326,11 +322,12 @@ int CV_KDTreeTest_CPP::findNeighbors( Mat& points, Mat& neighbors ) for( int pi = 0; pi < points.rows; pi++ ) { // 1st way - tr->findNearest( points.ptr(pi), neighbors.cols, emax, neighbors.ptr(pi) ); + Mat nrow = neighbors.row(pi); + tr->findNearest( points.row(pi), neighbors.cols, emax, nrow ); // 2nd way vector neighborsIdx2( neighbors2.cols, 0 ); - tr->findNearest( points.ptr(pi), neighbors2.cols, emax, &neighborsIdx2 ); + tr->findNearest( points.row(pi), neighbors2.cols, emax, neighborsIdx2 ); vector::const_iterator it2 = neighborsIdx2.begin(); for( j = 0; it2 != neighborsIdx2.end(); ++it2, j++ ) neighbors2.at(pi,j) = *it2; diff --git a/modules/gpu/test/test_filters.cpp b/modules/gpu/test/test_filters.cpp index c3e65b531b..7fdca74686 100644 --- a/modules/gpu/test/test_filters.cpp +++ b/modules/gpu/test/test_filters.cpp @@ -344,7 +344,7 @@ protected: ts->printf(cvtest::TS::LOG, "Tesing %s\n", names[i]); cv::Mat cpuRes; - cv::morphologyEx(img, cpuRes, ops[i], kernel); + cv::morphologyEx(img, cpuRes, ops[i], (Mat)kernel); GpuMat gpuRes; cv::gpu::morphologyEx(GpuMat(img), gpuRes, ops[i], kernel); diff --git a/modules/gpu/test/test_hog.cpp b/modules/gpu/test/test_hog.cpp index 4cbbc8c552..c6089b0766 100644 --- a/modules/gpu/test/test_hog.cpp +++ b/modules/gpu/test/test_hog.cpp @@ -249,7 +249,7 @@ struct CV_GpuHogGetDescriptorsTestRunner: cv::gpu::HOGDescriptor cv::cvtColor(img_rgb, img, CV_BGR2BGRA); computeBlockHistograms(cv::gpu::GpuMat(img)); // Everything is fine with interpolation for left top subimage - CHECK(cv::norm(block_hists, descriptors.rowRange(0, 1)) == 0.f, cvtest::TS::FAIL_INVALID_OUTPUT); + CHECK(cv::norm((cv::Mat)block_hists, (cv::Mat)descriptors.rowRange(0, 1)) == 0.f, cvtest::TS::FAIL_INVALID_OUTPUT); img_rgb = cv::imread(std::string(ts->get_data_path()) + "hog/positive2.png"); CHECK(!img_rgb.empty(), cvtest::TS::FAIL_MISSING_TEST_DATA); diff --git a/modules/gpu/test/test_operator_async_call.cpp b/modules/gpu/test/test_operator_async_call.cpp index 34459298ad..34843c79de 100644 --- a/modules/gpu/test/test_operator_async_call.cpp +++ b/modules/gpu/test/test_operator_async_call.cpp @@ -74,7 +74,7 @@ struct CV_AsyncGpuMatTest : public cvtest::BaseTest Mat cpu_gold0(100, 100, CV_8UC1, Scalar::all(255)); Mat cpu_gold1(100, 100, CV_8UC1, Scalar::all(128)); - if (norm(cpudst0, cpu_gold0, NORM_INF) > 0 || norm(cpudst1, cpu_gold1, NORM_INF) > 0) + if (norm((Mat)cpudst0, cpu_gold0, NORM_INF) > 0 || norm((Mat)cpudst1, cpu_gold1, NORM_INF) > 0) ts->set_failed_test_info(cvtest::TS::FAIL_GENERIC); else ts->set_failed_test_info(cvtest::TS::OK); diff --git a/modules/gpu/test/test_operator_convert_to.cpp b/modules/gpu/test/test_operator_convert_to.cpp index b604de33e1..c5c55b3d95 100644 --- a/modules/gpu/test/test_operator_convert_to.cpp +++ b/modules/gpu/test/test_operator_convert_to.cpp @@ -68,7 +68,7 @@ void CV_GpuMatOpConvertToTest::run(int /* start_from */) bool passed = true; int lastType = CV_32F; - if (TargetArchs::builtWith(NATIVE_DOUBLE) && DeviceInfo().supports(NATIVE_DOUBLE)) + if (TargetArchs::builtWith(NATIVE_DOUBLE) && DeviceInfo().supports(NATIVE_DOUBLE)) lastType = CV_64F; for (int i = 0; i <= lastType && passed; ++i) @@ -92,7 +92,7 @@ void CV_GpuMatOpConvertToTest::run(int /* start_from */) cpumatsrc.convertTo(cpumatdst, dst_type, 0.5, 3.0); gpumatsrc.convertTo(gpumatdst, dst_type, 0.5, 3.0); - double r = norm(cpumatdst, gpumatdst, NORM_INF); + double r = norm(cpumatdst, (Mat)gpumatdst, NORM_INF); if (r > 1) { ts->printf(cvtest::TS::LOG, diff --git a/modules/gpu/test/test_operator_copy_to.cpp b/modules/gpu/test/test_operator_copy_to.cpp index fccf0ab83a..dc1e2280bd 100644 --- a/modules/gpu/test/test_operator_copy_to.cpp +++ b/modules/gpu/test/test_operator_copy_to.cpp @@ -106,7 +106,7 @@ bool CV_GpuMatOpCopyToTest::compare_matrix(cv::Mat & cpumat, gpu::GpuMat & gpuma cv::waitKey(0); #endif - double ret = norm(cmat, gmat); + double ret = norm(cmat, (Mat)gmat); if (ret < 1.0) return true; @@ -123,7 +123,7 @@ void CV_GpuMatOpCopyToTest::run( int /* start_from */) int lastType = CV_32F; - if (TargetArchs::builtWith(NATIVE_DOUBLE) && DeviceInfo().supports(NATIVE_DOUBLE)) + if (TargetArchs::builtWith(NATIVE_DOUBLE) && DeviceInfo().supports(NATIVE_DOUBLE)) lastType = CV_64F; for (int i = 0 ; i <= lastType; i++) diff --git a/modules/gpu/test/test_operator_set_to.cpp b/modules/gpu/test/test_operator_set_to.cpp index db0908cfa3..f09f411714 100644 --- a/modules/gpu/test/test_operator_set_to.cpp +++ b/modules/gpu/test/test_operator_set_to.cpp @@ -78,7 +78,7 @@ bool CV_GpuMatOpSetToTest::testSetTo(cv::Mat& cpumat, gpu::GpuMat& gpumat, const cpumat.setTo(s, cpumask); gpumat.setTo(s, gpumask); - double ret = norm(cpumat, gpumat, NORM_INF); + double ret = norm(cpumat, (Mat)gpumat, NORM_INF); if (ret < std::numeric_limits::epsilon()) return true; @@ -100,7 +100,7 @@ void CV_GpuMatOpSetToTest::run( int /* start_from */) int lastType = CV_32F; - if (TargetArchs::builtWith(NATIVE_DOUBLE) && DeviceInfo().supports(NATIVE_DOUBLE)) + if (TargetArchs::builtWith(NATIVE_DOUBLE) && DeviceInfo().supports(NATIVE_DOUBLE)) lastType = CV_64F; for (int i = 0; i <= lastType; i++) diff --git a/modules/gpu/test/test_stereo_bm.cpp b/modules/gpu/test/test_stereo_bm.cpp index da925ca16b..7a4806e6f5 100644 --- a/modules/gpu/test/test_stereo_bm.cpp +++ b/modules/gpu/test/test_stereo_bm.cpp @@ -106,7 +106,7 @@ struct CV_GpuStereoBMTest : public cvtest::BaseTest bm(cv::gpu::GpuMat(img_l), cv::gpu::GpuMat(img_r), disp); disp.convertTo(disp, img_reference.type()); - double norm = cv::norm(disp, img_reference, cv::NORM_INF); + double norm = cv::norm((Mat)disp, img_reference, cv::NORM_INF); //cv::imwrite(std::string(ts->get_data_path()) + "stereobm/aloe-disp.png", disp); diff --git a/modules/gpu/test/test_stereo_bm_async.cpp b/modules/gpu/test/test_stereo_bm_async.cpp index 89afab884c..f9632dd283 100644 --- a/modules/gpu/test/test_stereo_bm_async.cpp +++ b/modules/gpu/test/test_stereo_bm_async.cpp @@ -70,7 +70,7 @@ struct CV_AsyncStereoBMTest : public cvtest::BaseTest stream.waitForCompletion(); disp.convertTo(disp, img_reference.type()); - double norm = cv::norm(disp, img_reference, cv::NORM_INF); + double norm = cv::norm((Mat)disp, img_reference, cv::NORM_INF); if (norm >= 100) { diff --git a/modules/gpu/test/test_stereo_bp.cpp b/modules/gpu/test/test_stereo_bp.cpp index cf277c2b91..7788917375 100644 --- a/modules/gpu/test/test_stereo_bp.cpp +++ b/modules/gpu/test/test_stereo_bp.cpp @@ -67,7 +67,7 @@ struct CV_GpuStereoBPTest : public cvtest::BaseTest disp.convertTo(disp, img_template.type()); - double norm = cv::norm(disp, img_template, cv::NORM_INF); + double norm = cv::norm((cv::Mat)disp, img_template, cv::NORM_INF); if (norm >= 0.5) { ts->printf(cvtest::TS::LOG, "\nStereoBP norm = %f\n", norm); diff --git a/modules/gpu/test/test_stereo_csbp.cpp b/modules/gpu/test/test_stereo_csbp.cpp index c2ff012a6a..e9d72850ef 100644 --- a/modules/gpu/test/test_stereo_csbp.cpp +++ b/modules/gpu/test/test_stereo_csbp.cpp @@ -67,7 +67,7 @@ struct CV_GpuStereoCSBPTest : public cvtest::BaseTest disp.convertTo(disp, img_template.type()); - double norm = cv::norm(disp, img_template, cv::NORM_INF); + double norm = cv::norm((cv::Mat)disp, img_template, cv::NORM_INF); if (norm >= 0.5) { ts->printf(cvtest::TS::LOG, "\nConstantSpaceStereoBP norm = %f\n", norm); diff --git a/modules/highgui/include/opencv2/highgui/highgui.hpp b/modules/highgui/include/opencv2/highgui/highgui.hpp index 9aa29aff82..b171d790c6 100644 --- a/modules/highgui/include/opencv2/highgui/highgui.hpp +++ b/modules/highgui/include/opencv2/highgui/highgui.hpp @@ -66,7 +66,9 @@ CV_EXPORTS_W double getWindowProperty(const string& winname, int prop_id);//YV //Only for Qt //------------------------ -CV_EXPORTS CvFont fontQt(const string& nameFont, int pointSize CV_DEFAULT(-1), Scalar color CV_DEFAULT(Scalar::all(0)), int weight CV_DEFAULT(CV_FONT_NORMAL), int style CV_DEFAULT(CV_STYLE_NORMAL), int spacing CV_DEFAULT(0)); +CV_EXPORTS CvFont fontQt(const string& nameFont, int pointSize CV_DEFAULT(-1), + Scalar color CV_DEFAULT(Scalar::all(0)), int weight CV_DEFAULT(CV_FONT_NORMAL), + int style CV_DEFAULT(CV_STYLE_NORMAL), int spacing CV_DEFAULT(0)); CV_EXPORTS void addText( const Mat& img, const string& text, Point org, CvFont font); CV_EXPORTS void displayOverlay(const string& winname, const string& text, int delayms); @@ -81,10 +83,12 @@ CV_EXPORTS int startLoop(int (*pt2Func)(int argc, char *argv[]), int argc, char CV_EXPORTS void stopLoop(); typedef void (CV_CDECL *ButtonCallback)(int state, void* userdata); -CV_EXPORTS int createButton( const string& bar_name, ButtonCallback on_change , void* userdata CV_DEFAULT(NULL), int type CV_DEFAULT(CV_PUSH_BUTTON), bool initial_button_state CV_DEFAULT(0)); +CV_EXPORTS int createButton( const string& bar_name, ButtonCallback on_change, + void* userdata CV_DEFAULT(NULL), int type CV_DEFAULT(CV_PUSH_BUTTON), + bool initial_button_state CV_DEFAULT(0)); //------------------------- -CV_EXPORTS_W void imshow( const string& winname, const Mat& mat ); +CV_EXPORTS_W void imshow( const string& winname, const InputArray& mat ); typedef void (CV_CDECL *TrackbarCallback)(int pos, void* userdata); @@ -102,12 +106,12 @@ typedef void (*MouseCallback )(int event, int x, int y, int flags, void* param); CV_EXPORTS void setMouseCallback( const string& windowName, MouseCallback onMouse, void* param=0); CV_EXPORTS_W Mat imread( const string& filename, int flags=1 ); -CV_EXPORTS_W bool imwrite( const string& filename, const Mat& img, +CV_EXPORTS_W bool imwrite( const string& filename, const InputArray& img, const vector& params=vector()); -CV_EXPORTS_W Mat imdecode( const Mat& buf, int flags ); -CV_EXPORTS_W bool imencode( const string& ext, const Mat& img, - CV_OUT vector& buf, - const vector& params=vector()); +CV_EXPORTS_W Mat imdecode( const InputArray& buf, int flags ); +CV_EXPORTS_W bool imencode( const string& ext, const InputArray& img, + vector& buf, + const vector& params=vector()); CV_EXPORTS_W int waitKey(int delay=0); diff --git a/modules/highgui/src/loadsave.cpp b/modules/highgui/src/loadsave.cpp index 87d4963c47..87cf61a2de 100644 --- a/modules/highgui/src/loadsave.cpp +++ b/modules/highgui/src/loadsave.cpp @@ -295,9 +295,10 @@ static bool imwrite_( const string& filename, const Mat& image, return code; } -bool imwrite( const string& filename, const Mat& img, +bool imwrite( const string& filename, const InputArray& _img, const vector& params ) { + Mat img = _img.getMat(); return imwrite_(filename, img, params, false); } @@ -388,17 +389,17 @@ imdecode_( const Mat& buf, int flags, int hdrtype, Mat* mat=0 ) } -Mat imdecode( const Mat& buf, int flags ) +Mat imdecode( const InputArray& _buf, int flags ) { - Mat img; + Mat buf = _buf.getMat(), img; imdecode_( buf, flags, LOAD_MAT, &img ); return img; } -bool imencode( const string& ext, const Mat& image, +bool imencode( const string& ext, const InputArray& _image, vector& buf, const vector& params ) { - Mat temp; + Mat temp, image = _image.getMat(); const Mat* pimage = ℑ int channels = image.channels(); diff --git a/modules/highgui/src/window.cpp b/modules/highgui/src/window.cpp index 57b3f44c6a..0fbca111c0 100644 --- a/modules/highgui/src/window.cpp +++ b/modules/highgui/src/window.cpp @@ -126,41 +126,38 @@ CV_IMPL double cvGetWindowProperty(const char* name, int prop_id) } } -namespace cv -{ - -void namedWindow( const string& winname, int flags ) +void cv::namedWindow( const string& winname, int flags ) { cvNamedWindow( winname.c_str(), flags ); } -void destroyWindow( const string& winname ) +void cv::destroyWindow( const string& winname ) { cvDestroyWindow( winname.c_str() ); } -void setWindowProperty(const string& winname, int prop_id, double prop_value) +void cv::setWindowProperty(const string& winname, int prop_id, double prop_value) { cvSetWindowProperty( winname.c_str(),prop_id,prop_value); } -double getWindowProperty(const string& winname, int prop_id) +double cv::getWindowProperty(const string& winname, int prop_id) { return cvGetWindowProperty(winname.c_str(),prop_id); } -void imshow( const string& winname, const Mat& img ) +void cv::imshow( const string& winname, const InputArray& img ) { - CvMat _img = img; - cvShowImage( winname.c_str(), &_img ); + CvMat c_img = img.getMat(); + cvShowImage( winname.c_str(), &c_img ); } -int waitKey(int delay) +int cv::waitKey(int delay) { return cvWaitKey(delay); } -int createTrackbar(const string& trackbarName, const string& winName, +int cv::createTrackbar(const string& trackbarName, const string& winName, int* value, int count, TrackbarCallback callback, void* userdata) { @@ -168,83 +165,81 @@ int createTrackbar(const string& trackbarName, const string& winName, value, count, callback, userdata); } -void setTrackbarPos( const string& trackbarName, const string& winName, int value ) +void cv::setTrackbarPos( const string& trackbarName, const string& winName, int value ) { cvSetTrackbarPos(trackbarName.c_str(), winName.c_str(), value ); } -int getTrackbarPos( const string& trackbarName, const string& winName ) +int cv::getTrackbarPos( const string& trackbarName, const string& winName ) { return cvGetTrackbarPos(trackbarName.c_str(), winName.c_str()); } -void setMouseCallback( const string& windowName, MouseCallback onMouse, void* param) +void cv::setMouseCallback( const string& windowName, MouseCallback onMouse, void* param) { cvSetMouseCallback(windowName.c_str(), onMouse, param); } -int startWindowThread() +int cv::startWindowThread() { return cvStartWindowThread(); } #if defined (HAVE_QT) -CvFont fontQt(const string& nameFont, int pointSize, Scalar color, int weight, int style, int spacing) +CvFont cv::fontQt(const string& nameFont, int pointSize, Scalar color, int weight, int style, int spacing) { return cvFontQt(nameFont.c_str(), pointSize,color,weight, style); } -void addText( const Mat& img, const string& text, Point org, CvFont font) +void cv::addText( const Mat& img, const string& text, Point org, CvFont font) { CvMat _img = img; cvAddText( &_img, text.c_str(), org,&font); } -void displayStatusBar(const string& name, const string& text, int delayms) +void cv::displayStatusBar(const string& name, const string& text, int delayms) { cvDisplayStatusBar(name.c_str(),text.c_str(), delayms); } -void createOpenGLCallback(const string& name, OpenGLCallback callback, void* param) +void cv::createOpenGLCallback(const string& name, OpenGLCallback callback, void* param) { cvCreateOpenGLCallback(name.c_str(),callback, param); } -void displayOverlay(const string& name, const string& text, int delayms) +void cv::displayOverlay(const string& name, const string& text, int delayms) { cvDisplayOverlay(name.c_str(),text.c_str(), delayms); } -int startLoop(int (*pt2Func)(int argc, char *argv[]), int argc, char* argv[]) +int cv::startLoop(int (*pt2Func)(int argc, char *argv[]), int argc, char* argv[]) { return cvStartLoop(pt2Func, argc, argv); } -void stopLoop() +void cv::stopLoop() { cvStopLoop(); } -void saveWindowParameters(const string& windowName) +void cv::saveWindowParameters(const string& windowName) { cvSaveWindowParameters(windowName.c_str()); } -void loadWindowParameters(const string& windowName) +void cv::loadWindowParameters(const string& windowName) { cvLoadWindowParameters(windowName.c_str()); } -int createButton(const string& button_name, ButtonCallback on_change, void* userdata, int button_type , bool initial_button_state ) +int cv::createButton(const string& button_name, ButtonCallback on_change, void* userdata, int button_type , bool initial_button_state ) { return cvCreateButton(button_name.c_str(), on_change, userdata, button_type , initial_button_state ); } #endif -} - #if defined WIN32 || defined _WIN32 // see window_w32.cpp #elif defined (HAVE_GTK) // see window_gtk.cpp #elif defined (HAVE_COCOA) // see window_carbon.cpp diff --git a/modules/imgproc/include/opencv2/imgproc/imgproc.hpp b/modules/imgproc/include/opencv2/imgproc/imgproc.hpp index 7f81b0d8c4..89bed25a8b 100644 --- a/modules/imgproc/include/opencv2/imgproc/imgproc.hpp +++ b/modules/imgproc/include/opencv2/imgproc/imgproc.hpp @@ -61,7 +61,7 @@ namespace cv //! various border interpolation methods enum { BORDER_REPLICATE=IPL_BORDER_REPLICATE, BORDER_CONSTANT=IPL_BORDER_CONSTANT, BORDER_REFLECT=IPL_BORDER_REFLECT, BORDER_WRAP=IPL_BORDER_WRAP, - BORDER_REFLECT_101=IPL_BORDER_REFLECT_101, BORDER_REFLECT101=BORDER_REFLECT_101, + BORDER_REFLECT_101=IPL_BORDER_REFLECT_101, BORDER_REFLECT101=BORDER_REFLECT_101, BORDER_TRANSPARENT=IPL_BORDER_TRANSPARENT, BORDER_DEFAULT=BORDER_REFLECT_101, BORDER_ISOLATED=16 }; @@ -287,28 +287,28 @@ enum { KERNEL_GENERAL=0, KERNEL_SYMMETRICAL=1, KERNEL_ASYMMETRICAL=2, KERNEL_SMOOTH=4, KERNEL_INTEGER=8 }; //! returns type (one of KERNEL_*) of 1D or 2D kernel specified by its coefficients. -CV_EXPORTS int getKernelType(const Mat& kernel, Point anchor); +CV_EXPORTS int getKernelType(const InputArray& kernel, Point anchor); //! returns the primitive row filter with the specified kernel CV_EXPORTS Ptr getLinearRowFilter(int srcType, int bufType, - const Mat& kernel, int anchor, + const InputArray& kernel, int anchor, int symmetryType); //! returns the primitive column filter with the specified kernel CV_EXPORTS Ptr getLinearColumnFilter(int bufType, int dstType, - const Mat& kernel, int anchor, + const InputArray& kernel, int anchor, int symmetryType, double delta=0, int bits=0); //! returns 2D filter with the specified kernel CV_EXPORTS Ptr getLinearFilter(int srcType, int dstType, - const Mat& kernel, + const InputArray& kernel, Point anchor=Point(-1,-1), double delta=0, int bits=0); //! returns the separable linear filter engine CV_EXPORTS Ptr createSeparableLinearFilter(int srcType, int dstType, - const Mat& rowKernel, const Mat& columnKernel, + const InputArray& rowKernel, const InputArray& columnKernel, Point _anchor=Point(-1,-1), double delta=0, int _rowBorderType=BORDER_DEFAULT, int _columnBorderType=-1, @@ -316,7 +316,7 @@ CV_EXPORTS Ptr createSeparableLinearFilter(int srcType, int dstTyp //! returns the non-separable linear filter engine CV_EXPORTS Ptr createLinearFilter(int srcType, int dstType, - const Mat& kernel, Point _anchor=Point(-1,-1), + const InputArray& kernel, Point _anchor=Point(-1,-1), double delta=0, int _rowBorderType=BORDER_DEFAULT, int _columnBorderType=-1, const Scalar& _borderValue=Scalar()); @@ -328,9 +328,9 @@ CV_EXPORTS Ptr createGaussianFilter( int type, Size ksize, double sigma1, double sigma2=0, int borderType=BORDER_DEFAULT); //! initializes kernels of the generalized Sobel operator -CV_EXPORTS_W void getDerivKernels( CV_OUT Mat& kx, CV_OUT Mat& ky, - int dx, int dy, int ksize, - bool normalize=false, int ktype=CV_32F ); +CV_EXPORTS_W void getDerivKernels( OutputArray kx, OutputArray ky, + int dx, int dy, int ksize, + bool normalize=false, int ktype=CV_32F ); //! returns filter engine for the generalized Sobel operator CV_EXPORTS Ptr createDerivFilter( int srcType, int dstType, int dx, int dy, int ksize, @@ -358,14 +358,14 @@ CV_EXPORTS Ptr getMorphologyRowFilter(int op, int type, int ksize //! returns vertical 1D morphological filter CV_EXPORTS Ptr getMorphologyColumnFilter(int op, int type, int ksize, int anchor=-1); //! returns 2D morphological filter -CV_EXPORTS Ptr getMorphologyFilter(int op, int type, const Mat& kernel, +CV_EXPORTS Ptr getMorphologyFilter(int op, int type, const InputArray& kernel, Point anchor=Point(-1,-1)); //! returns "magic" border value for erosion and dilation. It is automatically transformed to Scalar::all(-DBL_MAX) for dilation. static inline Scalar morphologyDefaultBorderValue() { return Scalar::all(DBL_MAX); } //! returns morphological filter engine. Only MORPH_ERODE and MORPH_DILATE are supported. -CV_EXPORTS Ptr createMorphologyFilter(int op, int type, const Mat& kernel, +CV_EXPORTS Ptr createMorphologyFilter(int op, int type, const InputArray& kernel, Point anchor=Point(-1,-1), int _rowBorderType=BORDER_CONSTANT, int _columnBorderType=-1, const Scalar& _borderValue=morphologyDefaultBorderValue()); @@ -378,126 +378,127 @@ CV_EXPORTS_W Mat getStructuringElement(int shape, Size ksize, Point anchor=Point template<> CV_EXPORTS void Ptr::delete_obj(); //! copies 2D array to a larger destination array with extrapolation of the outer part of src using the specified border mode -CV_EXPORTS_W void copyMakeBorder( const Mat& src, CV_OUT Mat& dst, +CV_EXPORTS_W void copyMakeBorder( const InputArray& src, OutputArray dst, int top, int bottom, int left, int right, int borderType, const Scalar& value=Scalar() ); //! smooths the image using median filter. -CV_EXPORTS_W void medianBlur( const Mat& src, CV_OUT Mat& dst, int ksize ); +CV_EXPORTS_W void medianBlur( const InputArray& src, OutputArray dst, int ksize ); //! smooths the image using Gaussian filter. -CV_EXPORTS_AS(gaussianBlur) void GaussianBlur( const Mat& src, CV_OUT Mat& dst, Size ksize, - double sigma1, double sigma2=0, - int borderType=BORDER_DEFAULT ); +CV_EXPORTS_AS(gaussianBlur) void GaussianBlur( const InputArray& src, + OutputArray dst, Size ksize, + double sigma1, double sigma2=0, + int borderType=BORDER_DEFAULT ); //! smooths the image using bilateral filter -CV_EXPORTS_W void bilateralFilter( const Mat& src, CV_OUT Mat& dst, int d, - double sigmaColor, double sigmaSpace, - int borderType=BORDER_DEFAULT ); +CV_EXPORTS_W void bilateralFilter( const InputArray& src, OutputArray dst, int d, + double sigmaColor, double sigmaSpace, + int borderType=BORDER_DEFAULT ); //! smooths the image using the box filter. Each pixel is processed in O(1) time -CV_EXPORTS_W void boxFilter( const Mat& src, CV_OUT Mat& dst, int ddepth, - Size ksize, Point anchor=Point(-1,-1), - bool normalize=true, - int borderType=BORDER_DEFAULT ); +CV_EXPORTS_W void boxFilter( const InputArray& src, OutputArray dst, int ddepth, + Size ksize, Point anchor=Point(-1,-1), + bool normalize=true, + int borderType=BORDER_DEFAULT ); //! a synonym for normalized box filter -CV_EXPORTS_W void blur( const Mat& src, CV_OUT Mat& dst, +CV_EXPORTS_W void blur( const InputArray& src, OutputArray dst, Size ksize, Point anchor=Point(-1,-1), int borderType=BORDER_DEFAULT ); //! applies non-separable 2D linear filter to the image -CV_EXPORTS_W void filter2D( const Mat& src, CV_OUT Mat& dst, int ddepth, - const Mat& kernel, Point anchor=Point(-1,-1), - double delta=0, int borderType=BORDER_DEFAULT ); +CV_EXPORTS_W void filter2D( const InputArray& src, OutputArray dst, int ddepth, + const InputArray& kernel, Point anchor=Point(-1,-1), + double delta=0, int borderType=BORDER_DEFAULT ); //! applies separable 2D linear filter to the image -CV_EXPORTS_W void sepFilter2D( const Mat& src, CV_OUT Mat& dst, int ddepth, - const Mat& kernelX, const Mat& kernelY, - Point anchor=Point(-1,-1), - double delta=0, int borderType=BORDER_DEFAULT ); +CV_EXPORTS_W void sepFilter2D( const InputArray& src, OutputArray dst, int ddepth, + const InputArray& kernelX, const InputArray& kernelY, + Point anchor=Point(-1,-1), + double delta=0, int borderType=BORDER_DEFAULT ); //! applies generalized Sobel operator to the image -CV_EXPORTS_AS(sobel) void Sobel( const Mat& src, CV_OUT Mat& dst, int ddepth, - int dx, int dy, int ksize=3, - double scale=1, double delta=0, - int borderType=BORDER_DEFAULT ); +CV_EXPORTS_AS(sobel) void Sobel( const InputArray& src, OutputArray dst, int ddepth, + int dx, int dy, int ksize=3, + double scale=1, double delta=0, + int borderType=BORDER_DEFAULT ); //! applies the vertical or horizontal Scharr operator to the image -CV_EXPORTS_AS(scharr) void Scharr( const Mat& src, CV_OUT Mat& dst, int ddepth, - int dx, int dy, double scale=1, double delta=0, - int borderType=BORDER_DEFAULT ); +CV_EXPORTS_AS(scharr) void Scharr( const InputArray& src, OutputArray dst, int ddepth, + int dx, int dy, double scale=1, double delta=0, + int borderType=BORDER_DEFAULT ); //! applies Laplacian operator to the image -CV_EXPORTS_AS(laplacian) void Laplacian( const Mat& src, CV_OUT Mat& dst, int ddepth, - int ksize=1, double scale=1, double delta=0, - int borderType=BORDER_DEFAULT ); +CV_EXPORTS_AS(laplacian) void Laplacian( const InputArray& src, OutputArray dst, int ddepth, + int ksize=1, double scale=1, double delta=0, + int borderType=BORDER_DEFAULT ); //! applies Canny edge detector and produces the edge map. -CV_EXPORTS_AS(canny) void Canny( const Mat& image, CV_OUT Mat& edges, - double threshold1, double threshold2, - int apertureSize=3, bool L2gradient=false ); +CV_EXPORTS_AS(canny) void Canny( const InputArray& image, OutputArray edges, + double threshold1, double threshold2, + int apertureSize=3, bool L2gradient=false ); //! computes minimum eigen value of 2x2 derivative covariation matrix at each pixel - the cornerness criteria -CV_EXPORTS_W void cornerMinEigenVal( const Mat& src, CV_OUT Mat& dst, +CV_EXPORTS_W void cornerMinEigenVal( const InputArray& src, OutputArray dst, int blockSize, int ksize=3, int borderType=BORDER_DEFAULT ); //! computes Harris cornerness criteria at each image pixel -CV_EXPORTS_W void cornerHarris( const Mat& src, CV_OUT Mat& dst, int blockSize, - int ksize, double k, - int borderType=BORDER_DEFAULT ); +CV_EXPORTS_W void cornerHarris( const InputArray& src, OutputArray dst, int blockSize, + int ksize, double k, + int borderType=BORDER_DEFAULT ); //! computes both eigenvalues and the eigenvectors of 2x2 derivative covariation matrix at each pixel. The output is stored as 6-channel matrix. -CV_EXPORTS_W void cornerEigenValsAndVecs( const Mat& src, CV_OUT Mat& dst, - int blockSize, int ksize, - int borderType=BORDER_DEFAULT ); +CV_EXPORTS_W void cornerEigenValsAndVecs( const InputArray& src, OutputArray dst, + int blockSize, int ksize, + int borderType=BORDER_DEFAULT ); //! computes another complex cornerness criteria at each pixel -CV_EXPORTS_W void preCornerDetect( const Mat& src, CV_OUT Mat& dst, int ksize, - int borderType=BORDER_DEFAULT ); +CV_EXPORTS_W void preCornerDetect( const InputArray& src, OutputArray dst, int ksize, + int borderType=BORDER_DEFAULT ); //! adjusts the corner locations with sub-pixel accuracy to maximize the certain cornerness criteria -CV_EXPORTS void cornerSubPix( const Mat& image, vector& corners, +CV_EXPORTS void cornerSubPix( const InputArray& image, InputOutputArray corners, Size winSize, Size zeroZone, TermCriteria criteria ); //! finds the strong enough corners where the cornerMinEigenVal() or cornerHarris() report the local maxima -CV_EXPORTS_W void goodFeaturesToTrack( const Mat& image, CV_OUT vector& corners, +CV_EXPORTS_W void goodFeaturesToTrack( const InputArray& image, OutputArray corners, int maxCorners, double qualityLevel, double minDistance, - const Mat& mask=Mat(), int blockSize=3, + const InputArray& mask=InputArray(), int blockSize=3, bool useHarrisDetector=false, double k=0.04 ); //! finds lines in the black-n-white image using the standard or pyramid Hough transform -CV_EXPORTS_AS(houghLines) void HoughLines( const Mat& image, CV_OUT vector& lines, - double rho, double theta, int threshold, - double srn=0, double stn=0 ); +CV_EXPORTS_AS(houghLines) void HoughLines( const InputArray& image, OutputArray lines, + double rho, double theta, int threshold, + double srn=0, double stn=0 ); //! finds line segments in the black-n-white image using probabalistic Hough transform -CV_EXPORTS_AS(houghLinesP) void HoughLinesP( Mat& image, CV_OUT vector& lines, - double rho, double theta, int threshold, - double minLineLength=0, double maxLineGap=0 ); +CV_EXPORTS_AS(houghLinesP) void HoughLinesP( const InputArray& image, OutputArray lines, + double rho, double theta, int threshold, + double minLineLength=0, double maxLineGap=0 ); //! finds circles in the grayscale image using 2+1 gradient Hough transform -CV_EXPORTS_AS(houghCircles) void HoughCircles( const Mat& image, CV_OUT vector& circles, - int method, double dp, double minDist, - double param1=100, double param2=100, - int minRadius=0, int maxRadius=0 ); +CV_EXPORTS_AS(houghCircles) void HoughCircles( const InputArray& image, OutputArray circles, + int method, double dp, double minDist, + double param1=100, double param2=100, + int minRadius=0, int maxRadius=0 ); //! erodes the image (applies the local minimum operator) -CV_EXPORTS_W void erode( const Mat& src, CV_OUT Mat& dst, const Mat& kernel, - Point anchor=Point(-1,-1), int iterations=1, - int borderType=BORDER_CONSTANT, - const Scalar& borderValue=morphologyDefaultBorderValue() ); +CV_EXPORTS_W void erode( const InputArray& src, OutputArray dst, const InputArray& kernel, + Point anchor=Point(-1,-1), int iterations=1, + int borderType=BORDER_CONSTANT, + const Scalar& borderValue=morphologyDefaultBorderValue() ); //! dilates the image (applies the local maximum operator) -CV_EXPORTS_W void dilate( const Mat& src, CV_OUT Mat& dst, const Mat& kernel, - Point anchor=Point(-1,-1), int iterations=1, - int borderType=BORDER_CONSTANT, - const Scalar& borderValue=morphologyDefaultBorderValue() ); +CV_EXPORTS_W void dilate( const InputArray& src, OutputArray dst, const InputArray& kernel, + Point anchor=Point(-1,-1), int iterations=1, + int borderType=BORDER_CONSTANT, + const Scalar& borderValue=morphologyDefaultBorderValue() ); //! applies an advanced morphological operation to the image -CV_EXPORTS_W void morphologyEx( const Mat& src, CV_OUT Mat& dst, - int op, const Mat& kernel, - Point anchor=Point(-1,-1), int iterations=1, - int borderType=BORDER_CONSTANT, - const Scalar& borderValue=morphologyDefaultBorderValue() ); +CV_EXPORTS_W void morphologyEx( const InputArray& src, OutputArray dst, + int op, const InputArray& kernel, + Point anchor=Point(-1,-1), int iterations=1, + int borderType=BORDER_CONSTANT, + const Scalar& borderValue=morphologyDefaultBorderValue() ); //! interpolation algorithm enum @@ -512,37 +513,41 @@ enum }; //! resizes the image -CV_EXPORTS_W void resize( const Mat& src, CV_OUT Mat& dst, - Size dsize, double fx=0, double fy=0, - int interpolation=INTER_LINEAR ); +CV_EXPORTS_W void resize( const InputArray& src, OutputArray dst, + Size dsize, double fx=0, double fy=0, + int interpolation=INTER_LINEAR ); //! warps the image using affine transformation -CV_EXPORTS_W void warpAffine( const Mat& src, CV_OUT Mat& dst, - const Mat& M, Size dsize, - int flags=INTER_LINEAR, - int borderMode=BORDER_CONSTANT, - const Scalar& borderValue=Scalar()); +CV_EXPORTS_W void warpAffine( const InputArray& src, OutputArray dst, + const InputArray& M, Size dsize, + int flags=INTER_LINEAR, + int borderMode=BORDER_CONSTANT, + const Scalar& borderValue=Scalar()); //! warps the image using perspective transformation -CV_EXPORTS_W void warpPerspective( const Mat& src, CV_OUT Mat& dst, - const Mat& M, Size dsize, - int flags=INTER_LINEAR, - int borderMode=BORDER_CONSTANT, - const Scalar& borderValue=Scalar()); +CV_EXPORTS_W void warpPerspective( const InputArray& src, OutputArray dst, + const InputArray& M, Size dsize, + int flags=INTER_LINEAR, + int borderMode=BORDER_CONSTANT, + const Scalar& borderValue=Scalar()); -enum { INTER_BITS=5, INTER_BITS2=INTER_BITS*2, +enum +{ + INTER_BITS=5, INTER_BITS2=INTER_BITS*2, INTER_TAB_SIZE=(1<& dst, int maxlevel ); +CV_EXPORTS void buildPyramid( const InputArray& src, OutputArrayOfArrays dst, int maxlevel ); //! corrects lens distortion for the given camera matrix and distortion coefficients -CV_EXPORTS_W void undistort( const Mat& src, CV_OUT Mat& dst, const Mat& cameraMatrix, - const Mat& distCoeffs, const Mat& newCameraMatrix=Mat() ); +CV_EXPORTS_W void undistort( const InputArray& src, OutputArray dst, + const InputArray& cameraMatrix, + const InputArray& distCoeffs, + const InputArray& newCameraMatrix=InputArray() ); + //! initializes maps for cv::remap() to correct lens distortion and optionally rectify the image -CV_EXPORTS_W void initUndistortRectifyMap( const Mat& cameraMatrix, const Mat& distCoeffs, - const Mat& R, const Mat& newCameraMatrix, - Size size, int m1type, CV_OUT Mat& map1, CV_OUT Mat& map2 ); +CV_EXPORTS_W void initUndistortRectifyMap( const InputArray& cameraMatrix, const InputArray& distCoeffs, + const InputArray& R, const InputArray& newCameraMatrix, + Size size, int m1type, OutputArray map1, OutputArray map2 ); enum { @@ -614,42 +631,39 @@ enum }; //! initializes maps for cv::remap() for wide-angle -CV_EXPORTS_W float initWideAngleProjMap( const Mat& cameraMatrix, const Mat& distCoeffs, - Size imageSize, int destImageWidth, - int m1type, CV_OUT Mat& map1, CV_OUT Mat& map2, - int projType=PROJ_SPHERICAL_EQRECT, double alpha=0); +CV_EXPORTS_W float initWideAngleProjMap( const InputArray& cameraMatrix, const InputArray& distCoeffs, + Size imageSize, int destImageWidth, + int m1type, OutputArray map1, OutputArray map2, + int projType=PROJ_SPHERICAL_EQRECT, double alpha=0); //! returns the default new camera matrix (by default it is the same as cameraMatrix unless centerPricipalPoint=true) -CV_EXPORTS_W Mat getDefaultNewCameraMatrix( const Mat& cameraMatrix, Size imgsize=Size(), - bool centerPrincipalPoint=false ); -//! returns points' coordinates after lens distortion correction -CV_EXPORTS void undistortPoints( const Mat& src, CV_OUT vector& dst, - const Mat& cameraMatrix, const Mat& distCoeffs, - const Mat& R=Mat(), const Mat& P=Mat()); +CV_EXPORTS_W Mat getDefaultNewCameraMatrix( const InputArray& cameraMatrix, Size imgsize=Size(), + bool centerPrincipalPoint=false ); + //! returns points' coordinates after lens distortion correction -CV_EXPORTS_W void undistortPoints( const Mat& src, CV_OUT Mat& dst, - const Mat& cameraMatrix, const Mat& distCoeffs, - const Mat& R=Mat(), const Mat& P=Mat()); +CV_EXPORTS void undistortPoints( const InputArray& src, OutputArray dst, + const InputArray& cameraMatrix, const InputArray& distCoeffs, + const InputArray& R=InputArray(), const InputArray& P=InputArray()); template<> CV_EXPORTS void Ptr::delete_obj(); //! computes the joint dense histogram for a set of images. CV_EXPORTS void calcHist( const Mat* images, int nimages, - const int* channels, const Mat& mask, - Mat& hist, int dims, const int* histSize, + const int* channels, const InputArray& mask, + OutputArray hist, int dims, const int* histSize, const float** ranges, bool uniform=true, bool accumulate=false ); //! computes the joint sparse histogram for a set of images. CV_EXPORTS void calcHist( const Mat* images, int nimages, - const int* channels, const Mat& mask, + const int* channels, const InputArray& mask, SparseMat& hist, int dims, const int* histSize, const float** ranges, bool uniform=true, bool accumulate=false ); //! computes back projection for the set of images CV_EXPORTS void calcBackProject( const Mat* images, int nimages, - const int* channels, const Mat& hist, - Mat& backProject, const float** ranges, + const int* channels, const InputArray& hist, + OutputArray backProject, const float** ranges, double scale=1, bool uniform=true ); //! computes back projection for the set of images @@ -659,25 +673,26 @@ CV_EXPORTS void calcBackProject( const Mat* images, int nimages, double scale=1, bool uniform=true ); //! compares two histograms stored in dense arrays -CV_EXPORTS_W double compareHist( const Mat& H1, const Mat& H2, int method ); +CV_EXPORTS_W double compareHist( const InputArray& H1, const InputArray& H2, int method ); //! compares two histograms stored in sparse arrays CV_EXPORTS double compareHist( const SparseMat& H1, const SparseMat& H2, int method ); //! normalizes the grayscale image brightness and contrast by normalizing its histogram -CV_EXPORTS_W void equalizeHist( const Mat& src, CV_OUT Mat& dst ); +CV_EXPORTS_W void equalizeHist( const InputArray& src, OutputArray dst ); -CV_EXPORTS float EMD( const Mat& signature1, const Mat& signature2, - int distType, const Mat& cost=Mat(), - float* lowerBound=0, Mat* flow=0 ); +CV_EXPORTS float EMD( const InputArray& signature1, const InputArray& signature2, + int distType, const InputArray& cost=InputArray(), + float* lowerBound=0, OutputArray flow=OutputArray() ); //! segments the image using watershed algorithm -CV_EXPORTS_W void watershed( const Mat& image, Mat& markers ); +CV_EXPORTS_W void watershed( const InputArray& image, InputOutputArray markers ); //! filters image using meanshift algorithm -CV_EXPORTS_W void pyrMeanShiftFiltering( const Mat& src, CV_OUT Mat& dst, - double sp, double sr, int maxLevel=1, - TermCriteria termcrit=TermCriteria(TermCriteria::MAX_ITER+TermCriteria::EPS,5,1) ); +CV_EXPORTS_W void pyrMeanShiftFiltering( const InputArray& src, OutputArray dst, + double sp, double sr, int maxLevel=1, + TermCriteria termcrit=TermCriteria( + TermCriteria::MAX_ITER+TermCriteria::EPS,5,1) ); //! class of the pixel in GrabCut algorithm enum @@ -697,9 +712,9 @@ enum }; //! segments the image using GrabCut algorithm -CV_EXPORTS_W void grabCut( const Mat& img, Mat& mask, Rect rect, - Mat& bgdModel, Mat& fgdModel, - int iterCount, int mode = GC_EVAL ); +CV_EXPORTS_W void grabCut( const InputArray& img, InputOutputArray mask, Rect rect, + InputOutputArray bgdModel, InputOutputArray fgdModel, + int iterCount, int mode = GC_EVAL ); //! the inpainting algorithm enum @@ -709,35 +724,33 @@ enum }; //! restores the damaged image areas using one of the available intpainting algorithms -CV_EXPORTS_W void inpaint( const Mat& src, const Mat& inpaintMask, - CV_OUT Mat& dst, double inpaintRange, int flags ); +CV_EXPORTS_W void inpaint( const InputArray& src, const InputArray& inpaintMask, + OutputArray dst, double inpaintRange, int flags ); //! builds the discrete Voronoi diagram -CV_EXPORTS_AS(distanceTransformWithLabels) - void distanceTransform( const Mat& src, CV_OUT Mat& dst, Mat& labels, - int distanceType, int maskSize ); +CV_EXPORTS_W void distanceTransform( const InputArray& src, OutputArray dst, + OutputArray labels, int distanceType, int maskSize ); //! computes the distance transform map -CV_EXPORTS_W void distanceTransform( const Mat& src, CV_OUT Mat& dst, +CV_EXPORTS void distanceTransform( const InputArray& src, OutputArray dst, int distanceType, int maskSize ); -enum { FLOODFILL_FIXED_RANGE = 1 << 16, - FLOODFILL_MASK_ONLY = 1 << 17 }; +enum { FLOODFILL_FIXED_RANGE = 1 << 16, FLOODFILL_MASK_ONLY = 1 << 17 }; //! fills the semi-uniform image region starting from the specified seed point -CV_EXPORTS_W int floodFill( Mat& image, +CV_EXPORTS int floodFill( InputOutputArray image, Point seedPoint, Scalar newVal, CV_OUT Rect* rect=0, Scalar loDiff=Scalar(), Scalar upDiff=Scalar(), int flags=4 ); //! fills the semi-uniform image region and/or the mask starting from the specified seed point -CV_EXPORTS_AS(floodFillMask) int floodFill( Mat& image, Mat& mask, - Point seedPoint, Scalar newVal, CV_OUT Rect* rect=0, - Scalar loDiff=Scalar(), Scalar upDiff=Scalar(), - int flags=4 ); +CV_EXPORTS_W int floodFill( InputOutputArray image, InputOutputArray mask, + Point seedPoint, Scalar newVal, CV_OUT Rect* rect=0, + Scalar loDiff=Scalar(), Scalar upDiff=Scalar(), + int flags=4 ); //! converts image from one color space to another -CV_EXPORTS_W void cvtColor( const Mat& src, CV_OUT Mat& dst, int code, int dstCn=0 ); +CV_EXPORTS_W void cvtColor( const InputArray& src, OutputArray dst, int code, int dstCn=0 ); //! raster image moments class CV_EXPORTS_W_MAP Moments @@ -762,7 +775,7 @@ public: }; //! computes moments of the rasterized shape or a vector of points -CV_EXPORTS_W Moments moments( const Mat& array, bool binaryImage=false ); +CV_EXPORTS_W Moments moments( const InputArray& array, bool binaryImage=false ); //! computes 7 Hu invariants from the moments CV_EXPORTS void HuMoments( const Moments& moments, double hu[7] ); @@ -771,7 +784,8 @@ CV_EXPORTS void HuMoments( const Moments& moments, double hu[7] ); enum { TM_SQDIFF=0, TM_SQDIFF_NORMED=1, TM_CCORR=2, TM_CCORR_NORMED=3, TM_CCOEFF=4, TM_CCOEFF_NORMED=5 }; //! computes the proximity map for the raster template and the image where the template is searched for -CV_EXPORTS_W void matchTemplate( const Mat& image, const Mat& templ, CV_OUT Mat& result, int method ); +CV_EXPORTS_W void matchTemplate( const InputArray& image, const InputArray& templ, + OutputArray result, int method ); //! mode of the contour retrieval algorithm enum @@ -786,80 +800,64 @@ enum enum { CHAIN_APPROX_NONE=CV_CHAIN_APPROX_NONE, - CHAIN_APPROX_SIMPLE=CV_CHAIN_APPROX_SIMPLE, - CHAIN_APPROX_TC89_L1=CV_CHAIN_APPROX_TC89_L1, - CHAIN_APPROX_TC89_KCOS=CV_CHAIN_APPROX_TC89_KCOS + CHAIN_APPROX_SIMPLE=CV_CHAIN_APPROX_SIMPLE, + CHAIN_APPROX_TC89_L1=CV_CHAIN_APPROX_TC89_L1, + CHAIN_APPROX_TC89_KCOS=CV_CHAIN_APPROX_TC89_KCOS }; //! retrieves contours and the hierarchical information from black-n-white image. -CV_EXPORTS void findContours( Mat& image, CV_OUT vector >& contours, - vector& hierarchy, int mode, +CV_EXPORTS void findContours( InputOutputArray image, OutputArrayOfArrays contours, + OutputArray hierarchy, int mode, int method, Point offset=Point()); //! retrieves contours from black-n-white image. -CV_EXPORTS void findContours( Mat& image, CV_OUT vector >& contours, +CV_EXPORTS void findContours( InputOutputArray image, OutputArrayOfArrays contours, int mode, int method, Point offset=Point()); //! draws contours in the image -CV_EXPORTS void drawContours( Mat& image, const vector >& contours, +CV_EXPORTS void drawContours( InputOutputArray image, const InputArrayOfArrays& contours, int contourIdx, const Scalar& color, int thickness=1, int lineType=8, - const vector& hierarchy=vector(), + const InputArray& hierarchy=InputArray(), int maxLevel=INT_MAX, Point offset=Point() ); //! approximates contour or a curve using Douglas-Peucker algorithm -CV_EXPORTS void approxPolyDP( const Mat& curve, - CV_OUT vector& approxCurve, - double epsilon, bool closed ); -//! approximates contour or a curve using Douglas-Peucker algorithm -CV_EXPORTS void approxPolyDP( const Mat& curve, - CV_OUT vector& approxCurve, +CV_EXPORTS void approxPolyDP( const InputArray& curve, + OutputArray approxCurve, double epsilon, bool closed ); + //! computes the contour perimeter (closed=true) or a curve length -CV_EXPORTS_W double arcLength( const Mat& curve, bool closed ); +CV_EXPORTS_W double arcLength( const InputArray& curve, bool closed ); //! computes the bounding rectangle for a contour -CV_EXPORTS_W Rect boundingRect( const Mat& points ); +CV_EXPORTS_W Rect boundingRect( const InputArray& points ); //! computes the contour area -CV_EXPORTS_W double contourArea( const Mat& contour, bool oriented=false ); +CV_EXPORTS_W double contourArea( const InputArray& contour, bool oriented=false ); //! computes the minimal rotated rectangle for a set of points -CV_EXPORTS_W RotatedRect minAreaRect( const Mat& points ); +CV_EXPORTS_W RotatedRect minAreaRect( const InputArray& points ); //! computes the minimal enclosing circle for a set of points -CV_EXPORTS_W void minEnclosingCircle( const Mat& points, - Point2f& center, float& radius ); +CV_EXPORTS_W void minEnclosingCircle( const InputArray& points, + Point2f& center, float& radius ); //! matches two contours using one of the available algorithms -CV_EXPORTS_W double matchShapes( const Mat& contour1, - const Mat& contour2, - int method, double parameter ); -//! computes convex hull for a set of 2D points. -CV_EXPORTS void convexHull( const Mat& points, CV_OUT vector& hull, bool clockwise=false ); -//! computes convex hull for a set of 2D points. -CV_EXPORTS void convexHull( const Mat& points, CV_OUT vector& hull, bool clockwise=false ); +CV_EXPORTS_W double matchShapes( const InputArray& contour1, const InputArray& contour2, + int method, double parameter ); //! computes convex hull for a set of 2D points. -CV_EXPORTS void convexHull( const Mat& points, CV_OUT vector& hull, bool clockwise=false ); +CV_EXPORTS void convexHull( const InputArray& points, OutputArray hull, + bool clockwise=false, bool returnPoints=true ); //! returns true iff the contour is convex. Does not support contours with self-intersection -CV_EXPORTS_W bool isContourConvex( const Mat& contour ); +CV_EXPORTS_W bool isContourConvex( const InputArray& contour ); //! fits ellipse to the set of 2D points -CV_EXPORTS_W RotatedRect fitEllipse( const Mat& points ); +CV_EXPORTS_W RotatedRect fitEllipse( const InputArray& points ); //! fits line to the set of 2D points using M-estimator algorithm -CV_EXPORTS void fitLine( const Mat& points, CV_OUT Vec4f& line, int distType, - double param, double reps, double aeps ); -//! fits line to the set of 3D points using M-estimator algorithm -CV_EXPORTS void fitLine( const Mat& points, CV_OUT Vec6f& line, int distType, - double param, double reps, double aeps ); +CV_EXPORTS void fitLine( const InputArray& points, OutputArray line, int distType, + double param, double reps, double aeps ); //! checks if the point is inside the contour. Optionally computes the signed distance from the point to the contour boundary -CV_EXPORTS_W double pointPolygonTest( const Mat& contour, - Point2f pt, bool measureDist ); - -//! estimates the best-fit affine transformation that maps one 2D point set to another or one image to another. -CV_EXPORTS_W Mat estimateRigidTransform( const Mat& A, const Mat& B, - bool fullAffine ); - +CV_EXPORTS_W double pointPolygonTest( const InputArray& contour, Point2f pt, bool measureDist ); + } - // 2009-01-12, Xavier Delacour struct lsh_hash { diff --git a/modules/imgproc/src/accum.cpp b/modules/imgproc/src/accum.cpp index f19314b5e2..243a476037 100644 --- a/modules/imgproc/src/accum.cpp +++ b/modules/imgproc/src/accum.cpp @@ -45,555 +45,406 @@ namespace cv { -inline float sqr(uchar a) { return CV_8TO32F_SQR(a); } -inline float sqr(float a) { return a*a; } - -inline double sqr(double a) { return a*a; } - -inline Vec3f sqr(const Vec3b& a) -{ - return Vec3f(CV_8TO32F_SQR(a[0]), CV_8TO32F_SQR(a[1]), CV_8TO32F_SQR(a[2])); -} -inline Vec3f sqr(const Vec3f& a) -{ - return Vec3f(a[0]*a[0], a[1]*a[1], a[2]*a[2]); -} -inline Vec3d sqr(const Vec3d& a) -{ - return Vec3d(a[0]*a[0], a[1]*a[1], a[2]*a[2]); -} -inline float multiply(uchar a, uchar b) { return CV_8TO32F(a)*CV_8TO32F(b); } -inline float multiply(float a, float b) { return a*b; } -inline double multiply(double a, double b) { return a*b; } -inline Vec3f multiply(const Vec3b& a, const Vec3b& b) -{ - return Vec3f( - CV_8TO32F(a[0])*CV_8TO32F(b[0]), - CV_8TO32F(a[1])*CV_8TO32F(b[1]), - CV_8TO32F(a[2])*CV_8TO32F(b[2])); -} -inline Vec3f multiply(const Vec3f& a, const Vec3f& b) -{ - return Vec3f(a[0]*b[0], a[1]*b[1], a[2]*b[2]); -} -inline Vec3d multiply(const Vec3d& a, const Vec3d& b) -{ - return Vec3d(a[0]*b[0], a[1]*b[1], a[2]*b[2]); -} - -inline float addw(uchar a, float alpha, float b, float beta) -{ - return b*beta + CV_8TO32F(a)*alpha; -} -inline float addw(float a, float alpha, float b, float beta) -{ - return b*beta + a*alpha; -} -inline double addw(uchar a, double alpha, double b, double beta) -{ - return b*beta + CV_8TO32F(a)*alpha; -} -inline double addw(float a, double alpha, double b, double beta) -{ - return b*beta + a*alpha; -} -inline double addw(double a, double alpha, double b, double beta) -{ - return b*beta + a*alpha; -} - -inline Vec3f addw(const Vec3b& a, float alpha, const Vec3f& b, float beta) -{ - return Vec3f(b[0]*beta + CV_8TO32F(a[0])*alpha, - b[1]*beta + CV_8TO32F(a[1])*alpha, - b[2]*beta + CV_8TO32F(a[2])*alpha); -} -inline Vec3f addw(const Vec3f& a, float alpha, const Vec3f& b, float beta) -{ - return Vec3f(b[0]*beta + a[0]*alpha, b[1]*beta + a[1]*alpha, b[2]*beta + a[2]*alpha); -} -inline Vec3d addw(const Vec3b& a, double alpha, const Vec3d& b, double beta) -{ - return Vec3d(b[0]*beta + CV_8TO32F(a[0])*alpha, - b[1]*beta + CV_8TO32F(a[1])*alpha, - b[2]*beta + CV_8TO32F(a[2])*alpha); -} -inline Vec3d addw(const Vec3f& a, double alpha, const Vec3d& b, double beta) -{ - return Vec3d(b[0]*beta + a[0]*alpha, b[1]*beta + a[1]*alpha, b[2]*beta + a[2]*alpha); -} -inline Vec3d addw(const Vec3d& a, double alpha, const Vec3d& b, double beta) -{ - return Vec3d(b[0]*beta + a[0]*alpha, b[1]*beta + a[1]*alpha, b[2]*beta + a[2]*alpha); -} - template void -acc_( const Mat& _src, Mat& _dst ) +acc_( const T* src, AT* dst, const uchar* mask, int len, int cn ) { - Size size = _src.size(); - size.width *= _src.channels(); - - if( _src.isContinuous() && _dst.isContinuous() ) - { - size.width *= size.height; - size.height = 1; - } - - int i, j; - for( i = 0; i < size.height; i++ ) + int i = 0; + + if( !mask ) { - const T* src = (const T*)(_src.data + _src.step*i); - AT* dst = (AT*)(_dst.data + _dst.step*i); - - for( j = 0; j <= size.width - 4; j += 4 ) + len *= cn; + for( ; i <= len - 4; i += 4 ) { - AT t0 = dst[j] + src[j], t1 = dst[j+1] + src[j+1]; - dst[j] = t0; dst[j+1] = t1; - t0 = dst[j+2] + src[j+2]; t1 = dst[j+3] + src[j+3]; - dst[j+2] = t0; dst[j+3] = t1; + AT t0, t1; + t0 = src[i] + dst[i]; + t1 = src[i+1] + dst[i+1]; + dst[i] = t0; dst[i+1] = t1; + + t0 = src[i+2] + dst[i+2]; + t1 = src[i+3] + dst[i+3]; + dst[i+2] = t0; dst[i+3] = t1; } - - for( ; j < size.width; j++ ) - dst[j] += src[j]; + + for( ; i < len; i++ ) + dst[i] += src[i]; } -} - - -template void -accSqr_( const Mat& _src, Mat& _dst ) -{ - Size size = _src.size(); - size.width *= _src.channels(); - - if( _src.isContinuous() && _dst.isContinuous() ) + else if( cn == 1 ) { - size.width *= size.height; - size.height = 1; + for( ; i < len; i++ ) + { + if( mask[i] ) + dst[i] += src[i]; + } } - - int i, j; - for( i = 0; i < size.height; i++ ) + else if( cn == 3 ) { - const T* src = (const T*)(_src.data + _src.step*i); - AT* dst = (AT*)(_dst.data + _dst.step*i); - - for( j = 0; j <= size.width - 4; j += 4 ) + for( ; i < len; i++, src += 3, dst += 3 ) { - AT t0 = dst[j] + sqr(src[j]), t1 = dst[j+1] + sqr(src[j+1]); - dst[j] = t0; dst[j+1] = t1; - t0 = dst[j+2] + sqr(src[j+2]); t1 = dst[j+3] + sqr(src[j+3]); - dst[j+2] = t0; dst[j+3] = t1; + if( mask[i] ) + { + AT t0 = src[0] + dst[0]; + AT t1 = src[1] + dst[1]; + AT t2 = src[2] + dst[2]; + + dst[0] = t0; dst[1] = t1; dst[2] = t2; + } } - - for( ; j < size.width; j++ ) - dst[j] += sqr(src[j]); + } + else + { + for( ; i < len; i++, src += cn, dst += cn ) + if( mask[i] ) + { + for( int k = 0; k < cn; k++ ) + dst[k] += src[k]; + } } } - + template void -accProd_( const Mat& _src1, const Mat& _src2, Mat& _dst ) +accSqr_( const T* src, AT* dst, const uchar* mask, int len, int cn ) { - Size size = _src1.size(); - size.width *= _src1.channels(); - - if( _src1.isContinuous() && _src2.isContinuous() && _dst.isContinuous() ) - { - size.width *= size.height; - size.height = 1; - } - - int i, j; - for( i = 0; i < size.height; i++ ) + int i = 0; + + if( !mask ) { - const T* src1 = (const T*)(_src1.data + _src1.step*i); - const T* src2 = (const T*)(_src2.data + _src2.step*i); - AT* dst = (AT*)(_dst.data + _dst.step*i); - - for( j = 0; j <= size.width - 4; j += 4 ) + len *= cn; + for( ; i <= len - 4; i += 4 ) { AT t0, t1; - t0 = dst[j] + multiply(src1[j], src2[j]); - t1 = dst[j+1] + multiply(src1[j+1], src2[j+1]); - dst[j] = t0; dst[j+1] = t1; - t0 = dst[j+2] + multiply(src1[j+2], src2[j+2]); - t1 = dst[j+3] + multiply(src1[j+3], src2[j+3]); - dst[j+2] = t0; dst[j+3] = t1; + t0 = (AT)src[i]*src[i] + dst[i]; + t1 = (AT)src[i+1]*src[i+1] + dst[i+1]; + dst[i] = t0; dst[i+1] = t1; + + t0 = (AT)src[i+2]*src[i+2] + dst[i+2]; + t1 = (AT)src[i+3]*src[i+3] + dst[i+3]; + dst[i+2] = t0; dst[i+3] = t1; } - - for( ; j < size.width; j++ ) - dst[j] += multiply(src1[j], src2[j]); - } -} - - -template void -accW_( const Mat& _src, Mat& _dst, double _alpha ) -{ - AT alpha = (AT)_alpha, beta = (AT)(1 - _alpha); - Size size = _src.size(); - size.width *= _src.channels(); - - if( _src.isContinuous() && _dst.isContinuous() ) - { - size.width *= size.height; - size.height = 1; + + for( ; i < len; i++ ) + dst[i] += (AT)src[i]*src[i]; } - - int i, j; - for( i = 0; i < size.height; i++ ) + else if( cn == 1 ) { - const T* src = (const T*)(_src.data + _src.step*i); - AT* dst = (AT*)(_dst.data + _dst.step*i); - - for( j = 0; j <= size.width - 4; j += 4 ) + for( ; i < len; i++ ) { - AT t0, t1; - t0 = addw(src[j], alpha, dst[j], beta); - t1 = addw(src[j+1], alpha, dst[j+1], beta); - dst[j] = t0; dst[j+1] = t1; - t0 = addw(src[j+2], alpha, dst[j+2], beta); - t1 = addw(src[j+3], alpha, dst[j+3], beta); - dst[j+2] = t0; dst[j+3] = t1; + if( mask[i] ) + dst[i] += (AT)src[i]*src[i]; } - - for( ; j < size.width; j++ ) - dst[j] = addw(src[j], alpha, dst[j], beta); } -} - - -template void -accMask_( const Mat& _src, Mat& _dst, const Mat& _mask ) -{ - Size size = _src.size(); - - if( _src.isContinuous() && _dst.isContinuous() && _mask.isContinuous() ) + else if( cn == 3 ) { - size.width *= size.height; - size.height = 1; + for( ; i < len; i++, src += 3, dst += 3 ) + { + if( mask[i] ) + { + AT t0 = (AT)src[0]*src[0] + dst[0]; + AT t1 = (AT)src[1]*src[1] + dst[1]; + AT t2 = (AT)src[2]*src[2] + dst[2]; + + dst[0] = t0; dst[1] = t1; dst[2] = t2; + } + } } - - int i, j; - for( i = 0; i < size.height; i++ ) + else { - const T* src = (const T*)(_src.data + _src.step*i); - AT* dst = (AT*)(_dst.data + _dst.step*i); - const uchar* mask = _mask.data + _mask.step*i; - - for( j = 0; j < size.width; j++ ) - if( mask[j] ) - dst[j] += src[j]; + for( ; i < len; i++, src += cn, dst += cn ) + if( mask[i] ) + { + for( int k = 0; k < cn; k++ ) + dst[k] += (AT)src[k]*src[k]; + } } } - - + + template void -accSqrMask_( const Mat& _src, Mat& _dst, const Mat& _mask ) +accProd_( const T* src1, const T* src2, AT* dst, const uchar* mask, int len, int cn ) { - Size size = _src.size(); - - if( _src.isContinuous() && _dst.isContinuous() && _mask.isContinuous() ) + int i = 0; + + if( !mask ) { - size.width *= size.height; - size.height = 1; + len *= cn; + for( ; i <= len - 4; i += 4 ) + { + AT t0, t1; + t0 = (AT)src1[i]*src2[i] + dst[i]; + t1 = (AT)src1[i+1]*src2[i+1] + dst[i+1]; + dst[i] = t0; dst[i+1] = t1; + + t0 = (AT)src1[i+2]*src2[i+2] + dst[i+2]; + t1 = (AT)src1[i+3]*src2[i+3] + dst[i+3]; + dst[i+2] = t0; dst[i+3] = t1; + } + + for( ; i < len; i++ ) + dst[i] += (AT)src1[i]*src2[i]; } - - int i, j; - for( i = 0; i < size.height; i++ ) + else if( cn == 1 ) { - const T* src = (const T*)(_src.data + _src.step*i); - AT* dst = (AT*)(_dst.data + _dst.step*i); - const uchar* mask = _mask.data + _mask.step*i; - - for( j = 0; j < size.width; j++ ) - if( mask[j] ) - dst[j] += sqr(src[j]); + for( ; i < len; i++ ) + { + if( mask[i] ) + dst[i] += (AT)src1[i]*src2[i]; + } } -} - - -template void -accProdMask_( const Mat& _src1, const Mat& _src2, Mat& _dst, const Mat& _mask ) -{ - Size size = _src1.size(); - - if( _src1.isContinuous() && _src2.isContinuous() && - _dst.isContinuous() && _mask.isContinuous() ) + else if( cn == 3 ) { - size.width *= size.height; - size.height = 1; + for( ; i < len; i++, src1 += 3, src2 += 3, dst += 3 ) + { + if( mask[i] ) + { + AT t0 = (AT)src1[0]*src2[0] + dst[0]; + AT t1 = (AT)src1[1]*src2[1] + dst[1]; + AT t2 = (AT)src1[2]*src2[2] + dst[2]; + + dst[0] = t0; dst[1] = t1; dst[2] = t2; + } + } } - - int i, j; - for( i = 0; i < size.height; i++ ) + else { - const T* src1 = (const T*)(_src1.data + _src1.step*i); - const T* src2 = (const T*)(_src2.data + _src2.step*i); - AT* dst = (AT*)(_dst.data + _dst.step*i); - const uchar* mask = _mask.data + _mask.step*i; - - for( j = 0; j < size.width; j++ ) - if( mask[j] ) - dst[j] += multiply(src1[j], src2[j]); + for( ; i < len; i++, src1 += cn, src2 += cn, dst += cn ) + if( mask[i] ) + { + for( int k = 0; k < cn; k++ ) + dst[k] += (AT)src1[k]*src2[k]; + } } } - + template void -accWMask_( const Mat& _src, Mat& _dst, double _alpha, const Mat& _mask ) +accW_( const T* src, AT* dst, const uchar* mask, int len, int cn, double alpha ) { - typedef typename DataType::channel_type AT1; - AT1 alpha = (AT1)_alpha, beta = (AT1)(1 - _alpha); - Size size = _src.size(); - - if( _src.isContinuous() && _dst.isContinuous() && _mask.isContinuous() ) + AT a = (AT)alpha, b = 1 - a; + int i = 0; + + if( !mask ) { - size.width *= size.height; - size.height = 1; + len *= cn; + for( ; i <= len - 4; i += 4 ) + { + AT t0, t1; + t0 = src[i]*a + dst[i]*b; + t1 = src[i+1]*a + dst[i+1]*b; + dst[i] = t0; dst[i+1] = t1; + + t0 = src[i+2]*a + dst[i+2]*b; + t1 = src[i+3]*a + dst[i+3]*b; + dst[i+2] = t0; dst[i+3] = t1; + } + + for( ; i < len; i++ ) + dst[i] = src[i]*a + dst[i]*b; } - - int i, j; - for( i = 0; i < size.height; i++ ) + else if( cn == 1 ) { - const T* src = (const T*)(_src.data + _src.step*i); - AT* dst = (AT*)(_dst.data + _dst.step*i); - const uchar* mask = _mask.data + _mask.step*i; - - for( j = 0; j < size.width; j++ ) - if( mask[j] ) - dst[j] = addw(src[j], alpha, dst[j], beta); + for( ; i < len; i++ ) + { + if( mask[i] ) + dst[i] = src[i]*a + dst[i]*b; + } } -} - - -typedef void (*AccFunc)(const Mat&, Mat&); -typedef void (*AccMaskFunc)(const Mat&, Mat&, const Mat&); -typedef void (*AccProdFunc)(const Mat&, const Mat&, Mat&); -typedef void (*AccProdMaskFunc)(const Mat&, const Mat&, Mat&, const Mat&); -typedef void (*AccWFunc)(const Mat&, Mat&, double); -typedef void (*AccWMaskFunc)(const Mat&, Mat&, double, const Mat&); - -void accumulate( const Mat& src, Mat& dst, const Mat& mask ) -{ - CV_Assert( dst.size() == src.size() && dst.channels() == src.channels() ); - - if( !mask.data ) + else if( cn == 3 ) { - AccFunc func = 0; - if( src.depth() == CV_8U && dst.depth() == CV_32F ) - func = acc_; - else if( src.depth() == CV_8U && dst.depth() == CV_64F ) - func = acc_; - else if( src.depth() == CV_32F && dst.depth() == CV_32F ) - func = acc_; - else if( src.depth() == CV_32F && dst.depth() == CV_64F ) - func = acc_; - else if( src.depth() == CV_64F && dst.depth() == CV_64F ) - func = acc_; - else - CV_Error( CV_StsUnsupportedFormat, "" ); - - func( src, dst ); + for( ; i < len; i++, src += 3, dst += 3 ) + { + if( mask[i] ) + { + AT t0 = src[0]*a + dst[0]*b; + AT t1 = src[1]*a + dst[1]*b; + AT t2 = src[2]*a + dst[2]*b; + + dst[0] = t0; dst[1] = t1; dst[2] = t2; + } + } } else { - CV_Assert( mask.size() == src.size() && mask.type() == CV_8UC1 ); - - AccMaskFunc func = 0; - if( src.type() == CV_8UC1 && dst.type() == CV_32FC1 ) - func = accMask_; - else if( src.type() == CV_8UC3 && dst.type() == CV_32FC3 ) - func = accMask_; - else if( src.type() == CV_8UC1 && dst.type() == CV_64FC1 ) - func = accMask_; - else if( src.type() == CV_8UC3 && dst.type() == CV_64FC3 ) - func = accMask_; - else if( src.type() == CV_32FC1 && dst.type() == CV_32FC1 ) - func = accMask_; - else if( src.type() == CV_32FC3 && dst.type() == CV_32FC3 ) - func = accMask_; - else if( src.type() == CV_32FC1 && dst.type() == CV_64FC1 ) - func = accMask_; - else if( src.type() == CV_32FC3 && dst.type() == CV_64FC3 ) - func = accMask_; - else if( src.type() == CV_64FC1 && dst.type() == CV_64FC1 ) - func = accMask_; - else if( src.type() == CV_64FC3 && dst.type() == CV_64FC3 ) - func = accMask_; - else - CV_Error( CV_StsUnsupportedFormat, "" ); - - func( src, dst, mask ); + for( ; i < len; i++, src += cn, dst += cn ) + if( mask[i] ) + { + for( int k = 0; k < cn; k++ ) + dst[k] += src[k]*a + dst[k]*b; + } } } -void accumulateSquare( const Mat& src, Mat& dst, const Mat& mask ) +#define DEF_ACC_FUNCS(suffix, type, acctype) \ +static void acc_##suffix(const type* src, acctype* dst, \ + const uchar* mask, int len, int cn) \ +{ acc_(src, dst, mask, len, cn); } \ +\ +static void accSqr_##suffix(const type* src, acctype* dst, \ + const uchar* mask, int len, int cn) \ +{ accSqr_(src, dst, mask, len, cn); } \ +\ +static void accProd_##suffix(const type* src1, const type* src2, \ + acctype* dst, const uchar* mask, int len, int cn) \ +{ accProd_(src1, src2, dst, mask, len, cn); } \ +\ +static void accW_##suffix(const type* src, acctype* dst, \ + const uchar* mask, int len, int cn, double alpha) \ +{ accW_(src, dst, mask, len, cn, alpha); } + + +DEF_ACC_FUNCS(8u32f, uchar, float) +DEF_ACC_FUNCS(8u64f, uchar, double) +DEF_ACC_FUNCS(16u32f, ushort, float) +DEF_ACC_FUNCS(16u64f, ushort, double) +DEF_ACC_FUNCS(32f, float, float) +DEF_ACC_FUNCS(32f64f, float, double) +DEF_ACC_FUNCS(64f, double, double) + + +typedef void (*AccFunc)(const uchar*, uchar*, const uchar*, int, int); +typedef void (*AccProdFunc)(const uchar*, const uchar*, uchar*, const uchar*, int, int); +typedef void (*AccWFunc)(const uchar*, uchar*, const uchar*, int, int, double); + +static AccFunc accTab[] = +{ + (AccFunc)acc_8u32f, (AccFunc)acc_8u64f, + (AccFunc)acc_16u32f, (AccFunc)acc_16u64f, + (AccFunc)acc_32f, (AccFunc)acc_32f64f, + (AccFunc)acc_64f +}; + +static AccFunc accSqrTab[] = +{ + (AccFunc)accSqr_8u32f, (AccFunc)accSqr_8u64f, + (AccFunc)accSqr_16u32f, (AccFunc)accSqr_16u64f, + (AccFunc)accSqr_32f, (AccFunc)accSqr_32f64f, + (AccFunc)accSqr_64f +}; + +static AccProdFunc accProdTab[] = +{ + (AccProdFunc)accProd_8u32f, (AccProdFunc)accProd_8u64f, + (AccProdFunc)accProd_16u32f, (AccProdFunc)accProd_16u64f, + (AccProdFunc)accProd_32f, (AccProdFunc)accProd_32f64f, + (AccProdFunc)accProd_64f +}; + +static AccWFunc accWTab[] = +{ + (AccWFunc)accW_8u32f, (AccWFunc)accW_8u64f, + (AccWFunc)accW_16u32f, (AccWFunc)accW_16u64f, + (AccWFunc)accW_32f, (AccWFunc)accW_32f64f, + (AccWFunc)accW_64f +}; + +inline int getAccTabIdx(int sdepth, int ddepth) +{ + return sdepth == CV_8U && ddepth == CV_32F ? 0 : + sdepth == CV_8U && ddepth == CV_64F ? 1 : + sdepth == CV_16U && ddepth == CV_32F ? 2 : + sdepth == CV_16U && ddepth == CV_64F ? 3 : + sdepth == CV_32F && ddepth == CV_32F ? 4 : + sdepth == CV_32F && ddepth == CV_64F ? 5 : + sdepth == CV_64F && ddepth == CV_64F ? 6 : -1; +} + +} + +void cv::accumulate( const InputArray& _src, InputOutputArray _dst, const InputArray& _mask ) { - CV_Assert( dst.size() == src.size() && dst.channels() == src.channels() ); + Mat src = _src.getMat(), dst = _dst.getMat(), mask = _mask.getMat(); + int sdepth = src.depth(), ddepth = dst.depth(), cn = src.channels(); - if( !mask.data ) - { - AccFunc func = 0; - if( src.depth() == CV_8U && dst.depth() == CV_32F ) - func = accSqr_; - else if( src.depth() == CV_8U && dst.depth() == CV_64F ) - func = accSqr_; - else if( src.depth() == CV_32F && dst.depth() == CV_32F ) - func = accSqr_; - else if( src.depth() == CV_32F && dst.depth() == CV_64F ) - func = accSqr_; - else if( src.depth() == CV_64F && dst.depth() == CV_64F ) - func = accSqr_; - else - CV_Error( CV_StsUnsupportedFormat, "" ); - - func( src, dst ); - } - else - { - CV_Assert( mask.size() == src.size() && mask.type() == CV_8UC1 ); - - AccMaskFunc func = 0; - if( src.type() == CV_8UC1 && dst.type() == CV_32FC1 ) - func = accSqrMask_; - else if( src.type() == CV_8UC3 && dst.type() == CV_32FC3 ) - func = accSqrMask_; - else if( src.type() == CV_8UC1 && dst.type() == CV_64FC1 ) - func = accSqrMask_; - else if( src.type() == CV_8UC3 && dst.type() == CV_64FC3 ) - func = accSqrMask_; - else if( src.type() == CV_32FC1 && dst.type() == CV_32FC1 ) - func = accSqrMask_; - else if( src.type() == CV_32FC3 && dst.type() == CV_32FC3 ) - func = accSqrMask_; - else if( src.type() == CV_32FC1 && dst.type() == CV_64FC1 ) - func = accSqrMask_; - else if( src.type() == CV_32FC3 && dst.type() == CV_64FC3 ) - func = accSqrMask_; - else if( src.type() == CV_64FC1 && dst.type() == CV_64FC1 ) - func = accSqrMask_; - else if( src.type() == CV_64FC3 && dst.type() == CV_64FC3 ) - func = accSqrMask_; - else - CV_Error( CV_StsUnsupportedFormat, "" ); - - func( src, dst, mask ); - } + CV_Assert( dst.size == src.size && dst.channels() == cn ); + + if( !mask.empty() ) + CV_Assert( mask.size == src.size && mask.type() == CV_8U ); + + int fidx = getAccTabIdx(sdepth, ddepth); + AccFunc func = fidx >= 0 ? accTab[fidx] : 0; + CV_Assert( func != 0 ); + + const Mat* arrays[] = {&src, &dst, &mask, 0}; + uchar* ptrs[3]; + NAryMatIterator it(arrays, ptrs); + int len = (int)it.size; + + for( size_t i = 0; i < it.nplanes; i++, ++it ) + func(ptrs[0], ptrs[1], ptrs[2], len, cn); } -void accumulateProduct( const Mat& src1, const Mat& src2, Mat& dst, const Mat& mask ) +void cv::accumulateSquare( const InputArray& _src, InputOutputArray _dst, const InputArray& _mask ) { - CV_Assert( dst.size() == src1.size() && dst.channels() == src1.channels() && - src1.size() == src2.size() && src1.type() == src2.type() ); + Mat src = _src.getMat(), dst = _dst.getMat(), mask = _mask.getMat(); + int sdepth = src.depth(), ddepth = dst.depth(), cn = src.channels(); - if( !mask.data ) - { - AccProdFunc func = 0; - if( src1.depth() == CV_8U && dst.depth() == CV_32F ) - func = accProd_; - else if( src1.depth() == CV_8U && dst.depth() == CV_64F ) - func = accProd_; - else if( src1.depth() == CV_32F && dst.depth() == CV_32F ) - func = accProd_; - else if( src1.depth() == CV_32F && dst.depth() == CV_64F ) - func = accProd_; - else if( src1.depth() == CV_64F && dst.depth() == CV_64F ) - func = accProd_; - else - CV_Error( CV_StsUnsupportedFormat, "" ); - - func( src1, src2, dst ); - } - else - { - CV_Assert( mask.size() == src1.size() && mask.type() == CV_8UC1 ); - - AccProdMaskFunc func = 0; - if( src1.type() == CV_8UC1 && dst.type() == CV_32FC1 ) - func = accProdMask_; - else if( src1.type() == CV_8UC3 && dst.type() == CV_32FC3 ) - func = accProdMask_; - else if( src1.type() == CV_8UC1 && dst.type() == CV_64FC1 ) - func = accProdMask_; - else if( src1.type() == CV_8UC3 && dst.type() == CV_64FC3 ) - func = accProdMask_; - else if( src1.type() == CV_32FC1 && dst.type() == CV_32FC1 ) - func = accProdMask_; - else if( src1.type() == CV_32FC3 && dst.type() == CV_32FC3 ) - func = accProdMask_; - else if( src1.type() == CV_32FC1 && dst.type() == CV_64FC1 ) - func = accProdMask_; - else if( src1.type() == CV_32FC3 && dst.type() == CV_64FC3 ) - func = accProdMask_; - else if( src1.type() == CV_64FC1 && dst.type() == CV_64FC1 ) - func = accProdMask_; - else if( src1.type() == CV_64FC3 && dst.type() == CV_64FC3 ) - func = accProdMask_; - else - CV_Error( CV_StsUnsupportedFormat, "" ); - - func( src1, src2, dst, mask ); - } + CV_Assert( dst.size == src.size && dst.channels() == cn ); + + if( !mask.empty() ) + CV_Assert( mask.size == src.size && mask.type() == CV_8U ); + + int fidx = getAccTabIdx(sdepth, ddepth); + AccFunc func = fidx >= 0 ? accSqrTab[fidx] : 0; + CV_Assert( func != 0 ); + + const Mat* arrays[] = {&src, &dst, &mask, 0}; + uchar* ptrs[3]; + NAryMatIterator it(arrays, ptrs); + int len = (int)it.size; + + for( size_t i = 0; i < it.nplanes; i++, ++it ) + func(ptrs[0], ptrs[1], ptrs[2], len, cn); } - -void accumulateWeighted( const Mat& src, Mat& dst, double alpha, const Mat& mask ) +void cv::accumulateProduct( const InputArray& _src1, const InputArray& _src2, + InputOutputArray _dst, const InputArray& _mask ) { - CV_Assert( dst.size() == src.size() && dst.channels() == src.channels() ); + Mat src1 = _src1.getMat(), src2 = _src2.getMat(), dst = _dst.getMat(), mask = _mask.getMat(); + int sdepth = src1.depth(), ddepth = dst.depth(), cn = src1.channels(); - if( !mask.data ) - { - AccWFunc func = 0; - if( src.depth() == CV_8U && dst.depth() == CV_32F ) - func = accW_; - else if( src.depth() == CV_8U && dst.depth() == CV_64F ) - func = accW_; - else if( src.depth() == CV_32F && dst.depth() == CV_32F ) - func = accW_; - else if( src.depth() == CV_32F && dst.depth() == CV_64F ) - func = accW_; - else if( src.depth() == CV_64F && dst.depth() == CV_64F ) - func = accW_; - else - CV_Error( CV_StsUnsupportedFormat, "" ); - - func( src, dst, alpha ); - } - else - { - CV_Assert( mask.size() == src.size() && mask.type() == CV_8UC1 ); - - AccWMaskFunc func = 0; - if( src.type() == CV_8UC1 && dst.type() == CV_32FC1 ) - func = accWMask_; - else if( src.type() == CV_8UC3 && dst.type() == CV_32FC3 ) - func = accWMask_; - else if( src.type() == CV_8UC1 && dst.type() == CV_64FC1 ) - func = accWMask_; - else if( src.type() == CV_8UC3 && dst.type() == CV_64FC3 ) - func = accWMask_; - else if( src.type() == CV_32FC1 && dst.type() == CV_32FC1 ) - func = accWMask_; - else if( src.type() == CV_32FC3 && dst.type() == CV_32FC3 ) - func = accWMask_; - else if( src.type() == CV_32FC1 && dst.type() == CV_64FC1 ) - func = accWMask_; - else if( src.type() == CV_32FC3 && dst.type() == CV_64FC3 ) - func = accWMask_; - else if( src.type() == CV_64FC1 && dst.type() == CV_64FC1 ) - func = accWMask_; - else if( src.type() == CV_64FC3 && dst.type() == CV_64FC3 ) - func = accWMask_; - else - CV_Error( CV_StsUnsupportedFormat, "" ); - - func( src, dst, alpha, mask ); - } + CV_Assert( src2.size && src1.size && src2.type() == src1.type() ); + CV_Assert( dst.size == src1.size && dst.channels() == cn ); + + if( !mask.empty() ) + CV_Assert( mask.size == src1.size && mask.type() == CV_8U ); + + int fidx = getAccTabIdx(sdepth, ddepth); + AccProdFunc func = fidx >= 0 ? accProdTab[fidx] : 0; + CV_Assert( func != 0 ); + + const Mat* arrays[] = {&src1, &src2, &dst, &mask, 0}; + uchar* ptrs[4]; + NAryMatIterator it(arrays, ptrs); + int len = (int)it.size; + + for( size_t i = 0; i < it.nplanes; i++, ++it ) + func(ptrs[0], ptrs[1], ptrs[2], ptrs[3], len, cn); } + +void cv::accumulateWeighted( const InputArray& _src, CV_IN_OUT InputOutputArray _dst, + double alpha, const InputArray& _mask ) +{ + Mat src = _src.getMat(), dst = _dst.getMat(), mask = _mask.getMat(); + int sdepth = src.depth(), ddepth = dst.depth(), cn = src.channels(); + + CV_Assert( dst.size == src.size && dst.channels() == cn ); + + if( !mask.empty() ) + CV_Assert( mask.size == src.size && mask.type() == CV_8U ); + + int fidx = getAccTabIdx(sdepth, ddepth); + AccWFunc func = fidx >= 0 ? accWTab[fidx] : 0; + CV_Assert( func != 0 ); + + const Mat* arrays[] = {&src, &dst, &mask, 0}; + uchar* ptrs[3]; + NAryMatIterator it(arrays, ptrs); + int len = (int)it.size; + + for( size_t i = 0; i < it.nplanes; i++, ++it ) + func(ptrs[0], ptrs[1], ptrs[2], len, cn, alpha); } diff --git a/modules/imgproc/src/canny.cpp b/modules/imgproc/src/canny.cpp index 49ed796b7a..bca30be00e 100644 --- a/modules/imgproc/src/canny.cpp +++ b/modules/imgproc/src/canny.cpp @@ -335,14 +335,14 @@ CV_IMPL void cvCanny( const void* srcarr, void* dstarr, } } -void cv::Canny( const Mat& image, Mat& edges, +void cv::Canny( const InputArray& image, OutputArray _edges, double threshold1, double threshold2, int apertureSize, bool L2gradient ) { - Mat src = image; - edges.create(src.size(), CV_8U); - CvMat _src = src, _dst = edges; - cvCanny( &_src, &_dst, threshold1, threshold2, + Mat src = image.getMat(); + _edges.create(src.size(), CV_8U); + CvMat c_src = src, c_dst = _edges.getMat(); + cvCanny( &c_src, &c_dst, threshold1, threshold2, apertureSize + (L2gradient ? CV_CANNY_L2_GRADIENT : 0)); } diff --git a/modules/imgproc/src/color.cpp b/modules/imgproc/src/color.cpp index d8304332c7..bbf033bdae 100644 --- a/modules/imgproc/src/color.cpp +++ b/modules/imgproc/src/color.cpp @@ -2618,13 +2618,15 @@ static void Bayer2RGB_VNG_8u( const Mat& srcmat, Mat& dstmat, int code ) } } +} ////////////////////////////////////////////////////////////////////////////////////////// // The main function // ////////////////////////////////////////////////////////////////////////////////////////// -void cvtColor( const Mat& src, Mat& dst, int code, int dcn ) +void cv::cvtColor( const InputArray& _src, OutputArray _dst, int code, int dcn ) { + Mat src = _src.getMat(), dst; Size sz = src.size(); int scn = src.channels(), depth = src.depth(), bidx; @@ -2638,7 +2640,9 @@ void cvtColor( const Mat& src, Mat& dst, int code, int dcn ) dcn = code == CV_BGR2BGRA || code == CV_RGB2BGRA || code == CV_BGRA2RGBA ? 4 : 3; bidx = code == CV_BGR2BGRA || code == CV_BGRA2BGR ? 0 : 2; - dst.create( sz, CV_MAKETYPE(depth, dcn)); + _dst.create( sz, CV_MAKETYPE(depth, dcn)); + dst = _dst.getMat(); + if( depth == CV_8U ) CvtColorLoop(src, dst, RGB2RGB(scn, dcn, bidx)); else if( depth == CV_16U ) @@ -2650,7 +2654,8 @@ void cvtColor( const Mat& src, Mat& dst, int code, int dcn ) case CV_BGR2BGR565: case CV_BGR2BGR555: case CV_RGB2BGR565: case CV_RGB2BGR555: case CV_BGRA2BGR565: case CV_BGRA2BGR555: case CV_RGBA2BGR565: case CV_RGBA2BGR555: CV_Assert( (scn == 3 || scn == 4) && depth == CV_8U ); - dst.create(sz, CV_8UC2); + _dst.create(sz, CV_8UC2); + dst = _dst.getMat(); CvtColorLoop(src, dst, RGB2RGB5x5(scn, code == CV_BGR2BGR565 || code == CV_BGR2BGR555 || @@ -2664,7 +2669,8 @@ void cvtColor( const Mat& src, Mat& dst, int code, int dcn ) case CV_BGR5652BGRA: case CV_BGR5552BGRA: case CV_BGR5652RGBA: case CV_BGR5552RGBA: if(dcn <= 0) dcn = 3; CV_Assert( (dcn == 3 || dcn == 4) && scn == 2 && depth == CV_8U ); - dst.create(sz, CV_MAKETYPE(depth, dcn)); + _dst.create(sz, CV_MAKETYPE(depth, dcn)); + dst = _dst.getMat(); CvtColorLoop(src, dst, RGB5x52RGB(dcn, code == CV_BGR5652BGR || code == CV_BGR5552BGR || @@ -2676,7 +2682,9 @@ void cvtColor( const Mat& src, Mat& dst, int code, int dcn ) case CV_BGR2GRAY: case CV_BGRA2GRAY: case CV_RGB2GRAY: case CV_RGBA2GRAY: CV_Assert( scn == 3 || scn == 4 ); - dst.create(sz, CV_MAKETYPE(depth, 1)); + _dst.create(sz, CV_MAKETYPE(depth, 1)); + dst = _dst.getMat(); + bidx = code == CV_BGR2GRAY || code == CV_BGRA2GRAY ? 0 : 2; if( depth == CV_8U ) @@ -2689,14 +2697,17 @@ void cvtColor( const Mat& src, Mat& dst, int code, int dcn ) case CV_BGR5652GRAY: case CV_BGR5552GRAY: CV_Assert( scn == 2 && depth == CV_8U ); - dst.create(sz, CV_8UC1); + _dst.create(sz, CV_8UC1); + dst = _dst.getMat(); + CvtColorLoop(src, dst, RGB5x52Gray(code == CV_BGR5652GRAY ? 6 : 5)); break; case CV_GRAY2BGR: case CV_GRAY2BGRA: if( dcn <= 0 ) dcn = 3; CV_Assert( scn == 1 && (dcn == 3 || dcn == 4)); - dst.create(sz, CV_MAKETYPE(depth, dcn)); + _dst.create(sz, CV_MAKETYPE(depth, dcn)); + dst = _dst.getMat(); if( depth == CV_8U ) CvtColorLoop(src, dst, Gray2RGB(dcn)); @@ -2708,7 +2719,8 @@ void cvtColor( const Mat& src, Mat& dst, int code, int dcn ) case CV_GRAY2BGR565: case CV_GRAY2BGR555: CV_Assert( scn == 1 && depth == CV_8U ); - dst.create(sz, CV_8UC2); + _dst.create(sz, CV_8UC2); + dst = _dst.getMat(); CvtColorLoop(src, dst, Gray2RGB5x5(code == CV_GRAY2BGR565 ? 6 : 5)); break; @@ -2723,7 +2735,8 @@ void cvtColor( const Mat& src, Mat& dst, int code, int dcn ) const float* coeffs_f = code == CV_BGR2YCrCb || code == CV_RGB2YCrCb ? 0 : yuv_f; const int* coeffs_i = code == CV_BGR2YCrCb || code == CV_RGB2YCrCb ? 0 : yuv_i; - dst.create(sz, CV_MAKETYPE(depth, 3)); + _dst.create(sz, CV_MAKETYPE(depth, 3)); + dst = _dst.getMat(); if( depth == CV_8U ) CvtColorLoop(src, dst, RGB2YCrCb_i(scn, bidx, coeffs_i)); @@ -2745,7 +2758,8 @@ void cvtColor( const Mat& src, Mat& dst, int code, int dcn ) const float* coeffs_f = code == CV_YCrCb2BGR || code == CV_YCrCb2RGB ? 0 : yuv_f; const int* coeffs_i = code == CV_YCrCb2BGR || code == CV_YCrCb2RGB ? 0 : yuv_i; - dst.create(sz, CV_MAKETYPE(depth, dcn)); + _dst.create(sz, CV_MAKETYPE(depth, dcn)); + dst = _dst.getMat(); if( depth == CV_8U ) CvtColorLoop(src, dst, YCrCb2RGB_i(dcn, bidx, coeffs_i)); @@ -2760,7 +2774,8 @@ void cvtColor( const Mat& src, Mat& dst, int code, int dcn ) CV_Assert( scn == 3 || scn == 4 ); bidx = code == CV_BGR2XYZ ? 0 : 2; - dst.create(sz, CV_MAKETYPE(depth, 3)); + _dst.create(sz, CV_MAKETYPE(depth, 3)); + dst = _dst.getMat(); if( depth == CV_8U ) CvtColorLoop(src, dst, RGB2XYZ_i(scn, bidx, 0)); @@ -2775,7 +2790,8 @@ void cvtColor( const Mat& src, Mat& dst, int code, int dcn ) CV_Assert( scn == 3 && (dcn == 3 || dcn == 4) ); bidx = code == CV_XYZ2BGR ? 0 : 2; - dst.create(sz, CV_MAKETYPE(depth, dcn)); + _dst.create(sz, CV_MAKETYPE(depth, dcn)); + dst = _dst.getMat(); if( depth == CV_8U ) CvtColorLoop(src, dst, XYZ2RGB_i(dcn, bidx, 0)); @@ -2794,8 +2810,9 @@ void cvtColor( const Mat& src, Mat& dst, int code, int dcn ) int hrange = depth == CV_32F ? 360 : code == CV_BGR2HSV || code == CV_RGB2HSV || code == CV_BGR2HLS || code == CV_RGB2HLS ? 180 : 255; - dst.create(sz, CV_MAKETYPE(depth, 3)); - + _dst.create(sz, CV_MAKETYPE(depth, 3)); + dst = _dst.getMat(); + if( code == CV_BGR2HSV || code == CV_RGB2HSV || code == CV_BGR2HSV_FULL || code == CV_RGB2HSV_FULL ) { @@ -2824,8 +2841,9 @@ void cvtColor( const Mat& src, Mat& dst, int code, int dcn ) int hrange = depth == CV_32F ? 360 : code == CV_HSV2BGR || code == CV_HSV2RGB || code == CV_HLS2BGR || code == CV_HLS2RGB ? 180 : 255; - dst.create(sz, CV_MAKETYPE(depth, dcn)); - + _dst.create(sz, CV_MAKETYPE(depth, dcn)); + dst = _dst.getMat(); + if( code == CV_HSV2BGR || code == CV_HSV2RGB || code == CV_HSV2BGR_FULL || code == CV_HSV2RGB_FULL ) { @@ -2853,8 +2871,9 @@ void cvtColor( const Mat& src, Mat& dst, int code, int dcn ) bool srgb = code == CV_BGR2Lab || code == CV_RGB2Lab || code == CV_BGR2Luv || code == CV_RGB2Luv; - dst.create(sz, CV_MAKETYPE(depth, 3)); - + _dst.create(sz, CV_MAKETYPE(depth, 3)); + dst = _dst.getMat(); + if( code == CV_BGR2Lab || code == CV_RGB2Lab || code == CV_LBGR2Lab || code == CV_LRGB2Lab ) { @@ -2883,8 +2902,9 @@ void cvtColor( const Mat& src, Mat& dst, int code, int dcn ) bool srgb = code == CV_Lab2BGR || code == CV_Lab2RGB || code == CV_Luv2BGR || code == CV_Luv2RGB; - dst.create(sz, CV_MAKETYPE(depth, dcn)); - + _dst.create(sz, CV_MAKETYPE(depth, dcn)); + dst = _dst.getMat(); + if( code == CV_Lab2BGR || code == CV_Lab2RGB || code == CV_Lab2LBGR || code == CV_Lab2LRGB ) { @@ -2906,7 +2926,10 @@ void cvtColor( const Mat& src, Mat& dst, int code, int dcn ) case CV_BayerBG2GRAY: case CV_BayerGB2GRAY: case CV_BayerRG2GRAY: case CV_BayerGR2GRAY: if(dcn <= 0) dcn = 1; CV_Assert( scn == 1 && dcn == 1 && depth == CV_8U ); - dst.create(sz, depth); + + _dst.create(sz, depth); + dst = _dst.getMat(); + Bayer2Gray_8u(src, dst, code); break; @@ -2914,7 +2937,9 @@ void cvtColor( const Mat& src, Mat& dst, int code, int dcn ) case CV_BayerBG2BGR_VNG: case CV_BayerGB2BGR_VNG: case CV_BayerRG2BGR_VNG: case CV_BayerGR2BGR_VNG: if(dcn <= 0) dcn = 3; CV_Assert( scn == 1 && dcn == 3 && depth == CV_8U ); - dst.create(sz, CV_MAKETYPE(depth, dcn)); + + _dst.create(sz, CV_MAKETYPE(depth, dcn)); + dst = _dst.getMat(); if( code == CV_BayerBG2BGR || code == CV_BayerGB2BGR || code == CV_BayerRG2BGR || code == CV_BayerGR2BGR ) @@ -2926,8 +2951,6 @@ void cvtColor( const Mat& src, Mat& dst, int code, int dcn ) CV_Error( CV_StsBadFlag, "Unknown/unsupported color conversion code" ); } } - -} CV_IMPL void cvCvtColor( const CvArr* srcarr, CvArr* dstarr, int code ) diff --git a/modules/imgproc/src/contours.cpp b/modules/imgproc/src/contours.cpp index 3aa37ff995..bc57a01b00 100644 --- a/modules/imgproc/src/contours.cpp +++ b/modules/imgproc/src/contours.cpp @@ -1469,37 +1469,40 @@ cvFindContours( void* img, CvMemStorage* storage, return count; } -namespace cv -{ -static void -_findContours( Mat& image, vector >& contours, - vector* hierarchy, int mode, int method, Point offset ) +void cv::findContours( const InputOutputArray _image, OutputArrayOfArrays _contours, + OutputArray _hierarchy, int mode, int method, Point offset ) { + Mat image = _image.getMat(); MemStorage storage(cvCreateMemStorage()); - CvMat _image = image; - CvSeq* _contours = 0; - if( hierarchy ) - hierarchy->clear(); - cvFindContours(&_image, storage, &_contours, sizeof(CvContour), mode, method, offset); - if( !_contours ) + CvMat _cimage = image; + CvSeq* _ccontours = 0; + if( _hierarchy.needed() ) + _hierarchy.clear(); + cvFindContours(&_cimage, storage, &_ccontours, sizeof(CvContour), mode, method, offset); + if( !_ccontours ) { - contours.clear(); + _contours.clear(); return; } - Seq all_contours(cvTreeToNodeSeq( _contours, sizeof(CvSeq), storage )); + Seq all_contours(cvTreeToNodeSeq( _ccontours, sizeof(CvSeq), storage )); size_t i, total = all_contours.size(); - contours.resize(total); + _contours.create(total, 1, 0, -1, true); SeqIterator it = all_contours.begin(); for( i = 0; i < total; i++, ++it ) { CvSeq* c = *it; ((CvContour*)c)->color = (int)i; - Seq(c).copyTo(contours[i]); + _contours.create(c->total, 1, CV_32SC2, i, true); + Mat ci = _contours.getMat(i); + CV_Assert( ci.isContinuous() ); + cvCvtSeqToArray(c, ci.data); } - if( hierarchy ) + if( _hierarchy.needed() ) { - hierarchy->resize(total); + _hierarchy.create(1, total, CV_32SC4, -1, true); + Vec4i* hierarchy = _hierarchy.getMat().ptr(); + it = all_contours.begin(); for( i = 0; i < total; i++, ++it ) { @@ -1508,62 +1511,57 @@ _findContours( Mat& image, vector >& contours, int h_prev = c->h_prev ? ((CvContour*)c->h_prev)->color : -1; int v_next = c->v_next ? ((CvContour*)c->v_next)->color : -1; int v_prev = c->v_prev ? ((CvContour*)c->v_prev)->color : -1; - (*hierarchy)[i] = Vec4i(h_next, h_prev, v_next, v_prev); + hierarchy[i] = Vec4i(h_next, h_prev, v_next, v_prev); } } } -} -void cv::findContours( Mat& image, vector >& contours, - vector& hierarchy, int mode, int method, Point offset ) +void cv::findContours( InputOutputArray _image, OutputArrayOfArrays _contours, + int mode, int method, Point offset) { - _findContours(image, contours, &hierarchy, mode, method, offset); -} - -void cv::findContours( Mat& image, vector >& contours, - int mode, int method, Point offset) -{ - _findContours(image, contours, 0, mode, method, offset); + findContours(_image, _contours, OutputArrayOfArrays(), mode, method, offset); } namespace cv { -static void addChildContour(const vector >& contours, - const vector& hierarchy, +static void addChildContour(const InputArrayOfArrays& contours, + size_t ncontours, + const Vec4i* hierarchy, int i, vector& seq, vector& block) { - size_t count = contours.size(); for( ; i >= 0; i = hierarchy[i][0] ) { - const vector& ci = contours[i]; + Mat ci = contours.getMat(i); cvMakeSeqHeaderForArray(CV_SEQ_POLYGON, sizeof(CvSeq), sizeof(Point), - !ci.empty() ? (void*)&ci[0] : 0, (int)ci.size(), + !ci.empty() ? (void*)ci.data : 0, (int)ci.total(), &seq[i], &block[i] ); int h_next = hierarchy[i][0], h_prev = hierarchy[i][1], v_next = hierarchy[i][2], v_prev = hierarchy[i][3]; - seq[i].h_next = (size_t)h_next < count ? &seq[h_next] : 0; - seq[i].h_prev = (size_t)h_prev < count ? &seq[h_prev] : 0; - seq[i].v_next = (size_t)v_next < count ? &seq[v_next] : 0; - seq[i].v_prev = (size_t)v_prev < count ? &seq[v_prev] : 0; + seq[i].h_next = (size_t)h_next < ncontours ? &seq[h_next] : 0; + seq[i].h_prev = (size_t)h_prev < ncontours ? &seq[h_prev] : 0; + seq[i].v_next = (size_t)v_next < ncontours ? &seq[v_next] : 0; + seq[i].v_prev = (size_t)v_prev < ncontours ? &seq[v_prev] : 0; if( v_next >= 0 ) - addChildContour(contours, hierarchy, v_next, seq, block); + addChildContour(contours, ncontours, hierarchy, v_next, seq, block); } } } -void cv::drawContours( Mat& image, const vector >& contours, +void cv::drawContours( InputOutputArray _image, const InputArrayOfArrays& _contours, int contourIdx, const Scalar& color, int thickness, - int lineType, const vector& hierarchy, + int lineType, const InputArray& _hierarchy, int maxLevel, Point offset ) { - CvMat _image = image; + Mat image = _image.getMat(), hierarchy = _hierarchy.getMat(); + CvMat _cimage = image; - size_t i = 0, first = 0, last = contours.size(); + size_t ncontours = _contours.total(); + size_t i = 0, first = 0, last = ncontours; vector seq; vector block; @@ -1585,9 +1583,13 @@ void cv::drawContours( Mat& image, const vector >& contours, for( i = first; i < last; i++ ) { - const vector& ci = contours[i]; - cvMakeSeqHeaderForArray(CV_SEQ_POLYGON, sizeof(CvSeq), sizeof(Point), - !ci.empty() ? (void*)&ci[0] : 0, (int)ci.size(), &seq[i], &block[i] ); + Mat ci = _contours.getMat(i); + if( ci.empty() ) + continue; + int npoints = ci.checkVector(2, CV_32S); + CV_Assert( npoints > 0 ); + cvMakeSeqHeaderForArray( CV_SEQ_POLYGON, sizeof(CvSeq), sizeof(Point), + ci.data, npoints, &seq[i], &block[i] ); } if( hierarchy.empty() || maxLevel == 0 ) @@ -1599,13 +1601,15 @@ void cv::drawContours( Mat& image, const vector >& contours, else { size_t count = last - first; - CV_Assert(hierarchy.size() == contours.size()); - if( count == contours.size() ) + CV_Assert(hierarchy.total() == ncontours && hierarchy.type() == CV_32SC4 ); + const Vec4i* h = hierarchy.ptr(); + + if( count == ncontours ) { for( i = first; i < last; i++ ) { - int h_next = hierarchy[i][0], h_prev = hierarchy[i][1], - v_next = hierarchy[i][2], v_prev = hierarchy[i][3]; + int h_next = h[i][0], h_prev = h[i][1], + v_next = h[i][2], v_prev = h[i][3]; seq[i].h_next = (size_t)h_next < count ? &seq[h_next] : 0; seq[i].h_prev = (size_t)h_prev < count ? &seq[h_prev] : 0; seq[i].v_next = (size_t)v_next < count ? &seq[v_next] : 0; @@ -1614,85 +1618,88 @@ void cv::drawContours( Mat& image, const vector >& contours, } else { - int child = hierarchy[first][2]; + int child = h[first][2]; if( child >= 0 ) { - addChildContour(contours, hierarchy, child, seq, block); + addChildContour(_contours, ncontours, h, child, seq, block); seq[first].v_next = &seq[child]; } } } - cvDrawContours( &_image, &seq[first], color, color, contourIdx >= 0 ? + cvDrawContours( &_cimage, &seq[first], color, color, contourIdx >= 0 ? -maxLevel : maxLevel, thickness, lineType, offset ); } -void cv::approxPolyDP( const Mat& curve, vector& approxCurve, +void cv::approxPolyDP( const InputArray& _curve, OutputArray _approxCurve, double epsilon, bool closed ) { - CV_Assert(curve.checkVector(2, CV_32S) >= 0); - CvMat _curve = curve; + Mat curve = _curve.getMat(); + int npoints = curve.checkVector(2), depth = curve.depth(); + CV_Assert( npoints >= 0 && (depth == CV_32S || depth == CV_32F)); + CvMat _ccurve = curve; MemStorage storage(cvCreateMemStorage()); - Seq seq(cvApproxPoly(&_curve, sizeof(CvContour), storage, CV_POLY_APPROX_DP, epsilon, closed)); - seq.copyTo(approxCurve); + CvSeq* result = cvApproxPoly(&_ccurve, sizeof(CvContour), storage, CV_POLY_APPROX_DP, epsilon, closed); + if( result->total > 0 ) + { + _approxCurve.create(result->total, 1, CV_MAKETYPE(curve.depth(), 2), -1, true); + cvCvtSeqToArray(result, _approxCurve.getMat().data ); + } } -void cv::approxPolyDP( const Mat& curve, vector& approxCurve, - double epsilon, bool closed ) -{ - CV_Assert(curve.checkVector(2, CV_32F) >= 0); - CvMat _curve = curve; - MemStorage storage(cvCreateMemStorage()); - Seq seq(cvApproxPoly(&_curve, sizeof(CvContour), storage, CV_POLY_APPROX_DP, epsilon, closed)); - seq.copyTo(approxCurve); -} -double cv::arcLength( const Mat& curve, bool closed ) +double cv::arcLength( const InputArray& _curve, bool closed ) { + Mat curve = _curve.getMat(); CV_Assert(curve.checkVector(2) >= 0 && (curve.depth() == CV_32F || curve.depth() == CV_32S)); - CvMat _curve = curve; - return cvArcLength(&_curve, CV_WHOLE_SEQ, closed); + CvMat _ccurve = curve; + return cvArcLength(&_ccurve, CV_WHOLE_SEQ, closed); } -cv::Rect cv::boundingRect( const Mat& points ) +cv::Rect cv::boundingRect( const InputArray& _points ) { + Mat points = _points.getMat(); CV_Assert(points.checkVector(2) >= 0 && (points.depth() == CV_32F || points.depth() == CV_32S)); - CvMat _points = points; - return cvBoundingRect(&_points, 0); + CvMat _cpoints = points; + return cvBoundingRect(&_cpoints, 0); } -double cv::contourArea( const Mat& contour, bool oriented ) +double cv::contourArea( const InputArray& _contour, bool oriented ) { + Mat contour = _contour.getMat(); CV_Assert(contour.checkVector(2) >= 0 && (contour.depth() == CV_32F || contour.depth() == CV_32S)); - CvMat _contour = contour; - return cvContourArea(&_contour, CV_WHOLE_SEQ, oriented); + CvMat _ccontour = contour; + return cvContourArea(&_ccontour, CV_WHOLE_SEQ, oriented); } -cv::RotatedRect cv::minAreaRect( const Mat& points ) +cv::RotatedRect cv::minAreaRect( const InputArray& _points ) { + Mat points = _points.getMat(); CV_Assert(points.checkVector(2) >= 0 && (points.depth() == CV_32F || points.depth() == CV_32S)); - CvMat _points = points; - return cvMinAreaRect2(&_points, 0); + CvMat _cpoints = points; + return cvMinAreaRect2(&_cpoints, 0); } -void cv::minEnclosingCircle( const Mat& points, +void cv::minEnclosingCircle( const InputArray& _points, Point2f& center, float& radius ) { + Mat points = _points.getMat(); CV_Assert(points.checkVector(2) >= 0 && (points.depth() == CV_32F || points.depth() == CV_32S)); - CvMat _points = points; - cvMinEnclosingCircle( &_points, (CvPoint2D32f*)¢er, &radius ); + CvMat _cpoints = points; + cvMinEnclosingCircle( &_cpoints, (CvPoint2D32f*)¢er, &radius ); } -double cv::matchShapes( const Mat& contour1, - const Mat& contour2, +double cv::matchShapes( const InputArray& _contour1, + const InputArray& _contour2, int method, double parameter ) { + Mat contour1 = _contour1.getMat(), contour2 = _contour2.getMat(); CV_Assert(contour1.checkVector(2) >= 0 && contour2.checkVector(2) >= 0 && (contour1.depth() == CV_32F || contour1.depth() == CV_32S) && contour1.depth() == contour2.depth()); @@ -1702,79 +1709,68 @@ double cv::matchShapes( const Mat& contour1, } -void cv::convexHull( const Mat& points, vector& hull, bool clockwise ) -{ - int nelems = points.checkVector(2); - CV_Assert(nelems >= 0 && (points.depth() == CV_32F || points.depth() == CV_32S)); - hull.resize(nelems); - CvMat _points = Mat(points), _hull=Mat(hull); - cvConvexHull2(&_points, &_hull, clockwise ? CV_CLOCKWISE : CV_COUNTER_CLOCKWISE, 0); - hull.resize(_hull.cols + _hull.rows - 1); -} - - -void cv::convexHull( const Mat& points, - vector& hull, bool clockwise ) -{ - int nelems = points.checkVector(2, CV_32S); - CV_Assert(nelems >= 0); - hull.resize(nelems); - CvMat _points = Mat(points), _hull=Mat(hull); - cvConvexHull2(&_points, &_hull, clockwise ? CV_CLOCKWISE : CV_COUNTER_CLOCKWISE, 1); - hull.resize(_hull.cols + _hull.rows - 1); -} - - -void cv::convexHull( const Mat& points, - vector& hull, bool clockwise ) +void cv::convexHull( const InputArray& _points, OutputArray _hull, bool clockwise, bool returnPoints ) { - int nelems = points.checkVector(2, CV_32F); - CV_Assert(nelems >= 0); - hull.resize(nelems); - CvMat _points = Mat(points), _hull=Mat(hull); - cvConvexHull2(&_points, &_hull, clockwise ? CV_CLOCKWISE : CV_COUNTER_CLOCKWISE, 1); - hull.resize(_hull.cols + _hull.rows - 1); + Mat points = _points.getMat(); + int nelems = points.checkVector(2), depth = points.depth(); + CV_Assert(nelems >= 0 && (depth == CV_32F || depth == CV_32S)); + + if( nelems == 0 ) + { + _hull.release(); + return; + } + + returnPoints = !_hull.fixedType() ? returnPoints : _hull.type() != CV_32S; + Mat hull(nelems, 1, returnPoints ? CV_MAKETYPE(depth, 2) : CV_32S); + CvMat _cpoints = points, _chull = hull; + cvConvexHull2(&_cpoints, &_chull, clockwise ? CV_CLOCKWISE : CV_COUNTER_CLOCKWISE, returnPoints); + _hull.create(_chull.rows, 1, hull.type(), -1, true); + Mat dhull = _hull.getMat(), shull(dhull.size(), dhull.type(), hull.data); + shull.copyTo(dhull); } -bool cv::isContourConvex( const Mat& contour ) +bool cv::isContourConvex( const InputArray& _contour ) { + Mat contour = _contour.getMat(); CV_Assert(contour.checkVector(2) >= 0 && (contour.depth() == CV_32F || contour.depth() == CV_32S)); CvMat c = Mat(contour); return cvCheckContourConvexity(&c) > 0; } -cv::RotatedRect cv::fitEllipse( const Mat& points ) +cv::RotatedRect cv::fitEllipse( const InputArray& _points ) { + Mat points = _points.getMat(); CV_Assert(points.checkVector(2) >= 0 && (points.depth() == CV_32F || points.depth() == CV_32S)); - CvMat _points = points; - return cvFitEllipse2(&_points); + CvMat _cpoints = points; + return cvFitEllipse2(&_cpoints); } -void cv::fitLine( const Mat& points, Vec4f& line, int distType, +void cv::fitLine( const InputArray& _points, OutputArray _line, int distType, double param, double reps, double aeps ) { - CV_Assert(points.checkVector(2) >= 0 && - (points.depth() == CV_32F || points.depth() == CV_32S)); - CvMat _points = points; - cvFitLine(&_points, distType, param, reps, aeps, &line[0]); + Mat points = _points.getMat(); + bool is3d = points.checkVector(3) >= 0, is2d = is3d ? false : points.checkVector(2) >= 0; + + CV_Assert((is2d || is3d) && (points.depth() == CV_32F || points.depth() == CV_32S)); + CvMat _cpoints = points; + float line[6]; + cvFitLine(&_cpoints, distType, param, reps, aeps, &line[0]); + + _line.create(is2d ? 4 : 6, 1, CV_32F, -1, true); + Mat l = _line.getMat(); + CV_Assert( l.isContinuous() ); + memcpy( l.data, line, (is2d ? 4 : 6)*sizeof(line[0]) ); } -void cv::fitLine( const Mat& points, Vec6f& line, int distType, - double param, double reps, double aeps ) -{ - CV_Assert(points.checkVector(3) >= 0 && - (points.depth() == CV_32F || points.depth() == CV_32S)); - CvMat _points = points; - cvFitLine(&_points, distType, param, reps, aeps, &line[0]); -} - -double cv::pointPolygonTest( const Mat& contour, +double cv::pointPolygonTest( const InputArray& _contour, Point2f pt, bool measureDist ) { + Mat contour = _contour.getMat(); CV_Assert(contour.checkVector(2) >= 0 && (contour.depth() == CV_32F || contour.depth() == CV_32S)); CvMat c = Mat(contour); diff --git a/modules/imgproc/src/corner.cpp b/modules/imgproc/src/corner.cpp index 31a1351051..469f6aaa7c 100644 --- a/modules/imgproc/src/corner.cpp +++ b/modules/imgproc/src/corner.cpp @@ -297,36 +297,47 @@ cornerEigenValsVecs( const Mat& src, Mat& eigenv, int block_size, calcEigenValsVecs( cov, eigenv ); } +} -void cornerMinEigenVal( const Mat& src, Mat& dst, int blockSize, int ksize, int borderType ) +void cv::cornerMinEigenVal( const InputArray& _src, OutputArray _dst, int blockSize, int ksize, int borderType ) { - dst.create( src.size(), CV_32F ); + Mat src = _src.getMat(); + _dst.create( src.size(), CV_32F ); + Mat dst = _dst.getMat(); cornerEigenValsVecs( src, dst, blockSize, ksize, MINEIGENVAL, 0, borderType ); } -void cornerHarris( const Mat& src, Mat& dst, int blockSize, int ksize, double k, int borderType ) +void cv::cornerHarris( const InputArray& _src, OutputArray _dst, int blockSize, int ksize, double k, int borderType ) { - dst.create( src.size(), CV_32F ); + Mat src = _src.getMat(); + _dst.create( src.size(), CV_32F ); + Mat dst = _dst.getMat(); cornerEigenValsVecs( src, dst, blockSize, ksize, HARRIS, k, borderType ); } -void cornerEigenValsAndVecs( const Mat& src, Mat& dst, int blockSize, int ksize, int borderType ) +void cv::cornerEigenValsAndVecs( const InputArray& _src, OutputArray _dst, int blockSize, int ksize, int borderType ) { - if( dst.rows != src.rows || dst.cols*dst.channels() != src.cols*6 || dst.depth() != CV_32F ) - dst.create( src.size(), CV_32FC(6) ); + Mat src = _src.getMat(); + Size dsz = _dst.size(); + int dtype = _dst.type(); + + if( dsz.height != src.rows || dsz.width*CV_MAT_CN(dtype) != src.cols*6 || CV_MAT_DEPTH(dtype) != CV_32F ) + _dst.create( src.size(), CV_32FC(6) ); + Mat dst = _dst.getMat(); cornerEigenValsVecs( src, dst, blockSize, ksize, EIGENVALSVECS, 0, borderType ); } -void preCornerDetect( const Mat& src, Mat& dst, int ksize, int borderType ) +void cv::preCornerDetect( const InputArray& _src, OutputArray _dst, int ksize, int borderType ) { - Mat Dx, Dy, D2x, D2y, Dxy; + Mat Dx, Dy, D2x, D2y, Dxy, src = _src.getMat(); CV_Assert( src.type() == CV_8UC1 || src.type() == CV_32FC1 ); - dst.create( src.size(), CV_32F ); - + _dst.create( src.size(), CV_32F ); + Mat dst = _dst.getMat(); + Sobel( src, Dx, CV_32F, 1, 0, ksize, 1, 0, borderType ); Sobel( src, Dy, CV_32F, 0, 1, ksize, 1, 0, borderType ); Sobel( src, D2x, CV_32F, 2, 0, ksize, 1, 0, borderType ); @@ -358,9 +369,6 @@ void preCornerDetect( const Mat& src, Mat& dst, int ksize, int borderType ) } } - -} - CV_IMPL void cvCornerMinEigenVal( const CvArr* srcarr, CvArr* dstarr, int block_size, int aperture_size ) diff --git a/modules/imgproc/src/cornersubpix.cpp b/modules/imgproc/src/cornersubpix.cpp index c4c77f34bc..6d32608244 100644 --- a/modules/imgproc/src/cornersubpix.cpp +++ b/modules/imgproc/src/cornersubpix.cpp @@ -254,13 +254,17 @@ cvFindCornerSubPix( const void* srcarr, CvPoint2D32f* corners, } } -void cv::cornerSubPix( const Mat& image, vector& corners, +void cv::cornerSubPix( const InputArray& _image, InputOutputArray _corners, Size winSize, Size zeroZone, TermCriteria criteria ) { - CvMat _image = image; - cvFindCornerSubPix(&_image, (CvPoint2D32f*)&corners[0], (int)corners.size(), - winSize, zeroZone, criteria ); + Mat corners = _corners.getMat(); + int ncorners = corners.checkVector(2); + CV_Assert( ncorners >= 0 && corners.depth() == CV_32F ); + CvMat c_image = _image.getMat(); + + cvFindCornerSubPix( &c_image, (CvPoint2D32f*)corners.data, ncorners, + winSize, zeroZone, criteria ); } /* End of file. */ diff --git a/modules/imgproc/src/deriv.cpp b/modules/imgproc/src/deriv.cpp index 3f5bfbbc90..1f2177ea16 100644 --- a/modules/imgproc/src/deriv.cpp +++ b/modules/imgproc/src/deriv.cpp @@ -111,16 +111,16 @@ void icvSepConvSmall3_32f( float* src, int src_step, float* dst, int dst_step, namespace cv { -static void getScharrKernels( Mat& kx, Mat& ky, int dx, int dy, bool normalize, int ktype ) +static void getScharrKernels( OutputArray _kx, OutputArray _ky, + int dx, int dy, bool normalize, int ktype ) { const int ksize = 3; CV_Assert( ktype == CV_32F || ktype == CV_64F ); - - if( kx.cols != ksize || kx.rows != 1 || kx.type() != ktype ) - kx.create( ksize, 1, ktype ); - if( ky.cols != ksize || ky.rows != 1 || ky.type() != ktype ) - ky.create( ksize, 1, ktype ); + _kx.create(ksize, 1, ktype, -1, true); + _ky.create(ksize, 1, ktype, -1, true); + Mat kx = _kx.getMat(); + Mat ky = _ky.getMat(); CV_Assert( dx >= 0 && dy >= 0 && dx+dy == 1 ); @@ -142,7 +142,8 @@ static void getScharrKernels( Mat& kx, Mat& ky, int dx, int dy, bool normalize, } -static void getSobelKernels( Mat& kx, Mat& ky, int dx, int dy, int _ksize, bool normalize, int ktype ) +static void getSobelKernels( OutputArray _kx, OutputArray _ky, + int dx, int dy, int _ksize, bool normalize, int ktype ) { int i, j, ksizeX = _ksize, ksizeY = _ksize; if( ksizeX == 1 && dx > 0 ) @@ -152,10 +153,10 @@ static void getSobelKernels( Mat& kx, Mat& ky, int dx, int dy, int _ksize, bool CV_Assert( ktype == CV_32F || ktype == CV_64F ); - if( kx.cols != ksizeX || kx.rows != 1 || kx.type() != ktype ) - kx.create( ksizeX, 1, ktype ); - if( ky.cols != ksizeY || ky.rows != 1 || ky.type() != ktype ) - ky.create( ksizeY, 1, ktype ); + _kx.create(ksizeX, 1, ktype, -1, true); + _ky.create(ksizeY, 1, ktype, -1, true); + Mat kx = _kx.getMat(); + Mat ky = _ky.getMat(); if( _ksize % 2 == 0 || _ksize > 31 ) CV_Error( CV_StsOutOfRange, "The kernel size must be odd and not larger than 31" ); @@ -218,9 +219,10 @@ static void getSobelKernels( Mat& kx, Mat& ky, int dx, int dy, int _ksize, bool } } +} -void getDerivKernels( Mat& kx, Mat& ky, int dx, int dy, - int ksize, bool normalize, int ktype ) +void cv::getDerivKernels( OutputArray kx, OutputArray ky, int dx, int dy, + int ksize, bool normalize, int ktype ) { if( ksize <= 0 ) getScharrKernels( kx, ky, dx, dy, normalize, ktype ); @@ -229,8 +231,8 @@ void getDerivKernels( Mat& kx, Mat& ky, int dx, int dy, } -Ptr createDerivFilter(int srcType, int dstType, - int dx, int dy, int ksize, int borderType ) +cv::Ptr cv::createDerivFilter(int srcType, int dstType, + int dx, int dy, int ksize, int borderType ) { Mat kx, ky; getDerivKernels( kx, ky, dx, dy, ksize, false, CV_32F ); @@ -238,9 +240,11 @@ Ptr createDerivFilter(int srcType, int dstType, kx, ky, Point(-1,-1), 0, borderType ); } - #if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7) +namespace cv +{ + static bool IPPDerivScharr(const Mat& src, Mat& dst, int ddepth, int dx, int dy, double scale) { int bufSize = 0; @@ -344,9 +348,7 @@ static bool IPPDeriv(const Mat& src, Mat& dst, int ddepth, int dx, int dy, int k if(ksize == 3 || ksize == 5) { if( ddepth < 0 ) - ddepth = src.depth(); - - dst.create( src.size(), CV_MAKETYPE(ddepth, src.channels()) ); + ddepth = src.depth(); if(src.type() == CV_8U && dst.type() == CV_16S && scale == 1) { @@ -462,21 +464,25 @@ static bool IPPDeriv(const Mat& src, Mat& dst, int ddepth, int dx, int dy, int k return IPPDerivScharr(src, dst, ddepth, dx, dy, scale); return false; - } +} + #endif - -void Sobel( const Mat& src, Mat& dst, int ddepth, int dx, int dy, - int ksize, double scale, double delta, int borderType ) +void cv::Sobel( const InputArray& _src, OutputArray _dst, int ddepth, int dx, int dy, + int ksize, double scale, double delta, int borderType ) { + Mat src = _src.getMat(); + _dst.create( src.size(), CV_MAKETYPE(ddepth, src.channels()) ); + Mat dst = _dst.getMat(); + #if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7) - if(dx < 3 && dy < 3 && src.channels() == 1 && borderType == 1) - { - if(IPPDeriv(src, dst, ddepth, dx, dy, ksize,scale) == true) - return; - } + if(dx < 3 && dy < 3 && src.channels() == 1 && borderType == 1) + { + if(IPPDeriv(src, dst, ddepth, dx, dy, ksize,scale)) + return; + } #endif int ktype = std::max(CV_32F, std::max(ddepth, src.depth())); @@ -495,15 +501,19 @@ void Sobel( const Mat& src, Mat& dst, int ddepth, int dx, int dy, } -void Scharr( const Mat& src, Mat& dst, int ddepth, int dx, int dy, - double scale, double delta, int borderType ) +void cv::Scharr( const InputArray& _src, OutputArray _dst, int ddepth, int dx, int dy, + double scale, double delta, int borderType ) { + Mat src = _src.getMat(); + _dst.create( src.size(), CV_MAKETYPE(ddepth, src.channels()) ); + Mat dst = _dst.getMat(); + #if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7) - if(dx < 2 && dy < 2 && src.channels() == 1 && borderType == 1) - { - if(IPPDerivScharr(src, dst, ddepth, dx, dy, scale) == true) - return; - } + if(dx < 2 && dy < 2 && src.channels() == 1 && borderType == 1) + { + if(IPPDerivScharr(src, dst, ddepth, dx, dy, scale)) + return; + } #endif int ktype = std::max(CV_32F, std::max(ddepth, src.depth())); @@ -522,9 +532,13 @@ void Scharr( const Mat& src, Mat& dst, int ddepth, int dx, int dy, } -void Laplacian( const Mat& src, Mat& dst, int ddepth, int ksize, - double scale, double delta, int borderType ) +void cv::Laplacian( const InputArray& _src, OutputArray _dst, int ddepth, int ksize, + double scale, double delta, int borderType ) { + Mat src = _src.getMat(); + _dst.create( src.size(), CV_MAKETYPE(ddepth, src.channels()) ); + Mat dst = _dst.getMat(); + if( ksize == 1 || ksize == 3 ) { float K[2][9] = @@ -548,7 +562,6 @@ void Laplacian( const Mat& src, Mat& dst, int ddepth, int ksize, if( ddepth < 0 ) ddepth = src.depth(); int dtype = CV_MAKETYPE(ddepth, src.channels()); - dst.create( src.size(), dtype ); int dy0 = std::min(std::max((int)(STRIPE_SIZE/(getElemSize(src.type())*src.cols)), 1), src.rows); Ptr fx = createSeparableLinearFilter(src.type(), @@ -578,8 +591,6 @@ void Laplacian( const Mat& src, Mat& dst, int ddepth, int ksize, } } -} - ///////////////////////////////////////////////////////////////////////////////////////// CV_IMPL void diff --git a/modules/imgproc/src/distransform.cpp b/modules/imgproc/src/distransform.cpp index a4e0f9da8d..a52780e7f0 100644 --- a/modules/imgproc/src/distransform.cpp +++ b/modules/imgproc/src/distransform.cpp @@ -850,21 +850,24 @@ cvDistTransform( const void* srcarr, void* dstarr, } } -void cv::distanceTransform( const Mat& src, Mat& dst, Mat& labels, +void cv::distanceTransform( const InputArray& _src, OutputArray _dst, OutputArray _labels, int distanceType, int maskSize ) { - dst.create(src.size(), CV_32F); - labels.create(src.size(), CV_32S); - CvMat _src = src, _dst = dst, _labels = labels; - cvDistTransform(&_src, &_dst, distanceType, maskSize, 0, &_labels); + Mat src = _src.getMat(); + _dst.create(src.size(), CV_32F); + _labels.create(src.size(), CV_32S); + CvMat c_src = src, c_dst = _dst.getMat(), c_labels = _labels.getMat(); + cvDistTransform(&c_src, &c_dst, distanceType, maskSize, 0, &c_labels); } -void cv::distanceTransform( const Mat& src, Mat& dst, +void cv::distanceTransform( const InputArray& _src, OutputArray _dst, int distanceType, int maskSize ) { - dst.create(src.size(), CV_32F); - CvMat _src = src, _dst = dst; - cvDistTransform(&_src, &_dst, distanceType, maskSize, 0, 0); + Mat src = _src.getMat(); + _dst.create(src.size(), CV_32F); + Mat dst = _dst.getMat(); + CvMat c_src = src, c_dst = _dst.getMat(); + cvDistTransform(&c_src, &c_dst, distanceType, maskSize, 0, 0); } /* End of file. */ diff --git a/modules/imgproc/src/emd.cpp b/modules/imgproc/src/emd.cpp index d6cbf804c2..ec52ded822 100644 --- a/modules/imgproc/src/emd.cpp +++ b/modules/imgproc/src/emd.cpp @@ -1138,22 +1138,25 @@ icvDistC( const float *x, const float *y, void *user_param ) } -namespace cv +float cv::EMD( const InputArray& _signature1, const InputArray& _signature2, + int distType, const InputArray& _cost, + float* lowerBound, OutputArray _flow ) { + Mat signature1 = _signature1.getMat(), signature2 = _signature2.getMat(); + Mat cost = _cost.getMat(), flow; -float EMD( const Mat& signature1, const Mat& signature2, - int distType, const Mat& cost, float* lowerBound, Mat* flow ) -{ - CvMat _signature1 = signature1; - CvMat _signature2 = signature2; - CvMat _cost = cost, _flow; - if( flow ) - _flow = *flow; + CvMat _csignature1 = signature1; + CvMat _csignature2 = signature2; + CvMat _ccost = cost, _cflow; + if( _flow.needed() ) + { + _flow.create((int)signature1.total(), (int)signature2.total(), CV_32F); + flow = _flow.getMat(); + _cflow = flow; + } - return cvCalcEMD2( &_signature1, &_signature2, distType, 0, cost.empty() ? 0 : &_cost, - flow ? &_flow : 0, lowerBound, 0 ); -} - + return cvCalcEMD2( &_csignature1, &_csignature2, distType, 0, cost.empty() ? 0 : &_ccost, + _flow.needed() ? &_cflow : 0, lowerBound, 0 ); } /* End of file. */ diff --git a/modules/imgproc/src/featureselect.cpp b/modules/imgproc/src/featureselect.cpp index b469db5388..92ce27f76c 100644 --- a/modules/imgproc/src/featureselect.cpp +++ b/modules/imgproc/src/featureselect.cpp @@ -50,13 +50,16 @@ template struct greaterThanPtr bool operator()(const T* a, const T* b) const { return *a > *b; } }; -void goodFeaturesToTrack( const Mat& image, vector& corners, - int maxCorners, double qualityLevel, double minDistance, - const Mat& mask, int blockSize, - bool useHarrisDetector, double harrisK ) +} + +void cv::goodFeaturesToTrack( const InputArray& _image, OutputArray _corners, + int maxCorners, double qualityLevel, double minDistance, + const InputArray& _mask, int blockSize, + bool useHarrisDetector, double harrisK ) { + Mat image = _image.getMat(), mask = _mask.getMat(); + CV_Assert( qualityLevel > 0 && minDistance >= 0 && maxCorners >= 0 ); - CV_Assert( mask.empty() || (mask.type() == CV_8UC1 && mask.size() == image.size()) ); Mat eig, tmp; @@ -90,7 +93,7 @@ void goodFeaturesToTrack( const Mat& image, vector& corners, } sort( tmpCorners, greaterThanPtr() ); - corners.clear(); + vector corners; size_t i, j, total = tmpCorners.size(), ncorners = 0; if(minDistance >= 1) @@ -182,7 +185,10 @@ void goodFeaturesToTrack( const Mat& image, vector& corners, break; } } -/* + + Mat(corners).convertTo(_corners, _corners.fixedType() ? _corners.type() : CV_32F); + + /* for( i = 0; i < total; i++ ) { int ofs = (int)((const uchar*)tmpCorners[i] - eig.data); @@ -209,8 +215,6 @@ void goodFeaturesToTrack( const Mat& image, vector& corners, } */ } - -} CV_IMPL void cvGoodFeaturesToTrack( const void* _image, void*, void*, diff --git a/modules/imgproc/src/filter.cpp b/modules/imgproc/src/filter.cpp index 27fb2a03e7..786f7a6ab3 100644 --- a/modules/imgproc/src/filter.cpp +++ b/modules/imgproc/src/filter.cpp @@ -46,30 +46,16 @@ Base Image Filter \****************************************************************************************/ -namespace cv -{ - -BaseRowFilter::BaseRowFilter() { ksize = anchor = -1; } -BaseRowFilter::~BaseRowFilter() {} - -BaseColumnFilter::BaseColumnFilter() { ksize = anchor = -1; } -BaseColumnFilter::~BaseColumnFilter() {} -void BaseColumnFilter::reset() {} - -BaseFilter::BaseFilter() { ksize = Size(-1,-1); anchor = Point(-1,-1); } -BaseFilter::~BaseFilter() {} -void BaseFilter::reset() {} - /* Various border types, image boundaries are denoted with '|' - * BORDER_REPLICATE: aaaaaa|abcdefgh|hhhhhhh - * BORDER_REFLECT: fedcba|abcdefgh|hgfedcb - * BORDER_REFLECT_101: gfedcb|abcdefgh|gfedcba - * BORDER_WRAP: cdefgh|abcdefgh|abcdefg - * BORDER_CONSTANT: iiiiii|abcdefgh|iiiiiii with some specified 'i' -*/ -int borderInterpolate( int p, int len, int borderType ) + * BORDER_REPLICATE: aaaaaa|abcdefgh|hhhhhhh + * BORDER_REFLECT: fedcba|abcdefgh|hgfedcb + * BORDER_REFLECT_101: gfedcb|abcdefgh|gfedcba + * BORDER_WRAP: cdefgh|abcdefgh|abcdefg + * BORDER_CONSTANT: iiiiii|abcdefgh|iiiiiii with some specified 'i' + */ +int cv::borderInterpolate( int p, int len, int borderType ) { if( (unsigned)p < (unsigned)len ) ; @@ -104,6 +90,20 @@ int borderInterpolate( int p, int len, int borderType ) } +namespace cv +{ + +BaseRowFilter::BaseRowFilter() { ksize = anchor = -1; } +BaseRowFilter::~BaseRowFilter() {} + +BaseColumnFilter::BaseColumnFilter() { ksize = anchor = -1; } +BaseColumnFilter::~BaseColumnFilter() {} +void BaseColumnFilter::reset() {} + +BaseFilter::BaseFilter() { ksize = Size(-1,-1); anchor = Point(-1,-1); } +BaseFilter::~BaseFilter() {} +void BaseFilter::reset() {} + FilterEngine::FilterEngine() { srcType = dstType = bufType = -1; @@ -454,13 +454,15 @@ void FilterEngine::apply(const Mat& src, Mat& dst, dst.data + dstOfs.y*dst.step + dstOfs.x*dst.elemSize(), (int)dst.step ); } +} /****************************************************************************************\ * Separable linear filter * \****************************************************************************************/ -int getKernelType(const Mat& _kernel, Point anchor) +int cv::getKernelType(const InputArray& __kernel, Point anchor) { + Mat _kernel = __kernel.getMat(); CV_Assert( _kernel.channels() == 1 ); int i, sz = _kernel.rows*_kernel.cols; @@ -495,6 +497,9 @@ int getKernelType(const Mat& _kernel, Point anchor) } +namespace cv +{ + struct RowNoVec { RowNoVec() {} @@ -2527,10 +2532,13 @@ template struct FixedPtCastEx int SHIFT, DELTA; }; -Ptr getLinearRowFilter( int srcType, int bufType, - const Mat& kernel, int anchor, - int symmetryType ) +} + +cv::Ptr cv::getLinearRowFilter( int srcType, int bufType, + const InputArray& _kernel, int anchor, + int symmetryType ) { + Mat kernel = _kernel.getMat(); int sdepth = CV_MAT_DEPTH(srcType), ddepth = CV_MAT_DEPTH(bufType); int cn = CV_MAT_CN(srcType); CV_Assert( cn == CV_MAT_CN(bufType) && @@ -2577,11 +2585,12 @@ Ptr getLinearRowFilter( int srcType, int bufType, } -Ptr getLinearColumnFilter( int bufType, int dstType, - const Mat& kernel, int anchor, +cv::Ptr cv::getLinearColumnFilter( int bufType, int dstType, + const InputArray& _kernel, int anchor, int symmetryType, double delta, int bits ) { + Mat kernel = _kernel.getMat(); int sdepth = CV_MAT_DEPTH(bufType), ddepth = CV_MAT_DEPTH(dstType); int cn = CV_MAT_CN(dstType); CV_Assert( cn == CV_MAT_CN(bufType) && @@ -2672,13 +2681,14 @@ Ptr getLinearColumnFilter( int bufType, int dstType, } -Ptr createSeparableLinearFilter( +cv::Ptr cv::createSeparableLinearFilter( int _srcType, int _dstType, - const Mat& _rowKernel, const Mat& _columnKernel, + const InputArray& __rowKernel, const InputArray& __columnKernel, Point _anchor, double _delta, int _rowBorderType, int _columnBorderType, const Scalar& _borderValue ) { + Mat _rowKernel = __rowKernel.getMat(), _columnKernel = __columnKernel.getMat(); _srcType = CV_MAT_TYPE(_srcType); _dstType = CV_MAT_TYPE(_dstType); int sdepth = CV_MAT_DEPTH(_srcType), ddepth = CV_MAT_DEPTH(_dstType); @@ -2742,6 +2752,9 @@ Ptr createSeparableLinearFilter( * Non-separable linear filter * \****************************************************************************************/ +namespace cv +{ + void preprocess2DKernel( const Mat& kernel, vector& coords, vector& coeffs ) { int i, j, k, nz = countNonZero(kernel), ktype = kernel.type(); @@ -2868,11 +2881,13 @@ template struct Filter2D : public BaseFi VecOp vecOp; }; +} -Ptr getLinearFilter(int srcType, int dstType, - const Mat& _kernel, Point anchor, +cv::Ptr cv::getLinearFilter(int srcType, int dstType, + const InputArray& __kernel, Point anchor, double delta, int bits) { + Mat _kernel = __kernel.getMat(); int sdepth = CV_MAT_DEPTH(srcType), ddepth = CV_MAT_DEPTH(dstType); int cn = CV_MAT_CN(srcType), kdepth = _kernel.depth(); CV_Assert( cn == CV_MAT_CN(dstType) && ddepth >= sdepth ); @@ -2946,11 +2961,13 @@ Ptr getLinearFilter(int srcType, int dstType, } -Ptr createLinearFilter( int _srcType, int _dstType, const Mat& _kernel, - Point _anchor, double _delta, - int _rowBorderType, int _columnBorderType, - const Scalar& _borderValue ) +cv::Ptr cv::createLinearFilter( int _srcType, int _dstType, + const InputArray& __kernel, + Point _anchor, double _delta, + int _rowBorderType, int _columnBorderType, + const Scalar& _borderValue ) { + Mat _kernel = __kernel.getMat(); _srcType = CV_MAT_TYPE(_srcType); _dstType = CV_MAT_TYPE(_dstType); int cn = CV_MAT_CN(_srcType); @@ -2977,10 +2994,12 @@ Ptr createLinearFilter( int _srcType, int _dstType, const Mat& _ke } -void filter2D( const Mat& src, Mat& dst, int ddepth, - const Mat& kernel, Point anchor, - double delta, int borderType ) +void cv::filter2D( const InputArray& _src, OutputArray _dst, int ddepth, + const InputArray& _kernel, Point anchor, + double delta, int borderType ) { + Mat src = _src.getMat(), kernel = _kernel.getMat(); + if( ddepth < 0 ) ddepth = src.depth(); @@ -2991,7 +3010,8 @@ void filter2D( const Mat& src, Mat& dst, int ddepth, int dft_filter_size = 50; #endif - dst.create( src.size(), CV_MAKETYPE(ddepth, src.channels()) ); + _dst.create( src.size(), CV_MAKETYPE(ddepth, src.channels()) ); + Mat dst = _dst.getMat(); anchor = normalizeAnchor(anchor, kernel.size()); if( kernel.cols*kernel.rows >= dft_filter_size ) @@ -3015,22 +3035,23 @@ void filter2D( const Mat& src, Mat& dst, int ddepth, } -void sepFilter2D( const Mat& src, Mat& dst, int ddepth, - const Mat& kernelX, const Mat& kernelY, Point anchor, - double delta, int borderType ) +void cv::sepFilter2D( const InputArray& _src, OutputArray _dst, int ddepth, + const InputArray& _kernelX, const InputArray& _kernelY, Point anchor, + double delta, int borderType ) { + Mat src = _src.getMat(), kernelX = _kernelX.getMat(), kernelY = _kernelY.getMat(); + if( ddepth < 0 ) ddepth = src.depth(); - dst.create( src.size(), CV_MAKETYPE(ddepth, src.channels()) ); + _dst.create( src.size(), CV_MAKETYPE(ddepth, src.channels()) ); + Mat dst = _dst.getMat(); Ptr f = createSeparableLinearFilter(src.type(), dst.type(), kernelX, kernelY, anchor, delta, borderType & ~BORDER_ISOLATED ); f->apply(src, dst, Rect(0,0,-1,-1), Point(), (borderType & BORDER_ISOLATED) != 0 ); } -} - CV_IMPL void cvFilter2D( const CvArr* srcarr, CvArr* dstarr, const CvMat* _kernel, CvPoint anchor ) diff --git a/modules/imgproc/src/floodfill.cpp b/modules/imgproc/src/floodfill.cpp index de5d07ee47..6ddf196fdb 100644 --- a/modules/imgproc/src/floodfill.cpp +++ b/modules/imgproc/src/floodfill.cpp @@ -1114,25 +1114,25 @@ cvFloodFill( CvArr* arr, CvPoint seed_point, } -int cv::floodFill( Mat& image, Point seedPoint, +int cv::floodFill( InputOutputArray _image, Point seedPoint, Scalar newVal, Rect* rect, Scalar loDiff, Scalar upDiff, int flags ) { CvConnectedComp ccomp; - CvMat _image = image; - cvFloodFill(&_image, seedPoint, newVal, loDiff, upDiff, &ccomp, flags, 0); + CvMat c_image = _image.getMat(); + cvFloodFill(&c_image, seedPoint, newVal, loDiff, upDiff, &ccomp, flags, 0); if( rect ) *rect = ccomp.rect; return cvRound(ccomp.area); } -int cv::floodFill( Mat& image, Mat& mask, +int cv::floodFill( InputOutputArray _image, InputOutputArray _mask, Point seedPoint, Scalar newVal, Rect* rect, Scalar loDiff, Scalar upDiff, int flags ) { CvConnectedComp ccomp; - CvMat _image = image, _mask = mask; - cvFloodFill(&_image, seedPoint, newVal, loDiff, upDiff, &ccomp, flags, &_mask); + CvMat c_image = _image.getMat(), c_mask = _mask.getMat(); + cvFloodFill(&c_image, seedPoint, newVal, loDiff, upDiff, &ccomp, flags, &c_mask); if( rect ) *rect = ccomp.rect; return cvRound(ccomp.area); diff --git a/modules/imgproc/src/grabcut.cpp b/modules/imgproc/src/grabcut.cpp index d2244759cd..9cd8c774c0 100644 --- a/modules/imgproc/src/grabcut.cpp +++ b/modules/imgproc/src/grabcut.cpp @@ -375,10 +375,10 @@ void initGMMs( const Mat& img, const Mat& mask, GMM& bgdGMM, GMM& fgdGMM ) CV_Assert( !bgdSamples.empty() && !fgdSamples.empty() ); Mat _bgdSamples( (int)bgdSamples.size(), 3, CV_32FC1, &bgdSamples[0][0] ); kmeans( _bgdSamples, GMM::componentsCount, bgdLabels, - TermCriteria( CV_TERMCRIT_ITER, kMeansItCount, 0.0), 0, kMeansType, 0 ); + TermCriteria( CV_TERMCRIT_ITER, kMeansItCount, 0.0), 0, kMeansType ); Mat _fgdSamples( (int)fgdSamples.size(), 3, CV_32FC1, &fgdSamples[0][0] ); kmeans( _fgdSamples, GMM::componentsCount, fgdLabels, - TermCriteria( CV_TERMCRIT_ITER, kMeansItCount, 0.0), 0, kMeansType, 0 ); + TermCriteria( CV_TERMCRIT_ITER, kMeansItCount, 0.0), 0, kMeansType ); bgdGMM.initLearning(); for( int i = 0; i < (int)bgdSamples.size(); i++ ) @@ -521,10 +521,15 @@ void estimateSegmentation( GCGraph& graph, Mat& mask ) } } -void cv::grabCut( const Mat& img, Mat& mask, Rect rect, - Mat& bgdModel, Mat& fgdModel, - int iterCount, int mode ) +void cv::grabCut( const InputArray& _img, InputOutputArray _mask, Rect rect, + InputOutputArray _bgdModel, InputOutputArray _fgdModel, + int iterCount, int mode ) { + Mat img = _img.getMat(); + Mat& mask = _mask.getMatRef(); + Mat& bgdModel = _bgdModel.getMatRef(); + Mat& fgdModel = _fgdModel.getMatRef(); + if( img.empty() ) CV_Error( CV_StsBadArg, "image is empty" ); if( img.type() != CV_8UC3 ) diff --git a/modules/imgproc/src/histogram.cpp b/modules/imgproc/src/histogram.cpp index 5f60ff41e0..6070e1e9cd 100644 --- a/modules/imgproc/src/histogram.cpp +++ b/modules/imgproc/src/histogram.cpp @@ -43,6 +43,10 @@ namespace cv { +template<> void Ptr::delete_obj() +{ cvReleaseHist(&obj); } + + ////////////////// Helper functions ////////////////////// static const size_t OUT_OF_RANGE = (size_t)1 << (sizeof(size_t)*8 - 2); @@ -586,18 +590,22 @@ calcHist_8u( vector& _ptrs, const vector& _deltas, } } +} -void calcHist( const Mat* images, int nimages, const int* channels, - const Mat& mask, Mat& hist, int dims, const int* histSize, - const float** ranges, bool uniform, bool accumulate ) +void cv::calcHist( const Mat* images, int nimages, const int* channels, + const InputArray& _mask, OutputArray _hist, int dims, const int* histSize, + const float** ranges, bool uniform, bool accumulate ) { + Mat mask = _mask.getMat(); + CV_Assert(dims > 0 && histSize); - hist.create(dims, histSize, CV_32F); - - Mat ihist = hist; + + uchar* histdata = _hist.getMat().data; + _hist.create(dims, histSize, CV_32F); + Mat hist = _hist.getMat(), ihist = hist; ihist.flags = (ihist.flags & ~CV_MAT_TYPE_MASK)|CV_32S; - if( !accumulate ) + if( !accumulate || histdata != hist.data ) hist = Scalar(0.); else hist.convertTo(ihist, CV_32S); @@ -626,7 +634,9 @@ void calcHist( const Mat* images, int nimages, const int* channels, ihist.convertTo(hist, CV_32F); } - +namespace cv +{ + template static void calcSparseHist_( vector& _ptrs, const vector& _deltas, Size imsize, SparseMat& hist, int dims, const float** _ranges, @@ -803,11 +813,13 @@ static void calcHist( const Mat* images, int nimages, const int* channels, } } +} -void calcHist( const Mat* images, int nimages, const int* channels, - const Mat& mask, SparseMat& hist, int dims, const int* histSize, +void cv::calcHist( const Mat* images, int nimages, const int* channels, + const InputArray& _mask, SparseMat& hist, int dims, const int* histSize, const float** ranges, bool uniform, bool accumulate ) { + Mat mask = _mask.getMat(); calcHist( images, nimages, channels, mask, hist, dims, histSize, ranges, uniform, accumulate, false ); } @@ -815,6 +827,8 @@ void calcHist( const Mat* images, int nimages, const int* channels, /////////////////////////////////////// B A C K P R O J E C T //////////////////////////////////// +namespace cv +{ template static void calcBackProj_( vector& _ptrs, const vector& _deltas, @@ -1102,12 +1116,14 @@ calcBackProj_8u( vector& _ptrs, const vector& _deltas, } } } + +} - -void calcBackProject( const Mat* images, int nimages, const int* channels, - const Mat& hist, Mat& backProject, - const float** ranges, double scale, bool uniform ) +void cv::calcBackProject( const Mat* images, int nimages, const int* channels, + const InputArray& _hist, OutputArray _backProject, + const float** ranges, double scale, bool uniform ) { + Mat hist = _hist.getMat(); vector ptrs; vector deltas; vector uniranges; @@ -1115,7 +1131,8 @@ void calcBackProject( const Mat* images, int nimages, const int* channels, int dims = hist.dims == 2 && hist.size[1] == 1 ? 1 : hist.dims; CV_Assert( dims > 0 && hist.data ); - backProject.create( images[0].size(), images[0].depth() ); + _backProject.create( images[0].size(), images[0].depth() ); + Mat backProject = _backProject.getMat(); histPrepareImages( images, nimages, channels, backProject, dims, hist.size, ranges, uniform, ptrs, deltas, imsize, uniranges ); const double* _uniranges = uniform ? &uniranges[0] : 0; @@ -1131,7 +1148,10 @@ void calcBackProject( const Mat* images, int nimages, const int* channels, CV_Error(CV_StsUnsupportedFormat, ""); } - + +namespace cv +{ + template static void calcSparseBackProj_( vector& _ptrs, const vector& _deltas, Size imsize, const SparseMat& hist, int dims, const float** _ranges, @@ -1259,11 +1279,12 @@ calcSparseBackProj_8u( vector& _ptrs, const vector& _deltas, ptrs[i] += deltas[i*2 + 1]; } } - -void calcBackProject( const Mat* images, int nimages, const int* channels, - const SparseMat& hist, Mat& backProject, - const float** ranges, double scale, bool uniform ) +} + +void cv::calcBackProject( const Mat* images, int nimages, const int* channels, + const SparseMat& hist, Mat& backProject, + const float** ranges, double scale, bool uniform ) { vector ptrs; vector deltas; @@ -1295,13 +1316,14 @@ void calcBackProject( const Mat* images, int nimages, const int* channels, ////////////////// C O M P A R E H I S T O G R A M S //////////////////////// -double compareHist( const Mat& H1, const Mat& H2, int method ) +double cv::compareHist( const InputArray& _H1, const InputArray& _H2, int method ) { + Mat H1 = _H1.getMat(), H2 = _H2.getMat(); const Mat* arrays[] = {&H1, &H2, 0}; Mat planes[2]; NAryMatIterator it(arrays, planes); double result = 0; - int i, len; + int j, len = (int)it.size; CV_Assert( H1.type() == H2.type() && H1.type() == CV_32F ); @@ -1309,7 +1331,7 @@ double compareHist( const Mat& H1, const Mat& H2, int method ) CV_Assert( it.planes[0].isContinuous() && it.planes[1].isContinuous() ); - for( i = 0; i < it.nplanes; i++, ++it ) + for( size_t i = 0; i < it.nplanes; i++, ++it ) { const float* h1 = (const float*)it.planes[0].data; const float* h2 = (const float*)it.planes[1].data; @@ -1317,20 +1339,20 @@ double compareHist( const Mat& H1, const Mat& H2, int method ) if( method == CV_COMP_CHISQR ) { - for( i = 0; i < len; i++ ) + for( j = 0; j < len; j++ ) { - double a = h1[i] - h2[i]; - double b = h1[i] + h2[i]; + double a = h1[j] - h2[j]; + double b = h1[j] + h2[j]; if( fabs(b) > FLT_EPSILON ) result += a*a/b; } } else if( method == CV_COMP_CORREL ) { - for( i = 0; i < len; i++ ) + for( j = 0; j < len; j++ ) { - double a = h1[i]; - double b = h2[i]; + double a = h1[j]; + double b = h2[j]; s12 += a*b; s1 += a; @@ -1341,15 +1363,15 @@ double compareHist( const Mat& H1, const Mat& H2, int method ) } else if( method == CV_COMP_INTERSECT ) { - for( i = 0; i < len; i++ ) - result += std::min(h1[i], h2[i]); + for( j = 0; j < len; j++ ) + result += std::min(h1[j], h2[j]); } else if( method == CV_COMP_BHATTACHARYYA ) { - for( i = 0; i < len; i++ ) + for( j = 0; j < len; j++ ) { - double a = h1[i]; - double b = h2[i]; + double a = h1[j]; + double b = h2[j]; result += std::sqrt(a*b); s1 += a; s2 += b; @@ -1361,9 +1383,7 @@ double compareHist( const Mat& H1, const Mat& H2, int method ) if( method == CV_COMP_CORREL ) { - size_t total = 1; - for( i = 0; i < H1.dims; i++ ) - total *= H1.size[i]; + size_t total = H1.total(); double scale = 1./total; double num = s12 - s1*s2*scale; double denom2 = (s11 - s1*s1*scale)*(s22 - s2*s2*scale); @@ -1380,7 +1400,7 @@ double compareHist( const Mat& H1, const Mat& H2, int method ) } -double compareHist( const SparseMat& H1, const SparseMat& H2, int method ) +double cv::compareHist( const SparseMat& H1, const SparseMat& H2, int method ) { double result = 0; int i, dims = H1.dims(); @@ -1491,12 +1511,6 @@ double compareHist( const SparseMat& H1, const SparseMat& H2, int method ) } -template<> void Ptr::delete_obj() -{ cvReleaseHist(&obj); } - -} - - const int CV_HIST_DEFAULT_TYPE = CV_32F; /* Creates new histogram */ @@ -2395,11 +2409,13 @@ CV_IMPL void cvEqualizeHist( const CvArr* srcarr, CvArr* dstarr ) } -void cv::equalizeHist( const Mat& src, Mat& dst ) +void cv::equalizeHist( const InputArray& _src, OutputArray _dst ) { - dst.create( src.size(), src.type() ); - CvMat _src = src, _dst = dst; - cvEqualizeHist( &_src, &_dst ); + Mat src = _src.getMat(); + _dst.create( src.size(), src.type() ); + Mat dst = _dst.getMat(); + CvMat _csrc = src, _cdst = dst; + cvEqualizeHist( &_csrc, &_cdst ); } /* Implementation of RTTI and Generic Functions for CvHistogram */ diff --git a/modules/imgproc/src/hough.cpp b/modules/imgproc/src/hough.cpp index a83d8211d9..51d32602ee 100644 --- a/modules/imgproc/src/hough.cpp +++ b/modules/imgproc/src/hough.cpp @@ -1090,44 +1090,53 @@ namespace cv const int STORAGE_SIZE = 1 << 12; -void HoughLines( const Mat& image, vector& lines, - double rho, double theta, int threshold, - double srn, double stn ) +static void seqToMat(const CvSeq* seq, OutputArray& _arr) { - CvMemStorage* storage = cvCreateMemStorage(STORAGE_SIZE); - CvMat _image = image; - CvSeq* seq = cvHoughLines2( &_image, storage, srn == 0 && stn == 0 ? + if( seq ) + { + _arr.create(1, seq->total, seq->flags, -1, true); + Mat arr = _arr.getMat(); + cvCvtSeqToArray(seq, arr.data); + } + else + _arr.release(); +} + +} + +void cv::HoughLines( const InputArray& _image, OutputArray _lines, + double rho, double theta, int threshold, + double srn, double stn ) +{ + Ptr storage = cvCreateMemStorage(STORAGE_SIZE); + CvMat c_image = _image.getMat(); + CvSeq* seq = cvHoughLines2( &c_image, storage, srn == 0 && stn == 0 ? CV_HOUGH_STANDARD : CV_HOUGH_MULTI_SCALE, rho, theta, threshold, srn, stn ); - Seq(seq).copyTo(lines); - cvReleaseMemStorage(&storage); + seqToMat(seq, _lines); } -void HoughLinesP( Mat& image, vector& lines, - double rho, double theta, int threshold, - double minLineLength, double maxGap ) +void cv::HoughLinesP( const InputArray& _image, OutputArray _lines, + double rho, double theta, int threshold, + double minLineLength, double maxGap ) { - CvMemStorage* storage = cvCreateMemStorage(STORAGE_SIZE); - CvMat _image = image; - CvSeq* seq = cvHoughLines2( &_image, storage, CV_HOUGH_PROBABILISTIC, + Ptr storage = cvCreateMemStorage(STORAGE_SIZE); + CvMat c_image = _image.getMat(); + CvSeq* seq = cvHoughLines2( &c_image, storage, CV_HOUGH_PROBABILISTIC, rho, theta, threshold, minLineLength, maxGap ); - Seq(seq).copyTo(lines); - cvReleaseMemStorage(&storage); + seqToMat(seq, _lines); } -void HoughCircles( const Mat& image, vector& circles, - int method, double dp, double min_dist, - double param1, double param2, - int minRadius, int maxRadius ) +void cv::HoughCircles( const InputArray& _image, OutputArray _circles, + int method, double dp, double min_dist, + double param1, double param2, + int minRadius, int maxRadius ) { - CvMemStorage* storage = cvCreateMemStorage(STORAGE_SIZE); - CvMat _image = image; - CvSeq* seq = cvHoughCircles( &_image, storage, method, + Ptr storage = cvCreateMemStorage(STORAGE_SIZE); + CvMat c_image = _image.getMat(); + CvSeq* seq = cvHoughCircles( &c_image, storage, method, dp, min_dist, param1, param2, minRadius, maxRadius ); - Seq(seq).copyTo(circles); - cvReleaseMemStorage(&storage); -} - + seqToMat(seq, _circles); } /* End of file. */ diff --git a/modules/imgproc/src/imgwarp.cpp b/modules/imgproc/src/imgwarp.cpp index 38467173df..2839f303ea 100644 --- a/modules/imgproc/src/imgwarp.cpp +++ b/modules/imgproc/src/imgwarp.cpp @@ -1313,10 +1313,12 @@ typedef void (*ResizeAreaFastFunc)( const Mat& src, Mat& dst, typedef void (*ResizeAreaFunc)( const Mat& src, Mat& dst, const DecimateAlpha* xofs, int xofs_count ); +} + ////////////////////////////////////////////////////////////////////////////////////////// -void resize( const Mat& src, Mat& dst, Size dsize, - double inv_scale_x, double inv_scale_y, int interpolation ) +void cv::resize( const InputArray& _src, OutputArray _dst, Size dsize, + double inv_scale_x, double inv_scale_y, int interpolation ) { static ResizeFunc linear_tab[] = { @@ -1420,6 +1422,7 @@ void resize( const Mat& src, Mat& dst, Size dsize, 0, resizeArea_, resizeArea_, 0 }; + Mat src = _src.getMat(); Size ssize = src.size(); CV_Assert( ssize.area() > 0 ); @@ -1434,7 +1437,8 @@ void resize( const Mat& src, Mat& dst, Size dsize, inv_scale_x = (double)dsize.width/src.cols; inv_scale_y = (double)dsize.height/src.rows; } - dst.create(dsize, src.type()); + _dst.create(dsize, src.type()); + Mat dst = _dst.getMat(); int depth = src.depth(), cn = src.channels(); double scale_x = 1./inv_scale_x, scale_y = 1./inv_scale_y; @@ -1653,6 +1657,9 @@ void resize( const Mat& src, Mat& dst, Size dsize, * General warping (affine, perspective, remap) * \****************************************************************************************/ +namespace cv +{ + template static void remapNearest( const Mat& _src, Mat& _dst, const Mat& _xy, int borderType, const Scalar& _borderValue ) @@ -2392,8 +2399,11 @@ typedef void (*RemapFunc)(const Mat& _src, Mat& _dst, const Mat& _xy, const Mat& _fxy, const void* _wtab, int borderType, const Scalar& _borderValue); -void remap( const Mat& src, Mat& dst, const Mat& map1, const Mat& map2, - int interpolation, int borderType, const Scalar& borderValue ) +} + +void cv::remap( const InputArray& _src, OutputArray _dst, + const InputArray& _map1, const InputArray& _map2, + int interpolation, int borderType, const Scalar& borderValue ) { static RemapNNFunc nn_tab[] = { @@ -2425,8 +2435,12 @@ void remap( const Mat& src, Mat& dst, const Mat& map1, const Mat& map2, remapLanczos4, float, 1>, 0, 0 }; + Mat src = _src.getMat(), map1 = _map1.getMat(), map2 = _map2.getMat(); + CV_Assert( (!map2.data || map2.size() == map1.size())); - dst.create( map1.size(), src.type() ); + + _dst.create( map1.size(), src.type() ); + Mat dst = _dst.getMat(); CV_Assert(dst.data != src.data); int depth = src.depth(), map_depth = map1.depth(); @@ -2650,9 +2664,11 @@ void remap( const Mat& src, Mat& dst, const Mat& map1, const Mat& map2, } -void convertMaps( const Mat& map1, const Mat& map2, Mat& dstmap1, Mat& dstmap2, - int dstm1type, bool nninterpolate ) +void cv::convertMaps( const InputArray& _map1, const InputArray& _map2, + OutputArray _dstmap1, OutputArray _dstmap2, + int dstm1type, bool nninterpolate ) { + Mat map1 = _map1.getMat(), map2 = _map2.getMat(), dstmap1, dstmap2; Size size = map1.size(); const Mat *m1 = &map1, *m2 = &map2; int m1type = m1->type(), m2type = m2->type(); @@ -2671,11 +2687,16 @@ void convertMaps( const Mat& map1, const Mat& map2, Mat& dstmap1, Mat& dstmap2, if( dstm1type <= 0 ) dstm1type = m1type == CV_16SC2 ? CV_32FC2 : CV_16SC2; CV_Assert( dstm1type == CV_16SC2 || dstm1type == CV_32FC1 || dstm1type == CV_32FC2 ); - dstmap1.create( size, dstm1type ); + _dstmap1.create( size, dstm1type ); + dstmap1 = _dstmap1.getMat(); + if( !nninterpolate && dstm1type != CV_32FC2 ) - dstmap2.create( size, dstm1type == CV_16SC2 ? CV_16UC1 : CV_32FC1 ); + { + _dstmap2.create( size, dstm1type == CV_16SC2 ? CV_16UC1 : CV_32FC1 ); + dstmap2 = _dstmap2.getMat(); + } else - dstmap2.release(); + _dstmap2.release(); if( m1type == dstm1type || (nninterpolate && ((m1type == CV_16SC2 && dstm1type == CV_32FC2) || @@ -2782,10 +2803,13 @@ void convertMaps( const Mat& map1, const Mat& map2, Mat& dstmap1, Mat& dstmap2, } -void warpAffine( const Mat& src, Mat& dst, const Mat& M0, Size dsize, - int flags, int borderType, const Scalar& borderValue ) +void cv::warpAffine( const InputArray& _src, OutputArray _dst, + const InputArray& _M0, Size dsize, + int flags, int borderType, const Scalar& borderValue ) { - dst.create( dsize, src.type() ); + Mat src = _src.getMat(), M0 = _M0.getMat(); + _dst.create( dsize, src.type() ); + Mat dst = _dst.getMat(); CV_Assert( dst.data != src.data && src.cols > 0 && src.rows > 0 ); const int BLOCK_SZ = 64; @@ -2917,10 +2941,13 @@ void warpAffine( const Mat& src, Mat& dst, const Mat& M0, Size dsize, } -void warpPerspective( const Mat& src, Mat& dst, const Mat& M0, Size dsize, - int flags, int borderType, const Scalar& borderValue ) +void cv::warpPerspective( const InputArray& _src, OutputArray _dst, const InputArray& _M0, + Size dsize, int flags, int borderType, const Scalar& borderValue ) { - dst.create( dsize, src.type() ); + Mat src = _src.getMat(), M0 = _M0.getMat(); + _dst.create( dsize, src.type() ); + Mat dst = _dst.getMat(); + CV_Assert( dst.data != src.data && src.cols > 0 && src.rows > 0 ); const int BLOCK_SZ = 32; @@ -2999,7 +3026,7 @@ void warpPerspective( const Mat& src, Mat& dst, const Mat& M0, Size dsize, } -Mat getRotationMatrix2D( Point2f center, double angle, double scale ) +cv::Mat cv::getRotationMatrix2D( Point2f center, double angle, double scale ) { angle *= CV_PI/180; double alpha = cos(angle)*scale; @@ -3042,7 +3069,7 @@ Mat getRotationMatrix2D( Point2f center, double angle, double scale ) * where: * cij - matrix coefficients, c22 = 1 */ -Mat getPerspectiveTransform( const Point2f src[], const Point2f dst[] ) +cv::Mat cv::getPerspectiveTransform( const Point2f src[], const Point2f dst[] ) { Mat M(3, 3, CV_64F), X(8, 1, CV_64F, M.data); double a[8][8], b[8]; @@ -3087,7 +3114,7 @@ Mat getPerspectiveTransform( const Point2f src[], const Point2f dst[] ) * where: * cij - matrix coefficients */ -Mat getAffineTransform( const Point2f src[], const Point2f dst[] ) +cv::Mat cv::getAffineTransform( const Point2f src[], const Point2f dst[] ) { Mat M(2, 3, CV_64F), X(6, 1, CV_64F, M.data); double a[6*6], b[6]; @@ -3110,10 +3137,13 @@ Mat getAffineTransform( const Point2f src[], const Point2f dst[] ) return M; } -void invertAffineTransform(const Mat& matM, Mat& _iM) +void cv::invertAffineTransform(const InputArray& _matM, OutputArray __iM) { + Mat matM = _matM.getMat(); CV_Assert(matM.rows == 2 && matM.cols == 3); - _iM.create(2, 3, matM.type()); + __iM.create(2, 3, matM.type()); + Mat _iM = __iM.getMat(); + if( matM.type() == CV_32F ) { const float* M = (const float*)matM.data; @@ -3148,8 +3178,6 @@ void invertAffineTransform(const Mat& matM, Mat& _iM) CV_Error( CV_StsUnsupportedFormat, "" ); } -} - CV_IMPL void cvResize( const CvArr* srcarr, CvArr* dstarr, int method ) { diff --git a/modules/imgproc/src/inpaint.cpp b/modules/imgproc/src/inpaint.cpp index 86fbbeb1a5..0fb66c257c 100644 --- a/modules/imgproc/src/inpaint.cpp +++ b/modules/imgproc/src/inpaint.cpp @@ -807,10 +807,11 @@ cvInpaint( const CvArr* _input_img, const CvArr* _inpaint_mask, CvArr* _output_i } } -void cv::inpaint( const Mat& src, const Mat& mask, Mat& dst, +void cv::inpaint( const InputArray& _src, const InputArray& _mask, OutputArray _dst, double inpaintRange, int flags ) { - dst.create( src.size(), src.type() ); - CvMat _src = src, _mask = mask, _dst = dst; - cvInpaint( &_src, &_mask, &_dst, inpaintRange, flags ); + Mat src = _src.getMat(); + _dst.create( src.size(), src.type() ); + CvMat c_src = src, c_mask = _mask.getMat(), c_dst = _dst.getMat(); + cvInpaint( &c_src, &c_mask, &c_dst, inpaintRange, flags ); } diff --git a/modules/imgproc/src/moments.cpp b/modules/imgproc/src/moments.cpp index fd0125cbc6..3e6b4d35c2 100644 --- a/modules/imgproc/src/moments.cpp +++ b/modules/imgproc/src/moments.cpp @@ -601,13 +601,14 @@ Moments::operator CvMoments() const return m; } + } -cv::Moments cv::moments( const Mat& array, bool binaryImage ) +cv::Moments cv::moments( const InputArray& _array, bool binaryImage ) { CvMoments om; - CvMat _array = array; - cvMoments(&_array, &om, binaryImage); + CvMat c_array = _array.getMat(); + cvMoments(&c_array, &om, binaryImage); return om; } diff --git a/modules/imgproc/src/morph.cpp b/modules/imgproc/src/morph.cpp index 901d6a096f..5446842cb1 100644 --- a/modules/imgproc/src/morph.cpp +++ b/modules/imgproc/src/morph.cpp @@ -821,10 +821,12 @@ template struct MorphFilter : BaseFilter vector ptrs; VecOp vecOp; }; + +} /////////////////////////////////// External Interface ///////////////////////////////////// -Ptr getMorphologyRowFilter(int op, int type, int ksize, int anchor) +cv::Ptr cv::getMorphologyRowFilter(int op, int type, int ksize, int anchor) { int depth = CV_MAT_DEPTH(type); if( anchor < 0 ) @@ -865,7 +867,7 @@ Ptr getMorphologyRowFilter(int op, int type, int ksize, int ancho return Ptr(0); } -Ptr getMorphologyColumnFilter(int op, int type, int ksize, int anchor) +cv::Ptr cv::getMorphologyColumnFilter(int op, int type, int ksize, int anchor) { int depth = CV_MAT_DEPTH(type); if( anchor < 0 ) @@ -907,8 +909,9 @@ Ptr getMorphologyColumnFilter(int op, int type, int ksize, int } -Ptr getMorphologyFilter(int op, int type, const Mat& kernel, Point anchor) +cv::Ptr cv::getMorphologyFilter(int op, int type, const InputArray& _kernel, Point anchor) { + Mat kernel = _kernel.getMat(); int depth = CV_MAT_DEPTH(type); anchor = normalizeAnchor(anchor, kernel.size()); CV_Assert( op == MORPH_ERODE || op == MORPH_DILATE ); @@ -940,10 +943,11 @@ Ptr getMorphologyFilter(int op, int type, const Mat& kernel, Point a } -Ptr createMorphologyFilter( int op, int type, const Mat& kernel, +cv::Ptr cv::createMorphologyFilter( int op, int type, const InputArray& _kernel, Point anchor, int _rowBorderType, int _columnBorderType, const Scalar& _borderValue ) { + Mat kernel = _kernel.getMat(); anchor = normalizeAnchor(anchor, kernel.size()); Ptr rowFilter; @@ -978,7 +982,7 @@ Ptr createMorphologyFilter( int op, int type, const Mat& kernel, } -Mat getStructuringElement(int shape, Size ksize, Point anchor) +cv::Mat cv::getStructuringElement(int shape, Size ksize, Point anchor) { int i, j; int r = 0, c = 0; @@ -1031,31 +1035,36 @@ Mat getStructuringElement(int shape, Size ksize, Point anchor) return elem; } -static void morphOp( int op, const Mat& src, Mat& dst, const Mat& _kernel, +namespace cv +{ + +static void morphOp( int op, const InputArray& _src, OutputArray& _dst, + const InputArray& _kernel, Point anchor, int iterations, int borderType, const Scalar& borderValue ) { - Mat kernel; - Size ksize = _kernel.data ? _kernel.size() : Size(3,3); + Mat src = _src.getMat(), kernel = _kernel.getMat(); + Size ksize = kernel.data ? kernel.size() : Size(3,3); anchor = normalizeAnchor(anchor, ksize); CV_Assert( anchor.inside(Rect(0, 0, ksize.width, ksize.height)) ); - if( iterations == 0 || _kernel.rows*_kernel.cols == 1 ) + _dst.create( src.size(), src.type() ); + Mat dst = _dst.getMat(); + + if( iterations == 0 || kernel.rows*kernel.cols == 1 ) { src.copyTo(dst); return; } - dst.create( src.size(), src.type() ); - - if( !_kernel.data ) + if( !kernel.data ) { kernel = getStructuringElement(MORPH_RECT, Size(1+iterations*2,1+iterations*2)); anchor = Point(iterations, iterations); iterations = 1; } - else if( iterations > 1 && countNonZero(_kernel) == _kernel.rows*_kernel.cols ) + else if( iterations > 1 && countNonZero(kernel) == kernel.rows*kernel.cols ) { anchor = Point(anchor.x*iterations, anchor.y*iterations); kernel = getStructuringElement(MORPH_RECT, @@ -1064,8 +1073,6 @@ static void morphOp( int op, const Mat& src, Mat& dst, const Mat& _kernel, anchor); iterations = 1; } - else - kernel = _kernel; Ptr f = createMorphologyFilter(op, src.type(), kernel, anchor, borderType, borderType, borderValue ); @@ -1074,29 +1081,36 @@ static void morphOp( int op, const Mat& src, Mat& dst, const Mat& _kernel, for( int i = 1; i < iterations; i++ ) f->apply( dst, dst ); } + +template<> void Ptr::delete_obj() +{ cvReleaseStructuringElement(&obj); } +} -void erode( const Mat& src, Mat& dst, const Mat& kernel, - Point anchor, int iterations, - int borderType, const Scalar& borderValue ) +void cv::erode( const InputArray& src, OutputArray dst, const InputArray& kernel, + Point anchor, int iterations, + int borderType, const Scalar& borderValue ) { morphOp( MORPH_ERODE, src, dst, kernel, anchor, iterations, borderType, borderValue ); } -void dilate( const Mat& src, Mat& dst, const Mat& kernel, - Point anchor, int iterations, - int borderType, const Scalar& borderValue ) +void cv::dilate( const InputArray& src, OutputArray dst, const InputArray& kernel, + Point anchor, int iterations, + int borderType, const Scalar& borderValue ) { morphOp( MORPH_DILATE, src, dst, kernel, anchor, iterations, borderType, borderValue ); } -void morphologyEx( const Mat& src, Mat& dst, int op, const Mat& kernel, - Point anchor, int iterations, int borderType, - const Scalar& borderValue ) +void cv::morphologyEx( const InputArray& _src, OutputArray _dst, int op, + const InputArray& kernel, Point anchor, int iterations, + int borderType, const Scalar& borderValue ) { - Mat temp; + Mat src = _src.getMat(), temp; + _dst.create(src.size(), src.type()); + Mat dst = _dst.getMat(); + switch( op ) { case MORPH_ERODE: @@ -1137,13 +1151,6 @@ void morphologyEx( const Mat& src, Mat& dst, int op, const Mat& kernel, } } - -template<> void Ptr::delete_obj() -{ cvReleaseStructuringElement(&obj); } - - -} - CV_IMPL IplConvKernel * cvCreateStructuringElementEx( int cols, int rows, int anchorX, int anchorY, diff --git a/modules/imgproc/src/pyramids.cpp b/modules/imgproc/src/pyramids.cpp index 8e5cb8242a..83a75de8da 100644 --- a/modules/imgproc/src/pyramids.cpp +++ b/modules/imgproc/src/pyramids.cpp @@ -399,11 +399,15 @@ pyrUp_( const Mat& _src, Mat& _dst ) typedef void (*PyrFunc)(const Mat&, Mat&); -void pyrDown( const Mat& _src, Mat& _dst, const Size& _dsz ) +} + +void cv::pyrDown( const InputArray& _src, OutputArray _dst, const Size& _dsz ) { - Size dsz = _dsz == Size() ? Size((_src.cols + 1)/2, (_src.rows + 1)/2) : _dsz; - _dst.create( dsz, _src.type() ); - int depth = _src.depth(); + Mat src = _src.getMat(); + Size dsz = _dsz == Size() ? Size((src.cols + 1)/2, (src.rows + 1)/2) : _dsz; + _dst.create( dsz, src.type() ); + Mat dst = _dst.getMat(); + int depth = src.depth(); PyrFunc func = 0; if( depth == CV_8U ) func = pyrDown_, PyrDownVec_32s8u>; @@ -416,14 +420,16 @@ void pyrDown( const Mat& _src, Mat& _dst, const Size& _dsz ) else CV_Error( CV_StsUnsupportedFormat, "" ); - func( _src, _dst ); + func( src, dst ); } -void pyrUp( const Mat& _src, Mat& _dst, const Size& _dsz ) +void cv::pyrUp( const InputArray& _src, OutputArray _dst, const Size& _dsz ) { - Size dsz = _dsz == Size() ? Size(_src.cols*2, _src.rows*2) : _dsz; - _dst.create( dsz, _src.type() ); - int depth = _src.depth(); + Mat src = _src.getMat(); + Size dsz = _dsz == Size() ? Size(src.cols*2, src.rows*2) : _dsz; + _dst.create( dsz, src.type() ); + Mat dst = _dst.getMat(); + int depth = src.depth(); PyrFunc func = 0; if( depth == CV_8U ) func = pyrUp_, NoVec >; @@ -436,17 +442,16 @@ void pyrUp( const Mat& _src, Mat& _dst, const Size& _dsz ) else CV_Error( CV_StsUnsupportedFormat, "" ); - func( _src, _dst ); + func( src, dst ); } -void buildPyramid( const Mat& _src, vector& _dst, int maxlevel ) +void cv::buildPyramid( const InputArray& _src, OutputArrayOfArrays _dst, int maxlevel ) { - _dst.resize( maxlevel + 1 ); - _dst[0] = _src; + Mat src = _src.getMat(); + _dst.create( maxlevel + 1, 1, 0 ); + _dst.getMatRef(0) = src; for( int i = 1; i <= maxlevel; i++ ) - pyrDown( _dst[i-1], _dst[i] ); -} - + pyrDown( _dst.getMatRef(i-1), _dst.getMatRef(i) ); } CV_IMPL void cvPyrDown( const void* srcarr, void* dstarr, int _filter ) diff --git a/modules/imgproc/src/samplers.cpp b/modules/imgproc/src/samplers.cpp index e21814c1e9..24e8deefa2 100644 --- a/modules/imgproc/src/samplers.cpp +++ b/modules/imgproc/src/samplers.cpp @@ -868,13 +868,15 @@ cvGetQuadrangleSubPix( const void* srcarr, void* dstarr, const CvMat* mat ) } -void cv::getRectSubPix( const Mat& image, Size patchSize, Point2f center, - Mat& patch, int patchType ) +void cv::getRectSubPix( const InputArray& _image, Size patchSize, Point2f center, + OutputArray _patch, int patchType ) { - patch.create(patchSize, patchType < 0 ? image.type() : + Mat image = _image.getMat(); + _patch.create(patchSize, patchType < 0 ? image.type() : CV_MAKETYPE(CV_MAT_DEPTH(patchType),image.channels())); - CvMat _image = image, _patch = patch; - cvGetRectSubPix(&_image, &_patch, center); + Mat patch = _patch.getMat(); + CvMat _cimage = image, _cpatch = patch; + cvGetRectSubPix(&_cimage, &_cpatch, center); } /* End of file. */ diff --git a/modules/imgproc/src/segmentation.cpp b/modules/imgproc/src/segmentation.cpp index 11cbd302df..f7bf82272a 100644 --- a/modules/imgproc/src/segmentation.cpp +++ b/modules/imgproc/src/segmentation.cpp @@ -303,10 +303,10 @@ cvWatershed( const CvArr* srcarr, CvArr* dstarr ) } -void cv::watershed( const Mat& src, Mat& markers ) +void cv::watershed( const InputArray& src, InputOutputArray markers ) { - CvMat _src = src, _markers = markers; - cvWatershed( &_src, &_markers ); + CvMat c_src = src.getMat(), c_markers = markers.getMat(); + cvWatershed( &c_src, &c_markers ); } @@ -523,14 +523,16 @@ cvPyrMeanShiftFiltering( const CvArr* srcarr, CvArr* dstarr, } } -void cv::pyrMeanShiftFiltering( const Mat& src, Mat& dst, +void cv::pyrMeanShiftFiltering( const InputArray& _src, OutputArray _dst, double sp, double sr, int maxLevel, TermCriteria termcrit ) { + Mat src = _src.getMat(); + if( src.empty() ) return; - dst.create( src.size(), src.type() ); - CvMat _src = src, _dst = dst; - cvPyrMeanShiftFiltering( &_src, &_dst, sp, sr, maxLevel, termcrit ); + _dst.create( src.size(), src.type() ); + CvMat c_src = src, c_dst = _dst.getMat(); + cvPyrMeanShiftFiltering( &c_src, &c_dst, sp, sr, maxLevel, termcrit ); } diff --git a/modules/imgproc/src/smooth.cpp b/modules/imgproc/src/smooth.cpp index 273ccc54f4..b9f93262ad 100644 --- a/modules/imgproc/src/smooth.cpp +++ b/modules/imgproc/src/smooth.cpp @@ -197,7 +197,9 @@ template struct ColumnSum : public BaseColumnFilter }; -Ptr getRowSumFilter(int srcType, int sumType, int ksize, int anchor) +} + +cv::Ptr cv::getRowSumFilter(int srcType, int sumType, int ksize, int anchor) { int sdepth = CV_MAT_DEPTH(srcType), ddepth = CV_MAT_DEPTH(sumType); CV_Assert( CV_MAT_CN(sumType) == CV_MAT_CN(srcType) ); @@ -232,8 +234,8 @@ Ptr getRowSumFilter(int srcType, int sumType, int ksize, int anch } -Ptr getColumnSumFilter(int sumType, int dstType, int ksize, - int anchor, double scale) +cv::Ptr cv::getColumnSumFilter(int sumType, int dstType, int ksize, + int anchor, double scale) { int sdepth = CV_MAT_DEPTH(sumType), ddepth = CV_MAT_DEPTH(dstType); CV_Assert( CV_MAT_CN(sumType) == CV_MAT_CN(dstType) ); @@ -272,7 +274,7 @@ Ptr getColumnSumFilter(int sumType, int dstType, int ksize, } -Ptr createBoxFilter( int srcType, int dstType, Size ksize, +cv::Ptr cv::createBoxFilter( int srcType, int dstType, Size ksize, Point anchor, bool normalize, int borderType ) { int sdepth = CV_MAT_DEPTH(srcType); @@ -292,14 +294,16 @@ Ptr createBoxFilter( int srcType, int dstType, Size ksize, } -void boxFilter( const Mat& src, Mat& dst, int ddepth, +void cv::boxFilter( const InputArray& _src, OutputArray _dst, int ddepth, Size ksize, Point anchor, bool normalize, int borderType ) { + Mat src = _src.getMat(); int sdepth = src.depth(), cn = src.channels(); if( ddepth < 0 ) ddepth = sdepth; - dst.create( src.size(), CV_MAKETYPE(ddepth, cn) ); + _dst.create( src.size(), CV_MAKETYPE(ddepth, cn) ); + Mat dst = _dst.getMat(); if( borderType != BORDER_CONSTANT && normalize ) { if( src.rows == 1 ) @@ -312,7 +316,7 @@ void boxFilter( const Mat& src, Mat& dst, int ddepth, f->apply( src, dst ); } -void blur( const Mat& src, CV_OUT Mat& dst, +void cv::blur( const InputArray& src, OutputArray dst, Size ksize, Point anchor, int borderType ) { boxFilter( src, dst, -1, ksize, anchor, true, borderType ); @@ -322,7 +326,7 @@ void blur( const Mat& src, CV_OUT Mat& dst, Gaussian Blur \****************************************************************************************/ -Mat getGaussianKernel( int n, double sigma, int ktype ) +cv::Mat cv::getGaussianKernel( int n, double sigma, int ktype ) { const int SMALL_GAUSSIAN_SIZE = 7; static const float small_gaussian_tab[][SMALL_GAUSSIAN_SIZE] = @@ -375,7 +379,7 @@ Mat getGaussianKernel( int n, double sigma, int ktype ) } -Ptr createGaussianFilter( int type, Size ksize, +cv::Ptr cv::createGaussianFilter( int type, Size ksize, double sigma1, double sigma2, int borderType ) { @@ -406,17 +410,20 @@ Ptr createGaussianFilter( int type, Size ksize, } -void GaussianBlur( const Mat& src, Mat& dst, Size ksize, +void cv::GaussianBlur( const InputArray& _src, OutputArray _dst, Size ksize, double sigma1, double sigma2, int borderType ) { + Mat src = _src.getMat(); + _dst.create( src.size(), src.type() ); + Mat dst = _dst.getMat(); + if( ksize.width == 1 && ksize.height == 1 ) { src.copyTo(dst); return; } - dst.create( src.size(), src.type() ); if( borderType != BORDER_CONSTANT ) { if( src.rows == 1 ) @@ -433,6 +440,9 @@ void GaussianBlur( const Mat& src, Mat& dst, Size ksize, Median Filter \****************************************************************************************/ +namespace cv +{ + #if _MSC_VER >= 1200 #pragma warning( disable: 4244 ) #endif @@ -1207,9 +1217,14 @@ medianBlur_SortNet( const Mat& _src, Mat& _dst, int m ) } } - -void medianBlur( const Mat& src0, Mat& dst, int ksize ) +} + +void cv::medianBlur( const InputArray& _src0, OutputArray _dst, int ksize ) { + Mat src0 = _src0.getMat(); + _dst.create( src0.size(), src0.type() ); + Mat dst = _dst.getMat(); + if( ksize <= 1 ) { src0.copyTo(dst); @@ -1225,8 +1240,7 @@ void medianBlur( const Mat& src0, Mat& dst, int ksize ) && src0.depth() > CV_8U #endif ); - - dst.create( src0.size(), src0.type() ); + Mat src; if( useSortNet ) { @@ -1266,6 +1280,9 @@ void medianBlur( const Mat& src0, Mat& dst, int ksize ) Bilateral Filtering \****************************************************************************************/ +namespace cv +{ + static void bilateralFilter_8u( const Mat& src, Mat& dst, int d, double sigma_color, double sigma_space, @@ -1497,12 +1514,16 @@ bilateralFilter_32f( const Mat& src, Mat& dst, int d, } } +} -void bilateralFilter( const Mat& src, Mat& dst, int d, +void cv::bilateralFilter( const InputArray& _src, OutputArray _dst, int d, double sigmaColor, double sigmaSpace, int borderType ) { - dst.create( src.size(), src.type() ); + Mat src = _src.getMat(); + _dst.create( src.size(), src.type() ); + Mat dst = _dst.getMat(); + if( src.depth() == CV_8U ) bilateralFilter_8u( src, dst, d, sigmaColor, sigmaSpace, borderType ); else if( src.depth() == CV_32F ) @@ -1512,8 +1533,6 @@ void bilateralFilter( const Mat& src, Mat& dst, int d, "Bilateral filtering is only implemented for 8u and 32f images" ); } -} - ////////////////////////////////////////////////////////////////////////////////////////// CV_IMPL void diff --git a/modules/imgproc/src/sumpixels.cpp b/modules/imgproc/src/sumpixels.cpp index 1c2012052e..0562f6a1e8 100644 --- a/modules/imgproc/src/sumpixels.cpp +++ b/modules/imgproc/src/sumpixels.cpp @@ -45,28 +45,17 @@ namespace cv { -template inline QT sqr(uchar a) { return a*a; } -template inline QT sqr(float a) { return a*a; } -template inline QT sqr(double a) { return a*a; } -template<> inline double sqr(uchar a) { return CV_8TO32F_SQR(a); } - - template -void integral_( const Mat& _src, Mat& _sum, Mat& _sqsum, Mat& _tilted ) +void integral_( const T* src, size_t srcstep, ST* sum, size_t sumstep, + QT* sqsum, size_t sqsumstep, ST* tilted, size_t tiltedstep, + Size size, int cn ) { - int cn = _src.channels(); - Size size = _src.size(); int x, y, k; - const T* src = (const T*)_src.data; - ST* sum = (ST*)_sum.data; - ST* tilted = (ST*)_tilted.data; - QT* sqsum = (QT*)_sqsum.data; - - int srcstep = (int)(_src.step/sizeof(T)); - int sumstep = (int)(_sum.step/sizeof(ST)); - int tiltedstep = (int)(_tilted.step/sizeof(ST)); - int sqsumstep = (int)(_sqsum.step/sizeof(QT)); + srcstep /= sizeof(T); + sumstep /= sizeof(ST); + tiltedstep /= sizeof(ST); + sqsumstep /= sizeof(QT); size.width *= cn; @@ -113,7 +102,7 @@ void integral_( const Mat& _src, Mat& _sum, Mat& _sqsum, Mat& _tilted ) { T it = src[x]; s += it; - sq += sqr(it); + sq += (QT)it*it; ST t = sum[x - sumstep] + s; QT tq = sqsum[x - sqsumstep] + sq; sum[x] = t; @@ -128,45 +117,55 @@ void integral_( const Mat& _src, Mat& _sum, Mat& _sqsum, Mat& _tilted ) ST* buf = _buf; ST s; QT sq; - for( k = 0; k < cn; k++, src++, sum++, tilted++, sqsum++, buf++ ) + for( k = 0; k < cn; k++, src++, sum++, tilted++, buf++ ) { sum[-cn] = tilted[-cn] = 0; - sqsum[-cn] = 0; for( x = 0, s = 0, sq = 0; x < size.width; x += cn ) { T it = src[x]; buf[x] = tilted[x] = it; s += it; - sq += sqr(it); + sq += (QT)it*it; sum[x] = s; - sqsum[x] = sq; + if( sqsum ) + sqsum[x] = sq; } if( size.width == cn ) buf[cn] = 0; + + if( sqsum ) + { + sqsum[-cn] = 0; + sqsum++; + } } for( y = 1; y < size.height; y++ ) { src += srcstep - cn; sum += sumstep - cn; - sqsum += sqsumstep - cn; tilted += tiltedstep - cn; buf += -cn; + + if( sqsum ) + sqsum += sqsumstep - cn; - for( k = 0; k < cn; k++, src++, sum++, sqsum++, tilted++, buf++ ) + for( k = 0; k < cn; k++, src++, sum++, tilted++, buf++ ) { T it = src[0]; ST t0 = s = it; - QT tq0 = sq = sqr(it); + QT tq0 = sq = (QT)it*it; sum[-cn] = 0; - sqsum[-cn] = 0; + if( sqsum ) + sqsum[-cn] = 0; tilted[-cn] = tilted[-tiltedstep]; sum[0] = sum[-sumstep] + t0; - sqsum[0] = sqsum[-sqsumstep] + tq0; + if( sqsum ) + sqsum[0] = sqsum[-sqsumstep] + tq0; tilted[0] = tilted[-tiltedstep] + t0 + buf[cn]; for( x = cn; x < size.width - cn; x += cn ) @@ -174,11 +173,12 @@ void integral_( const Mat& _src, Mat& _sum, Mat& _sqsum, Mat& _tilted ) ST t1 = buf[x]; buf[x - cn] = t1 + t0; t0 = it = src[x]; - tq0 = sqr(it); + tq0 = (QT)it*it; s += t0; sq += tq0; sum[x] = sum[x - sumstep] + s; - sqsum[x] = sqsum[x - sqsumstep] + sq; + if( sqsum ) + sqsum[x] = sqsum[x - sqsumstep] + sq; t1 += buf[x + cn] + t0 + tilted[x - tiltedstep - cn]; tilted[x] = t1; } @@ -188,79 +188,96 @@ void integral_( const Mat& _src, Mat& _sum, Mat& _sqsum, Mat& _tilted ) ST t1 = buf[x]; buf[x - cn] = t1 + t0; t0 = it = src[x]; - tq0 = sqr(it); + tq0 = (QT)it*it; s += t0; sq += tq0; sum[x] = sum[x - sumstep] + s; - sqsum[x] = sqsum[x - sqsumstep] + sq; + if( sqsum ) + sqsum[x] = sqsum[x - sqsumstep] + sq; tilted[x] = t0 + t1 + tilted[x - tiltedstep - cn]; buf[x] = t0; } + + if( sqsum ) + sqsum++; } } } } -typedef void (*IntegralFunc)(const Mat& _src, Mat& _sum, Mat& _sqsum, Mat& _tilted ); + +#define DEF_INTEGRAL_FUNC(suffix, T, ST, QT) \ +void integral_##suffix( T* src, size_t srcstep, ST* sum, size_t sumstep, QT* sqsum, size_t sqsumstep, \ + ST* tilted, size_t tiltedstep, Size size, int cn ) \ +{ integral_(src, srcstep, sum, sumstep, sqsum, sqsumstep, tilted, tiltedstep, size, cn); } + +DEF_INTEGRAL_FUNC(8u32s, uchar, int, double) +DEF_INTEGRAL_FUNC(8u32f, uchar, float, double) +DEF_INTEGRAL_FUNC(8u64f, uchar, double, double) +DEF_INTEGRAL_FUNC(32f, float, float, float) +DEF_INTEGRAL_FUNC(32f64f, float, double, double) +DEF_INTEGRAL_FUNC(64f, double, double, double) + +typedef void (*IntegralFunc)(const uchar* src, size_t srcstep, uchar* sum, size_t sumstep, + uchar* sqsum, size_t sqsumstep, uchar* tilted, size_t tstep, + Size size, int cn ); + +} + -static void -integral( const Mat& src, Mat& sum, Mat* _sqsum, Mat* _tilted, int sdepth ) +void cv::integral( const InputArray& _src, OutputArray _sum, OutputArray _sqsum, OutputArray _tilted, int sdepth ) { + Mat src = _src.getMat(), sum, sqsum, tilted; int depth = src.depth(), cn = src.channels(); Size isize(src.cols + 1, src.rows+1); - Mat sqsum, tilted; if( sdepth <= 0 ) sdepth = depth == CV_8U ? CV_32S : CV_64F; sdepth = CV_MAT_DEPTH(sdepth); - sum.create( isize, CV_MAKETYPE(sdepth, cn) ); + _sum.create( isize, CV_MAKETYPE(sdepth, cn) ); + sum = _sum.getMat(); - if( _tilted ) - _tilted->create( isize, CV_MAKETYPE(sdepth, cn) ); - else - _tilted = &tilted; + if( _tilted.needed() ) + { + _tilted.create( isize, CV_MAKETYPE(sdepth, cn) ); + tilted = _tilted.getMat(); + } - if( !_sqsum ) - _sqsum = &sqsum; + if( _sqsum.needed() ) + { + _sqsum.create( isize, CV_MAKETYPE(CV_64F, cn) ); + sqsum = _sqsum.getMat(); + } - if( _sqsum != &sqsum || _tilted->data ) - _sqsum->create( isize, CV_MAKETYPE(CV_64F, cn) ); - IntegralFunc func = 0; if( depth == CV_8U && sdepth == CV_32S ) - func = integral_; + func = (IntegralFunc)integral_8u32s; else if( depth == CV_8U && sdepth == CV_32F ) - func = integral_; + func = (IntegralFunc)integral_8u32f; else if( depth == CV_8U && sdepth == CV_64F ) - func = integral_; + func = (IntegralFunc)integral_8u64f; else if( depth == CV_32F && sdepth == CV_32F ) - func = integral_; + func = (IntegralFunc)integral_32f; else if( depth == CV_32F && sdepth == CV_64F ) - func = integral_; + func = (IntegralFunc)integral_32f64f; else if( depth == CV_64F && sdepth == CV_64F ) - func = integral_; + func = (IntegralFunc)integral_64f; else CV_Error( CV_StsUnsupportedFormat, "" ); - func( src, sum, *_sqsum, *_tilted ); -} - -void integral( const Mat& src, Mat& sum, int sdepth ) -{ - integral( src, sum, 0, 0, sdepth ); + func( src.data, src.step, sum.data, sum.step, sqsum.data, sqsum.step, + tilted.data, tilted.step, src.size(), cn ); } - -void integral( const Mat& src, Mat& sum, Mat& sqsum, int sdepth ) + +void cv::integral( const InputArray& src, OutputArray sum, int sdepth ) { - integral( src, sum, &sqsum, 0, sdepth ); + integral( src, sum, OutputArray(), OutputArray(), sdepth ); } -void integral( const Mat& src, Mat& sum, Mat& sqsum, Mat& tilted, int sdepth ) +void cv::integral( const InputArray& src, OutputArray sum, OutputArray sqsum, int sdepth ) { - integral( src, sum, &sqsum, &tilted, sdepth ); -} - + integral( src, sum, sqsum, OutputArray(), sdepth ); } @@ -283,7 +300,8 @@ cvIntegral( const CvArr* image, CvArr* sumImage, tilted0 = tilted = cv::cvarrToMat(tiltedSumImage); ptilted = &tilted; } - cv::integral( src, sum, psqsum, ptilted, sum.depth() ); + cv::integral( src, sum, psqsum ? cv::OutputArray(*psqsum) : cv::OutputArray(), + ptilted ? cv::OutputArray(*ptilted) : cv::OutputArray(), sum.depth() ); CV_Assert( sum.data == sum0.data && sqsum.data == sqsum0.data && tilted.data == tilted0.data ); } diff --git a/modules/imgproc/src/templmatch.cpp b/modules/imgproc/src/templmatch.cpp index 9c4188c05b..a82f348637 100644 --- a/modules/imgproc/src/templmatch.cpp +++ b/modules/imgproc/src/templmatch.cpp @@ -233,10 +233,11 @@ cv::crossCorr( const Mat& img, const Mat& templ, Mat& corr, icvCrossCorr( &_img, &_templ, &_corr, anchor, delta, borderType ); }*/ +} /*****************************************************************************************/ -void matchTemplate( const Mat& _img, const Mat& _templ, Mat& result, int method ) +void cv::matchTemplate( const InputArray& _img, const InputArray& _templ, OutputArray _result, int method ) { CV_Assert( CV_TM_SQDIFF <= method && method <= CV_TM_CCOEFF_NORMED ); @@ -246,17 +247,19 @@ void matchTemplate( const Mat& _img, const Mat& _templ, Mat& result, int method method == CV_TM_SQDIFF_NORMED || method == CV_TM_CCOEFF_NORMED; - Mat img = _img, templ = _templ; + Mat img = _img.getMat(), templ = _templ.getMat(); if( img.rows < templ.rows || img.cols < templ.cols ) std::swap(img, templ); CV_Assert( (img.depth() == CV_8U || img.depth() == CV_32F) && img.type() == templ.type() ); + Size corrSize(img.cols - templ.cols + 1, img.rows - templ.rows + 1); + _result.create(corrSize, CV_32F); + Mat result = _result.getMat(); + int cn = img.channels(); - crossCorr( img, templ, result, - Size(img.cols - templ.cols + 1, img.rows - templ.rows + 1), - CV_32F, Point(0,0), 0, 0); + crossCorr( img, templ, result, result.size(), result.type(), Point(0,0), 0, 0); if( method == CV_TM_CCORR ) return; @@ -368,8 +371,6 @@ void matchTemplate( const Mat& _img, const Mat& _templ, Mat& result, int method } } -} - CV_IMPL void cvMatchTemplate( const CvArr* _img, const CvArr* _templ, CvArr* _result, int method ) diff --git a/modules/imgproc/src/thresh.cpp b/modules/imgproc/src/thresh.cpp index f041e438dd..2b0da32195 100644 --- a/modules/imgproc/src/thresh.cpp +++ b/modules/imgproc/src/thresh.cpp @@ -475,20 +475,24 @@ getThreshVal_Otsu_8u( const Mat& _src ) return max_val; } - -double threshold( const Mat& _src, Mat& _dst, double thresh, double maxval, int type ) +} + +double cv::threshold( const InputArray& _src, OutputArray _dst, double thresh, double maxval, int type ) { + Mat src = _src.getMat(); bool use_otsu = (type & THRESH_OTSU) != 0; type &= THRESH_MASK; if( use_otsu ) { - CV_Assert( _src.type() == CV_8UC1 ); - thresh = getThreshVal_Otsu_8u(_src); + CV_Assert( src.type() == CV_8UC1 ); + thresh = getThreshVal_Otsu_8u(src); } - _dst.create( _src.size(), _src.type() ); - if( _src.depth() == CV_8U ) + _dst.create( src.size(), src.type() ); + Mat dst = _dst.getMat(); + + if( src.depth() == CV_8U ) { int ithresh = cvFloor(thresh); thresh = ithresh; @@ -506,16 +510,16 @@ double threshold( const Mat& _src, Mat& _dst, double thresh, double maxval, int int v = type == THRESH_BINARY ? (ithresh >= 255 ? 0 : imaxval) : type == THRESH_BINARY_INV ? (ithresh >= 255 ? imaxval : 0) : type == THRESH_TRUNC ? imaxval : 0; - _dst = Scalar::all(v); + dst = Scalar::all(v); } else - _src.copyTo(_dst); + src.copyTo(dst); } else - thresh_8u( _src, _dst, (uchar)ithresh, (uchar)imaxval, type ); + thresh_8u( src, dst, (uchar)ithresh, (uchar)imaxval, type ); } - else if( _src.depth() == CV_32F ) - thresh_32f( _src, _dst, (float)thresh, (float)maxval, type ); + else if( src.depth() == CV_32F ) + thresh_32f( src, dst, (float)thresh, (float)maxval, type ); else CV_Error( CV_StsUnsupportedFormat, "" ); @@ -523,31 +527,33 @@ double threshold( const Mat& _src, Mat& _dst, double thresh, double maxval, int } -void adaptiveThreshold( const Mat& _src, Mat& _dst, double maxValue, - int method, int type, int blockSize, double delta ) +void cv::adaptiveThreshold( const InputArray& _src, OutputArray _dst, double maxValue, + int method, int type, int blockSize, double delta ) { - CV_Assert( _src.type() == CV_8UC1 ); + Mat src = _src.getMat(); + CV_Assert( src.type() == CV_8UC1 ); CV_Assert( blockSize % 2 == 1 && blockSize > 1 ); - Size size = _src.size(); + Size size = src.size(); - _dst.create( size, _src.type() ); + _dst.create( size, src.type() ); + Mat dst = _dst.getMat(); if( maxValue < 0 ) { - _dst = Scalar(0); + dst = Scalar(0); return; } - Mat _mean; + Mat mean; - if( _src.data != _dst.data ) - _mean = _dst; + if( src.data != dst.data ) + mean = dst; if( method == ADAPTIVE_THRESH_MEAN_C ) - boxFilter( _src, _mean, _src.type(), Size(blockSize, blockSize), + boxFilter( src, mean, src.type(), Size(blockSize, blockSize), Point(-1,-1), true, BORDER_REPLICATE ); else if( method == ADAPTIVE_THRESH_GAUSSIAN_C ) - GaussianBlur( _src, _mean, Size(blockSize, blockSize), 0, 0, BORDER_REPLICATE ); + GaussianBlur( src, mean, Size(blockSize, blockSize), 0, 0, BORDER_REPLICATE ); else CV_Error( CV_StsBadFlag, "Unknown/unsupported adaptive threshold method" ); @@ -565,7 +571,7 @@ void adaptiveThreshold( const Mat& _src, Mat& _dst, double maxValue, else CV_Error( CV_StsBadFlag, "Unknown/unsupported threshold type" ); - if( _src.isContinuous() && _mean.isContinuous() && _dst.isContinuous() ) + if( src.isContinuous() && mean.isContinuous() && dst.isContinuous() ) { size.width *= size.height; size.height = 1; @@ -573,17 +579,15 @@ void adaptiveThreshold( const Mat& _src, Mat& _dst, double maxValue, for( i = 0; i < size.height; i++ ) { - const uchar* src = _src.data + _src.step*i; - const uchar* mean = _mean.data + _mean.step*i; - uchar* dst = _dst.data + _dst.step*i; + const uchar* sdata = src.data + src.step*i; + const uchar* mdata = mean.data + mean.step*i; + uchar* ddata = dst.data + dst.step*i; for( j = 0; j < size.width; j++ ) - dst[j] = tab[src[j] - mean[j] + 255]; + ddata[j] = tab[sdata[j] - mdata[j] + 255]; } } -} - CV_IMPL double cvThreshold( const void* srcarr, void* dstarr, double thresh, double maxval, int type ) { diff --git a/modules/imgproc/src/undistort.cpp b/modules/imgproc/src/undistort.cpp index de328e547c..8ef359edc4 100644 --- a/modules/imgproc/src/undistort.cpp +++ b/modules/imgproc/src/undistort.cpp @@ -42,12 +42,10 @@ #include "precomp.hpp" -namespace cv -{ - -Mat getDefaultNewCameraMatrix( const Mat& cameraMatrix, Size imgsize, +cv::Mat cv::getDefaultNewCameraMatrix( const InputArray& _cameraMatrix, Size imgsize, bool centerPrincipalPoint ) { + Mat cameraMatrix = _cameraMatrix.getMat(); if( !centerPrincipalPoint && cameraMatrix.type() == CV_64F ) return cameraMatrix; @@ -61,35 +59,42 @@ Mat getDefaultNewCameraMatrix( const Mat& cameraMatrix, Size imgsize, return newCameraMatrix; } -void initUndistortRectifyMap( const Mat& _cameraMatrix, const Mat& _distCoeffs, - const Mat& matR, const Mat& _newCameraMatrix, - Size size, int m1type, Mat& map1, Mat& map2 ) +void cv::initUndistortRectifyMap( const InputArray& _cameraMatrix, const InputArray& _distCoeffs, + const InputArray& _matR, const InputArray& _newCameraMatrix, + Size size, int m1type, OutputArray _map1, OutputArray _map2 ) { + Mat cameraMatrix = _cameraMatrix.getMat(), distCoeffs = _distCoeffs.getMat(); + Mat matR = _matR.getMat(), newCameraMatrix = _newCameraMatrix.getMat(); + if( m1type <= 0 ) m1type = CV_16SC2; CV_Assert( m1type == CV_16SC2 || m1type == CV_32FC1 || m1type == CV_32FC2 ); - map1.create( size, m1type ); + _map1.create( size, m1type ); + Mat map1 = _map1.getMat(), map2; if( m1type != CV_32FC2 ) - map2.create( size, m1type == CV_16SC2 ? CV_16UC1 : CV_32FC1 ); + { + _map2.create( size, m1type == CV_16SC2 ? CV_16UC1 : CV_32FC1 ); + map2 = _map2.getMat(); + } else - map2.release(); + _map2.release(); - Mat_ R = Mat_::eye(3, 3), distCoeffs; - Mat_ A = Mat_(_cameraMatrix), Ar; + Mat_ R = Mat_::eye(3, 3); + Mat_ A = Mat_(cameraMatrix), Ar; - if( _newCameraMatrix.data ) - Ar = Mat_(_newCameraMatrix); + if( newCameraMatrix.data ) + Ar = Mat_(newCameraMatrix); else Ar = getDefaultNewCameraMatrix( A, size, true ); if( matR.data ) R = Mat_(matR); - if( _distCoeffs.data ) - distCoeffs = Mat_(_distCoeffs); + if( distCoeffs.data ) + distCoeffs = Mat_(distCoeffs); else { - distCoeffs.create(8, 1); + distCoeffs.create(8, 1, CV_64F); distCoeffs = 0.; } @@ -156,28 +161,33 @@ void initUndistortRectifyMap( const Mat& _cameraMatrix, const Mat& _distCoeffs, } -void undistort( const Mat& src, Mat& dst, const Mat& _cameraMatrix, - const Mat& _distCoeffs, const Mat& _newCameraMatrix ) +void cv::undistort( const InputArray& _src, OutputArray _dst, const InputArray& _cameraMatrix, + const InputArray& _distCoeffs, const InputArray& _newCameraMatrix ) { - dst.create( src.size(), src.type() ); + Mat src = _src.getMat(), cameraMatrix = _cameraMatrix.getMat(); + Mat distCoeffs = _distCoeffs.getMat(), newCameraMatrix = _newCameraMatrix.getMat(); + + _dst.create( src.size(), src.type() ); + Mat dst = _dst.getMat(); + CV_Assert( dst.data != src.data ); int stripe_size0 = std::min(std::max(1, (1 << 12) / std::max(src.cols, 1)), src.rows); Mat map1(stripe_size0, src.cols, CV_16SC2), map2(stripe_size0, src.cols, CV_16UC1); - Mat_ A, distCoeffs, Ar, I = Mat_::eye(3,3); + Mat_ A, Ar, I = Mat_::eye(3,3); - _cameraMatrix.convertTo(A, CV_64F); - if( _distCoeffs.data ) - distCoeffs = Mat_(_distCoeffs); + cameraMatrix.convertTo(A, CV_64F); + if( distCoeffs.data ) + distCoeffs = Mat_(distCoeffs); else { - distCoeffs.create(5, 1); + distCoeffs.create(5, 1, CV_64F); distCoeffs = 0.; } - if( _newCameraMatrix.data ) - _newCameraMatrix.convertTo(Ar, CV_64F); + if( newCameraMatrix.data ) + newCameraMatrix.convertTo(Ar, CV_64F); else A.copyTo(Ar); @@ -196,8 +206,6 @@ void undistort( const Mat& src, Mat& dst, const Mat& _cameraMatrix, } } -} - CV_IMPL void cvUndistort2( const CvArr* srcarr, CvArr* dstarr, const CvMat* Aarr, const CvMat* dist_coeffs, const CvMat* newAarr ) @@ -373,48 +381,34 @@ void cvUndistortPoints( const CvMat* _src, CvMat* _dst, const CvMat* _cameraMatr } -namespace cv +void cv::undistortPoints( const InputArray& _src, OutputArray _dst, + const InputArray& _cameraMatrix, + const InputArray& _distCoeffs, + const InputArray& _Rmat, + const InputArray& _Pmat ) { + Mat src = _src.getMat(), cameraMatrix = _cameraMatrix.getMat(); + Mat distCoeffs = _distCoeffs.getMat(), R = _Rmat.getMat(), P = _Pmat.getMat(); -void undistortPoints( const Mat& src, Mat& dst, - const Mat& cameraMatrix, const Mat& distCoeffs, - const Mat& R, const Mat& P ) -{ CV_Assert( src.isContinuous() && (src.depth() == CV_32F || src.depth() == CV_64F) && ((src.rows == 1 && src.channels() == 2) || src.cols*src.channels() == 2)); - dst.create(src.size(), src.type()); - CvMat _src = src, _dst = dst, _cameraMatrix = cameraMatrix; - CvMat matR, matP, _distCoeffs, *pR=0, *pP=0, *pD=0; - if( R.data ) - pR = &(matR = R); - if( P.data ) - pP = &(matP = P); - if( distCoeffs.data ) - pD = &(_distCoeffs = distCoeffs); - cvUndistortPoints(&_src, &_dst, &_cameraMatrix, pD, pR, pP); -} - -void undistortPoints( const Mat& src, std::vector& dst, - const Mat& cameraMatrix, const Mat& distCoeffs, - const Mat& R, const Mat& P ) -{ - size_t sz = src.cols*src.rows*src.channels()/2; - CV_Assert( src.isContinuous() && src.depth() == CV_32F && - ((src.rows == 1 && src.channels() == 2) || src.cols*src.channels() == 2)); + _dst.create(src.size(), src.type(), -1, true); + Mat dst = _dst.getMat(); - dst.resize(sz); - CvMat _src = src, _dst = Mat(dst), _cameraMatrix = cameraMatrix; - CvMat matR, matP, _distCoeffs, *pR=0, *pP=0, *pD=0; + CvMat _csrc = src, _cdst = dst, _ccameraMatrix = cameraMatrix; + CvMat matR, matP, _cdistCoeffs, *pR=0, *pP=0, *pD=0; if( R.data ) pR = &(matR = R); if( P.data ) pP = &(matP = P); if( distCoeffs.data ) - pD = &(_distCoeffs = distCoeffs); - cvUndistortPoints(&_src, &_dst, &_cameraMatrix, pD, pR, pP); + pD = &(_cdistCoeffs = distCoeffs); + cvUndistortPoints(&_csrc, &_cdst, &_ccameraMatrix, pD, pR, pP); } +namespace cv +{ static Point2f mapPointSpherical(const Point2f& p, float alpha, Vec4d* J, int projType) { @@ -492,11 +486,13 @@ static Point2f invMapPointSpherical(Point2f _p, float alpha, int projType) return i < maxiter ? Point2f((float)q[0], (float)q[1]) : Point2f(-FLT_MAX, -FLT_MAX); } +} -float initWideAngleProjMap( const Mat& cameraMatrix0, const Mat& distCoeffs0, +float cv::initWideAngleProjMap( const InputArray& _cameraMatrix0, const InputArray& _distCoeffs0, Size imageSize, int destImageWidth, int m1type, - Mat& map1, Mat& map2, int projType, double _alpha ) + OutputArray _map1, OutputArray _map2, int projType, double _alpha ) { + Mat cameraMatrix0 = _cameraMatrix0.getMat(), distCoeffs0 = _distCoeffs0.getMat(); double k[8] = {0,0,0,0,0,0,0,0}, M[9]={0,0,0,0,0,0,0,0,0}; Mat distCoeffs(distCoeffs0.rows, distCoeffs0.cols, CV_MAKETYPE(CV_64F,distCoeffs0.channels()), k); Mat cameraMatrix(3,3,CV_64F,M); @@ -562,15 +558,15 @@ float initWideAngleProjMap( const Mat& cameraMatrix0, const Mat& distCoeffs0, if(m1type == CV_32FC2) { + _map1.create(mapxy.size(), mapxy.type()); + Mat map1 = _map1.getMat(); mapxy.copyTo(map1); - map2.release(); + _map2.release(); } else - convertMaps(mapxy, Mat(), map1, map2, m1type, false); + convertMaps(mapxy, Mat(), _map1, _map2, m1type, false); return scale; } -} - /* End of file */ diff --git a/modules/imgproc/src/utils.cpp b/modules/imgproc/src/utils.cpp index 5609d6f68f..dd2ecbc0fd 100644 --- a/modules/imgproc/src/utils.cpp +++ b/modules/imgproc/src/utils.cpp @@ -195,13 +195,17 @@ static void copyMakeConstBorder_8u( const uchar* src, size_t srcstep, Size srcro memcpy(dst + (i + srcroi.height)*dststep, constBuf, dstroi.width); } +} -void copyMakeBorder( const Mat& src, Mat& dst, int top, int bottom, - int left, int right, int borderType, const Scalar& value ) +void cv::copyMakeBorder( const InputArray& _src, OutputArray _dst, int top, int bottom, + int left, int right, int borderType, const Scalar& value ) { + Mat src = _src.getMat(); CV_Assert( top >= 0 && bottom >= 0 && left >= 0 && right >= 0 ); - dst.create( src.rows + top + bottom, src.cols + left + right, src.type() ); + _dst.create( src.rows + top + bottom, src.cols + left + right, src.type() ); + Mat dst = _dst.getMat(); + if( borderType != BORDER_CONSTANT ) copyMakeBorder_8u( src.data, src.step, src.size(), dst.data, dst.step, dst.size(), @@ -215,8 +219,6 @@ void copyMakeBorder( const Mat& src, Mat& dst, int top, int bottom, top, left, (int)src.elemSize(), (uchar*)buf ); } } - -} CV_IMPL void diff --git a/modules/imgproc/test/test_imgwarp.cpp b/modules/imgproc/test/test_imgwarp.cpp index 6bd1b86152..09e96aa883 100644 --- a/modules/imgproc/test/test_imgwarp.cpp +++ b/modules/imgproc/test/test_imgwarp.cpp @@ -524,7 +524,7 @@ int CV_WarpAffineTest::prepare_test_case( int test_case_idx ) angle = cvtest::randReal(rng)*360; scale = ((double)dst.rows/src.rows + (double)dst.cols/src.cols)*0.5; getRotationMatrix2D(center, angle, scale).convertTo(mat, mat.depth()); - rng.fill( tmp, CV_RAND_NORMAL, cvScalarAll(1.), cvScalarAll(0.01) ); + rng.fill( tmp, CV_RAND_NORMAL, Scalar::all(1.), Scalar::all(0.01) ); cv::max(tmp, 0.9, tmp); cv::min(tmp, 1.1, tmp); cv::multiply(tmp, mat, mat, 1.); @@ -639,7 +639,7 @@ int CV_WarpPerspectiveTest::prepare_test_case( int test_case_idx ) float buf[16]; Mat tmp( 1, 16, CV_32FC1, buf ); - rng.fill( tmp, CV_RAND_NORMAL, cvScalarAll(0.), cvScalarAll(0.1) ); + rng.fill( tmp, CV_RAND_NORMAL, Scalar::all(0.), Scalar::all(0.1) ); for( i = 0; i < 4; i++ ) { diff --git a/modules/ml/src/ann_mlp.cpp b/modules/ml/src/ann_mlp.cpp index b8851bdaca..6e412b6ebb 100644 --- a/modules/ml/src/ann_mlp.cpp +++ b/modules/ml/src/ann_mlp.cpp @@ -1228,7 +1228,7 @@ int CvANN_MLP::train_rprop( CvVectors x0, CvVectors u, const double* sw ) __BEGIN__; - int i, ivcount, ovcount, l_count, total = 0, max_iter, buf_sz, dcount0, dcount=0; + int i, ivcount, ovcount, l_count, total = 0, max_iter, buf_sz, dcount0; double *buf_ptr; double prev_E = DBL_MAX*0.5, epsilon; double dw_plus, dw_minus, dw_min, dw_max; @@ -1294,10 +1294,7 @@ int CvANN_MLP::train_rprop( CvVectors x0, CvVectors u, const double* sw ) */ for( iter = 0; iter < max_iter; iter++ ) { - int n1, n2, si, j, k; - double* w; - CvMat _w, _dEdw, hdr1, hdr2, ghdr1, ghdr2, _df; - CvMat *x1, *x2, *grad1, *grad2, *temp; + int n1, n2, j, k; double E = 0; // first, iterate through all the samples and compute dEdw diff --git a/modules/ml/src/knearest.cpp b/modules/ml/src/knearest.cpp index 46189325ac..1d7055c140 100644 --- a/modules/ml/src/knearest.cpp +++ b/modules/ml/src/knearest.cpp @@ -355,8 +355,6 @@ float CvKNearest::find_nearest( const CvMat* _samples, int k, CvMat* _results, float result = 0.f; const int max_blk_count = 128, max_buf_sz = 1 << 12; - int i, count, count_scale, blk_count0, blk_count = 0, buf_sz, k1; - if( !samples ) CV_Error( CV_StsError, "The search tree must be constructed first using train method" ); @@ -395,15 +393,15 @@ float CvKNearest::find_nearest( const CvMat* _samples, int k, CvMat* _results, "The distances from the neighbors (if present) must be floating-point matrix of x size" ); } - count = _samples->rows; - count_scale = k*2; - blk_count0 = MIN( count, max_blk_count ); - buf_sz = MIN( blk_count0 * count_scale, max_buf_sz ); + int count = _samples->rows; + int count_scale = k*2; + int blk_count0 = MIN( count, max_blk_count ); + int buf_sz = MIN( blk_count0 * count_scale, max_buf_sz ); blk_count0 = MAX( buf_sz/count_scale, 1 ); blk_count0 += blk_count0 % 2; blk_count0 = MIN( blk_count0, count ); buf_sz = blk_count0 * count_scale + k; - k1 = get_sample_count(); + int k1 = get_sample_count(); k1 = MIN( k1, k ); cv::parallel_for(cv::BlockedRange(0, count), P1(this, buf_sz, k, _samples, _neighbors, k1, diff --git a/modules/ml/test/test_emknearestkmeans.cpp b/modules/ml/test/test_emknearestkmeans.cpp index e1d4360a4a..14f5f9352a 100644 --- a/modules/ml/test/test_emknearestkmeans.cpp +++ b/modules/ml/test/test_emknearestkmeans.cpp @@ -203,7 +203,7 @@ void CV_KMeansTest::run( int /*start_from*/ ) int code = cvtest::TS::OK; Mat bestLabels; // 1. flag==KMEANS_PP_CENTERS - kmeans( data, 3, bestLabels, TermCriteria( TermCriteria::COUNT, iters, 0.0), 0, KMEANS_PP_CENTERS, 0 ); + kmeans( data, 3, bestLabels, TermCriteria( TermCriteria::COUNT, iters, 0.0), 0, KMEANS_PP_CENTERS, OutputArray() ); if( calcErr( bestLabels, labels, sizes, false ) > 0.01f ) { ts->printf( cvtest::TS::LOG, "bad accuracy if flag==KMEANS_PP_CENTERS" ); @@ -211,7 +211,7 @@ void CV_KMeansTest::run( int /*start_from*/ ) } // 2. flag==KMEANS_RANDOM_CENTERS - kmeans( data, 3, bestLabels, TermCriteria( TermCriteria::COUNT, iters, 0.0), 0, KMEANS_RANDOM_CENTERS, 0 ); + kmeans( data, 3, bestLabels, TermCriteria( TermCriteria::COUNT, iters, 0.0), 0, KMEANS_RANDOM_CENTERS, OutputArray() ); if( calcErr( bestLabels, labels, sizes, false ) > 0.01f ) { ts->printf( cvtest::TS::LOG, "bad accuracy if flag==KMEANS_PP_CENTERS" ); @@ -223,7 +223,7 @@ void CV_KMeansTest::run( int /*start_from*/ ) RNG rng; for( int i = 0; i < 0.5f * pointsCount; i++ ) bestLabels.at( rng.next() % pointsCount, 0 ) = rng.next() % 3; - kmeans( data, 3, bestLabels, TermCriteria( TermCriteria::COUNT, iters, 0.0), 0, KMEANS_USE_INITIAL_LABELS, 0 ); + kmeans( data, 3, bestLabels, TermCriteria( TermCriteria::COUNT, iters, 0.0), 0, KMEANS_USE_INITIAL_LABELS, OutputArray() ); if( calcErr( bestLabels, labels, sizes, false ) > 0.01f ) { ts->printf( cvtest::TS::LOG, "bad accuracy if flag==KMEANS_PP_CENTERS" ); diff --git a/modules/objdetect/src/planardetect.cpp b/modules/objdetect/src/planardetect.cpp index dbc7a4add4..3c78531f66 100644 --- a/modules/objdetect/src/planardetect.cpp +++ b/modules/objdetect/src/planardetect.cpp @@ -184,7 +184,7 @@ bool PlanarObjectDetector::operator()(const vector& pyr, const vector mask; - matH = findHomography(Mat(fromPt), Mat(toPt), mask, RANSAC, 10); + matH = findHomography(fromPt, toPt, RANSAC, 10, mask); if( matH.data ) { const Mat_& H = matH; diff --git a/modules/ts/include/opencv2/ts/ts.hpp b/modules/ts/include/opencv2/ts/ts.hpp index 96fbbde011..3af8bf99a6 100644 --- a/modules/ts/include/opencv2/ts/ts.hpp +++ b/modules/ts/include/opencv2/ts/ts.hpp @@ -24,20 +24,6 @@ using cv::Rect; class CV_EXPORTS TS; -enum -{ - TYPE_MASK_8U = 1 << CV_8U, - TYPE_MASK_8S = 1 << CV_8S, - TYPE_MASK_16U = 1 << CV_16U, - TYPE_MASK_16S = 1 << CV_16S, - TYPE_MASK_32S = 1 << CV_32S, - TYPE_MASK_32F = 1 << CV_32F, - TYPE_MASK_64F = 1 << CV_64F, - TYPE_MASK_ALL = (TYPE_MASK_64F<<1)-1, - TYPE_MASK_ALL_BUT_8S = TYPE_MASK_ALL & ~TYPE_MASK_8S, - TYPE_MASK_FLT = TYPE_MASK_32F + TYPE_MASK_64F -}; - CV_EXPORTS int64 readSeed(const char* str); CV_EXPORTS void randUni( RNG& rng, Mat& a, const Scalar& param1, const Scalar& param2 ); diff --git a/modules/ts/src/ts_func.cpp b/modules/ts/src/ts_func.cpp index 59d11637b6..80ad6d6412 100644 --- a/modules/ts/src/ts_func.cpp +++ b/modules/ts/src/ts_func.cpp @@ -71,7 +71,7 @@ int randomType(RNG& rng, int typeMask, int minChannels, int maxChannels) { int channels = rng.uniform(minChannels, maxChannels+1); int depth = 0; - CV_Assert((typeMask & TYPE_MASK_ALL) != 0); + CV_Assert((typeMask & DEPTH_MASK_ALL) != 0); for(;;) { depth = rng.uniform(CV_8U, CV_64F+1); diff --git a/modules/video/include/opencv2/video/background_segm.hpp b/modules/video/include/opencv2/video/background_segm.hpp index c362bd1935..fbc745d88a 100644 --- a/modules/video/include/opencv2/video/background_segm.hpp +++ b/modules/video/include/opencv2/video/background_segm.hpp @@ -358,7 +358,7 @@ public: //! the virtual destructor virtual ~BackgroundSubtractor(); //! the update operator that takes the next video frame and returns the current foreground mask as 8-bit binary image. - CV_WRAP_AS(apply) virtual void operator()(const Mat& image, CV_OUT Mat& fgmask, + CV_WRAP_AS(apply) virtual void operator()(const InputArray& image, OutputArray fgmask, double learningRate=0); }; @@ -383,7 +383,7 @@ public: //! the destructor virtual ~BackgroundSubtractorMOG(); //! the update operator - virtual void operator()(const Mat& image, Mat& fgmask, double learningRate=0); + virtual void operator()(const InputArray& image, OutputArray fgmask, double learningRate=0); //! re-initiaization method virtual void initialize(Size frameSize, int frameType); @@ -400,52 +400,73 @@ public: }; -class CV_EXPORTS_W BackgroundSubtractorMOG2 : public BackgroundSubtractor +class BackgroundSubtractorMOG2 : public BackgroundSubtractor { public: //! the default constructor - CV_WRAP BackgroundSubtractorMOG2(); + BackgroundSubtractorMOG2(); //! the full constructor that takes the length of the history, the number of gaussian mixtures, the background ratio parameter and the noise strength - CV_WRAP BackgroundSubtractorMOG2(double alphaT, - double sigma=15, - int nmixtures=5, - bool postFiltering=false, - double minArea=15, - bool detectShadows=true, - bool removeForeground=false, - - double Tb=16, - double Tg=9, - double TB=0.9, - double CT=0.05, - - int shadowOutputValue=127, - double tau=0.5); - + BackgroundSubtractorMOG2(int history, float varThreshold, bool bShadowDetection=1); //! the destructor virtual ~BackgroundSubtractorMOG2(); //! the update operator - virtual void operator()(const Mat& image, Mat& fgmask, double learningRate=0); + virtual void operator()(const InputArray& image, OutputArray fgmask, double learningRate=-1); //! re-initiaization method - virtual void initialize(Size frameSize, - double alphaT, - double sigma=15, - int nmixtures=5, - bool postFiltering=false, - double minArea=15, - bool detectShadows=true, - bool removeForeground=false, - - double Tb=16, - double Tg=9, - double TB=0.9, - double CT=0.05, - - int nShadowDetection=127, - double tau=0.5); + virtual void initialize(Size frameSize, int frameType); + + Size frameSize; + int frameType; + Mat bgmodel; + Mat bgmodelUsedModes;//keep track of number of modes per pixel + int nframes; + int history; + int nmixtures; + //! here it is the maximum allowed number of mixture comonents. + //! Actual number is determined dynamically per pixel + float varThreshold; + // threshold on the squared Mahalan. dist. to decide if it is well described + //by the background model or not. Related to Cthr from the paper. + //This does not influence the update of the background. A typical value could be 4 sigma + //and that is varThreshold=4*4=16; Corresponds to Tb in the paper. + + ///////////////////////// + //less important parameters - things you might change but be carefull + //////////////////////// + float backgroundRatio; + //corresponds to fTB=1-cf from the paper + //TB - threshold when the component becomes significant enough to be included into + //the background model. It is the TB=1-cf from the paper. So I use cf=0.1 => TB=0. + //For alpha=0.001 it means that the mode should exist for approximately 105 frames before + //it is considered foreground + //float noiseSigma; + float varThresholdGen; + //correspondts to Tg - threshold on the squared Mahalan. dist. to decide + //when a sample is close to the existing components. If it is not close + //to any a new component will be generated. I use 3 sigma => Tg=3*3=9. + //Smaller Tg leads to more generated components and higher Tg might make + //lead to small number of components but they can grow too large + float fVarInit; + float fVarMin; + float fVarMax; + //initial variance for the newly generated components. + //It will will influence the speed of adaptation. A good guess should be made. + //A simple way is to estimate the typical standard deviation from the images. + //I used here 10 as a reasonable value + // min and max can be used to further control the variance + float fCT;//CT - complexity reduction prior + //this is related to the number of samples needed to accept that a component + //actually exists. We use CT=0.05 of all the samples. By setting CT=0 you get + //the standard Stauffer&Grimson algorithm (maybe not exact but very similar) - void* model; + //shadow detection parameters + bool bShadowDetection;//default 1 - do shadow detection + unsigned char nShadowDetection;//do shadow detection - insert this value as the detection result - 127 default value + float fTau; + // Tau - shadow threshold. The shadow is detected if the pixel is darker + //version of the background. Tau is a threshold on how much darker the shadow can be. + //Tau= 0.5 means that if pixel is more than 2 times darker then it is not shadow + //See: Prati,Mikic,Trivedi,Cucchiarra,"Detecting Moving Shadows...",IEEE PAMI,2003. }; } diff --git a/modules/video/include/opencv2/video/tracking.hpp b/modules/video/include/opencv2/video/tracking.hpp index 5e5a051eab..35e77790cd 100644 --- a/modules/video/include/opencv2/video/tracking.hpp +++ b/modules/video/include/opencv2/video/tracking.hpp @@ -244,30 +244,30 @@ namespace cv { //! updates motion history image using the current silhouette -CV_EXPORTS_W void updateMotionHistory( const Mat& silhouette, Mat& mhi, - double timestamp, double duration ); +CV_EXPORTS_W void updateMotionHistory( const InputArray& silhouette, InputOutputArray mhi, + double timestamp, double duration ); //! computes the motion gradient orientation image from the motion history image -CV_EXPORTS_W void calcMotionGradient( const Mat& mhi, CV_OUT Mat& mask, - CV_OUT Mat& orientation, +CV_EXPORTS_W void calcMotionGradient( const InputArray& mhi, OutputArray mask, + OutputArray orientation, double delta1, double delta2, int apertureSize=3 ); //! computes the global orientation of the selected motion history image part -CV_EXPORTS_W double calcGlobalOrientation( const Mat& orientation, const Mat& mask, - const Mat& mhi, double timestamp, +CV_EXPORTS_W double calcGlobalOrientation( const InputArray& orientation, const InputArray& mask, + const InputArray& mhi, double timestamp, double duration ); -CV_EXPORTS_W void segmentMotion(const Mat& mhi, Mat& segmask, +CV_EXPORTS_W void segmentMotion(const InputArray& mhi, OutputArray segmask, vector& boundingRects, double timestamp, double segThresh); //! updates the object tracking window using CAMSHIFT algorithm -CV_EXPORTS_W RotatedRect CamShift( const Mat& probImage, CV_IN_OUT Rect& window, +CV_EXPORTS_W RotatedRect CamShift( const InputArray& probImage, CV_IN_OUT Rect& window, TermCriteria criteria ); //! updates the object tracking window using meanshift algorithm -CV_EXPORTS_W int meanShift( const Mat& probImage, CV_IN_OUT Rect& window, +CV_EXPORTS_W int meanShift( const InputArray& probImage, CV_IN_OUT Rect& window, TermCriteria criteria ); /*! @@ -315,9 +315,9 @@ public: enum { OPTFLOW_USE_INITIAL_FLOW=4, OPTFLOW_FARNEBACK_GAUSSIAN=256 }; //! computes sparse optical flow using multi-scale Lucas-Kanade algorithm -CV_EXPORTS_W void calcOpticalFlowPyrLK( const Mat& prevImg, const Mat& nextImg, - const vector& prevPts, CV_OUT vector& nextPts, - CV_OUT vector& status, CV_OUT vector& err, +CV_EXPORTS_W void calcOpticalFlowPyrLK( const InputArray& prevImg, const InputArray& nextImg, + const InputArray& prevPts, CV_OUT InputOutputArray nextPts, + OutputArray status, OutputArray err, Size winSize=Size(15,15), int maxLevel=3, TermCriteria criteria=TermCriteria( TermCriteria::COUNT+TermCriteria::EPS, @@ -326,10 +326,15 @@ CV_EXPORTS_W void calcOpticalFlowPyrLK( const Mat& prevImg, const Mat& nextImg, int flags=0 ); //! computes dense optical flow using Farneback algorithm -CV_EXPORTS_W void calcOpticalFlowFarneback( const Mat& prev, const Mat& next, - CV_OUT Mat& flow, double pyr_scale, int levels, int winsize, +CV_EXPORTS_W void calcOpticalFlowFarneback( const InputArray& prev, const InputArray& next, + CV_OUT InputOutputArray flow, double pyr_scale, int levels, int winsize, int iterations, int poly_n, double poly_sigma, int flags ); +//! estimates the best-fit Euqcidean, similarity, affine or perspective transformation +// that maps one 2D point set to another or one image to another. +CV_EXPORTS_W Mat estimateRigidTransform( const InputArray& src, const InputArray& dst, + bool fullAffine); + } #endif diff --git a/modules/video/src/bgfg_gaussmix.cpp b/modules/video/src/bgfg_gaussmix.cpp index da4519b1b8..14358dea2d 100644 --- a/modules/video/src/bgfg_gaussmix.cpp +++ b/modules/video/src/bgfg_gaussmix.cpp @@ -59,7 +59,7 @@ namespace cv { BackgroundSubtractor::~BackgroundSubtractor() {} -void BackgroundSubtractor::operator()(const Mat&, Mat&, double) +void BackgroundSubtractor::operator()(const InputArray&, OutputArray, double) { } @@ -381,15 +381,17 @@ static void process8uC3( BackgroundSubtractorMOG& obj, const Mat& image, Mat& fg } } -void BackgroundSubtractorMOG::operator()(const Mat& image, Mat& fgmask, double learningRate) +void BackgroundSubtractorMOG::operator()(const InputArray& _image, OutputArray _fgmask, double learningRate) { + Mat image = _image.getMat(); bool needToInitialize = nframes == 0 || learningRate >= 1 || image.size() != frameSize || image.type() != frameType; if( needToInitialize ) initialize(image.size(), image.type()); CV_Assert( image.depth() == CV_8U ); - fgmask.create( image.size(), CV_8U ); + _fgmask.create( image.size(), CV_8U ); + Mat fgmask = _fgmask.getMat(); ++nframes; learningRate = learningRate >= 0 && nframes > 1 ? learningRate : 1./min( nframes, history ); diff --git a/modules/video/src/bgfg_gaussmix2.cpp b/modules/video/src/bgfg_gaussmix2.cpp index e216a8979d..655db00e66 100644 --- a/modules/video/src/bgfg_gaussmix2.cpp +++ b/modules/video/src/bgfg_gaussmix2.cpp @@ -62,8 +62,12 @@ //http://www.zoranz.net/Publications/zivkovic2004PAMI.pdf // // +//Example usage with as cpp class +// BackgroundSubtractorMOG2 bg_model; +//For each new image the model is updates using: +// bg_model(img, fgmask); // -// Example usage as part of the CvBGStatModel: +//Example usage as part of the CvBGStatModel: // CvBGStatModel* bg_model = cvCreateGaussianBGModel2( first_frame ); // // //update for each frame @@ -73,12 +77,29 @@ // cvReleaseBGStatModel( &bg_model ); // //Author: Z.Zivkovic, www.zoranz.net -//Date: 27-April-2005, Version:0.9 +//Date: 7-April-2011, Version:1.0 ///////////*/ #include "precomp.hpp" -#define CV_BG_MODEL_MOG2 3 /* "Mixture of Gaussians 2". */ + +/* + Interface of Gaussian mixture algorithm from: + + "Improved adaptive Gausian mixture model for background subtraction" + Z.Zivkovic + International Conference Pattern Recognition, UK, August, 2004 + http://www.zoranz.net/Publications/zivkovic2004ICPR.pdf + + Advantages: + -fast - number of Gausssian components is constantly adapted per pixel. + -performs also shadow detection (see bgfg_segm_test.cpp example) + + */ + + +#define CV_BG_MODEL_MOG2 3 /* "Mixture of Gaussians 2". */ + /* default parameters of gaussian background detection algorithm */ #define CV_BGFG_MOG2_STD_THRESHOLD 4.0f /* lambda=2.5 is 99% */ @@ -86,302 +107,491 @@ #define CV_BGFG_MOG2_BACKGROUND_THRESHOLD 0.9f /* threshold sum of weights for background test */ #define CV_BGFG_MOG2_STD_THRESHOLD_GENERATE 3.0f /* lambda=2.5 is 99% */ #define CV_BGFG_MOG2_NGAUSSIANS 5 /* = K = number of Gaussians in mixture */ -#define CV_BGFG_MOG2_SIGMA_INIT 15.0f -#define CV_BGFG_MOG2_MINAREA 15.0f +#define CV_BGFG_MOG2_VAR_INIT 15.0f /* initial variance for new components*/ +#define CV_BGFG_MOG2_VAR_MIN 4.0f +#define CV_BGFG_MOG2_VAR_MAX 5*CV_BGFG_MOG2_VAR_INIT +#define CV_BGFG_MOG2_MINAREA 15.0f /* for postfiltering */ /* additional parameters */ -#define CV_BGFG_MOG2_CT 0.05f /* complexity reduction prior constant 0 - no reduction of number of components*/ +#define CV_BGFG_MOG2_CT 0.05f /* complexity reduction prior constant 0 - no reduction of number of components*/ #define CV_BGFG_MOG2_SHADOW_VALUE 127 /* value to use in the segmentation mask for shadows, sot 0 not to do shadow detection*/ #define CV_BGFG_MOG2_SHADOW_TAU 0.5f /* Tau - shadow threshold, see the paper for explanation*/ -struct CvGaussBGStatModel2Params -{ - bool bPostFiltering;//defult 1 - do postfiltering +typedef struct CvGaussBGStatModel2Params +{ + //image info + int nWidth; + int nHeight; + int nND;//number of data dimensions (image channels) + + bool bPostFiltering;//defult 1 - do postfiltering - will make shadow detection results also give value 255 double minArea; // for postfiltering - bool bShadowDetection;//default 1 - do shadow detection - bool bRemoveForeground;//default 0, set to 1 to remove foreground pixels from the image and return background image - bool bInit;//default 1, faster updates at start + bool bInit;//default 1, faster updates at start - ///////////////////////// - //very important parameters - things you will change - //////////////////////// - float fAlphaT; - //alpha - speed of update - if the time interval you want to average over is T - //set alpha=1/T. It is also usefull at start to make T slowly increase - //from 1 until the desired T - float fTb; - //Tb - threshold on the squared Mahalan. dist. to decide if it is well described - //by the background model or not. Related to Cthr from the paper. - //This does not influence the update of the background. A typical value could be 4 sigma - //and that is Tb=4*4=16; - - ///////////////////////// - //less important parameters - things you might change but be carefull - //////////////////////// - float fTg; - //Tg - threshold on the squared Mahalan. dist. to decide - //when a sample is close to the existing components. If it is not close - //to any a new component will be generated. I use 3 sigma => Tg=3*3=9. - //Smaller Tg leads to more generated components and higher Tg might make - //lead to small number of components but they can grow too large - float fTB;//1-cf from the paper - //TB - threshold when the component becomes significant enough to be included into - //the background model. It is the TB=1-cf from the paper. So I use cf=0.1 => TB=0. - //For alpha=0.001 it means that the mode should exist for approximately 105 frames before - //it is considered foreground - float fSigma; - //initial standard deviation for the newly generated components. - //It will will influence the speed of adaptation. A good guess should be made. - //A simple way is to estimate the typical standard deviation from the images. - //I used here 10 as a reasonable value - float fCT;//CT - complexity reduction prior - //this is related to the number of samples needed to accept that a component - //actually exists. We use CT=0.05 of all the samples. By setting CT=0 you get - //the standard Stauffer&Grimson algorithm (maybe not exact but very similar) + ///////////////////////// + //very important parameters - things you will change + //////////////////////// + float fAlphaT; + //alpha - speed of update - if the time interval you want to average over is T + //set alpha=1/T. It is also usefull at start to make T slowly increase + //from 1 until the desired T + float fTb; + //Tb - threshold on the squared Mahalan. dist. to decide if it is well described + //by the background model or not. Related to Cthr from the paper. + //This does not influence the update of the background. A typical value could be 4 sigma + //and that is Tb=4*4=16; + + ///////////////////////// + //less important parameters - things you might change but be carefull + //////////////////////// + float fTg; + //Tg - threshold on the squared Mahalan. dist. to decide + //when a sample is close to the existing components. If it is not close + //to any a new component will be generated. I use 3 sigma => Tg=3*3=9. + //Smaller Tg leads to more generated components and higher Tg might make + //lead to small number of components but they can grow too large + float fTB;//1-cf from the paper + //TB - threshold when the component becomes significant enough to be included into + //the background model. It is the TB=1-cf from the paper. So I use cf=0.1 => TB=0. + //For alpha=0.001 it means that the mode should exist for approximately 105 frames before + //it is considered foreground + float fVarInit; + float fVarMax; + float fVarMin; + //initial standard deviation for the newly generated components. + //It will will influence the speed of adaptation. A good guess should be made. + //A simple way is to estimate the typical standard deviation from the images. + //I used here 10 as a reasonable value + float fCT;//CT - complexity reduction prior + //this is related to the number of samples needed to accept that a component + //actually exists. We use CT=0.05 of all the samples. By setting CT=0 you get + //the standard Stauffer&Grimson algorithm (maybe not exact but very similar) - //even less important parameters - int nM;//max number of modes - const - 4 is usually enough + //even less important parameters + int nM;//max number of modes - const - 4 is usually enough - //shadow detection parameters - unsigned char nShadowDetection;//do shadow detection - insert this value as the detection result - float fTau; - // Tau - shadow threshold. The shadow is detected if the pixel is darker - //version of the background. Tau is a threshold on how much darker the shadow can be. - //Tau= 0.5 means that if pixel is more than 2 times darker then it is not shadow - //See: Prati,Mikic,Trivedi,Cucchiarra,"Detecting Moving Shadows...",IEEE PAMI,2003. -}; - -struct CvPBGMMGaussian + //shadow detection parameters + bool bShadowDetection;//default 1 - do shadow detection + unsigned char nShadowDetection;//do shadow detection - insert this value as the detection result + float fTau; + // Tau - shadow threshold. The shadow is detected if the pixel is darker + //version of the background. Tau is a threshold on how much darker the shadow can be. + //Tau= 0.5 means that if pixel is more than 2 times darker then it is not shadow + //See: Prati,Mikic,Trivedi,Cucchiarra,"Detecting Moving Shadows...",IEEE PAMI,2003. +} CvGaussBGStatModel2Params; + +#define CV_BGFG_MOG2_NDMAX 3 + +typedef struct CvPBGMMGaussian { - float sigma; - float muR; - float muG; - float muB; - float weight; -}; - -struct CvGaussBGStatModel2Data -{ - int nWidth,nHeight,nSize,nNBands;//image info - // dynamic array for the mixture of Gaussians - std::vector rGMM; - std::vector rnUsedModes;//number of Gaussian components per pixel -}; + float weight; + float mean[CV_BGFG_MOG2_NDMAX]; + float variance; +}CvPBGMMGaussian; + +typedef struct CvGaussBGStatModel2Data +{ + CvPBGMMGaussian* rGMM; //array for the mixture of Gaussians + unsigned char* rnUsedModes;//number of Gaussian components per pixel (maximum 255) +} CvGaussBGStatModel2Data; //only foreground image is updated //no filtering included -struct CvGaussBGModel2 +typedef struct CvGaussBGModel2 { + CV_BG_STAT_MODEL_FIELDS(); CvGaussBGStatModel2Params params; - CvGaussBGStatModel2Data data; - int countFrames; -}; + CvGaussBGStatModel2Data data; + int countFrames; +} +CvGaussBGModel2; -static int _icvRemoveShadowGMM(long posPixel, - float red, float green, float blue, +CVAPI(CvBGStatModel*) cvCreateGaussianBGModel2( IplImage* first_frame, + CvGaussBGStatModel2Params* params CV_DEFAULT(NULL) ); +//shadow detection performed per pixel +// should work for rgb data, could be usefull for gray scale and depth data as well +// See: Prati,Mikic,Trivedi,Cucchiarra,"Detecting Moving Shadows...",IEEE PAMI,2003. +CV_INLINE int _icvRemoveShadowGMM(float* data, int nD, unsigned char nModes, - CvPBGMMGaussian* m_aGaussians, + CvPBGMMGaussian* pGMM, float m_fTb, float m_fTB, float m_fTau) { - //calculate distances to the modes (+ sort???) - //here we need to go in descending order!!! - long pos; float tWeight = 0; float numerator, denominator; - // check all the distributions, marked as background: + // check all the components marked as background: for (int iModes=0;iModes= m_fTau))//m_nBeta=1 - { - float dR=a * muR - red; - float dG=a * muG - green; - float dB=a * muB - blue; - - //square distance -slower and less accurate - //float maxDistance = cvSqrt(m_fTb*var); - //if ((fabs(dR) <= maxDistance) && (fabs(dG) <= maxDistance) && (fabs(dB) <= maxDistance)) - //circle - float dist=(dR*dR+dG*dG+dB*dB); - if (dist= m_fTau)) + { + + float dist2a=0.0f; + + for (int iD=0;iD m_fTB) { - break; + return 0; }; }; return 0; } -static int _icvUpdatePixelBackgroundGMM(long posPixel, - float red, float green, float blue, +//update GMM - the base update function performed per pixel +// +//"Efficient Adaptive Density Estimapion per Image Pixel for the Task of Background Subtraction" +//Z.Zivkovic, F. van der Heijden +//Pattern Recognition Letters, vol. 27, no. 7, pages 773-780, 2006. +// +//The algorithm similar to the standard Stauffer&Grimson algorithm with +//additional selection of the number of the Gaussian components based on: +// +//"Recursive unsupervised learning of finite mixture models " +//Z.Zivkovic, F.van der Heijden +//IEEE Trans. on Pattern Analysis and Machine Intelligence, vol.26, no.5, pages 651-656, 2004 +//http://www.zoranz.net/Publications/zivkovic2004PAMI.pdf + +CV_INLINE int _icvUpdateGMM(float* data, int nD, unsigned char* pModesUsed, - CvPBGMMGaussian* m_aGaussians, + CvPBGMMGaussian* pGMM, int m_nM, float m_fAlphaT, float m_fTb, float m_fTB, float m_fTg, - float m_fSigma, + float m_fVarInit, + float m_fVarMax, + float m_fVarMin, float m_fPrune) { - //calculate distances to the modes (+ sort???) - //here we need to go in descending order!!! - - long pos; - - - bool bFitsPDF=0; - bool bBackground=0; + //calculate distances to the modes (+ sort) + //here we need to go in descending order!!! + bool bBackground=0;//return value -> true - the pixel classified as background + //internal: + bool bFitsPDF=0;//if it remains zero a new GMM mode will be added float m_fOneMinAlpha=1-m_fAlphaT; - - unsigned char nModes=*pModesUsed; + unsigned char nModes=*pModesUsed;//current number of modes in GMM float totalWeight=0.0f; ////// //go through all modes - for (int iModes=0;iModesweight;//need only weight if fit is found + weight=m_fOneMinAlpha*weight+m_fPrune; //// //fit not found yet if (!bFitsPDF) { - //check if it belongs to some of the modes - //calculate distance - float var = m_aGaussians[pos].sigma; - float muR = m_aGaussians[pos].muR; - float muG = m_aGaussians[pos].muG; - float muB = m_aGaussians[pos].muB; - - float dR=muR - red; - float dG=muG - green; - float dB=muB - blue; + //check if it belongs to some of the remaining modes + float var=pGauss->variance; - /////// - //check if it fits the current mode (Factor * sigma) - - //square distance -slower and less accurate - //float maxDistance = cvSqrt(m_fTg*var); - //if ((fabs(dR) <= maxDistance) && (fabs(dG) <= maxDistance) && (fabs(dB) <= maxDistance)) - //circle - float dist=(dR*dR+dG*dG+dB*dB); - //background? - m_fTb - if ((totalWeightmean[0]-data[0]; + dist2=dData*dData; +#else + float dData[CV_BGFG_MOG2_NDMAX]; + + for (int iD=0;iDmean[iD]-data[iD]; + dist2+=dData[iD]*dData[iD]; + } +#endif + //background? - m_fTb - usually larger than m_fTg + if ((totalWeight20*m_fAlphaT?20*m_fAlphaT:k; - //float sigmanew = var + k*((0.33*(dR*dR+dG*dG+dB*dB))-var); - //float sigmanew = var + k*((dR*dR+dG*dG+dB*dB)-var); - //float sigmanew = var + k*((0.33*dist)-var); - float sigmanew = var + k*(dist-var); - //limit the variance - //m_aGaussians[pos].sigma = sigmanew>70?70:sigmanew; - //m_aGaussians[pos].sigma = sigmanew>5*m_fSigma?5*m_fSigma:sigmanew; - m_aGaussians[pos].sigma =sigmanew< 4 ? 4 : sigmanew>5*m_fSigma?5*m_fSigma:sigmanew; - //m_aGaussians[pos].sigma =sigmanew< 4 ? 4 : sigmanew>3*m_fSigma?3*m_fSigma:sigmanew; - //m_aGaussians[pos].sigma = m_fSigma; + + float k = m_fAlphaT/weight; + + //update mean +#if (CV_BGFG_MOG2_NDMAX==1) + pGauss->mean[0]-=k*dData; +#else + for (int iD=0;iDmean[iD]-=k*dData[iD]; + } +#endif + + //update variance + float varnew = var + k*(dist2-var); + //limit the variance + pGauss->variance = MIN(m_fVarMax,MAX(varnew,m_fVarMin)); + //sort //all other weights are at the same place and - //only the matched (iModes) is higher -> just find the new place for it - for (int iLocal = iModes;iLocal>0;iLocal--) + //only the matched (iModes) is higher -> just find the new place for it + for (int iLocal = iMode;iLocal>0;iLocal--) { - long posLocal=posPixel + iLocal; - if (weight < (m_aGaussians[posLocal-1].weight)) + //check one up + if (weight < (pGMM[iLocal-1].weight)) { break; } else { - //swap - CvPBGMMGaussian temp = m_aGaussians[posLocal]; - m_aGaussians[posLocal] = m_aGaussians[posLocal-1]; - m_aGaussians[posLocal-1] = temp; + //swap one up + CvPBGMMGaussian temp = pGMM[iLocal]; + pGMM[iLocal] = pGMM[iLocal-1]; + pGMM[iLocal-1] = temp; + pGauss--; } } - - //belongs to the mode + //belongs to the mode - bFitsPDF becomes 1 ///// } - else + }//!bFitsPDF) + + //check prune + if (weight<-m_fPrune) + { + weight=0.0; + nModes--; + } + + pGauss->weight=weight;//update weight by the calculated value + totalWeight+=weight; + } + //go through all modes + ////// + + //renormalize weights + for (iMode = 0; iMode < nModes; iMode++) + { + pGMM[iMode].weight = pGMM[iMode].weight/totalWeight; + } + + //make new mode if needed and exit + if (!bFitsPDF) + { + if (nModes==m_nM) + { + //replace the weakest + pGauss=pGMM+m_nM-1; + } + else + { + //add a new one + pGauss=pGMM+nModes; + nModes++; + } + + if (nModes==1) + { + pGauss->weight=1; + } + else + { + pGauss->weight=m_fAlphaT; + + //renormalize all weights + for (iMode = 0; iMode < nModes-1; iMode++) { - weight=m_fOneMinAlpha*weight+m_fPrune; - //check prune - if (weight<-m_fPrune) - { - weight=0.0; - nModes--; - // bPrune=1; - //break;//the components are sorted so we can skip the rest - } + pGMM[iMode].weight *=m_fOneMinAlpha; } - //check if it fits the current mode (2.5 sigma) - /////// } + + //init + memcpy(pGauss->mean,data,nD*sizeof(float)); + pGauss->variance=m_fVarInit; + + //sort + //find the new place for it + for (int iLocal = nModes-1;iLocal>0;iLocal--) + { + //check one up + if (m_fAlphaT < (pGMM[iLocal-1].weight)) + { + break; + } + else + { + //swap one up + CvPBGMMGaussian temp = pGMM[iLocal]; + pGMM[iLocal] = pGMM[iLocal-1]; + pGMM[iLocal-1] = temp; + } + } + } + + //set the number of modes + *pModesUsed=nModes; + + return bBackground; +} + +// a bit more efficient implementation for common case of 3 channel (rgb) images +CV_INLINE int _icvUpdateGMM_C3(float r,float g, float b, + unsigned char* pModesUsed, + CvPBGMMGaussian* pGMM, + int m_nM, + float m_fAlphaT, + float m_fTb, + float m_fTB, + float m_fTg, + float m_fVarInit, + float m_fVarMax, + float m_fVarMin, + float m_fPrune) +{ + //calculate distances to the modes (+ sort) + //here we need to go in descending order!!! + bool bBackground=0;//return value -> true - the pixel classified as background + + //internal: + bool bFitsPDF=0;//if it remains zero a new GMM mode will be added + float m_fOneMinAlpha=1-m_fAlphaT; + unsigned char nModes=*pModesUsed;//current number of modes in GMM + float totalWeight=0.0f; + + ////// + //go through all modes + int iMode=0; + CvPBGMMGaussian* pGauss=pGMM; + for (;iModeweight;//need only weight if fit is found + weight=m_fOneMinAlpha*weight+m_fPrune; + + //// //fit not found yet - ///// - else + if (!bFitsPDF) { - weight=m_fOneMinAlpha*weight+m_fPrune; - //check prune - if (weight<-m_fPrune) + //check if it belongs to some of the remaining modes + float var=pGauss->variance; + + //calculate difference and distance + float muR = pGauss->mean[0]; + float muG = pGauss->mean[1]; + float muB = pGauss->mean[2]; + + float dR=muR - r; + float dG=muG - g; + float dB=muB - b; + + float dist2=(dR*dR+dG*dG+dB*dB); + + //background? - m_fTb - usually larger than m_fTg + if ((totalWeightmean[0] = muR - k*(dR); + pGauss->mean[1] = muG - k*(dG); + pGauss->mean[2] = muB - k*(dB); + + //update variance + float varnew = var + k*(dist2-var); + //limit the variance + pGauss->variance = MIN(m_fVarMax,MAX(varnew,m_fVarMin)); + + //sort + //all other weights are at the same place and + //only the matched (iModes) is higher -> just find the new place for it + for (int iLocal = iMode;iLocal>0;iLocal--) { + //check one up + if (weight < (pGMM[iLocal-1].weight)) + { + break; + } + else + { + //swap one up + CvPBGMMGaussian temp = pGMM[iLocal]; + pGMM[iLocal] = pGMM[iLocal-1]; + pGMM[iLocal-1] = temp; + pGauss--; + } + } + //belongs to the mode - bFitsPDF becomes 1 + ///// + } + + }//!bFitsPDF) + + //check prunning + if (weight<-m_fPrune) + { weight=0.0; nModes--; - } } + + pGauss->weight=weight; totalWeight+=weight; - m_aGaussians[pos].weight=weight; } //go through all modes ////// //renormalize weights - for (int iLocal = 0; iLocal < nModes; iLocal++) + for (iMode = 0; iMode < nModes; iMode++) { - m_aGaussians[posPixel+ iLocal].weight = m_aGaussians[posPixel+ iLocal].weight/totalWeight; + pGMM[iMode].weight = pGMM[iMode].weight/totalWeight; } //make new mode if needed and exit @@ -390,47 +600,53 @@ static int _icvUpdatePixelBackgroundGMM(long posPixel, if (nModes==m_nM) { //replace the weakest + pGauss=pGMM+m_nM-1; } else { //add a new one + pGauss=pGMM+nModes; nModes++; } - pos=posPixel+nModes-1; if (nModes==1) - m_aGaussians[pos].weight=1; + { + pGauss->weight=1; + } else - m_aGaussians[pos].weight=m_fAlphaT; - - //renormalize weights - int iLocal; - for (iLocal = 0; iLocal < nModes-1; iLocal++) { - m_aGaussians[posPixel+ iLocal].weight *=m_fOneMinAlpha; + pGauss->weight=m_fAlphaT; + + //renormalize all weights + for (iMode = 0; iMode < nModes-1; iMode++) + { + pGMM[iMode].weight *=m_fOneMinAlpha; + } } - m_aGaussians[pos].muR=red; - m_aGaussians[pos].muG=green; - m_aGaussians[pos].muB=blue; - m_aGaussians[pos].sigma=m_fSigma; + //init + pGauss->mean[0]=r; + pGauss->mean[1]=g; + pGauss->mean[2]=b; + + pGauss->variance=m_fVarInit; //sort //find the new place for it - for (iLocal = nModes-1;iLocal>0;iLocal--) + for (int iLocal = nModes-1;iLocal>0;iLocal--) { - long posLocal=posPixel + iLocal; - if (m_fAlphaT < (m_aGaussians[posLocal-1].weight)) - { + //check one up + if (m_fAlphaT < (pGMM[iLocal-1].weight)) + { break; - } - else - { - //swap - CvPBGMMGaussian temp = m_aGaussians[posLocal]; - m_aGaussians[posLocal] = m_aGaussians[posLocal-1]; - m_aGaussians[posLocal-1] = temp; - } + } + else + { + //swap one up + CvPBGMMGaussian temp = pGMM[iLocal]; + pGMM[iLocal] = pGMM[iLocal-1]; + pGMM[iLocal-1] = temp; + } } } @@ -440,238 +656,639 @@ static int _icvUpdatePixelBackgroundGMM(long posPixel, return bBackground; } -static void _icvReplacePixelBackgroundGMM(long pos, - unsigned char* pData, - CvPBGMMGaussian* m_aGaussians) +//the main function to update the background model +void icvUpdatePixelBackgroundGMM2( const CvArr* srcarr, CvArr* dstarr , + CvPBGMMGaussian *pGMM, + unsigned char *pUsedModes, + //CvGaussBGStatModel2Params* pGMMPar, + int nM, + float fTb, + float fTB, + float fTg, + float fVarInit, + float fVarMax, + float fVarMin, + float fCT, + float fTau, + bool bShadowDetection, + unsigned char nShadowDetection, + float alpha) +{ + CvMat sstub, *src = cvGetMat(srcarr, &sstub); + CvMat dstub, *dst = cvGetMat(dstarr, &dstub); + CvSize size = cvGetMatSize(src); + int nD=CV_MAT_CN(src->type); + + //reshape if possible + if( CV_IS_MAT_CONT(src->type & dst->type) ) + { + size.width *= size.height; + size.height = 1; + } + + int x, y; + float data[CV_BGFG_MOG2_NDMAX]; + float prune=-alpha*fCT; + + //general nD + + if (nD!=3) + { + switch (CV_MAT_DEPTH(src->type)) + { + case CV_8U: + for( y = 0; y < size.height; y++ ) + { + uchar* sptr = src->data.ptr + src->step*y; + uchar* pDataOutput = dst->data.ptr + dst->step*y; + for( x = 0; x < size.width; x++, + pGMM+=nM,pUsedModes++,pDataOutput++,sptr+=nD) + { + //convert data + for (int iD=0;iDdata.s + src->step*y; + uchar* pDataOutput = dst->data.ptr + dst->step*y; + for( x = 0; x < size.width; x++, + pGMM+=nM,pUsedModes++,pDataOutput++,sptr+=nD) + { + //convert data + for (int iD=0;iDdata.s + src->step*y); + uchar* pDataOutput = dst->data.ptr + dst->step*y; + for( x = 0; x < size.width; x++, + pGMM+=nM,pUsedModes++,pDataOutput++,sptr+=nD) + { + //convert data + for (int iD=0;iDdata.i + src->step*y; + uchar* pDataOutput = dst->data.ptr + dst->step*y; + for( x = 0; x < size.width; x++, + pGMM+=nM,pUsedModes++,pDataOutput++,sptr+=nD) + { + //convert data + for (int iD=0;iDdata.fl + src->step*y; + uchar* pDataOutput = dst->data.ptr + dst->step*y; + for( x = 0; x < size.width; x++, + pGMM+=nM,pUsedModes++,pDataOutput++,sptr+=nD) + { + //update GMM model + int result = _icvUpdateGMM(sptr,nD,pUsedModes,pGMM,nM,alpha, fTb, fTB, fTg, fVarInit, fVarMax, fVarMin,prune); + //detect shadows in the foreground + if (bShadowDetection) + if (result==0) result= _icvRemoveShadowGMM(data,nD,(*pUsedModes),pGMM,fTb,fTB,fTau); + //generate output + (* pDataOutput)= (result==1) ? 0 : (result==2) ? (nShadowDetection) : 255; + } + } + break; + case CV_64F: + for( y = 0; y < size.height; y++ ) + { + double* sptr = src->data.db + src->step*y; + uchar* pDataOutput = dst->data.ptr + dst->step*y; + for( x = 0; x < size.width; x++, + pGMM+=nM,pUsedModes++,pDataOutput++,sptr+=nD) + { + //convert data + for (int iD=0;iDtype)) + { + case CV_8U: + for( y = 0; y < size.height; y++ ) + { + uchar* sptr = src->data.ptr + src->step*y; + uchar* pDataOutput = dst->data.ptr + dst->step*y; + for( x = 0; x < size.width; x++, + pGMM+=nM,pUsedModes++,pDataOutput++,sptr+=nD) + { + //convert data + data[0]=float(sptr[0]),data[1]=float(sptr[1]),data[2]=float(sptr[2]); + //update GMM model + int result = _icvUpdateGMM_C3(data[0],data[1],data[2],pUsedModes,pGMM,nM,alpha, fTb, fTB, fTg, fVarInit, fVarMax, fVarMin,prune); + //detect shadows in the foreground + if (bShadowDetection) + if (result==0) result= _icvRemoveShadowGMM(data,nD,(*pUsedModes),pGMM,fTb,fTB,fTau); + //generate output + (* pDataOutput)= (result==1) ? 0 : (result==2) ? (nShadowDetection) : 255; + } + } + break; + case CV_16S: + for( y = 0; y < size.height; y++ ) + { + short* sptr = src->data.s + src->step*y; + uchar* pDataOutput = dst->data.ptr + dst->step*y; + for( x = 0; x < size.width; x++, + pGMM+=nM,pUsedModes++,pDataOutput++,sptr+=nD) + { + //convert data + data[0]=float(sptr[0]),data[1]=float(sptr[1]),data[2]=float(sptr[2]); + //update GMM model + int result = _icvUpdateGMM_C3(data[0],data[1],data[2],pUsedModes,pGMM,nM,alpha, fTb, fTB, fTg, fVarInit, fVarMax, fVarMin,prune); + //detect shadows in the foreground + if (bShadowDetection) + if (result==0) result= _icvRemoveShadowGMM(data,nD,(*pUsedModes),pGMM,fTb,fTB,fTau); + //generate output + (* pDataOutput)= (result==1) ? 0 : (result==2) ? (nShadowDetection) : 255; + } + } + break; + case CV_16U: + for( y = 0; y < size.height; y++ ) + { + unsigned short* sptr = (unsigned short*) src->data.s + src->step*y; + uchar* pDataOutput = dst->data.ptr + dst->step*y; + for( x = 0; x < size.width; x++, + pGMM+=nM,pUsedModes++,pDataOutput++,sptr+=nD) + { + //convert data + data[0]=float(sptr[0]),data[1]=float(sptr[1]),data[2]=float(sptr[2]); + //update GMM model + int result = _icvUpdateGMM_C3(data[0],data[1],data[2],pUsedModes,pGMM,nM,alpha, fTb, fTB, fTg, fVarInit, fVarMax, fVarMin,prune); + //detect shadows in the foreground + if (bShadowDetection) + if (result==0) result= _icvRemoveShadowGMM(data,nD,(*pUsedModes),pGMM,fTb,fTB,fTau); + //generate output + (* pDataOutput)= (result==1) ? 0 : (result==2) ? (nShadowDetection) : 255; + } + } + break; + case CV_32S: + for( y = 0; y < size.height; y++ ) + { + int* sptr = src->data.i + src->step*y; + uchar* pDataOutput = dst->data.ptr + dst->step*y; + for( x = 0; x < size.width; x++, + pGMM+=nM,pUsedModes++,pDataOutput++,sptr+=nD) + { + //convert data + data[0]=float(sptr[0]),data[1]=float(sptr[1]),data[2]=float(sptr[2]); + //update GMM model + int result = _icvUpdateGMM_C3(data[0],data[1],data[2],pUsedModes,pGMM,nM,alpha, fTb, fTB, fTg, fVarInit, fVarMax, fVarMin,prune); + //detect shadows in the foreground + if (bShadowDetection) + if (result==0) result= _icvRemoveShadowGMM(data,nD,(*pUsedModes),pGMM,fTb,fTB,fTau); + //generate output + (* pDataOutput)= (result==1) ? 0 : (result==2) ? (nShadowDetection) : 255; + } + } + break; + case CV_32F: + for( y = 0; y < size.height; y++ ) + { + float* sptr = src->data.fl + src->step*y; + uchar* pDataOutput = dst->data.ptr + dst->step*y; + for( x = 0; x < size.width; x++, + pGMM+=nM,pUsedModes++,pDataOutput++,sptr+=nD) + { + //update GMM model + int result = _icvUpdateGMM_C3(sptr[0],sptr[1],sptr[2],pUsedModes,pGMM,nM,alpha, fTb, fTB, fTg, fVarInit, fVarMax, fVarMin,prune); + //detect shadows in the foreground + if (bShadowDetection) + if (result==0) result= _icvRemoveShadowGMM(data,nD,(*pUsedModes),pGMM,fTb,fTB,fTau); + //generate output + (* pDataOutput)= (result==1) ? 0 : (result==2) ? (nShadowDetection) : 255; + } + } + break; + case CV_64F: + for( y = 0; y < size.height; y++ ) + { + double* sptr = src->data.db + src->step*y; + uchar* pDataOutput = dst->data.ptr + dst->step*y; + for( x = 0; x < size.width; x++, + pGMM+=nM,pUsedModes++,pDataOutput++,sptr+=nD) + { + //convert data + data[0]=float(sptr[0]),data[1]=float(sptr[1]),data[2]=float(sptr[2]); + //update GMM model + int result = _icvUpdateGMM_C3(data[0],data[1],data[2],pUsedModes,pGMM,nM,alpha, fTb, fTB, fTg, fVarInit, fVarMax, fVarMin,prune); + //detect shadows in the foreground + if (bShadowDetection) + if (result==0) result= _icvRemoveShadowGMM(data,nD,(*pUsedModes),pGMM,fTb,fTB,fTau); + //generate output + (* pDataOutput)= (result==1) ? 0 : (result==2) ? (nShadowDetection) : 255; + } + } + break; + } + }//a bit faster for nD=3; +} + + + +////////////////////////////////////////////// +//implementation as part of the CvBGStatModel +static void CV_CDECL icvReleaseGaussianBGModel2( CvGaussBGModel2** bg_model ); +static int CV_CDECL icvUpdateGaussianBGModel2( IplImage* curr_frame, CvGaussBGModel2* bg_model ); + + +CV_IMPL CvBGStatModel* +cvCreateGaussianBGModel2( IplImage* first_frame, CvGaussBGStatModel2Params* parameters ) { - pData[0]=(unsigned char) m_aGaussians[pos].muR; - pData[1]=(unsigned char) m_aGaussians[pos].muG; - pData[2]=(unsigned char) m_aGaussians[pos].muB; + CvGaussBGModel2* bg_model = 0; + int w,h; + + CV_FUNCNAME( "cvCreateGaussianBGModel2" ); + + __BEGIN__; + + CvGaussBGStatModel2Params params; + + if( !CV_IS_IMAGE(first_frame) ) + CV_ERROR( CV_StsBadArg, "Invalid or NULL first_frame parameter" ); + + if( first_frame->nChannels>CV_BGFG_MOG2_NDMAX ) + CV_ERROR( CV_StsBadArg, "Maxumum number of channels in the image is excedded (change CV_BGFG_MOG2_MAXBANDS constant)!" ); + + + CV_CALL( bg_model = (CvGaussBGModel2*)cvAlloc( sizeof(*bg_model) )); + memset( bg_model, 0, sizeof(*bg_model) ); + bg_model->type = CV_BG_MODEL_MOG2; + bg_model->release = (CvReleaseBGStatModel) icvReleaseGaussianBGModel2; + bg_model->update = (CvUpdateBGStatModel) icvUpdateGaussianBGModel2; + + //init parameters + if( parameters == NULL ) + { + /* These constants are defined in cvaux/include/cvaux.h: */ + params.bShadowDetection = 1; + params.bPostFiltering=0; + params.minArea=CV_BGFG_MOG2_MINAREA; + + //set parameters + // K - max number of Gaussians per pixel + params.nM = CV_BGFG_MOG2_NGAUSSIANS;//4; + // Tb - the threshold - n var + //pGMM->fTb = 4*4; + params.fTb = CV_BGFG_MOG2_STD_THRESHOLD*CV_BGFG_MOG2_STD_THRESHOLD; + // Tbf - the threshold + //pGMM->fTB = 0.9f;//1-cf from the paper + params.fTB = CV_BGFG_MOG2_BACKGROUND_THRESHOLD; + // Tgenerate - the threshold + params.fTg = CV_BGFG_MOG2_STD_THRESHOLD_GENERATE*CV_BGFG_MOG2_STD_THRESHOLD_GENERATE;//update the mode or generate new + //pGMM->fSigma= 11.0f;//sigma for the new mode + params.fVarInit = CV_BGFG_MOG2_VAR_INIT; + params.fVarMax = CV_BGFG_MOG2_VAR_MAX; + params.fVarMin = CV_BGFG_MOG2_VAR_MIN; + // alpha - the learning factor + params.fAlphaT = 1.0f/CV_BGFG_MOG2_WINDOW_SIZE;//0.003f; + // complexity reduction prior constant + params.fCT = CV_BGFG_MOG2_CT;//0.05f; + + //shadow + // Shadow detection + params.nShadowDetection = (unsigned char)CV_BGFG_MOG2_SHADOW_VALUE;//value 0 to turn off + params.fTau = CV_BGFG_MOG2_SHADOW_TAU;//0.5f;// Tau - shadow threshold + } + else + { + params = *parameters; + } + + bg_model->params = params; + + //image data + w = first_frame->width; + h = first_frame->height; + + bg_model->params.nWidth = w; + bg_model->params.nHeight = h; + + bg_model->params.nND = first_frame->nChannels; + + + //allocate GMM data + + //GMM for each pixel + bg_model->data.rGMM = (CvPBGMMGaussian*) malloc(w*h * params.nM * sizeof(CvPBGMMGaussian)); + //used modes per pixel + bg_model->data.rnUsedModes = (unsigned char* ) malloc(w*h); + memset(bg_model->data.rnUsedModes,0,w*h);//no modes used + + //prepare storages + CV_CALL( bg_model->background = cvCreateImage(cvSize(w,h), IPL_DEPTH_8U, first_frame->nChannels)); + CV_CALL( bg_model->foreground = cvCreateImage(cvSize(w,h), IPL_DEPTH_8U, 1)); + + //for eventual filtering + CV_CALL( bg_model->storage = cvCreateMemStorage()); + + bg_model->countFrames = 0; + + __END__; + + if( cvGetErrStatus() < 0 ) + { + CvBGStatModel* base_ptr = (CvBGStatModel*)bg_model; + + if( bg_model && bg_model->release ) + bg_model->release( &base_ptr ); + else + cvFree( &bg_model ); + bg_model = 0; + } + + return (CvBGStatModel*)bg_model; } -static void icvUpdatePixelBackgroundGMM(CvGaussBGStatModel2Data* pGMMData,CvGaussBGStatModel2Params* pGMM, float m_fAlphaT, unsigned char* data,unsigned char* output) +static void CV_CDECL +icvReleaseGaussianBGModel2( CvGaussBGModel2** _bg_model ) { - int size=pGMMData->nSize; - unsigned char* pDataCurrent=data; - unsigned char* pUsedModes=&pGMMData->rnUsedModes[0]; - unsigned char* pDataOutput=output; - //some constants - int m_nM=pGMM->nM; - //float m_fAlphaT=pGMM->fAlphaT; - - float m_fTb=pGMM->fTb;//Tb - threshold on the Mahalan. dist. - float m_fTB=pGMM->fTB;//1-TF from the paper - float m_fTg=pGMM->fTg;//Tg - when to generate a new component - float m_fSigma=pGMM->fSigma;//initial sigma - float m_fCT=pGMM->fCT;//CT - complexity reduction prior - float m_fPrune=-m_fAlphaT*m_fCT; - float m_fTau=pGMM->fTau; - CvPBGMMGaussian* m_aGaussians=&pGMMData->rGMM[0]; - long posPixel=0; - bool m_bShadowDetection=pGMM->bShadowDetection; - unsigned char m_nShadowDetection=pGMM->nShadowDetection; - - //go through the image - for (int i=0;idata.rGMM); + free (bg_model->data.rnUsedModes); + + cvReleaseImage( &bg_model->background ); + cvReleaseImage( &bg_model->foreground ); + cvReleaseMemStorage(&bg_model->storage); + memset( bg_model, 0, sizeof(*bg_model) ); + cvFree( _bg_model ); + } + + __END__; +} + + +static int CV_CDECL +icvUpdateGaussianBGModel2( IplImage* curr_frame, CvGaussBGModel2* bg_model ) +{ + //checks + if ((curr_frame->height!=bg_model->params.nHeight)||(curr_frame->width!=bg_model->params.nWidth)||(curr_frame->nChannels!=bg_model->params.nND)) + CV_Error( CV_StsBadSize, "the image not the same size as the reserved GMM background model"); + + float alpha=bg_model->params.fAlphaT; + bg_model->countFrames++; + + //faster initial updates - increase value of alpha + if (bg_model->params.bInit){ + float alphaInit=(1.0f/(2*bg_model->countFrames+1)); + if (alphaInit>alpha) + { + alpha = alphaInit; + } + else + { + bg_model->params.bInit = 0; + } + } + + //update background + //icvUpdatePixelBackgroundGMM2( curr_frame, bg_model->foreground, bg_model->data.rGMM,bg_model->data.rnUsedModes,&(bg_model->params),alpha); + icvUpdatePixelBackgroundGMM2( curr_frame, bg_model->foreground, bg_model->data.rGMM,bg_model->data.rnUsedModes, + bg_model->params.nM, + bg_model->params.fTb, + bg_model->params.fTB, + bg_model->params.fTg, + bg_model->params.fVarInit, + bg_model->params.fVarMax, + bg_model->params.fVarMin, + bg_model->params.fCT, + bg_model->params.fTau, + bg_model->params.bShadowDetection, + bg_model->params.nShadowDetection, + alpha); + + //foreground filtering + if (bg_model->params.bPostFiltering==1) { - // retrieve the colors - float red = pDataCurrent[0]; - float green = pDataCurrent[1]; - float blue = pDataCurrent[2]; - - //update model+ background subtract - int result = _icvUpdatePixelBackgroundGMM(posPixel, red, green, blue,pUsedModes,m_aGaussians, - m_nM,m_fAlphaT, m_fTb, m_fTB, m_fTg, m_fSigma, m_fPrune); - unsigned char nMLocal=*pUsedModes; - - if (m_bShadowDetection) - if (!result) - { - result= _icvRemoveShadowGMM(posPixel, red, green, blue,nMLocal,m_aGaussians, - m_fTb, - m_fTB, - m_fTau); - } + int region_count = 0; + CvSeq *first_seq = NULL, *prev_seq = NULL, *seq = NULL; - - switch (result) + + //filter small regions + cvClearMemStorage(bg_model->storage); + + cvMorphologyEx( bg_model->foreground, bg_model->foreground, 0, 0, CV_MOP_OPEN, 1 ); + cvMorphologyEx( bg_model->foreground, bg_model->foreground, 0, 0, CV_MOP_CLOSE, 1 ); + + cvFindContours( bg_model->foreground, bg_model->storage, &first_seq, sizeof(CvContour), CV_RETR_LIST ); + for( seq = first_seq; seq; seq = seq->h_next ) { - case 0: - //foreground - (* pDataOutput)=255; - if (pGMM->bRemoveForeground) + CvContour* cnt = (CvContour*)seq; + if( cnt->rect.width * cnt->rect.height < bg_model->params.minArea ) + { + //delete small contour + prev_seq = seq->h_prev; + if( prev_seq ) { - _icvReplacePixelBackgroundGMM(posPixel,pDataCurrent,m_aGaussians); + prev_seq->h_next = seq->h_next; + if( seq->h_next ) seq->h_next->h_prev = prev_seq; } - break; - case 1: - //background - (* pDataOutput)=0; - break; - case 2: - //shadow - (* pDataOutput)=m_nShadowDetection; - if (pGMM->bRemoveForeground) + else { - _icvReplacePixelBackgroundGMM(posPixel,pDataCurrent,m_aGaussians); + first_seq = seq->h_next; + if( seq->h_next ) seq->h_next->h_prev = NULL; } - - break; + } + else + { + region_count++; + } } - posPixel+=m_nM; - pDataCurrent+=3; - pDataOutput++; - pUsedModes++; + bg_model->foreground_regions = first_seq; + cvZero(bg_model->foreground); + cvDrawContours(bg_model->foreground, first_seq, CV_RGB(0, 0, 255), CV_RGB(0, 0, 255), 10, -1); + + return region_count; } + + return 1; } namespace cv { +static const int defaultHistory2 = CV_BGFG_MOG2_WINDOW_SIZE; +static const float defaultVarThreshold2 = CV_BGFG_MOG2_STD_THRESHOLD*CV_BGFG_MOG2_STD_THRESHOLD; +static const int defaultNMixtures2 = CV_BGFG_MOG2_NGAUSSIANS; +static const float defaultBackgroundRatio2 = CV_BGFG_MOG2_BACKGROUND_THRESHOLD; +static const float defaultVarThresholdGen2 = CV_BGFG_MOG2_STD_THRESHOLD_GENERATE*CV_BGFG_MOG2_STD_THRESHOLD_GENERATE; +static const float defaultVarInit2 = CV_BGFG_MOG2_VAR_INIT; +static const float defaultVarMax2 = CV_BGFG_MOG2_VAR_MAX; +static const float defaultVarMin2 = CV_BGFG_MOG2_VAR_MIN; +static const float defaultfCT2 = CV_BGFG_MOG2_CT; +static const unsigned char defaultnShadowDetection2 = (unsigned char)CV_BGFG_MOG2_SHADOW_VALUE; +static const float defaultfTau = CV_BGFG_MOG2_SHADOW_TAU; + + BackgroundSubtractorMOG2::BackgroundSubtractorMOG2() { - model = 0; - initialize(Size(), 0); -} + frameSize = Size(0,0); + frameType = 0; + + nframes = 0; + history = defaultHistory2; + varThreshold = defaultVarThreshold2; + bShadowDetection = 1; -BackgroundSubtractorMOG2::BackgroundSubtractorMOG2(double alphaT, - double sigma, int nmixtures, bool postFiltering, double minArea, - bool detectShadows, bool removeForeground, double Tb, double Tg, - double TB, double CT, int shadowValue, double tau) -{ - model = 0; - initialize(Size(), alphaT, sigma, nmixtures, postFiltering, minArea, - detectShadows, removeForeground, Tb, Tg, TB, CT, shadowValue, tau); -} + nmixtures = defaultNMixtures2; + backgroundRatio = defaultBackgroundRatio2; + fVarInit = defaultVarInit2; + fVarMax = defaultVarMax2; + fVarMin = defaultVarMin2; + varThresholdGen = defaultVarThresholdGen2; + fCT = defaultfCT2; + nShadowDetection = defaultnShadowDetection2; + fTau = defaultfTau; +} -void BackgroundSubtractorMOG2::initialize(Size frameSize, double alphaT, - double sigma, int nmixtures, bool postFiltering, double minArea, - bool detectShadows, bool removeForeground, double Tb, double Tg, - double TB, double CT, int shadowValue, double tau) +BackgroundSubtractorMOG2::BackgroundSubtractorMOG2(int _history, float _varThreshold, bool _bShadowDetection) { - if(!model) - model = new CvGaussBGModel2; - - CvGaussBGModel2* bg_model = (CvGaussBGModel2*)model; - - bg_model->params.bRemoveForeground=removeForeground; - bg_model->params.bShadowDetection = detectShadows; - bg_model->params.bPostFiltering = postFiltering; - bg_model->params.minArea = minArea; - bg_model->params.nM = nmixtures; - bg_model->params.fTb = Tb; - bg_model->params.fTB = TB; - bg_model->params.fTg = Tg; - bg_model->params.fSigma = sigma; - bg_model->params.fAlphaT = alphaT; - bg_model->params.fCT = CT; - bg_model->params.nShadowDetection = shadowValue; - bg_model->params.fTau = tau; + frameSize = Size(0,0); + frameType = 0; - int w = frameSize.width; - int h = frameSize.height; - int size = w*h; - - if( (bg_model->data.nWidth != w || - bg_model->data.nHeight != h) && - w > 0 && h > 0 ) - { - bg_model->data.nWidth=w; - bg_model->data.nHeight=h; - bg_model->data.nNBands=3; - bg_model->data.nSize=size; - - //GMM for each pixel - bg_model->data.rGMM.resize(size * bg_model->params.nM); - } - //used modes per pixel - bg_model->data.rnUsedModes.resize(0); - bg_model->data.rnUsedModes.resize(size, (uchar)0); - bg_model->params.bInit = true; - bg_model->countFrames = 0; -} + nframes = 0; + history = _history > 0 ? _history : defaultHistory2; + varThreshold = (_varThreshold>0)? _varThreshold : defaultVarThreshold2; + bShadowDetection = _bShadowDetection; + nmixtures = defaultNMixtures2; + backgroundRatio = defaultBackgroundRatio2; + fVarInit = defaultVarInit2; + fVarMax = defaultVarMax2; + fVarMin = defaultVarMin2; + + varThresholdGen = defaultVarThresholdGen2; + fCT = defaultfCT2; + nShadowDetection = defaultnShadowDetection2; + fTau = defaultfTau; +} BackgroundSubtractorMOG2::~BackgroundSubtractorMOG2() { - delete (CvGaussBGModel2*)model; } -void BackgroundSubtractorMOG2::operator()(const Mat& image0, Mat& fgmask0, double learningRate) + +void BackgroundSubtractorMOG2::initialize(Size _frameSize, int _frameType) { - CvGaussBGModel2* bg_model = (CvGaussBGModel2*)model; + frameSize = _frameSize; + frameType = _frameType; + nframes = 0; - CV_Assert(bg_model != 0); - Mat image = image0, fgmask = fgmask0; - CV_Assert( image.type() == CV_8UC1 || image.type() == CV_8UC3 ); - - if( learningRate < 0 ) - learningRate = bg_model->params.fAlphaT; - if( learningRate >= 1 ) - { - learningRate = 1; - bg_model->params.bInit = true; - } - if( image.size() != Size(bg_model->data.nWidth, bg_model->data.nHeight) ) - initialize(image.size(), learningRate, bg_model->params.fSigma, - bg_model->params.nM, bg_model->params.bPostFiltering, - bg_model->params.minArea, bg_model->params.bShadowDetection, - bg_model->params.bRemoveForeground, - bg_model->params.fTb, bg_model->params.fTg, bg_model->params.fTB, - bg_model->params.fCT, bg_model->params.nShadowDetection, bg_model->params.fTau); + int nchannels = CV_MAT_CN(frameType); + CV_Assert( nchannels <= CV_BGFG_MOG2_NDMAX ); - //int i, j, k, n; - float alpha = (float)bg_model->params.fAlphaT; - bg_model->countFrames++; + // for each gaussian mixture of each pixel bg model we store ... + // the mixture weight (w), + // the mean (nchannels values) and + // the covariance + bgmodel.create( 1, frameSize.height*frameSize.width*nmixtures*(2 + CV_BGFG_MOG2_NDMAX), CV_32F ); + //make the array for keeping track of the used modes per pixel - all zeros at start + bgmodelUsedModes.create(frameSize,CV_8U); + bgmodelUsedModes = Scalar::all(0); +} + +void BackgroundSubtractorMOG2::operator()(const InputArray& _image, OutputArray _fgmask, double learningRate) +{ + Mat image = _image.getMat(); + bool needToInitialize = nframes == 0 || learningRate >= 1 || image.size() != frameSize || image.type() != frameType; - if (bg_model->params.bInit) - { - //faster initial updates - float alphaInit = 1.0f/(2*bg_model->countFrames+1); - if( alphaInit > alpha ) - alpha = alphaInit; - else - bg_model->params.bInit = false; - } + if( needToInitialize ) + initialize(image.size(), image.type()); - if( !image.isContinuous() || image.channels() != 3 ) - { - image.release(); - image.create(image0.size(), CV_8UC3); - if( image0.type() == image.type() ) - image0.copyTo(image); - else - cvtColor(image0, image, CV_GRAY2BGR); - } - - if( !fgmask.isContinuous() ) - fgmask.release(); - fgmask.create(image.size(), CV_8UC1); - - icvUpdatePixelBackgroundGMM(&bg_model->data,&bg_model->params,alpha,image.data,fgmask.data); + _fgmask.create( image.size(), CV_8U ); + Mat fgmask = _fgmask.getMat(); - if( bg_model->params.bPostFiltering ) - { - //foreground filtering: filter out small regions - morphologyEx(fgmask, fgmask, CV_MOP_OPEN, Mat()); - morphologyEx(fgmask, fgmask, CV_MOP_CLOSE, Mat()); - - vector > contours; - findContours(fgmask, contours, CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE); - fgmask = Scalar::all(0); - - for( size_t i = 0; i < contours.size(); i++ ) - { - if( boundingRect(Mat(contours[i])).area() < bg_model->params.minArea ) - continue; - drawContours(fgmask, contours, (int)i, Scalar::all(255), -1, 8, vector(), 1); - } - } + ++nframes; + learningRate = learningRate >= 0 && nframes > 1 ? learningRate : 1./min( 2*nframes, history ); + CV_Assert(learningRate >= 0); + CvMat _cimage = image, _cfgmask = fgmask; - fgmask.copyTo(fgmask0); + if (learningRate > 0) + icvUpdatePixelBackgroundGMM2( &_cimage, &_cfgmask, + (CvPBGMMGaussian*) bgmodel.data, + bgmodelUsedModes.data, + nmixtures,//nM + varThreshold,//fTb + backgroundRatio,//fTB + varThresholdGen,//fTg, + fVarInit, + fVarMax, + fVarMin, + fCT, + fTau, + bShadowDetection, + nShadowDetection, + float(learningRate)); } } diff --git a/modules/video/src/camshift.cpp b/modules/video/src/camshift.cpp index 0c8bf119bf..0472ad87d2 100644 --- a/modules/video/src/camshift.cpp +++ b/modules/video/src/camshift.cpp @@ -289,29 +289,25 @@ cvCamShift( const void* imgProb, CvRect windowIn, return itersUsed; } -namespace cv -{ -RotatedRect CamShift( const Mat& probImage, Rect& window, +cv::RotatedRect cv::CamShift( const InputArray& _probImage, Rect& window, TermCriteria criteria ) { CvConnectedComp comp; CvBox2D box; - CvMat _probImage = probImage; - cvCamShift(&_probImage, window, (CvTermCriteria)criteria, &comp, &box); + CvMat c_probImage = _probImage.getMat(); + cvCamShift(&c_probImage, window, (CvTermCriteria)criteria, &comp, &box); window = comp.rect; return RotatedRect(Point2f(box.center), Size2f(box.size), box.angle); } -int meanShift( const Mat& probImage, Rect& window, TermCriteria criteria ) +int cv::meanShift( const InputArray& _probImage, Rect& window, TermCriteria criteria ) { CvConnectedComp comp; - CvMat _probImage = probImage; - int iters = cvMeanShift(&_probImage, window, (CvTermCriteria)criteria, &comp ); + CvMat c_probImage = _probImage.getMat(); + int iters = cvMeanShift(&c_probImage, window, (CvTermCriteria)criteria, &comp ); window = comp.rect; return iters; } -} - /* End of file. */ diff --git a/modules/video/src/lkpyramid.cpp b/modules/video/src/lkpyramid.cpp index 4870dee26f..bc3f993584 100644 --- a/modules/video/src/lkpyramid.cpp +++ b/modules/video/src/lkpyramid.cpp @@ -42,18 +42,15 @@ #include #include -namespace cv -{ - -void calcOpticalFlowPyrLK( const Mat& prevImg, const Mat& nextImg, - const vector& prevPts, - vector& nextPts, - vector& status, vector& err, +void cv::calcOpticalFlowPyrLK( const InputArray& _prevImg, const InputArray& _nextImg, + const InputArray& _prevPts, InputOutputArray _nextPts, + OutputArray _status, OutputArray _err, Size winSize, int maxLevel, TermCriteria criteria, double derivLambda, int flags ) { + Mat prevImg = _prevImg.getMat(), nextImg = _nextImg.getMat(), prevPtsMat = _prevPts.getMat(); derivLambda = std::min(std::max(derivLambda, 0.), 1.); double lambda1 = 1. - derivLambda, lambda2 = derivLambda; const int derivKernelSize = 3; @@ -66,16 +63,34 @@ void calcOpticalFlowPyrLK( const Mat& prevImg, const Mat& nextImg, CV_Assert( prevImg.size() == nextImg.size() && prevImg.type() == nextImg.type() ); - size_t npoints = prevPts.size(); - nextPts.resize(npoints); - status.resize(npoints); - for( size_t i = 0; i < npoints; i++ ) - status[i] = true; - err.resize(npoints); - + size_t npoints = prevPtsMat.total(); if( npoints == 0 ) + { + _nextPts.release(); + _status.release(); + _err.release(); return; + } + + CV_Assert( prevPtsMat.isContinuous() ); + const Point2f* prevPts = (const Point2f*)prevPtsMat.data; + + _nextPts.create((int)npoints, 1, prevPtsMat.type(), -1, true); + Mat nextPtsMat = _nextPts.getMat(); + CV_Assert( nextPtsMat.isContinuous() ); + Point2f* nextPts = (Point2f*)nextPtsMat.data; + _status.create((int)npoints, 1, CV_8U, -1, true); + Mat statusMat = _status.getMat(); + CV_Assert( statusMat.isContinuous() ); + uchar* status = statusMat.data; + for( size_t i = 0; i < npoints; i++ ) + status[i] = true; + _err.create((int)npoints, 1, CV_32F, -1, true); + Mat errMat = _err.getMat(); + CV_Assert( errMat.isContinuous() ); + float* err = (float*)errMat.data; + vector prevPyr, nextPyr; int cn = prevImg.channels(); @@ -334,8 +349,6 @@ void calcOpticalFlowPyrLK( const Mat& prevImg, const Mat& nextImg, } } -} - static void intersect( CvPoint2D32f pt, CvSize win_size, CvSize imgSize, CvPoint* min_pt, CvPoint* max_pt ) @@ -1852,18 +1865,14 @@ cvEstimateRigidTransform( const CvArr* matA, const CvArr* matB, CvMat* matM, int return 1; } -namespace cv -{ - -Mat estimateRigidTransform( const Mat& A, - const Mat& B, - bool fullAffine ) +cv::Mat cv::estimateRigidTransform( const InputArray& A, + const InputArray& B, + bool fullAffine ) { Mat M(2, 3, CV_64F); - CvMat matA = A, matB = B, matM = M; + CvMat matA = A.getMat(), matB = B.getMat(), matM = M; cvEstimateRigidTransform(&matA, &matB, &matM, fullAffine); return M; } -} /* End of file. */ diff --git a/modules/video/src/motempl.cpp b/modules/video/src/motempl.cpp index 1c94354946..44eaa9dc4a 100644 --- a/modules/video/src/motempl.cpp +++ b/modules/video/src/motempl.cpp @@ -442,38 +442,40 @@ cvSegmentMotion( const CvArr* mhiimg, CvArr* segmask, CvMemStorage* storage, } -void cv::updateMotionHistory( const Mat& silhouette, Mat& mhi, +void cv::updateMotionHistory( const InputArray& _silhouette, InputOutputArray _mhi, double timestamp, double duration ) { - CvMat _silhouette = silhouette, _mhi = mhi; - cvUpdateMotionHistory( &_silhouette, &_mhi, timestamp, duration ); + CvMat c_silhouette = _silhouette.getMat(), c_mhi = _mhi.getMat(); + cvUpdateMotionHistory( &c_silhouette, &c_mhi, timestamp, duration ); } -void cv::calcMotionGradient( const Mat& mhi, Mat& mask, - Mat& orientation, +void cv::calcMotionGradient( const InputArray& _mhi, OutputArray _mask, + OutputArray _orientation, double delta1, double delta2, int aperture_size ) { - mask.create(mhi.size(), CV_8U); - orientation.create(mhi.size(), CV_32F); - CvMat _mhi = mhi, _mask = mask, _orientation = orientation; - cvCalcMotionGradient(&_mhi, &_mask, &_orientation, delta1, delta2, aperture_size); + Mat mhi = _mhi.getMat(); + _mask.create(mhi.size(), CV_8U); + _orientation.create(mhi.size(), CV_32F); + CvMat c_mhi = mhi, c_mask = _mask.getMat(), c_orientation = _orientation.getMat(); + cvCalcMotionGradient(&c_mhi, &c_mask, &c_orientation, delta1, delta2, aperture_size); } -double cv::calcGlobalOrientation( const Mat& orientation, const Mat& mask, - const Mat& mhi, double timestamp, +double cv::calcGlobalOrientation( const InputArray& _orientation, const InputArray& _mask, + const InputArray& _mhi, double timestamp, double duration ) { - CvMat _orientation = orientation, _mask = mask, _mhi = mhi; - return cvCalcGlobalOrientation(&_orientation, &_mask, &_mhi, timestamp, duration); + CvMat c_orientation = _orientation.getMat(), c_mask = _mask.getMat(), c_mhi = _mhi.getMat(); + return cvCalcGlobalOrientation(&c_orientation, &c_mask, &c_mhi, timestamp, duration); } -void cv::segmentMotion(const Mat& mhi, Mat& segmask, +void cv::segmentMotion(const InputArray& _mhi, OutputArray _segmask, vector& boundingRects, double timestamp, double segThresh) { - segmask.create(mhi.size(), CV_32F); - CvMat c_mhi = mhi, c_segmask = segmask; + Mat mhi = _mhi.getMat(); + _segmask.create(mhi.size(), CV_32F); + CvMat c_mhi = mhi, c_segmask = _segmask.getMat(); Ptr storage = cvCreateMemStorage(); Seq comps = cvSegmentMotion(&c_mhi, &c_segmask, storage, timestamp, segThresh); Seq::const_iterator it(comps); diff --git a/modules/video/src/optflowgf.cpp b/modules/video/src/optflowgf.cpp index 8d622e6a03..5b72af200e 100644 --- a/modules/video/src/optflowgf.cpp +++ b/modules/video/src/optflowgf.cpp @@ -561,22 +561,24 @@ FarnebackUpdateFlow_GaussianBlur( const Mat& _R0, const Mat& _R1, } } +} -void calcOpticalFlowFarneback( const Mat& prev0, const Mat& next0, - Mat& flow0, double pyr_scale, int levels, int winsize, +void cv::calcOpticalFlowFarneback( const InputArray& _prev0, const InputArray& _next0, + OutputArray _flow0, double pyr_scale, int levels, int winsize, int iterations, int poly_n, double poly_sigma, int flags ) { + Mat prev0 = _prev0.getMat(), next0 = _next0.getMat(); const int min_size = 32; const Mat* img[2] = { &prev0, &next0 }; - Mat fimg; int i, k; double scale; - Mat prevFlow, flow; + Mat prevFlow, flow, fimg; CV_Assert( prev0.size() == next0.size() && prev0.channels() == next0.channels() && prev0.channels() == 1 && pyr_scale < 1 ); - flow0.create( prev0.size(), CV_32FC2 ); + _flow0.create( prev0.size(), CV_32FC2 ); + Mat flow0 = _flow0.getMat(); for( k = 0, scale = 1; k < levels; k++ ) { @@ -643,7 +645,6 @@ void calcOpticalFlowFarneback( const Mat& prev0, const Mat& next0, } } -} CV_IMPL void cvCalcOpticalFlowFarneback( const CvArr* _prev, const CvArr* _next, diff --git a/modules/video/test/test_motiontemplates.cpp b/modules/video/test/test_motiontemplates.cpp index 452c73bc2c..fe7425a826 100644 --- a/modules/video/test/test_motiontemplates.cpp +++ b/modules/video/test/test_motiontemplates.cpp @@ -169,12 +169,15 @@ double CV_UpdateMHITest::get_success_error_level( int /*test_case_idx*/, int /*i void CV_UpdateMHITest::run_func() { - cvUpdateMotionHistory( test_array[INPUT][0], test_array[INPUT_OUTPUT][0], timestamp, duration ); + CvMat m = test_mat[INPUT_OUTPUT][0]; + cv::updateMotionHistory( test_mat[INPUT][0], test_mat[INPUT_OUTPUT][0], timestamp, duration); + m = test_mat[INPUT_OUTPUT][0]; } void CV_UpdateMHITest::prepare_to_validation( int /*test_case_idx*/ ) { + CvMat m0 = test_mat[REF_INPUT_OUTPUT][0]; test_updateMHI( test_mat[INPUT][0], test_mat[REF_INPUT_OUTPUT][0], timestamp, duration ); } @@ -290,8 +293,10 @@ double CV_MHIGradientTest::get_success_error_level( int /*test_case_idx*/, int / void CV_MHIGradientTest::run_func() { - cvCalcMotionGradient( test_array[INPUT][0], test_array[OUTPUT][0], - test_array[OUTPUT][1], delta1, delta2, aperture_size ); + cv::calcMotionGradient(test_mat[INPUT][0], test_mat[OUTPUT][0], + test_mat[OUTPUT][1], delta1, delta2, aperture_size ); + //cvCalcMotionGradient( test_array[INPUT][0], test_array[OUTPUT][0], + // test_array[OUTPUT][1], delta1, delta2, aperture_size ); } @@ -453,8 +458,10 @@ double CV_MHIGlobalOrientTest::get_success_error_level( int /*test_case_idx*/, i void CV_MHIGlobalOrientTest::run_func() { - angle = cvCalcGlobalOrientation( test_array[INPUT][2], test_array[INPUT][1], - test_array[INPUT][0], timestamp, duration ); + //angle = cvCalcGlobalOrientation( test_array[INPUT][2], test_array[INPUT][1], + // test_array[INPUT][0], timestamp, duration ); + angle = cv::calcGlobalOrientation(test_mat[INPUT][2], test_mat[INPUT][1], + test_mat[INPUT][0], timestamp, duration ); }