{
//! 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
};
//! computes the best-fit perspective transformation mapping srcPoints to dstPoints.
-CV_EXPORTS_AS(findHomographyAndOutliers) Mat findHomography( const Mat& srcPoints,
- const Mat& dstPoints,
- vector<uchar>& 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<uchar>& 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<Point2f>& 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<Point2f>& 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<int>* inliers = NULL );
+ OutputArray inliers = OutputArray() );
//! initializes camera matrix from a few 3D points and the corresponding projections.
-CV_EXPORTS_W Mat initCameraMatrix2D( const vector<vector<Point3f> >& objectPoints,
- const vector<vector<Point2f> >& 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<Point2f>& 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<Point2f>& 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<Point2f>& 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<Point2f>& 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
{
};
//! finds intrinsic and extrinsic camera parameters from several fews of a known calibration pattern.
-CV_EXPORTS_W double calibrateCamera( const vector<vector<Point3f> >& objectPoints,
- const vector<vector<Point2f> >& 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<Mat>& rvecs, CV_OUT vector<Mat>& 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,
CV_OUT double& aspectRatio );
//! finds intrinsic and extrinsic parameters of a stereo camera
-CV_EXPORTS_W double stereoCalibrate( const vector<vector<Point3f> >& objectPoints,
- const vector<vector<Point2f> >& imagePoints1,
- const vector<vector<Point2f> >& 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<vector<Point2f> >& imgpt1,
- const vector<vector<Point2f> >& 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<Point3f>& 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<Point2f>& dst );
+CV_EXPORTS void convertPointsFromHomogeneous( const InputArray& src, OutputArray dst );
//! the algorithm for finding fundamental matrix
enum
};
//! finds fundamental matrix from a set of corresponding 2D points
-CV_EXPORTS Mat findFundamentalMat( const Mat& points1, const Mat& points2,
- CV_OUT vector<uchar>& 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<Vec3f>& lines );
+CV_EXPORTS void computeCorrespondEpilines( const InputArray& points1,
+ int whichImage, const InputArray& F,
+ OutputArray lines );
template<> CV_EXPORTS void Ptr<CvStereoBMState>::delete_obj();
//! 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<CvStereoBMState> state;
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;
};
//! 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,
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
}
}
-namespace cv
-{
-
-bool findChessboardCorners( const Mat& image, Size patternSize,
- vector<Point2f>& 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<Point2f> 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<Point2f>& 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<Point2f>& centers, int flags )
+bool cv::findCirclesGrid( const InputArray& _image, Size patternSize,
+ OutputArray _centers, int flags )
{
+ Mat image = _image.getMat();
+ vector<Point2f> centers;
SimpleBlobDetector::Params params;
if(flags & CALIB_CB_WHITE_CIRCLES)
{
{
CirclesGridClusterFinder circlesGridClusterFinder;
circlesGridClusterFinder.findGrid(points, patternSize, centers);
+ Mat(centers).copyTo(_centers);
return !centers.empty();
}
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;
}
H = CirclesGridFinder::rectifyGrid(boxFinder.getDetectedGridSize(), centers, points, points);
}
}
-
+ Mat(centers).copyTo(_centers);
return false;
}
-}
-
/* End of file. */
}
-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 ||
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];
namespace cv
{
-static void collectCalibrationData( const vector<vector<Point3f> >& objectPoints,
- const vector<vector<Point2f> >& imagePoints,
- const vector<vector<Point2f> >& 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<Point3f>::type);
- imgPtMat.create(1, (int)total, DataType<Point2f>::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<Point2f>::type);
+ imgPtMat2->create(1, (int)total, CV_32FC2);
imgPtData2 = imgPtMat2->ptr<Point2f>();
}
Point3f* objPtData = objPtMat.ptr<Point3f>();
- Point2f* imgPtData = imgPtMat.ptr<Point2f>();
+ Point2f* imgPtData1 = imgPtMat1.ptr<Point2f>();
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<int>(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]) );
+ }
}
}
}
-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<Point2f>& 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<Point2f>& 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<vector<Point3f> >& objectPoints,
- const vector<vector<Point2f> >& 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<vector<Point2f> >(),
+ collectCalibrationData( objectPoints, imagePoints, InputArrayOfArrays(),
objPt, imgPt, 0, npoints );
CvMat _objPt = objPt, _imgPt = imgPt, _npoints = npoints, _cameraMatrix = cameraMatrix;
cvInitIntrinsicParams2D( &_objPt, &_imgPt, &_npoints,
}
-double cv::calibrateCamera( const vector<vector<Point3f> >& objectPoints,
- const vector<vector<Point2f> >& imagePoints,
- Size imageSize, Mat& cameraMatrix, Mat& distCoeffs,
- vector<Mat>& rvecs, vector<Mat>& 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<vector<Point2f> >(),
+ 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<double>(i), 3*sizeof(double));
+ memcpy(tv.data, tvecM.ptr<double>(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<vector<Point3f> >& objectPoints,
- const vector<vector<Point2f> >& imagePoints1,
- const vector<vector<Point2f> >& 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);
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<vector<Point2f> >& imgpt1_0,
- const vector<vector<Point2f> >& 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<Point2f> 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<Point2f>();
+ const Point2f* pt3data = pt3.ptr<Point2f>();
+ 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();
}
-float cv::rectify3Collinear( const Mat& cameraMatrix1, const Mat& distCoeffs1,
- const Mat& cameraMatrix2, const Mat& distCoeffs2,
- const Mat& cameraMatrix3, const Mat& distCoeffs3,
- const vector<vector<Point2f> >& imgpt1,
- const vector<vector<Point2f> >& 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;
P3.at<double>(0,3) *= P3.at<double>(0,0);
P3.at<double>(1,3) *= P3.at<double>(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<double>(idx,3)/P3.at<double>(idx,idx))/
(P2.at<double>(idx,3)/P2.at<double>(idx,idx)));
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<cv::Point2f> &patternPoints, const std::vector<cv::Point2f> &rectifiedPatternPoints, std::vector<cv::Point2f> ¢ers)
Mat dstKeypointsMat;
transform(Mat(srcKeypoints), dstKeypointsMat, H);
vector<Point2f> dstKeypoints;
- convertPointsHomogeneous(dstKeypointsMat, dstKeypoints);
+ convertPointsFromHomogeneous(dstKeypointsMat, dstKeypoints);
warpedKeypoints.clear();
for (size_t i = 0; i < dstKeypoints.size(); i++)
Mat centers;
const int clustersCount = 4;
kmeans(Mat(samples).reshape(1, 0), clustersCount, bestLabels, termCriteria, parameters.kmeansAttempts,
- KMEANS_RANDOM_CENTERS, ¢ers);
+ KMEANS_RANDOM_CENTERS, centers);
assert( centers.type() == CV_32FC1 );
vector<int> basisIndices;
}
}
-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<uchar>* 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<uchar>* 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<uchar>& 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<uchar>& 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<Vec3f>& 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<Point3f>& 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<Point2f>& 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. */
return j == i;
}
-int cv::estimateAffine3D(const Mat& from, const Mat& to, Mat& out, vector<uchar>& 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<Point3d> dFrom;
- vector<Point3d> 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<Point3f>(), from.ptr<Point3f>() + count, back_inserter(dFrom));
- copy(to.ptr<Point3f>(), to.ptr<Point3f>() + 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<double>::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 );
}
return 1;
}
}
+
+}
-bool find4QuadCornerSubpix(const Mat& img, std::vector<Point2f>& 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<Point2f>();
const int nbins = 256;
float ranges[] = {0, 256};
const float* _ranges = ranges;
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),
return true;
}
-
-}; // namespace std
/*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<char>& pointsMask, const Mat& objectPoints, const Mat& imagePoints,
- const Parameters& params, vector<int>& 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<Vec3f>(0, i) - modelObjectPoints.at<Vec3f>(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<Point2f> 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<int> localInliers;
- for (size_t i = 0; i < objectPoints.cols; i++)
- {
- Point2f p(imagePoints.at<Vec2f>(0, i)[0], imagePoints.at<Vec2f>(0, i)[1]);
- if ((norm(p - projected_points[i]) < params.reprojectionError)
- && (rotatedPoints.at<Vec3f>(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<char>& pointsMask, const Mat& objectPoints, const Mat& imagePoints,
+ const Parameters& params, vector<int>& inliers, Mat& rvec, Mat& tvec,
+ const Mat& rvecInit, const Mat& tvecInit, Mutex& resultsMutex)
{
- vector<char> 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<Vec3f>(0, i) - modelObjectPoints.at<Vec3f>(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<Point2f> 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<int> localInliers;
+ for (int i = 0; i < objectPoints.cols; i++)
+ {
+ Point2f p(imagePoints.at<Vec2f>(0, i)[0], imagePoints.at<Vec2f>(0, i)[1]);
+ if ((norm(p - projected_points[i]) < params.reprojectionError)
+ && (rotatedPoints.at<Vec3f>(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<int>& 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<int>& inliers;
- Mat &rvec, &tvec;
- Mat initRvec, initTvec;
-
- static RNG generator;
- static Mutex syncMutex;
-
- void generateVar(vector<char>& 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<char> 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<int>& 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<int>& inliers;
+ Mat initRvec, initTvec;
+
+ static RNG generator;
+ static Mutex syncMutex;
+
+ void generateVar(vector<char>& 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<int>* 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<int> 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<int> 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;
}
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);
}
typedef cv::Point_<short> 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<PixType>::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);
}
}
}
-
-
-void StereoSGBM::operator ()( const Mat& left, const Mat& right, Mat& disp )
-{
- CV_Assert( left.size() == right.size() && left.type() == right.type() &&
- left.depth() == DataType<PixType>::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);
}
}
}
-
-}
CvRect cvGetValidDisparityROI( CvRect roi1, CvRect roi2, int minDisparity,
int numberOfDisparities, int SADWindowSize )
const Mat& cameraMatrix, const Mat& distCoeffs, vector<Point2f>& 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 /////////////////////////////////////
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,
Mat rvec, tvec;
vector<int> 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;
// 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,
class CV_EXPORTS Exception : public std::exception
{
public:
- /*!
+ /*!
Default constructor
*/
Exception() { code = 0; line = 0; }
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()
{
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
};
typedef Vec<int, 2> Vec2i;
typedef Vec<int, 3> Vec3i;
typedef Vec<int, 4> Vec4i;
+typedef Vec<int, 6> Vec6i;
+typedef Vec<int, 8> Vec8i;
typedef Vec<float, 2> Vec2f;
typedef Vec<float, 3> Vec3f;
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);
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<<KIND_SHIFT, MAT=1<<KIND_SHIFT,
+ MATX=2<<KIND_SHIFT, STD_VECTOR=3<<KIND_SHIFT,
+ STD_VECTOR_VECTOR=4<<KIND_SHIFT,
+ STD_VECTOR_MAT=5<<KIND_SHIFT, EXPR=6<<KIND_SHIFT };
+ InputArray();
+ InputArray(const Mat& m);
+ InputArray(const MatExpr& expr);
+ template<typename _Tp> InputArray(const vector<_Tp>& vec);
+ template<typename _Tp> InputArray(const vector<vector<_Tp> >& vec);
+ InputArray(const vector<Mat>& vec);
+ template<typename _Tp, int m, int n> InputArray(const Matx<_Tp, m, n>& matx);
+ InputArray(const double& val);
+ Mat getMat(int i=-1) const;
+ void getMatVector(vector<Mat>& 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<typename _Tp> OutputArray(vector<_Tp>& vec);
+ template<typename _Tp> OutputArray(vector<vector<_Tp> >& vec);
+ OutputArray(vector<Mat>& vec);
+ template<typename _Tp, int m, int n> 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 };
Mat clone() const;
//! copies the matrix content to "m".
// It calls m.create(this->size(), this->type()).
- void copyTo( Mat& m ) const;
- template<typename _Tp> 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;
//! 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);
MStep step;
};
-
+
/*!
Random Number Generator
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();
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;
};
-
-
/*!
double epsilon; // the desired accuracy
};
+
//! swaps two matrices
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_cast<uchar>abs(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<Mat>& mv, Mat& dst);
+CV_EXPORTS_W void merge(const vector<Mat>& mv, OutputArray dst);
//! copies each plane of a multi-channel array to a dedicated array
CV_EXPORTS void split(const Mat& src, Mat* mvbegin);
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<Mat>& src, vector<Mat>& 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<Mat>& 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<Mat>& 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 <cmpop> 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 <cmpop> 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
//! 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
//! 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<typename _Tp, int m, int n, int nm> static void compute( const Matx<_Tp, m, n>& a,
Matx<_Tp, nm, 1>& w, Matx<_Tp, m, nm>& u, Matx<_Tp, n, nm>& vt );
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);
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();
template<typename _Tp> 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,
//! 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<Point>& pts );
+ int arcStart, int arcEnd, int delta,
+ CV_OUT vector<Point>& pts );
enum
{
{
public:
typedef _Tp value_type;
+ enum { buffer_padding = (int)((16 + sizeof(_Tp) - 1)/sizeof(_Tp)) };
//! the default contructor
AutoBuffer();
//! 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 //////////////////////////
//! 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 ++();
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;
\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
//! 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<int>* neighborsIdx,
- Mat* neighbors=0,
- vector<float>* dist=0,
- vector<int>* labels=0) const;
- CV_WRAP int findNearest(const vector<float>& vec, int K, int Emax,
- CV_OUT vector<int>* neighborsIdx,
- CV_OUT Mat* neighbors=0,
- CV_OUT vector<float>* dist=0,
- CV_OUT vector<int>* 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<int>* neighborsIdx, Mat* neighbors=0,
- vector<int>* labels=0) const;
- CV_WRAP void findOrthoRange(const vector<float>& minBounds, const vector<float>& maxBounds,
- CV_OUT vector<int>* neighborsIdx, CV_OUT Mat* neighbors=0,
- CV_OUT vector<int>* 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<int>* labels=0) const;
- //! returns vectors with the specified indices
- CV_WRAP void getPoints(const vector<int>& idxs, Mat& pts, CV_OUT vector<int>* 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
int index;
};
-#if 0
+
class CV_EXPORTS AlgorithmImpl;
/*!
Ptr<AlgorithmImpl> impl;
};
-#endif
}
return it;
}
-
-template<typename _Tp> 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<typename _Tp> inline Mat::operator vector<_Tp>() const
{
vector<_Tp> v;
///////////////////////////////////////////// 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);
}
}
}
+
+/////////////////////////////// Input/Output Arrays /////////////////////////////////
+
+template<typename _Tp> InputArray::InputArray(const vector<_Tp>& vec)
+ : flags(STD_VECTOR + DataType<_Tp>::type), obj((void*)&vec) {}
+
+template<typename _Tp> InputArray::InputArray(const vector<vector<_Tp> >& vec)
+ : flags(STD_VECTOR_VECTOR + DataType<_Tp>::type), obj((void*)&vec) {}
+
+template<typename _Tp, int m, int n> InputArray::InputArray(const Matx<_Tp, m, n>& mtx)
+ : flags(MATX + DataType<_Tp>::type), obj((void*)&mtx), sz(n, m) {}
+
+template<typename _Tp> OutputArray::OutputArray(vector<_Tp>& vec) : InputArray(vec) {}
+template<typename _Tp> OutputArray::OutputArray(vector<vector<_Tp> >& vec) : InputArray(vec) {}
+template<typename _Tp, int m, int n> OutputArray::OutputArray(Matx<_Tp, m, n>& mtx) : InputArray(mtx) {}
+
//////////////////////////////////// Matrix Expressions /////////////////////////////////////////
class CV_EXPORTS MatOp
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;
};
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;
/////////////////////////////// AutoBuffer ////////////////////////////////////////
template<typename _Tp, size_t fixed_size> inline AutoBuffer<_Tp, fixed_size>::AutoBuffer()
-: ptr(buf), size(fixed_size) {}
+{
+ ptr = alignPtr(buf, 16);
+ size = fixed_size;
+}
template<typename _Tp, size_t fixed_size> 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<typename _Tp, size_t fixed_size> inline AutoBuffer<_Tp, fixed_size>::~AutoBuffer()
{ deallocate(); }
template<typename _Tp, size_t fixed_size> 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;
}
}
return out;
}
-#if 0
template<typename _Tp> struct AlgorithmParamType {};
template<> struct AlgorithmParamType<int> { enum { type = CV_PARAM_TYPE_INT }; };
template<> struct AlgorithmParamType<double> { enum { type = CV_PARAM_TYPE_REAL }; };
{
setParamRange_(propId, AlgorithmParamType<_Tp>::type, &minVal, &maxVal);
}
-#endif
}
// 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,
/* ////////////////////////////////////////////////////////////////////
//
-// 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<class Op8> struct VBinOp8
+struct NOP {};
+
+template<typename T, class Op, class Op8>
+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<typename T, class Op16> struct VBinOp16
+template<typename T, class Op, class Op16>
+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<class Op32f> struct VBinOp32f
+
+template<class Op, class Op32>
+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<class Op, class Op32>
+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<class Op, class Op64>
+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
__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); }};
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); }};
}
};
+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<ushort, _VAdd16u> VAdd16u;
-typedef VBinOp16<ushort, _VSub16u> VSub16u;
-typedef VBinOp16<ushort, _VMin16u> VMin16u;
-typedef VBinOp16<ushort, _VMax16u> VMax16u;
-typedef VBinOp16<ushort, _VAbsDiff16u> VAbsDiff16u;
-
-typedef VBinOp16<short, _VAdd16s> VAdd16s;
-typedef VBinOp16<short, _VSub16s> VSub16s;
-typedef VBinOp16<short, _VMin16s> VMin16s;
-typedef VBinOp16<short, _VMax16s> VMax16s;
-typedef VBinOp16<short, _VAbsDiff16s> 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<uchar>::operator ()(uchar a, uchar b) const
+{ return CV_FAST_CAST_8U(a + b); }
+template<> inline uchar OpSub<uchar>::operator ()(uchar a, uchar b) const
+{ return CV_FAST_CAST_8U(a - b); }
+
+template<typename T> 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<short>::operator ()(short a, short b) const
+{ return saturate_cast<short>(std::abs(a - b)); }
-struct ippAdd8u
+template<> inline schar OpAbsDiff<schar>::operator ()(schar a, schar b) const
+{ return saturate_cast<schar>(std::abs(a - b)); }
+
+template<typename T, typename WT=T> 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<T>(std::abs(a - b)); }
};
-struct ippAdd16u
+template<typename T> 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<typename T> 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<typename T> 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<typename T> 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<uchar, OpAdd<uchar>, 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<schar, OpAdd<schar>, 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<ushort, OpAdd<ushort>, 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<short, OpAdd<short>, 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<OpAdd<int>, 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<OpAdd<float>, 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<OpAdd<double>, 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<uchar, OpSub<uchar>, 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<schar, OpSub<schar>, 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<ushort, OpSub<ushort>, 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<short, OpSub<short>, 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<OpSub<int>, 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<OpSub<float>, 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<OpSub<double>, IF_SIMD(_VSub64f)>(src1, step1, src2, step2, dst, step, sz);
+}
-struct ippMin32f
+template<> inline uchar OpMin<uchar>::operator ()(uchar a, uchar b) const { return CV_MIN_8U(a, b); }
+template<> inline uchar OpMax<uchar>::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<uchar, OpMax<uchar>, 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<schar, OpMax<schar>, 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<ushort, OpMax<ushort>, 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<short, OpMax<short>, 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<OpMax<int>, 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<OpMax<float>, 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<OpMax<double>, 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<uchar, OpMin<uchar>, 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<schar, OpMin<schar>, 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<ushort, OpMin<ushort>, 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<short, OpMin<short>, IF_SIMD(_VMin16s)>(src1, step1, src2, step2, dst, step, sz)));
+}
-template<typename T> 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<OpMin<int>, IF_SIMD(_VMin32s)>(src1, step1, src2, step2, dst, step, sz);
+}
-template<typename T> 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<OpMin<float>, IF_SIMD(_VMin32f)>(src1, step1, src2, step2, dst, step, sz)));
+}
-template<typename T> 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<OpMin<double>, IF_SIMD(_VMin64f)>(src1, step1, src2, step2, dst, step, sz);
+}
-template<class OPB, class OPI, class OPV> 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<uchar, OpAbsDiff<uchar>, 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<schar, OpAbsDiff<schar>, 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<ushort, OpAbsDiff<ushort>, 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<short, OpAbsDiff<short>, 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<OpAbsDiff<int>, 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<OpAbsDiff<float>, 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<OpAbsDiff<double>, 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<uchar, OpAnd<uchar>, 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<uchar, OpOr<uchar>, 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<uchar, OpXor<uchar>, 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<uchar, OpNot<uchar>, 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<uchar> _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<class OPB, class OPI, class OPV> 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<uchar> 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<uchar> 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<uchar>, AndOp<int>, ippAnd8u>);
-#else
- binaryMaskOp(a, b, c, mask, bitwiseOp_<AndOp<uchar>, AndOp<int>, 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<uchar>, OrOp<int>, ippOr8u>);
-#else
- binaryMaskOp(a, b, c, mask, bitwiseOp_<OrOp<uchar>, OrOp<int>, 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<uchar>, XorOp<int>, ippXor8u>);
-#else
- binaryMaskOp(a, b, c, mask, bitwiseOp_<XorOp<uchar>, XorOp<int>, 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<uchar>, AndOp<int>, 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<uchar>, OrOp<int>, 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<uchar>, XorOp<int>, 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<uchar> _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<uchar>::operator ()(uchar a, uchar b) const
-{ return CV_FAST_CAST_8U(a + b); }
-template<> inline uchar OpSub<uchar>::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_<OpAdd<uchar>, ippAdd8u>,
- 0,
- binaryOpC1_<OpAdd<ushort>, ippAdd16u>,
- binaryOpC1_<OpAdd<short>, ippAdd16s>,
- binaryOpC1_<OpAdd<int>, ippAdd32s>,
- binaryOpC1_<OpAdd<float>, ippAdd32f>,
- binaryOpC1_<OpAdd<double>, ippAdd64f>,
- 0
-#else
- binaryOpC1_<OpAdd<uchar>, VAdd8u>,
- 0,
- binaryOpC1_<OpAdd<ushort>, VAdd16u>,
- binaryOpC1_<OpAdd<short>, VAdd16s>,
- binaryOpC1_<OpAdd<int>, NoVec>,
- binaryOpC1_<OpAdd<float>, VAdd32f>,
- binaryOpC1_<OpAdd<double>, 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_<OpSub<uchar>, ippSub8u>,
- 0,
- binaryOpC1_<OpSub<ushort>, ippSub16u>,
- binaryOpC1_<OpSub<short>, ippSub16s>,
- binaryOpC1_<OpSub<int>, ippSub32s>,
- binaryOpC1_<OpSub<float>, ippSub32f>,
- binaryOpC1_<OpSub<double>, ippSub64f>,
- 0
-#else
- binaryOpC1_<OpSub<uchar>, VSub8u>,
- 0,
- binaryOpC1_<OpSub<ushort>, VSub16u>,
- binaryOpC1_<OpSub<short>, VSub16s>,
- binaryOpC1_<OpSub<int>, NoVec>,
- binaryOpC1_<OpSub<float>, VSub32f>,
- binaryOpC1_<OpSub<double>, 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_<OpAdd<uchar, int, uchar> >,
- 0,
- binarySOpCn_<OpAdd<ushort, int, ushort> >,
- binarySOpCn_<OpAdd<short, int, short> >,
- binarySOpCn_<OpAdd<int> >,
- binarySOpCn_<OpAdd<float> >,
- binarySOpCn_<OpAdd<double> >,
- 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_<OpRSub<uchar, int, uchar> >,
- 0,
- binarySOpCn_<OpRSub<ushort, int, ushort> >,
- binarySOpCn_<OpRSub<short, int, short> >,
- binarySOpCn_<OpRSub<int> >,
- binarySOpCn_<OpRSub<float> >,
- binarySOpCn_<OpRSub<double> >,
- 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<typename T, typename WT> 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 )
}
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 )
}
}
-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_<uchar, float>,
- 0,
- mul_<ushort, float>,
- mul_<short, float>,
- mul_<int, double>,
- mul_<float, float>,
- mul_<double, double>,
- 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<typename T> 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 )
double d = scale/(a * b);
b *= d;
a *= d;
-
+
T z0 = saturate_cast<T>(src2[i+1] * ((double)src1[i] * b));
T z1 = saturate_cast<T>(src2[i] * ((double)src1[i+1] * b));
T z2 = saturate_cast<T>(src2[i+3] * ((double)src1[i+2] * a));
T z3 = saturate_cast<T>(src2[i+2] * ((double)src1[i+3] * a));
-
+
dst[i] = z0; dst[i+1] = z1;
dst[i+2] = z2; dst[i+3] = z3;
}
T z1 = src2[i+1] != 0 ? saturate_cast<T>(src1[i+1]*scale/src2[i+1]) : 0;
T z2 = src2[i+2] != 0 ? saturate_cast<T>(src1[i+2]*scale/src2[i+2]) : 0;
T z3 = src2[i+3] != 0 ? saturate_cast<T>(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<T>(src1[i]*scale/src2[i]) : 0;
}
}
-
-void divide(const Mat& src1, const Mat& src2, Mat& dst, double scale)
-{
- static MulDivFunc tab[] =
- {
- div_<uchar>, 0, div_<ushort>, div_<short>,
- div_<int>, div_<float>, div_<double>, 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<typename T> 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 )
double d = scale/(a * b);
b *= d;
a *= d;
-
+
T z0 = saturate_cast<T>(src2[i+1] * b);
T z1 = saturate_cast<T>(src2[i] * b);
T z2 = saturate_cast<T>(src2[i+3] * a);
T z3 = saturate_cast<T>(src2[i+2] * a);
-
+
dst[i] = z0; dst[i+1] = z1;
dst[i+2] = z2; dst[i+3] = z3;
}
T z1 = src2[i+1] != 0 ? saturate_cast<T>(scale/src2[i+1]) : 0;
T z2 = src2[i+2] != 0 ? saturate_cast<T>(scale/src2[i+2]) : 0;
T z3 = src2[i+3] != 0 ? saturate_cast<T>(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<T>(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_<uchar>,
- 0,
- recip_<ushort>,
- recip_<short>,
- recip_<int>,
- recip_<float>,
- recip_<double>,
- 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<typename T, typename WT> 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<T>(src1[i]*alpha + src2[i]*beta + gamma);
- T t1 = saturate_cast<T>(src1[i+1]*alpha + src2[i+1]*beta + gamma);
- dst[i] = t0; dst[i+1] = t1;
+ T t0 = saturate_cast<T>(src1[x]*alpha + src2[x]*beta + gamma);
+ T t1 = saturate_cast<T>(src1[x+1]*alpha + src2[x+1]*beta + gamma);
+ dst[x] = t0; dst[x+1] = t1;
- t0 = saturate_cast<T>(src1[i+2]*alpha + src2[i+2]*beta + gamma);
- t1 = saturate_cast<T>(src1[i+3]*alpha + src2[i+3]*beta + gamma);
- dst[i+2] = t0; dst[i+3] = t1;
+ t0 = saturate_cast<T>(src1[x+2]*alpha + src2[x+2]*beta + gamma);
+ t1 = saturate_cast<T>(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<T>(src1[i]*alpha + src2[i]*beta + gamma);
+ for( ; x < size.width; x++ )
+ dst[x] = saturate_cast<T>(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_<uchar, float>(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<uchar>(t0);
+ dst[x+1] = saturate_cast<uchar>(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<uchar>(t0);
+ dst[x+3] = saturate_cast<uchar>(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<uchar>(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_<ushort, float>,
- addWeighted_<short, float>,
- addWeighted_<int, double>,
- addWeighted_<float, double>,
- addWeighted_<double, double>,
- 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_<schar, float>(src1, step1, src2, step2, dst, step, sz, scalars);
}
-
-/****************************************************************************************\
-* absdiff *
-\****************************************************************************************/
-
-template<typename T> 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<short>::operator ()(short a, short b)
-{ return saturate_cast<short>(std::abs(a - b)); }
+ addWeighted_<ushort, float>(src1, step1, src2, step2, dst, step, sz, scalars);
+}
-template<typename T, typename WT=T> 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<T>(std::abs(a - b)); }
-};
+ addWeighted_<short, float>(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_<OpAbsDiff<uchar>,ippAbsDiff8u>,
- 0,
- binaryOpC1_<OpAbsDiff<ushort>,ippAbsDiff16u>,
- binaryOpC1_<OpAbsDiff<short>,VAbsDiff16s>,
- binaryOpC1_<OpAbsDiff<int>,NoVec>,
- binaryOpC1_<OpAbsDiff<float>,ippAbsDiff32f>,
- binaryOpC1_<OpAbsDiff<double>,NoVec>,
- 0
-#else
- binaryOpC1_<OpAbsDiff<uchar>,VAbsDiff8u>,
- 0,
- binaryOpC1_<OpAbsDiff<ushort>,VAbsDiff16u>,
- binaryOpC1_<OpAbsDiff<short>,VAbsDiff16s>,
- binaryOpC1_<OpAbsDiff<int>,NoVec>,
- binaryOpC1_<OpAbsDiff<float>,VAbsDiff32f>,
- binaryOpC1_<OpAbsDiff<double>,NoVec>,
- 0
-#endif
- };
-
- binaryOp(src1, src2, dst, tab[src1.depth()]);
+ addWeighted_<int, double>(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_<OpAbsDiffS<uchar, int> >,
- 0,
- binarySOpCn_<OpAbsDiffS<ushort, int> >,
- binarySOpCn_<OpAbsDiffS<short, int> >,
- binarySOpCn_<OpAbsDiffS<int> >,
- binarySOpCn_<OpAbsDiffS<float> >,
- binarySOpCn_<OpAbsDiffS<double> >,
- 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_<float, double>(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_<double, double>(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<typename T, typename WT> 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<typename T, typename WT> struct InRangeC2
+template<typename T> 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<T,2> xtype;
- typedef Vec<WT,2> 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<typename T, typename WT> struct InRangeC3
-{
- typedef Vec<T,3> xtype;
- typedef Vec<WT,3> 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<typename T, typename WT> struct InRangeC4
-{
- typedef Vec<T,4> xtype;
- typedef Vec<WT,4> 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<class Op> 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<class Op> 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<WT>::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<WT>::depth, cn));
- scalarToRawData(_b, &b, CV_MAKETYPE(DataType<WT>::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_<InRangeC1<uchar, uchar> >,
- 0,
- inRange_<InRangeC1<ushort, ushort> >,
- inRange_<InRangeC1<short, short> >,
- inRange_<InRangeC1<int, int> >,
- inRange_<InRangeC1<float, float> >,
- inRange_<InRangeC1<double, double> >,
- 0,
-
- inRange_<InRangeC2<uchar, uchar> >,
- 0,
- inRange_<InRangeC2<ushort, ushort> >,
- inRange_<InRangeC2<short, short> >,
- inRange_<InRangeC2<int, int> >,
- inRange_<InRangeC2<float, float> >,
- inRange_<InRangeC2<double, double> >,
- 0,
-
- inRange_<InRangeC3<uchar, uchar> >,
- 0,
- inRange_<InRangeC3<ushort, ushort> >,
- inRange_<InRangeC3<short, short> >,
- inRange_<InRangeC3<int, int> >,
- inRange_<InRangeC3<float, float> >,
- inRange_<InRangeC3<double, double> >,
- 0,
-
- inRange_<InRangeC4<uchar, uchar> >,
- 0,
- inRange_<InRangeC4<ushort, ushort> >,
- inRange_<InRangeC4<short, short> >,
- inRange_<InRangeC4<int, int> >,
- inRange_<InRangeC4<float, float> >,
- inRange_<InRangeC4<double, double> >,
- 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_<InRangeC1<uchar, int> >,
- 0,
- inRangeS_<InRangeC1<ushort, int> >,
- inRangeS_<InRangeC1<short, int> >,
- inRangeS_<InRangeC1<int, int> >,
- inRangeS_<InRangeC1<float, float> >,
- inRangeS_<InRangeC1<double, double> >,
- 0,
-
- inRangeS_<InRangeC2<uchar, int> >,
- 0,
- inRangeS_<InRangeC2<ushort, int> >,
- inRangeS_<InRangeC2<short, int> >,
- inRangeS_<InRangeC2<int, int> >,
- inRangeS_<InRangeC2<float, float> >,
- inRangeS_<InRangeC2<double, double> >,
- 0,
-
- inRangeS_<InRangeC3<uchar, int> >,
- 0,
- inRangeS_<InRangeC3<ushort, int> >,
- inRangeS_<InRangeC3<short, int> >,
- inRangeS_<InRangeC3<int, int> >,
- inRangeS_<InRangeC3<float, float> >,
- inRangeS_<InRangeC3<double, double> >,
- 0,
-
- inRangeS_<InRangeC4<uchar, int> >,
- 0,
- inRangeS_<InRangeC4<ushort, int> >,
- inRangeS_<InRangeC4<short, int> >,
- inRangeS_<InRangeC4<int, int> >,
- inRangeS_<InRangeC4<float, float> >,
- inRangeS_<InRangeC4<double, double> >,
- 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<typename T, typename WT=T> 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<typename T, typename WT=T> 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<typename T, typename WT=T> 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_<CmpGT<uchar>,VCmpGT8u>,
- 0,
- binaryOpC1_<CmpGT<ushort>,NoVec>,
- binaryOpC1_<CmpGT<short>,NoVec>,
- binaryOpC1_<CmpGT<int>,NoVec>,
- binaryOpC1_<CmpGT<float>,NoVec>,
- binaryOpC1_<CmpGT<double>,NoVec>,
- 0
- },
-
- {
- binaryOpC1_<CmpEQ<uchar>,VCmpEQ8u>,
- 0,
- binaryOpC1_<CmpEQ<ushort>,NoVec>,
- binaryOpC1_<CmpEQ<ushort>,NoVec>, // same function as for ushort's
- binaryOpC1_<CmpEQ<int>,NoVec>,
- binaryOpC1_<CmpEQ<float>,NoVec>,
- binaryOpC1_<CmpEQ<double>,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<uchar> _buf(blocksize*esz);
+ uchar *buf = _buf;
+
+ if( depth1 > CV_32S )
+ convertAndUnrollScalar( src2, depth1, buf, blocksize );
+ else
{
- binarySOpC1_<CmpEQ<uchar, int> >,
- 0,
- binarySOpC1_<CmpEQ<ushort, int> >,
- binarySOpC1_<CmpEQ<short, int> >,
- binarySOpC1_<CmpEQ<int> >,
- binarySOpC1_<CmpEQ<float> >,
- binarySOpC1_<CmpEQ<double> >,
- 0
- },
-
- {
- binarySOpC1_<CmpGT<uchar, int> >,
- 0,
- binarySOpC1_<CmpGT<ushort, int> >,
- binarySOpC1_<CmpGT<short, int> >,
- binarySOpC1_<CmpGT<int> >,
- binarySOpC1_<CmpGT<float> >,
- binarySOpC1_<CmpGT<double> >,
- 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_<CmpGE<uchar, int> >,
- 0,
- binarySOpC1_<CmpGE<ushort, int> >,
- binarySOpC1_<CmpGE<short, int> >,
- binarySOpC1_<CmpGE<int> >,
- binarySOpC1_<CmpGE<float> >,
- binarySOpC1_<CmpGE<double> >,
- 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<typename T> 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<typename T> 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<typename T> 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<uchar>::operator ()(uchar a, uchar b) const { return CV_MIN_8U(a, b); }
-template<> inline uchar MaxOp<uchar>::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_<MinOp<uchar>,ippMin8u>,
- 0,
- binaryOpC1_<MinOp<ushort>,ippMin16u>,
- binaryOpC1_<MinOp<short>,VMin16s>,
- binaryOpC1_<MinOp<int>,NoVec>,
- binaryOpC1_<MinOp<float>,ippMin32f>,
- binaryOpC1_<MinOp<double>,ippMin64f>,
- 0
-#else
- binaryOpC1_<MinOp<uchar>,VMin8u>,
- 0,
- binaryOpC1_<MinOp<ushort>,VMin16u>,
- binaryOpC1_<MinOp<short>,VMin16s>,
- binaryOpC1_<MinOp<int>,NoVec>,
- binaryOpC1_<MinOp<float>,VMin32f>,
- binaryOpC1_<MinOp<double>,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_<MaxOp<uchar>,ippMax8u>,
- 0,
- binaryOpC1_<MaxOp<ushort>,ippMax16u>,
- binaryOpC1_<MaxOp<short>,VMax16s>,
- binaryOpC1_<MaxOp<int>,NoVec>,
- binaryOpC1_<MaxOp<float>,ippMax32f>,
- binaryOpC1_<MaxOp<double>,ippMax64f>,
- 0
-#else
- binaryOpC1_<MaxOp<uchar>,VMax8u>,
- 0,
- binaryOpC1_<MaxOp<ushort>,VMax16u>,
- binaryOpC1_<MaxOp<short>,VMax16s>,
- binaryOpC1_<MaxOp<int>,NoVec>,
- binaryOpC1_<MaxOp<float>,VMax32f>,
- binaryOpC1_<MaxOp<double>,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_<MinOp<uchar> >,
- 0,
- binarySOpC1_<MinOp<ushort> >,
- binarySOpC1_<MinOp<short> >,
- binarySOpC1_<MinOp<int> >,
- binarySOpC1_<MinOp<float> >,
- binarySOpC1_<MinOp<double> >,
- 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_<MaxOp<uchar> >,
- 0,
- binarySOpC1_<MaxOp<ushort> >,
- binarySOpC1_<MaxOp<short> >,
- binarySOpC1_<MaxOp<int> >,
- binarySOpC1_<MaxOp<float> >,
- binarySOpC1_<MaxOp<double> >,
- 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<uchar> _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. *
\****************************************************************************************/
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 );
}
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 );
}
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 );
}
{
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() );
}
{
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() );
}
{
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() );
}
{
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() );
}
{
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() );
}
{
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() );
}
{
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() );
}
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 );
}
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 );
}
cv::max( src1, value, dst );
}
-
/* End of file. */
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 )
do
{
offset -= pix_size;
- CV_MEMCPY_AUTO( (char*)data + offset, data, pix_size );
+ memcpy((char*)data + offset, data, pix_size);
}
while( offset > pix_size );
}
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 );
// 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,
{
/****************************************************************************************\
-* split *
+* split & merge *
\****************************************************************************************/
template<typename T> 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<typename T> 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<typename T> 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<typename T> 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_<uchar>, splitC2_<ushort>, splitC2_<int>, 0, splitC2_<int64>,
- splitC3_<uchar>, splitC3_<ushort>, splitC3_<int>, 0, splitC3_<int64>,
- splitC4_<uchar>, splitC4_<ushort>, splitC4_<int>, 0, splitC4_<int64>
- };
-
- 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<int> 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<Mat>& 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<typename T> 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<typename T> 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<typename T> 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<uchar> _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<Mat>& mv)
{
- static MergeFunc tab[] =
- {
- mergeC2_<uchar>, mergeC2_<ushort>, mergeC2_<int>, 0, mergeC2_<int64>,
- mergeC3_<uchar>, mergeC3_<ushort>, mergeC3_<int>, 0, mergeC3_<int64>,
- mergeC4_<uchar>, mergeC4_<ushort>, mergeC4_<int>, 0, mergeC4_<int64>
- };
-
- 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<int> pairs(total*2);
- int j, k, ni=0;
-
+ AutoBuffer<int> pairs(cn*2);
+ int j, ni=0;
+
for( i = 0, j = 0; i < n; i++, j += ni )
{
ni = mv[i].channels();
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<uchar> _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<Mat>& mv, Mat& dst)
+void cv::merge(const vector<Mat>& 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<typename T> 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<const Mat*> v(m + n);
- AutoBuffer<Mat> 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<uchar> 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<uchar> 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];
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_<uchar>;
- else if( esz1 == 2 )
- func = mixChannels_<ushort>;
- else if( esz1 == 4 )
- func = mixChannels_<int>;
- else if( esz1 == 8 )
- func = mixChannels_<int64>;
- 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<Mat>& src, vector<Mat>& dst,
- const int* fromTo, int npairs)
+void cv::mixChannels(const vector<Mat>& src, vector<Mat>& dst,
+ const int* fromTo, size_t npairs)
{
mixChannels(!src.empty() ? &src[0] : 0, src.size(),
!dst.empty() ? &dst[0] : 0, dst.size(), fromTo, npairs);
* convertScale[Abs] *
\****************************************************************************************/
-template<typename sT, typename dT> struct OpCvt
-{
- typedef sT type1;
- typedef dT rtype;
- rtype operator()(type1 x) const { return saturate_cast<rtype>(x); }
-};
-
-template<typename sT, typename dT, int _fbits> struct OpCvtFixPt
-{
- typedef sT type1;
- typedef dT rtype;
- enum { fbits = _fbits };
- rtype operator()(type1 x) const
- {
- return saturate_cast<rtype>((x + (1<<(fbits-1)))>>fbits);
- }
-};
-
-template<typename sT, typename dT> struct OpCvtAbs
-{
- typedef sT type1;
- typedef dT rtype;
- rtype operator()(type1 x) const { return saturate_cast<rtype>(std::abs(x)); }
-};
-
-template<typename sT, typename dT, int _fbits> struct OpCvtAbsFixPt
-{
- typedef sT type1;
- typedef dT rtype;
- enum { fbits = _fbits };
-
- rtype operator()(type1 x) const
- {
- return saturate_cast<rtype>((std::abs(x) + (1<<(fbits-1)))>>fbits);
- }
-};
-
-template<class Op> 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<typename T, class Op> static void
-cvtScale_( const Mat& srcmat, Mat& dstmat, double _scale, double _shift )
+template<typename T, typename DT, typename WT> 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<WT>(_scale), shift = saturate_cast<WT>(_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<DT>(std::abs(src[x]*scale + shift));
+ t1 = saturate_cast<DT>(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<DT>(std::abs(src[x+2]*scale + shift));
+ t1 = saturate_cast<DT>(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<DT>(std::abs(src[x]*scale + shift));
}
-}
-
-template<typename T, class OpFixPt, class Op, int MAX_SHIFT> static void
-cvtScaleInt_( const Mat& srcmat, Mat& dstmat, double _scale, double _shift )
+}
+
+template<typename T, typename DT, typename WT> 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_<T, Op>(srcmat, dstmat, _scale, _shift);
- return;
- }
- OpFixPt op;
- typedef typename OpFixPt::rtype DT;
- Size size = getContinuousSize( srcmat, dstmat, srcmat.channels() );
- int scale = saturate_cast<int>(_scale*(1<<OpFixPt::fbits)),
- shift = saturate_cast<int>(_shift*(1<<OpFixPt::fbits));
-
- 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<DT>(src[x]*scale + shift);
+ t1 = saturate_cast<DT>(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<DT>(src[x+2]*scale + shift);
+ t1 = saturate_cast<DT>(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<DT>(src[x]*scale + shift);
}
}
+
template<typename T, typename DT> 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;
t1 = saturate_cast<DT>(src[x+3]);
dst[x+2] = t0; dst[x+3] = t1;
}
-
+
for( ; x < size.width; x++ )
dst[x] = saturate_cast<DT>(src[x]);
}
}
-static const int FBITS = 15;
-#define ICV_SCALE(x) CV_DESCALE((x), FBITS)
+template<typename T> 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_<OpCvtAbs<double, uchar> >,
- cvtScaleLUT_<OpCvtAbs<double, uchar> >,
- cvtScaleInt_<ushort, OpCvtAbsFixPt<int, uchar, FBITS>, OpCvtAbs<float, uchar>, 0>,
- cvtScaleInt_<short, OpCvtAbsFixPt<int, uchar, FBITS>, OpCvtAbs<float, uchar>, 1<<15>,
- cvtScale_<int, OpCvtAbs<double, uchar> >,
- cvtScale_<float, OpCvtAbs<float, uchar> >,
- cvtScale_<double, OpCvtAbs<double, uchar> >, 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_<uchar, schar>, cvt_<uchar, ushort>, cvt_<uchar, short>,
- cvt_<uchar, int>, cvt_<uchar, float>, cvt_<uchar, double>, 0},
-
- {cvt_<schar, uchar>, 0, cvt_<schar, ushort>, cvt_<schar, short>,
- cvt_<schar, int>, cvt_<schar, float>, cvt_<schar, double>, 0},
-
- {cvt_<ushort, uchar>, cvt_<ushort, schar>, 0, cvt_<ushort, short>,
- cvt_<ushort, int>, cvt_<ushort, float>, cvt_<ushort, double>, 0},
-
- {cvt_<short, uchar>, cvt_<short, schar>, cvt_<short, ushort>, 0,
- cvt_<short, int>, cvt_<short, float>, cvt_<short, double>, 0},
-
- {cvt_<int, uchar>, cvt_<int, schar>, cvt_<int, ushort>,
- cvt_<int, short>, 0, cvt_<int, float>, cvt_<int, double>, 0},
-
- {cvt_<float, uchar>, cvt_<float, schar>, cvt_<float, ushort>,
- cvt_<float, short>, cvt_<float, int>, 0, cvt_<float, double>, 0},
-
- {cvt_<double, uchar>, cvt_<double, schar>, cvt_<double, ushort>,
- cvt_<double, short>, cvt_<double, int>, cvt_<double, float>, 0, 0},
-
- {0,0,0,0,0,0,0,0}
- };
-
- static CvtScaleFunc stab[8][8] =
- {
- {
- cvtScaleLUT_<OpCvt<double, uchar> >,
- cvtScaleLUT_<OpCvt<double, schar> >,
- cvtScaleLUT_<OpCvt<double, ushort> >,
- cvtScaleLUT_<OpCvt<double, short> >,
- cvtScaleLUT_<OpCvt<double, int> >,
- cvtScaleLUT_<OpCvt<double, float> >,
- cvtScaleLUT_<OpCvt<double, double> >, 0
- },
-
- {
- // this is copy of the above section,
- // since cvScaleLUT handles both 8u->? and 8s->? cases
- cvtScaleLUT_<OpCvt<double, uchar> >,
- cvtScaleLUT_<OpCvt<double, schar> >,
- cvtScaleLUT_<OpCvt<double, ushort> >,
- cvtScaleLUT_<OpCvt<double, short> >,
- cvtScaleLUT_<OpCvt<double, int> >,
- cvtScaleLUT_<OpCvt<double, float> >,
- cvtScaleLUT_<OpCvt<double, double> >, 0,
- },
-
- {
- cvtScaleInt_<ushort, OpCvtFixPt<int, uchar, FBITS>, OpCvt<float, uchar>, 0>,
- cvtScaleInt_<ushort, OpCvtFixPt<int, schar, FBITS>, OpCvt<float, schar>, 0>,
- cvtScaleInt_<ushort, OpCvtFixPt<int, ushort, FBITS>, OpCvt<float, ushort>, 0>,
- cvtScaleInt_<ushort, OpCvtFixPt<int, short, FBITS>, OpCvt<float, short>, 0>,
- cvtScale_<ushort, OpCvt<double, int> >,
- cvtScale_<ushort, OpCvt<double, float> >,
- cvtScale_<ushort, OpCvt<double, double> >, 0,
- },
-
- {
- cvtScaleInt_<short, OpCvtFixPt<int, uchar, FBITS>, OpCvt<float, uchar>, 1<<15>,
- cvtScaleInt_<short, OpCvtFixPt<int, schar, FBITS>, OpCvt<float, schar>, 1<<15>,
- cvtScaleInt_<short, OpCvtFixPt<int, ushort, FBITS>, OpCvt<float, ushort>, 1<<15>,
- cvtScaleInt_<short, OpCvtFixPt<int, short, FBITS>, OpCvt<float, short>, 1<<15>,
- cvtScale_<short, OpCvt<double, int> >,
- cvtScale_<short, OpCvt<double, float> >,
- cvtScale_<short, OpCvt<double, double> >, 0,
- },
-
- {
- cvtScale_<int, OpCvt<float, uchar> >,
- cvtScale_<int, OpCvt<float, schar> >,
- cvtScale_<int, OpCvt<double, ushort> >,
- cvtScale_<int, OpCvt<double, short> >,
- cvtScale_<int, OpCvt<double, int> >,
- cvtScale_<int, OpCvt<double, float> >,
- cvtScale_<int, OpCvt<double, double> >, 0,
- },
-
- {
- cvtScale_<float, OpCvt<float, uchar> >,
- cvtScale_<float, OpCvt<float, schar> >,
- cvtScale_<float, OpCvt<float, ushort> >,
- cvtScale_<float, OpCvt<float, short> >,
- cvtScale_<float, OpCvt<float, int> >,
- cvtScale_<float, OpCvt<float, float> >,
- cvtScale_<float, OpCvt<double, double> >, 0,
- },
-
- {
- cvtScale_<double, OpCvt<double, uchar> >,
- cvtScale_<double, OpCvt<double, schar> >,
- cvtScale_<double, OpCvt<double, ushort> >,
- cvtScale_<double, OpCvt<double, short> >,
- cvtScale_<double, OpCvt<double, int> >,
- cvtScale_<double, OpCvt<double, float> >,
- cvtScale_<double, OpCvt<double, double> >, 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<typename T> 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<typename T> 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<uchar>;
- else if( esz1 == 2 )
- func = LUT8u<ushort>;
- else if( esz1 == 4 )
- func = LUT8u<int>;
- else if( esz1 == 8 )
- func = LUT8u<int64>;
- 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;
}
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
}
}
-}
-
CV_IMPL void
cvSplit( const void* srcarr, void* dstarr0, void* dstarr1, void* dstarr2, void* dstarr3 )
{
// 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,
{
template<typename T> 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 )
{
}
}
-template<typename T> 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<typename T> 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_<type>(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_<type>(*(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_<uchar>, // 1
- copyMask_<ushort>, // 2
- copyMask_<Vec<uchar,3> >, // 3
- copyMask_<int>, // 4
+ copyMask8u,
+ copyMask16u,
+ copyMask8uC3,
+ copyMask32s,
0,
- copyMask_<Vec<ushort,3> >, // 6
+ copyMask16uC3,
0,
- copyMask_<Vec<int,2> >, // 8
+ copyMask32sC2,
0, 0, 0,
- copyMask_<Vec<int,3> >, // 12
+ copyMask32sC3,
0, 0, 0,
- copyMask_<Vec<int,4> >, // 16
+ copyMask32sC4,
0, 0, 0, 0, 0, 0, 0,
- copyMask_<Vec<int,6> >, // 24
+ copyMask32sC6,
0, 0, 0, 0, 0, 0, 0,
- copyMask_<Vec<int,8> > // 32
+ copyMask32sC8
};
-static SetMaskFunc setMaskFuncTab[] =
+BinaryFunc setMaskTab[] =
{
0,
- setMask_<uchar>, // 1
- setMask_<ushort>, // 2
- setMask_<Vec<uchar,3> >, // 3
- setMask_<int>, // 4
+ setMask8u,
+ setMask16u,
+ setMask8uC3,
+ setMask32s,
0,
- setMask_<Vec<ushort,3> >, // 6
+ setMask16uC3,
0,
- setMask_<Vec<int,2> >, // 8
+ setMask32sC2,
0, 0, 0,
- setMask_<Vec<int,3> >, // 12
+ setMask32sC3,
0, 0, 0,
- setMask_<Vec<int,4> >, // 16
+ setMask32sC4,
0, 0, 0, 0, 0, 0, 0,
- setMask_<Vec<int,6> >, // 24
+ setMask32sC6,
0, 0, 0, 0, 0, 0, 0,
- setMask_<Vec<int,8> > // 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<typename T> 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<int> _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_<uchar>, // 1
- flipHoriz_<ushort>, // 2
- flipHoriz_<Vec<uchar,3> >, // 3
- flipHoriz_<int>, // 4
- 0,
- flipHoriz_<Vec<ushort,3> >, // 6
- 0,
- flipHoriz_<Vec<int,2> >, // 8
- 0, 0, 0,
- flipHoriz_<Vec<int,3> >, // 12
- 0, 0, 0,
- flipHoriz_<Vec<int,4> >, // 16
- 0, 0, 0, 0, 0, 0, 0,
- flipHoriz_<Vec<int,6> >, // 24
- 0, 0, 0, 0, 0, 0, 0,
- flipHoriz_<Vec<int,8> > // 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;
{
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;
}
}
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;
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--;
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++;
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--;
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 );
}
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 );
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 );
}
{
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 );
}
}
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 );
}
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++;
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;
}
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;
}
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;
}
-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<KDTree::Node>().swap(nodes);
}
-int KDTree::findNearest(const float* vec, int K, int emax,
- vector<int>* neighborsIdx,
- Mat* neighbors,
- vector<float>* dist,
- vector<int>* 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<float>& vec, int K, int emax,
- vector<int>* neighborsIdx,
- Mat* neighbors,
- vector<float>* dist,
- vector<int>* 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) {}
};
-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<float>();
K = std::min(K, points.rows);
int dims = points.cols;
}
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<int>* neighborsIdx,
- Mat* neighbors, vector<int>* _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<float>();
+ const float* R = upperBound.ptr<float>();
- CV_Assert( L && R );
-
- vector<int> _idx, *idx = neighborsIdx ? neighborsIdx : &_idx;
+ vector<int> idx;
AutoBuffer<int> _stack(MAX_TREE_DEPTH*2 + 1);
int* stack = _stack;
int top = 0;
- idx->clear();
stack[top++] = 0;
while( --top >= 0 )
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 )
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<float>& L, const vector<float>& R,
- vector<int>* neighborsIdx, Mat* neighbors, vector<int>* _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>();
+ int* dstlabels = 0;
-void KDTree::getPoints(const int* idx, size_t nidx, Mat& pts, vector<int>* _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<float>(k);
- std::copy(src, src + dims, pts.ptr<float>(i));
- if(_labels)
- (*_labels)[i] = labels[k];
+ _pts.release();
+ _labels.release();
+ return;
}
-}
-
-
-void KDTree::getPoints(const vector<int>& idx, Mat& pts, vector<int>* _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<int>();
+ }
+ 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<float>(k);
- std::copy(src, src + dims, pts.ptr<float>(i));
- if(_labels) (*_labels)[i] = labels[k];
+ if( pts.data )
+ std::copy(src, src + dims, pts.ptr<float>(i));
+ if( dstlabels )
+ dstlabels[i] = srclabels ? srclabels[k] : k;
}
}
{
CV_Assert( (unsigned)ptidx < (unsigned)points.rows);
if(label)
- *label = label[ptidx];
+ *label = labels[ptidx];
return points.ptr<float>(ptidx);
}
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;
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 );
}
}
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 )
{
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<uchar> 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);
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;
}
-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;
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()));
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/:
*/
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;
AutoBuffer<uchar> 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];
}
-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,
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] )
return optimalDFTSizeTab[b];
}
-}
-
CV_IMPL void
cvDFT( const CvArr* srcarr, CvArr* dstarr, int flags, int nonzero_rows )
{
{
return CholImpl(A, m, b, n);
}
+
+}
/****************************************************************************************\
* Determinant of the matrix *
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;
#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);
}
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;
* 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;
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]
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;
/////////////////// finding eigenvalues and eigenvectors of a symmetric matrix ///////////////
+namespace cv
+{
+
template<typename Real> static inline Real hypot(Real a, Real b)
{
a = std::abs(a);
}
-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;
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 )
{
lda = (int)(src.step/elem_size);
if( computeEvects )
- {
- evects.create(n, n, type);
ldv = (int)(evects.step/elem_size);
- }
bool copy_evals = !evals.isContinuous();
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<typename T1, typename T2, typename T3> static void
}
-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;
{
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';
}
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<float>(), &lda, w.ptr<float>(),
+ vt.data ? vt.ptr<float>() : (float*)&v1, &ldv,
+ u.data ? u.ptr<float>() : (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<double>(), &lda, w.ptr<double>(),
+ vt.data ? vt.ptr<double>() : &v1, &ldv,
+ u.data ? u.ptr<double>() : &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<double> buffer(nb);
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),
}
-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 );
}
// 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,
{
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 )
{
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);
}
angle[i] = a*scale;
}
-
- return CV_OK;
}
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 )
{
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 )
{
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 )
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 )
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 )
for( ; i < len; i++ )
dst[i] = std::sqrt(src[i]);
- return CV_OK;
}
* 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<float> _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<float> _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;
}
}
}
* 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;
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<float> _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;
}
}
}
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),
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);
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,
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);
y[i] = buf[0].f * expTab[val0 & EXPTAB_MASK] * EXPPOLY( x0 );
}
-
- return CV_OK;
}
#undef EXPTAB_SCALE
#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<float>(y), dst.ptr<float>(y), size.width );
- else if( depth == CV_64F )
- for( int y = 0; y < size.height; y++ )
- Exp_64f( src.ptr<double>(y), dst.ptr<double>(y), size.width );
- else
- CV_Error( CV_StsUnsupportedFormat, "" );
}
#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
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);
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
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.);
y0 += LOGPOLY( x0, h0 == 510 );
y[i] = y0;
}
-
- return CV_OK;
}
#else
#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<float>(y), dst.ptr<float>(y), size.width );
- else if( depth == CV_64F )
- for( int y = 0; y < size.height; y++ )
- Log_64f( src.ptr<double>(y), dst.ptr<double>(y), size.width );
- else
- CV_Error( CV_StsUnsupportedFormat, "" );
-}
-
+}
/****************************************************************************************\
* P O W E R *
\****************************************************************************************/
template<typename T, typename WT>
-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];
a *= b;
dst[i] = saturate_cast<T>(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_<uchar, int>(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_<schar, int>(src, dst, len, power);
+}
+
+void iPow16u(const ushort* src, ushort* dst, int len, int power)
+{
+ iPow_<ushort, int>(src, dst, len, power);
+}
+
+void iPow16s(const short* src, short* dst, int len, int power)
+{
+ iPow_<short, int>(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_<int, int>(src, dst, len, power);
+}
+
+void iPow32f(const float* src, float* dst, int len, int power)
+{
+ iPow_<float, float>(src, dst, len, power);
+}
+
+void iPow64f(const double* src, double* dst, int len, int power)
+{
+ iPow_<double, double>(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;
}
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<uchar, int>, 0, IPow<ushort, int>, IPow<short, int>, IPow<int, int>,
- IPow<float, float>, IPow<double, double>, 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 ))
{
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<float>(++i);
+
+ a1 = coeffs.at<float>(i+1);
+ a2 = coeffs.at<float>(i+2);
+ a3 = coeffs.at<float>(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<double>(++i);
+
+ a1 = coeffs.at<double>(i+1);
+ a2 = coeffs.at<double>(i+2);
+ a3 = coeffs.at<double>(i+3);
}
-
+
if( a0 == 0 )
{
if( a1 == 0 )
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));
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<float>(0) = (float)x0;
+ roots.at<float>(1) = (float)x1;
+ roots.at<float>(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<double>(0) = x0;
+ roots.at<double>(1) = x1;
+ roots.at<double>(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<double> 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<C> 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);
}
+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;
// 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,
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;
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();
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) )
{
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;
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;
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<uchar> buf;
if( type == CV_32FC1 )
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 );
* Transform *
\****************************************************************************************/
-template<typename T, typename WT> 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<T>(_m[0]*src[x] + _m[1]);
- }
-}
template<typename T, typename WT> 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<T>(m[0]*v0 + m[1]*v1 + m[2]);
- T t1 = saturate_cast<T>(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<T>(_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<T>(m[0]*v0 + m[1]*v1 + m[2]);
+ T t1 = saturate_cast<T>(m[3]*v0 + m[4]*v1 + m[5]);
+ dst[x] = t0; dst[x+1] = t1;
}
}
-}
-
-template<typename T, typename WT> 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<T>(m[0]*v0 + m[1]*v1 + m[2]*v2 + m[3]);
- T t1 = saturate_cast<T>(m[4]*v0 + m[5]*v1 + m[6]*v2 + m[7]);
- T t2 = saturate_cast<T>(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<T>(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<T>(_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<T>(m[0]*v0 + m[1]*v1 + m[2]*v2 + m[3]);
+ T t1 = saturate_cast<T>(m[4]*v0 + m[5]*v1 + m[6]*v2 + m[7]);
+ T t2 = saturate_cast<T>(m[8]*v0 + m[9]*v1 + m[10]*v2 + m[11]);
+ dst[x] = t0; dst[x+1] = t1; dst[x+2] = t2;
}
}
-}
-
-
-template<typename T, typename WT> 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<T>(m[0]*v0 + m[1]*v1 + m[2]*v2 + m[3]*v3 + m[4]);
- T t1 = saturate_cast<T>(m[5]*v0 + m[6]*v1 + m[7]*v2 + m[8]*v3 + m[9]);
- dst[x] = t0; dst[x+1] = t1;
- t0 = saturate_cast<T>(m[10]*v0 + m[11]*v1 + m[12]*v2 + m[13]*v3 + m[14]);
- t1 = saturate_cast<T>(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<T>(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<T>(m[0]*v0 + m[1]*v1 + m[2]*v2 + m[3]*v3 + m[4]);
+ T t1 = saturate_cast<T>(m[5]*v0 + m[6]*v1 + m[7]*v2 + m[8]*v3 + m[9]);
+ dst[x] = t0; dst[x+1] = t1;
+ t0 = saturate_cast<T>(m[10]*v0 + m[11]*v1 + m[12]*v2 + m[13]*v3 + m[14]);
+ t1 = saturate_cast<T>(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<T>(_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<T>(s);
+ }
}
}
}
-
#if CV_SSE2
static inline void
m4 = _mm_setr_ps(m[4], m[9], m[14], m[19]);
}
-template<> void
-transformC3_<uchar, float>( 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 )
__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<uchar>((m00*v0 + m01*v1 + m02*v2 + m03)>>BITS);
- uchar t1 = saturate_cast<uchar>((m10*v0 + m11*v1 + m12*v2 + m13)>>BITS);
- uchar t2 = saturate_cast<uchar>((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<uchar>((m00*v0 + m01*v1 + m02*v2 + m03)>>BITS);
+ uchar t1 = saturate_cast<uchar>((m10*v0 + m11*v1 + m12*v2 + m13)>>BITS);
+ uchar t2 = saturate_cast<uchar>((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<T>(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<T>(_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_<ushort, float>( 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<T>(m[0]*v0 + m[1]*v1 + m[2]*v2 + m[3]);
- T t1 = saturate_cast<T>(m[4]*v0 + m[5]*v1 + m[6]*v2 + m[7]);
- T t2 = saturate_cast<T>(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<ushort>(m[0]*v0 + m[1]*v1 + m[2]*v2 + m[3]);
+ ushort t1 = saturate_cast<ushort>(m[4]*v0 + m[5]*v1 + m[6]*v2 + m[7]);
+ ushort t2 = saturate_cast<ushort>(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<T>(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<T>(_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_<float, float>( 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(
_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<T>(m[0]*v0 + m[1]*v1 + m[2]*v2 + m[3]);
- T t1 = saturate_cast<T>(m[4]*v0 + m[5]*v1 + m[6]*v2 + m[7]);
- T t2 = saturate_cast<T>(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<float>(m[0]*v0 + m[1]*v1 + m[2]*v2 + m[3]);
+ float t1 = saturate_cast<float>(m[4]*v0 + m[5]*v1 + m[6]*v2 + m[7]);
+ float t2 = saturate_cast<float>(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<T>(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<T>(_m[0]*src[x*3] + _m[1]*src[x*3+1] + _m[2]*src[x*3+2] + _m[3]);
- }
- }
-}
-
-
-template<> void
-transformC4_<float, float>( 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<T>(_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<typename T, typename WT> 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<typename T, typename WT> 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<T>(m[0]*src[x] + m[2]);
T t1 = saturate_cast<T>(m[4]*src[x+1] + m[5]);
dst[x] = t0; dst[x+1] = t1;
}
}
-}
-
-template<typename T, typename WT> 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<T>(m[0]*src[x] + m[3]);
T t1 = saturate_cast<T>(m[5]*src[x+1] + m[7]);
dst[x] = t0; dst[x+1] = t1; dst[x+2] = t2;
}
}
-}
-
-template<typename T, typename WT> 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<T>(m[0]*src[x] + m[4]);
T t1 = saturate_cast<T>(m[6]*src[x+1] + m[9]);
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_<uchar, float>, 0, transformC1_<ushort, float>, transformC1_<short,float>,
- transformC1_<int, double>, transformC1_<float, float>, transformC1_<double, double>, 0,
- transformC2_<uchar, float>, 0, transformC2_<ushort, float>, transformC2_<short,float>,
- transformC2_<int, double>, transformC2_<float, float>, transformC2_<double, double>, 0,
- transformC3_<uchar, float>, 0, transformC3_<ushort, float>, transformC3_<short,float>,
- transformC3_<int, double>, transformC3_<float, float>, transformC3_<double, double>, 0,
- transformC4_<uchar, float>, 0, transformC4_<ushort, float>, transformC4_<short,float>,
- transformC4_<int, double>, transformC4_<float, float>, transformC4_<double, double>, 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_<ushort, float>, diagtransC2_<short,float>,
- diagtransC2_<int, double>, diagtransC2_<float, float>, diagtransC2_<double, double>, 0,
- 0, 0, diagtransC3_<ushort, float>, diagtransC3_<short,float>,
- diagtransC3_<int, double>, diagtransC3_<float, float>, diagtransC3_<double, double>, 0,
- 0, 0, diagtransC4_<ushort, float>, diagtransC4_<short,float>,
- diagtransC4_<int, double>, diagtransC4_<float, float>, diagtransC4_<double, double>, 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<double> _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 )
{
{
double alpha, beta;
if( mtype == CV_32F )
- alpha = ((float*)m.data)[0], beta = ((float*)m.data)[1];
+ alpha = m.at<float>(0), beta = m.at<float>(1);
else
- alpha = ((double*)m.data)[0], beta = ((double*)m.data)[1];
- src.convertTo( dst, dst.type(), alpha, beta );
+ alpha = m.at<double>(0), beta = m.at<double>(1);
+ src.convertTo(dst, dst.type(), alpha, beta);
return;
}
{
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<float>(i, j) : m.at<double>(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<typename T> 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<typename T> 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<typename T> 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<typename T> 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_<float>;
- else
- func = perspectiveTransform2_<double>;
- }
- else if( scn == 2 && dcn == 3 )
- {
- if(depth == CV_32F)
- func = perspectiveTransform23_<float>;
- else
- func = perspectiveTransform23_<double>;
- }
- 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<double> _mbuf;
+ double* mbuf = _mbuf;
+
+ if( !m.isContinuous() || m.type() != mtype )
{
- if(depth == CV_32F)
- func = perspectiveTransform3_<float>;
- else
- func = perspectiveTransform3_<double>;
+ _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();
_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 );
}
* 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();
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<typename sT, typename dT> static void
MulTransposedR( const Mat& srcmat, Mat& dstmat, const Mat& deltamat, double scale )
{
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 );
(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 &&
* 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<typename T> 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<typename T, typename WT, typename ST> 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_<uchar, int, int64>,
- 0,
- dotprod_<ushort, double, double>,
- dotprod_<short, double, double>,
- dotprod_<int, double, double>,
- ippDotProd32f,
- dotprod_<double, double, double>,
- 0
- };
-#endif
-
- static DotProductFunc tab[] =
- {
- dotprod_<uchar, int, int64>,
- 0,
- dotprod_<ushort, double, double>,
- dotprod_<short, double, double>,
- dotprod_<int, double, double>,
- dotprod_<float, double, double>,
- dotprod_<double, double, double>,
- 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;
}
/****************************************************************************************\
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;
}
-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);
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)));
}
}
-Mat PCA::backProject(const Mat& data) const
+Mat PCA::backProject(const InputArray& data) const
{
Mat result;
backProject(data, result);
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; }
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())
}
+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
}
-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;
}
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);
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) );
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) );
mixChannels( &ch, 1, &mat, 1, _pairs, 1 );
}
+namespace cv
+{
Mat Mat::reshape(int new_cn, int new_rows) const
{
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<Mat>& 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<uchar>& v = *(const vector<uchar>*)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<vector<uchar> >& vv = *(const vector<vector<uchar> >*)obj;
+ CV_Assert( 0 <= i && i < (int)vv.size() );
+ const vector<uchar>& 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<Mat>& v = *(const vector<Mat>*)obj;
+ CV_Assert( 0 <= i && i < (int)v.size() );
+
+ return v[i];
+ }
+}
+
+
+void InputArray::getMatVector(vector<Mat>& 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<uchar>& v = *(const vector<uchar>*)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<vector<uchar> >& vv = *(const vector<vector<uchar> >*)obj;
+ size_t i, n = vv.size();
+ int t = CV_MAT_TYPE(flags);
+ mv.resize(n);
+
+ for( i = 0; i < n; i++ )
+ {
+ const vector<uchar>& 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<Mat>& v = *(const vector<Mat>*)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<uchar>& v = *(const vector<uchar>*)obj;
+ const vector<int>& iv = *(const vector<int>*)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<vector<uchar> >& vv = *(const vector<vector<uchar> >*)obj;
+ if( i < 0 )
+ return vv.empty() ? Size() : Size((int)vv.size(), 1);
+ CV_Assert( i < (int)vv.size() );
+ const vector<vector<int> >& ivv = *(const vector<vector<int> >*)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<Mat>& vv = *(const vector<Mat>*)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<Mat>& vv = *(const vector<Mat>*)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<uchar>& v = *(const vector<uchar>*)obj;
+ return v.empty();
+ }
+
+ if( k == NONE )
+ return true;
+
+ if( k == STD_VECTOR_VECTOR )
+ {
+ const vector<vector<uchar> >& vv = *(const vector<vector<uchar> >*)obj;
+ return vv.empty();
+ }
+
+ CV_Assert( k == STD_VECTOR_MAT );
+ //if( k == STD_VECTOR_MAT )
+ {
+ const vector<Mat>& vv = *(const vector<Mat>*)obj;
+ return vv.empty();
+ }
+}
+
+
+OutputArray::OutputArray() {}
+OutputArray::OutputArray(Mat& m) : InputArray(m) {}
+OutputArray::OutputArray(vector<Mat>& 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<uchar>* v = (vector<uchar>*)obj;
+
+ if( k == STD_VECTOR_VECTOR )
+ {
+ vector<vector<uchar> >& vv = *(vector<vector<uchar> >*)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<uchar>*)v)->resize(len);
+ break;
+ case 2:
+ ((vector<Vec2b>*)v)->resize(len);
+ break;
+ case 3:
+ ((vector<Vec3b>*)v)->resize(len);
+ break;
+ case 4:
+ ((vector<int>*)v)->resize(len);
+ break;
+ case 6:
+ ((vector<Vec3s>*)v)->resize(len);
+ break;
+ case 8:
+ ((vector<Vec2i>*)v)->resize(len);
+ break;
+ case 12:
+ ((vector<Vec3i>*)v)->resize(len);
+ break;
+ case 16:
+ ((vector<Vec4i>*)v)->resize(len);
+ break;
+ case 24:
+ ((vector<Vec6i>*)v)->resize(len);
+ break;
+ case 32:
+ ((vector<Vec8i>*)v)->resize(len);
+ break;
+ case 36:
+ ((vector<Vec<int, 9> >*)v)->resize(len);
+ break;
+ case 48:
+ ((vector<Vec<int, 12> >*)v)->resize(len);
+ break;
+ case 64:
+ ((vector<Vec<int, 16> >*)v)->resize(len);
+ break;
+ case 128:
+ ((vector<Vec<int, 32> >*)v)->resize(len);
+ break;
+ case 256:
+ ((vector<Vec<int, 64> >*)v)->resize(len);
+ break;
+ case 512:
+ ((vector<Vec<int, 128> >*)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<Mat>& v = *(vector<Mat>*)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<vector<uchar> >*)obj)->clear();
+ return;
+ }
+
+ CV_Assert( k == STD_VECTOR_MAT );
+ //if( k == STD_VECTOR_MAT )
+ {
+ ((vector<Mat>*)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<Mat>& v = *(vector<Mat>*)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;
}
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<Mat>& src, CV_OUT Mat& dst)
+void cv::hconcat(const InputArray& _src, OutputArray dst)
{
+ vector<Mat> 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;
}
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));
}
}
-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<Mat>& src, CV_OUT Mat& dst)
+void cv::vconcat(const InputArray& _src, OutputArray dst)
{
+ vector<Mat> 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();
//////////////////////////////////////////// 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);
}
////////////////////////////////////// transpose /////////////////////////////////////////
-
+
+namespace cv
+{
+
template<typename T> 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<typename T> 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_<type>(src, sstep, dst, dstep, sz); } \
+\
+static void transposeI_##suffix( uchar* data, size_t step, int n ) \
+{ transposeI_<type>(data, step, n); }
-template<typename T> 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_<uchar>, // 1
- transposeI_<ushort>, // 2
- transposeI_<Vec<uchar,3> >, // 3
- transposeI_<int>, // 4
- 0,
- transposeI_<Vec<ushort,3> >, // 6
- 0,
- transposeI_<Vec<int,2> >, // 8
- 0, 0, 0,
- transposeI_<Vec<int,3> >, // 12
- 0, 0, 0,
- transposeI_<Vec<int,4> >, // 16
- 0, 0, 0, 0, 0, 0, 0,
- transposeI_<Vec<int,6> >, // 24
- 0, 0, 0, 0, 0, 0, 0,
- transposeI_<Vec<int,8> > // 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_<uchar>, // 1
- transpose_<ushort>, // 2
- transpose_<Vec<uchar,3> >, // 3
- transpose_<int>, // 4
- 0,
- transpose_<Vec<ushort,3> >, // 6
- 0,
- transpose_<Vec<int,2> >, // 8
- 0, 0, 0,
- transpose_<Vec<int,3> >, // 12
- 0, 0, 0,
- transpose_<Vec<int,4> >, // 16
- 0, 0, 0, 0, 0, 0, 0,
- transpose_<Vec<int,6> >, // 24
- 0, 0, 0, 0, 0, 0, 0,
- transpose_<Vec<int,8> > // 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();
}
-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)));
////////////////////////////////////////// reduce ////////////////////////////////////////////
+namespace cv
+{
+
template<typename T, typename ST, class Op> static void
reduceR_( 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 );
{
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;
//////////////////////////////////////// sort ///////////////////////////////////////////
+namespace cv
+{
+
template<typename T> static void sort_( const Mat& src, Mat& dst, int flags )
{
AutoBuffer<T> buf;
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_<uchar>, sort_<schar>, sort_<ushort>, sort_<short>,
sort_<int>, sort_<float>, sort_<double>, 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_<uchar>, sortIdx_<schar>, sortIdx_<ushort>, sortIdx_<short>,
sortIdx_<int>, sortIdx_<float>, sortIdx_<double>, 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<Vec2f>& box, float* center, RNG& rng)
{
size_t j, dims = box.size();
}
-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();
vector<float> _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];
}
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];
}
}
}
-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) &&
for( k = 0; k < K; k++ )
{
const float* center = centers.ptr<float>(k);
- double dist = distance(sample, center, dims, simd);
+ double dist = distance(sample, center, dims);
if( min_dist > dist )
{
if( compactness < best_compactness )
{
best_compactness = compactness;
- if( _centers )
- centers.copyTo(*_centers);
+ if( _centers.needed() )
+ centers.copyTo(_centers);
_labels.copyTo(best_labels);
}
}
return best_compactness;
}
-}
-
CV_IMPL void cvSetIdentity( CvArr* arr, CvScalar value )
{
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;
}
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 )
{
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 )
{
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;
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;
}
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;
#include <stdlib.h>
#include <string.h>
-#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
{
#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<typename T1, typename T2=T1, typename T3=T1> struct OpAdd
{
T3 operator ()(T1 a, T2 b) const { return saturate_cast<T3>(b - a); }
};
-template<typename T1, typename T2=T1, typename T3=T1> struct OpMul
-{
- typedef T1 type1;
- typedef T2 type2;
- typedef T3 rtype;
- T3 operator ()(T1 a, T2 b) const { return saturate_cast<T3>(a * b); }
-};
-
-template<typename T1, typename T2=T1, typename T3=T1> struct OpDiv
-{
- typedef T1 type1;
- typedef T2 type2;
- typedef T3 rtype;
- T3 operator ()(T1 a, T2 b) const { return saturate_cast<T3>(a / b); }
-};
-
template<typename T> struct OpMin
{
typedef T type1;
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<class Op, class VecOp> 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<class Op> 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<WT>::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<class Op> 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<WT>(_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_*/
\***************************************************************************************/
template<typename T> 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<T>(t0);
- arr[i+1] = saturate_cast<T>(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<T>(t0);
- arr[i+3] = saturate_cast<T>(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<T>(t0);
- arr[i+1] = saturate_cast<T>(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<T>(t0);
- arr[i+3] = saturate_cast<T>(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<T>(t0);
+ arr[i+1] = saturate_cast<T>(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<T>(t0);
+ arr[i+3] = saturate_cast<T>(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<T>(t0);
+ arr[i+1] = saturate_cast<T>(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<T>(t0);
+ arr[i+3] = saturate_cast<T>(t1);
}
}
+ for( ; i < len; i++ )
+ {
+ int t0;
+ temp = RNG_NEXT(temp);
+
+ t0 = ((int)temp & p[i][0]) + p[i][1];
+ arr[i] = saturate_cast<T>(t0);
+ }
+
*state = temp;
}
};
template<typename T> 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<T>((int)v0);
+ arr[i+1] = saturate_cast<T>((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<T>((int)v0);
+ arr[i+3] = saturate_cast<T>((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<T>((int)v0);
- arr[i+1] = saturate_cast<T>((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<T>((int)v0);
- arr[i+3] = saturate_cast<T>((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<T>((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<T>((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;
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
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<typename T, typename PT> 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<T>(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<T>(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<T>(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<T>(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_<uchar>,
- RandBits_<schar>,
- RandBits_<ushort>,
- RandBits_<short>,
- RandBits_<int>, 0, 0, 0},
-
- {Randi_<uchar>,
- Randi_<schar>,
- Randi_<ushort>,
- Randi_<short>,
- Randi_<int>,
- Randf_, Randd_, 0},
-
- {Randn_<uchar,float>,
- Randn_<schar,float>,
- Randn_<ushort,float>,
- Randn_<short,float>,
- Randn_<int,float>,
- Randn_<float,float>,
- Randn_<double,double>, 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<double> _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
{
// 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<double> 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
#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<typename T> static void
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[] =
{
0, 0, 0, 0, 0, 0, 0,
randShuffle_<Vec<int,8> > // 32
};
-
+
+ Mat dst = _dst.getMat();
RNG& rng = _rng ? *_rng : theRNG();
CV_Assert( dst.elemSize() <= 32 );
RandShuffleFunc func = tab[dst.elemSize()];
func( dst, rng, iterFactor );
}
-}
-
CV_IMPL void
cvRandArr( CvRNG* _rng, CvArr* arr, int disttype, CvScalar param1, CvScalar param2 )
{
// !!! 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 )
// 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,
* sum *
\****************************************************************************************/
-template<typename T, typename WT, typename ST, int BLOCK_SIZE>
-static Scalar sumBlock_( const Mat& srcmat )
+template<typename T, typename ST>
+static size_t sum_(const T* src0, const uchar* mask, ST* dst, int len, int cn )
{
- assert( DataType<T>::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<typename T, typename ST>
-static Scalar sum_( const Mat& srcmat )
-{
- assert( DataType<T>::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_<uchar, unsigned, double, 1<<24>,
- sumBlock_<schar, int, double, 1<<24>,
- sumBlock_<ushort, unsigned, double, 1<<16>,
- sumBlock_<short, int, double, 1<<16>,
- sum_<int, double>,
- sum_<float, double>,
- sum_<double, double>, 0,
-
- sumBlock_<Vec<uchar, 2>, Vec<int, 2>, Vec<double, 2>, 1<<23>,
- sumBlock_<Vec<schar, 2>, Vec<int, 2>, Vec<double, 2>, 1<<24>,
- sumBlock_<Vec<ushort, 2>, Vec<int, 2>, Vec<double, 2>, 1<<15>,
- sumBlock_<Vec<short, 2>, Vec<int, 2>, Vec<double, 2>, 1<<16>,
- sum_<Vec<int, 2>, Vec<double, 2> >,
- sum_<Vec<float, 2>, Vec<double, 2> >,
- sum_<Vec<double, 2>, Vec<double, 2> >, 0,
-
- sumBlock_<Vec<uchar, 3>, Vec<int, 3>, Vec<double, 3>, 1<<23>,
- sumBlock_<Vec<schar, 3>, Vec<int, 3>, Vec<double, 3>, 1<<24>,
- sumBlock_<Vec<ushort, 3>, Vec<int, 3>, Vec<double, 3>, 1<<15>,
- sumBlock_<Vec<short, 3>, Vec<int, 3>, Vec<double, 3>, 1<<16>,
- sum_<Vec<int, 3>, Vec<double, 3> >,
- sum_<Vec<float, 3>, Vec<double, 3> >,
- sum_<Vec<double, 3>, Vec<double, 3> >, 0,
-
- sumBlock_<Vec<uchar, 4>, Vec<int, 4>, Vec<double, 4>, 1<<23>,
- sumBlock_<Vec<schar, 4>, Vec<int, 4>, Vec<double, 4>, 1<<24>,
- sumBlock_<Vec<ushort, 4>, Vec<int, 4>, Vec<double, 4>, 1<<15>,
- sumBlock_<Vec<short, 4>, Vec<int, 4>, Vec<double, 4>, 1<<16>,
- sum_<Vec<int, 4>, Vec<double, 4> >,
- sum_<Vec<float, 4>, Vec<double, 4> >,
- sum_<Vec<double, 4>, Vec<double, 4> >, 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<typename T>
-static int countNonZero_( const Mat& srcmat )
-{
- //assert( DataType<T>::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_<uchar>, countNonZero_<uchar>, countNonZero_<ushort>,
- countNonZero_<ushort>, countNonZero_<int>, countNonZero_<float>,
- countNonZero_<double>, 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<typename T, typename WT, typename ST, int BLOCK_SIZE>
-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<T>::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<typename T>
+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<typename T, typename ST>
-static Scalar mean_( const Mat& srcmat, const Mat& maskmat )
-{
- assert( DataType<T>::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<typename T, typename ST, typename SQT>
+static int sumsqr_(const T* src0, const uchar* mask, ST* sum, SQT* sqsum, int len, int cn )
{
- static MeanMaskFunc tab[]=
- {
- meanBlock_<uchar, int, double, 1<<23>, 0,
- meanBlock_<ushort, int, double, 1<<15>,
- meanBlock_<short, int, double, 1<<16>,
- mean_<int, double>,
- mean_<float, double>,
- mean_<double, double>, 0,
-
- meanBlock_<Vec<uchar, 2>, Vec<int, 2>, Vec<double, 2>, 1<<23>, 0,
- meanBlock_<Vec<ushort, 2>, Vec<int, 2>, Vec<double, 2>, 1<<15>,
- meanBlock_<Vec<short, 2>, Vec<int, 2>, Vec<double, 2>, 1<<16>,
- mean_<Vec<int, 2>, Vec<double, 2> >,
- mean_<Vec<float, 2>, Vec<double, 2> >,
- mean_<Vec<double, 2>, Vec<double, 2> >, 0,
-
- meanBlock_<Vec<uchar, 3>, Vec<int, 3>, Vec<double, 3>, 1<<23>, 0,
- meanBlock_<Vec<ushort, 3>, Vec<int, 3>, Vec<double, 3>, 1<<15>,
- meanBlock_<Vec<short, 3>, Vec<int, 3>, Vec<double, 3>, 1<<16>,
- mean_<Vec<int, 3>, Vec<double, 3> >,
- mean_<Vec<float, 3>, Vec<double, 3> >,
- mean_<Vec<double, 3>, Vec<double, 3> >, 0,
-
- meanBlock_<Vec<uchar, 4>, Vec<int, 4>, Vec<double, 4>, 1<<23>, 0,
- meanBlock_<Vec<ushort, 4>, Vec<int, 4>, Vec<double, 4>, 1<<15>,
- meanBlock_<Vec<short, 4>, Vec<int, 4>, Vec<double, 4>, 1<<16>,
- mean_<Vec<int, 4>, Vec<double, 4> >,
- mean_<Vec<float, 4>, Vec<double, 4> >,
- mean_<Vec<double, 4>, Vec<double, 4> >, 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<typename T, typename SqT> struct SqrC1
-{
- typedef T type1;
- typedef SqT rtype;
- rtype operator()(type1 x) const { return (SqT)x*x; }
-};
-template<typename T, typename SqT> struct SqrC2
-{
- typedef Vec<T, 2> type1;
- typedef Vec<SqT, 2> 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<typename T, typename SqT> struct SqrC3
-{
- typedef Vec<T, 3> type1;
- typedef Vec<SqT, 3> 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<typename T, typename SqT> struct SqrC4
-{
- typedef Vec<T, 4> type1;
- typedef Vec<SqT, 4> 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<uchar, double>::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<double, 2> SqrC2<uchar, double>::operator()(const Vec<uchar, 2>& x) const
-{ return Vec<double, 2>(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<double, 3> SqrC3<uchar, double>::operator() (const Vec<uchar, 3>& x) const
-{ return Vec<double, 3>(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<double, 4> SqrC4<uchar, double>::operator() (const Vec<uchar, 4>& x) const
-{ return Vec<double, 4>(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<class SqrOp> 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<ST>::channel_type ST1;
-
- assert( DataType<T>::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<int> _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<class SqrOp> 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<ST>::channel_type ST1;
-
- assert( DataType<T>::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<int> _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_<SqrC1<uchar, double> >, 0,
- meanStdDev_<SqrC1<ushort, double> >,
- meanStdDev_<SqrC1<short, double> >,
- meanStdDev_<SqrC1<int, double> >,
- meanStdDev_<SqrC1<float, double> >,
- meanStdDev_<SqrC1<double, double> >, 0,
-
- meanStdDev_<SqrC2<uchar, double> >, 0,
- meanStdDev_<SqrC2<ushort, double> >,
- meanStdDev_<SqrC2<short, double> >,
- meanStdDev_<SqrC2<int, double> >,
- meanStdDev_<SqrC2<float, double> >,
- meanStdDev_<SqrC2<double, double> >, 0,
-
- meanStdDev_<SqrC3<uchar, double> >, 0,
- meanStdDev_<SqrC3<ushort, double> >,
- meanStdDev_<SqrC3<short, double> >,
- meanStdDev_<SqrC3<int, double> >,
- meanStdDev_<SqrC3<float, double> >,
- meanStdDev_<SqrC3<double, double> >, 0,
-
- meanStdDev_<SqrC4<uchar, double> >, 0,
- meanStdDev_<SqrC4<ushort, double> >,
- meanStdDev_<SqrC4<short, double> >,
- meanStdDev_<SqrC4<int, double> >,
- meanStdDev_<SqrC4<float, double> >,
- meanStdDev_<SqrC4<double, double> >, 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<double> _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_<SqrC1<uchar, double> >, 0,
- meanStdDevMask_<SqrC1<ushort, double> >,
- meanStdDevMask_<SqrC1<short, double> >,
- meanStdDevMask_<SqrC1<int, double> >,
- meanStdDevMask_<SqrC1<float, double> >,
- meanStdDevMask_<SqrC1<double, double> >, 0,
-
- meanStdDevMask_<SqrC2<uchar, double> >, 0,
- meanStdDevMask_<SqrC2<ushort, double> >,
- meanStdDevMask_<SqrC2<short, double> >,
- meanStdDevMask_<SqrC2<int, double> >,
- meanStdDevMask_<SqrC2<float, double> >,
- meanStdDevMask_<SqrC2<double, double> >, 0,
-
- meanStdDevMask_<SqrC3<uchar, double> >, 0,
- meanStdDevMask_<SqrC3<ushort, double> >,
- meanStdDevMask_<SqrC3<short, double> >,
- meanStdDevMask_<SqrC3<int, double> >,
- meanStdDevMask_<SqrC3<float, double> >,
- meanStdDevMask_<SqrC3<double, double> >, 0,
-
- meanStdDevMask_<SqrC4<uchar, double> >, 0,
- meanStdDevMask_<SqrC4<ushort, double> >,
- meanStdDevMask_<SqrC4<short, double> >,
- meanStdDevMask_<SqrC4<int, double> >,
- meanStdDevMask_<SqrC4<float, double> >,
- meanStdDevMask_<SqrC4<double, double> >, 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<double>();
+ for( k = 0; k < cn; k++ )
+ dptr[k] = sptr[k];
+ for( ; k < dcn; k++ )
+ dptr[k] = 0;
}
}
-
/****************************************************************************************\
* minMaxLoc *
\****************************************************************************************/
+namespace cv
+{
+
template<typename T, typename WT> 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<T>::type == srcmat.type() );
- const T* src = (const T*)srcmat.data;
- size_t step = srcmat.step/sizeof(src[0]);
- WT minVal = saturate_cast<WT>(*_minVal), maxVal = saturate_cast<WT>(*_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<typename T, typename WT> static void
-minMaxIndxMask_( const Mat& srcmat, const Mat& maskmat,
- double* _minVal, double* _maxVal,
- size_t startIdx, size_t* _minIdx, size_t* _maxIdx )
-{
- assert( DataType<T>::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<WT>(*_minVal), maxVal = saturate_cast<WT>(*_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;
}
}
}
*_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_<uchar, int>, 0, minMaxIndx_<ushort, int>, minMaxIndx_<short, int>,
- minMaxIndx_<int, int>, minMaxIndx_<float, float>, minMaxIndx_<double, double>, 0
- };
- static MinMaxIndxMaskFunc tabm[] =
- {
- minMaxIndxMask_<uchar, int>, 0, minMaxIndxMask_<ushort, int>, minMaxIndxMask_<short, int>,
- minMaxIndxMask_<int, int>, minMaxIndxMask_<float, float>, minMaxIndxMask_<double, double>, 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;
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_<uchar, int>, 0, minMaxIndx_<ushort, int>, minMaxIndx_<short, int>,
- minMaxIndx_<int, int>, minMaxIndx_<float, float>, minMaxIndx_<double, double>, 0
- };
- static MinMaxIndxMaskFunc tabm[] =
- {
- minMaxIndxMask_<uchar, int>, 0, minMaxIndxMask_<ushort, int>, minMaxIndxMask_<short, int>,
- minMaxIndxMask_<int, int>, minMaxIndxMask_<float, float>, minMaxIndxMask_<double, double>, 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<typename T, typename WT=T> struct OpAbs
+namespace cv
{
- typedef T type1;
- typedef WT rtype;
- rtype operator()(type1 x) const { return (WT)std::abs(x); }
-};
-
-template<> inline uchar OpAbs<uchar, uchar>::operator()(uchar x) const { return x; }
-template<> inline ushort OpAbs<ushort, ushort>::operator()(ushort x) const { return x; }
-template<class ElemFunc, class UpdateFunc, class GlobUpdateFunc, int BLOCK_SIZE>
-static double normBlock_( const Mat& srcmat )
+template<typename T, typename ST> 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<T>::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<typename T, typename ST> 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<class ElemFunc, class UpdateFunc>
-static double norm_( const Mat& srcmat )
+template<typename T, typename ST> 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<T>::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<class ElemFunc, class UpdateFunc, class GlobUpdateFunc, int BLOCK_SIZE>
-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<T>::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<class ElemFunc, class UpdateFunc>
-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<T>::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<typename T, typename ST> 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<typename T, class ElemFunc, class UpdateFunc, class GlobUpdateFunc, int BLOCK_SIZE>
-static double normDiffBlock_( const Mat& srcmat1, const Mat& srcmat2 )
+template<typename T, typename ST> 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<T>::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<typename T, class ElemFunc, class UpdateFunc>
-static double normDiff_( const Mat& srcmat1, const Mat& srcmat2 )
+template<typename T, typename ST> 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<T>::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<typename T, class ElemFunc, class UpdateFunc, class GlobUpdateFunc, int BLOCK_SIZE>
-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<T>::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<typename T, class ElemFunc, class UpdateFunc>
-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<T>::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_<OpAbs<uchar>, OpMax<int> >,
- norm_<OpAbs<schar>, OpMax<int> >,
- norm_<OpAbs<ushort>, OpMax<int> >,
- norm_<OpAbs<short, int>, OpMax<int> >,
- norm_<OpAbs<int>, OpMax<int> >,
- norm_<OpAbs<float>, OpMax<float> >,
- norm_<OpAbs<double>, OpMax<double> >
- },
-
- {
- normBlock_<OpAbs<uchar>, OpAdd<unsigned>, OpAdd<double>, 1<<24>,
- normBlock_<OpAbs<schar>, OpAdd<unsigned>, OpAdd<double>, 1<<24>,
- normBlock_<OpAbs<ushort>, OpAdd<unsigned>, OpAdd<double>, 1<<16>,
- normBlock_<OpAbs<short, int>, OpAdd<unsigned>, OpAdd<double>, 1<<16>,
- norm_<OpAbs<int>, OpAdd<double> >,
- norm_<OpAbs<float>, OpAdd<double> >,
- norm_<OpAbs<double>, OpAdd<double> >
- },
-
- {
- normBlock_<SqrC1<uchar, unsigned>, OpAdd<unsigned>, OpAdd<double>, 1<<16>,
- normBlock_<SqrC1<schar, unsigned>, OpAdd<unsigned>, OpAdd<double>, 1<<16>,
- norm_<SqrC1<ushort, double>, OpAdd<double> >,
- norm_<SqrC1<short, double>, OpAdd<double> >,
- norm_<SqrC1<int, double>, OpAdd<double> >,
- norm_<SqrC1<float, double>, OpAdd<double> >,
- norm_<SqrC1<double, double>, OpAdd<double> >
- }
- };
+ (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<float>();
+
+ 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_<OpAbs<uchar>, OpMax<int> >,
- normMask_<OpAbs<schar>, OpMax<int> >,
- normMask_<OpAbs<ushort>, OpMax<int> >,
- normMask_<OpAbs<short, int>, OpMax<int> >,
- normMask_<OpAbs<int>, OpMax<int> >,
- normMask_<OpAbs<float>, OpMax<float> >,
- normMask_<OpAbs<double>, OpMax<double> >
- },
-
- {
- normMaskBlock_<OpAbs<uchar>, OpAdd<unsigned>, OpAdd<double>, 1<<24>,
- normMaskBlock_<OpAbs<schar>, OpAdd<unsigned>, OpAdd<double>, 1<<24>,
- normMaskBlock_<OpAbs<ushort>, OpAdd<unsigned>, OpAdd<double>, 1<<16>,
- normMaskBlock_<OpAbs<short, int>, OpAdd<unsigned>, OpAdd<double>, 1<<16>,
- normMask_<OpAbs<int>, OpAdd<double> >,
- normMask_<OpAbs<float>, OpAdd<double> >,
- normMask_<OpAbs<double>, OpAdd<double> >
- },
-
- {
- normMaskBlock_<SqrC1<uchar, unsigned>, OpAdd<unsigned>, OpAdd<double>, 1<<16>,
- normMaskBlock_<SqrC1<schar, unsigned>, OpAdd<unsigned>, OpAdd<double>, 1<<16>,
- normMask_<SqrC1<ushort, double>, OpAdd<double> >,
- normMask_<SqrC1<short, double>, OpAdd<double> >,
- normMask_<SqrC1<int, double>, OpAdd<double> >,
- normMask_<SqrC1<float, double>, OpAdd<double> >,
- normMask_<SqrC1<double, double>, OpAdd<double> >
- }
- };
-
- 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_<uchar, OpAbs<int>, OpMax<int> >,
- normDiff_<schar, OpAbs<int>, OpMax<int> >,
- normDiff_<ushort, OpAbs<int>, OpMax<int> >,
- normDiff_<short, OpAbs<int>, OpMax<int> >,
- normDiff_<int, OpAbs<int>, OpMax<int> >,
- normDiff_<float, OpAbs<float>, OpMax<float> >,
- normDiff_<double, OpAbs<double>, OpMax<double> >
- },
-
- {
- normDiffBlock_<uchar, OpAbs<int>, OpAdd<unsigned>, OpAdd<double>, 1<<24>,
- normDiffBlock_<schar, OpAbs<int>, OpAdd<unsigned>, OpAdd<double>, 1<<24>,
- normDiffBlock_<ushort, OpAbs<int>, OpAdd<unsigned>, OpAdd<double>, 1<<16>,
- normDiffBlock_<short, OpAbs<int>, OpAdd<unsigned>, OpAdd<double>, 1<<16>,
- normDiff_<int, OpAbs<int>, OpAdd<double> >,
- normDiff_<float, OpAbs<float>, OpAdd<double> >,
- normDiff_<double, OpAbs<double>, OpAdd<double> >
- },
-
- {
- normDiffBlock_<uchar, SqrC1<int, int>, OpAdd<unsigned>, OpAdd<double>, 1<<16>,
- normDiffBlock_<schar, SqrC1<int, int>, OpAdd<unsigned>, OpAdd<double>, 1<<16>,
- normDiff_<ushort, SqrC1<int, double>, OpAdd<double> >,
- normDiff_<short, SqrC1<int, double>, OpAdd<double> >,
- normDiff_<int, SqrC1<int, double>, OpAdd<double> >,
- normDiff_<float, SqrC1<float, double>, OpAdd<double> >,
- normDiff_<double, SqrC1<double, double>, OpAdd<double> >
- }
- };
+ 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<float>();
+ const float* data2 = src2.ptr<float>();
+
+ 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_<uchar, OpAbs<int>, OpMax<int> >,
- normDiffMask_<schar, OpAbs<int>, OpMax<int> >,
- normDiffMask_<ushort, OpAbs<int>, OpMax<int> >,
- normDiffMask_<short, OpAbs<int>, OpMax<int> >,
- normDiffMask_<int, OpAbs<int>, OpMax<int> >,
- normDiffMask_<float, OpAbs<float>, OpMax<float> >,
- normDiffMask_<double, OpAbs<double>, OpMax<double> >
- },
-
- {
- normDiffMaskBlock_<uchar, OpAbs<int>, OpAdd<unsigned>, OpAdd<double>, 1<<24>,
- normDiffMaskBlock_<schar, OpAbs<int>, OpAdd<unsigned>, OpAdd<double>, 1<<24>,
- normDiffMaskBlock_<ushort, OpAbs<int>, OpAdd<unsigned>, OpAdd<double>, 1<<16>,
- normDiffMaskBlock_<short, OpAbs<int>, OpAdd<unsigned>, OpAdd<double>, 1<<16>,
- normDiffMask_<int, OpAbs<int>, OpAdd<double> >,
- normDiffMask_<float, OpAbs<float>, OpAdd<double> >,
- normDiffMask_<double, OpAbs<double>, OpAdd<double> >
- },
-
- {
- normDiffMaskBlock_<uchar, SqrC1<int, int>, OpAdd<unsigned>, OpAdd<double>, 1<<16>,
- normDiffMaskBlock_<schar, SqrC1<int, int>, OpAdd<unsigned>, OpAdd<double>, 1<<16>,
- normDiffMask_<ushort, SqrC1<int, double>, OpAdd<double> >,
- normDiffMask_<short, SqrC1<int, double>, OpAdd<double> >,
- normDiffMask_<int, SqrC1<int, double>, OpAdd<double> >,
- normDiffMask_<float, SqrC1<float, double>, OpAdd<double> >,
- normDiffMask_<double, SqrC1<double, double>, OpAdd<double> >
- }
- };
- 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;
}
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)
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);
}
{
scaleAdd(src[0], alpha, src[1], dst);
}
+ double getMaxErr(int depth)
+ {
+ return depth <= CV_32S ? 2 : depth < CV_64F ? 1e-4 : 1e-12;
+ }
};
}
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)
{
BaseElemWiseOp::generateScalars(depth, rng);
cmpop = rng.uniform(0, 6);
+ if( depth < CV_32F )
+ gamma[0] = cvRound(gamma[0]);
}
void op(const vector<Mat>& src, Mat& dst, const Mat&)
{
}
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)
{
}
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)
{
}
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)
{
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;
}
}
}
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;
}
}
}
}
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)
{
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)
{
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)
{
}
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<Mat>& src, Mat& dst, const Mat&)
{
}
double getMaxErr(int)
{
- return 1e-6;
+ return 1e-5;
}
};
{}
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<Mat>& src, Mat& dst, const Mat& mask)
{
};
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<Mat>& src, Mat& dst, const Mat& mask)
{
};
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<int>& minidx, const vector<int>& maxidx,
double minval, double maxval, Mat& dst)
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('&'))));
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)));
+
+
+
TEST(Core_DFT, accuracy) { CxCore_DFTTest test; test.safe_run(); }
TEST(Core_MulSpectrums, accuracy) { CxCore_MulSpectrumsTest test; test.safe_run(); }
+
protected:
void run(int)
{
- int code = cvtest::TS::OK;
-
double diffPrjEps, diffBackPrjEps,
prjEps, backPrjEps,
evalEps, evecEps;
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<float>(mloc.y, mloc.x),
+ subEvec.at<float>(mloc.y, mloc.x));
+ ts->set_failed_test_info( cvtest::TS::FAIL_BAD_ACCURACY );
+ return;
+ }
+ }
}
prjEps = 1.265, backPrjEps = 1.265;
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;
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
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
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 );
}
};
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)) )
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(); }
+
+
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;
}
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++ )
for( int di = 0; di < data.cols; di++ )
res1.at<float>(pi, di) = point[di];
}
- // 2nd way
- tr->getPoints( idxs.ptr<int>(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;
{
vector<float> min( dims, minValue), max(dims, maxValue);
vector<int> 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;
for( int pi = 0; pi < points.rows; pi++ )
{
// 1st way
- tr->findNearest( points.ptr<float>(pi), neighbors.cols, emax, neighbors.ptr<int>(pi) );
+ Mat nrow = neighbors.row(pi);
+ tr->findNearest( points.row(pi), neighbors.cols, emax, nrow );
// 2nd way
vector<int> neighborsIdx2( neighbors2.cols, 0 );
- tr->findNearest( points.ptr<float>(pi), neighbors2.cols, emax, &neighborsIdx2 );
+ tr->findNearest( points.row(pi), neighbors2.cols, emax, neighborsIdx2 );
vector<int>::const_iterator it2 = neighborsIdx2.begin();
for( j = 0; it2 != neighborsIdx2.end(); ++it2, j++ )
neighbors2.at<int>(pi,j) = *it2;
ts->printf(cvtest::TS::LOG, "Tesing %s\n", names[i]);\r
\r
cv::Mat cpuRes;\r
- cv::morphologyEx(img, cpuRes, ops[i], kernel);\r
+ cv::morphologyEx(img, cpuRes, ops[i], (Mat)kernel);\r
\r
GpuMat gpuRes;\r
cv::gpu::morphologyEx(GpuMat(img), gpuRes, ops[i], kernel);\r
cv::cvtColor(img_rgb, img, CV_BGR2BGRA);\r
computeBlockHistograms(cv::gpu::GpuMat(img));\r
// Everything is fine with interpolation for left top subimage\r
- CHECK(cv::norm(block_hists, descriptors.rowRange(0, 1)) == 0.f, cvtest::TS::FAIL_INVALID_OUTPUT);\r
+ CHECK(cv::norm((cv::Mat)block_hists, (cv::Mat)descriptors.rowRange(0, 1)) == 0.f, cvtest::TS::FAIL_INVALID_OUTPUT);\r
\r
img_rgb = cv::imread(std::string(ts->get_data_path()) + "hog/positive2.png");\r
CHECK(!img_rgb.empty(), cvtest::TS::FAIL_MISSING_TEST_DATA);\r
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);
bool passed = true;
int lastType = CV_32F;
- if (TargetArchs::builtWith(NATIVE_DOUBLE) && DeviceInfo().supports(NATIVE_DOUBLE))\r
+ if (TargetArchs::builtWith(NATIVE_DOUBLE) && DeviceInfo().supports(NATIVE_DOUBLE))
lastType = CV_64F;
for (int i = 0; i <= lastType && passed; ++i)
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,
cv::waitKey(0);
#endif
- double ret = norm(cmat, gmat);
+ double ret = norm(cmat, (Mat)gmat);
if (ret < 1.0)
return true;
int lastType = CV_32F;
- if (TargetArchs::builtWith(NATIVE_DOUBLE) && DeviceInfo().supports(NATIVE_DOUBLE))\r
+ if (TargetArchs::builtWith(NATIVE_DOUBLE) && DeviceInfo().supports(NATIVE_DOUBLE))
lastType = CV_64F;
for (int i = 0 ; i <= lastType; i++)
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<double>::epsilon())
return true;
int lastType = CV_32F;
- if (TargetArchs::builtWith(NATIVE_DOUBLE) && DeviceInfo().supports(NATIVE_DOUBLE))\r
+ if (TargetArchs::builtWith(NATIVE_DOUBLE) && DeviceInfo().supports(NATIVE_DOUBLE))
lastType = CV_64F;
for (int i = 0; i <= lastType; i++)
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);
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)
{
\r
disp.convertTo(disp, img_template.type());\r
\r
- double norm = cv::norm(disp, img_template, cv::NORM_INF);\r
+ double norm = cv::norm((cv::Mat)disp, img_template, cv::NORM_INF);\r
if (norm >= 0.5)\r
{\r
ts->printf(cvtest::TS::LOG, "\nStereoBP norm = %f\n", norm);\r
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);
//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);
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);
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<int>& params=vector<int>());
-CV_EXPORTS_W Mat imdecode( const Mat& buf, int flags );
-CV_EXPORTS_W bool imencode( const string& ext, const Mat& img,
- CV_OUT vector<uchar>& buf,
- const vector<int>& params=vector<int>());
+CV_EXPORTS_W Mat imdecode( const InputArray& buf, int flags );
+CV_EXPORTS_W bool imencode( const string& ext, const InputArray& img,
+ vector<uchar>& buf,
+ const vector<int>& params=vector<int>());
CV_EXPORTS_W int waitKey(int delay=0);
return code;
}
-bool imwrite( const string& filename, const Mat& img,
+bool imwrite( const string& filename, const InputArray& _img,
const vector<int>& params )
{
+ Mat img = _img.getMat();
return imwrite_(filename, img, params, false);
}
}
-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<uchar>& buf, const vector<int>& params )
{
- Mat temp;
+ Mat temp, image = _image.getMat();
const Mat* pimage = ℑ
int channels = image.channels();
}
}
-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)
{
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
//! 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 };
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<BaseRowFilter> 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<BaseColumnFilter> 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<BaseFilter> 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<FilterEngine> 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,
//! returns the non-separable linear filter engine
CV_EXPORTS Ptr<FilterEngine> 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());
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<FilterEngine> createDerivFilter( int srcType, int dstType,
int dx, int dy, int ksize,
//! returns vertical 1D morphological filter
CV_EXPORTS Ptr<BaseColumnFilter> getMorphologyColumnFilter(int op, int type, int ksize, int anchor=-1);
//! returns 2D morphological filter
-CV_EXPORTS Ptr<BaseFilter> getMorphologyFilter(int op, int type, const Mat& kernel,
+CV_EXPORTS Ptr<BaseFilter> 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<FilterEngine> createMorphologyFilter(int op, int type, const Mat& kernel,
+CV_EXPORTS Ptr<FilterEngine> createMorphologyFilter(int op, int type, const InputArray& kernel,
Point anchor=Point(-1,-1), int _rowBorderType=BORDER_CONSTANT,
int _columnBorderType=-1,
const Scalar& _borderValue=morphologyDefaultBorderValue());
template<> CV_EXPORTS void Ptr<IplConvKernel>::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<Point2f>& 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<Point2f>& 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<Vec2f>& 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<Vec4i>& 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<Vec3f>& 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
};
//! 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<<INTER_BITS),
- INTER_TAB_SIZE2=INTER_TAB_SIZE*INTER_TAB_SIZE };
+ INTER_TAB_SIZE2=INTER_TAB_SIZE*INTER_TAB_SIZE
+};
//! warps the image using the precomputed maps. The maps are stored in either floating-point or integer fixed-point format
-CV_EXPORTS_W void remap( const Mat& src, CV_OUT Mat& dst, const Mat& map1, const Mat& map2,
- int interpolation, int borderMode=BORDER_CONSTANT,
- const Scalar& borderValue=Scalar());
+CV_EXPORTS_W void remap( const InputArray& src, OutputArray dst,
+ const InputArray& map1, const InputArray& map2,
+ int interpolation, int borderMode=BORDER_CONSTANT,
+ const Scalar& borderValue=Scalar());
//! converts maps for remap from floating-point to fixed-point format or backwards
-CV_EXPORTS_W void convertMaps( const Mat& map1, const Mat& map2,
- CV_OUT Mat& dstmap1, CV_OUT Mat& dstmap2,
- int dstmap1type, bool nninterpolation=false );
+CV_EXPORTS_W void convertMaps( const InputArray& map1, const InputArray& map2,
+ OutputArray dstmap1, OutputArray dstmap2,
+ int dstmap1type, bool nninterpolation=false );
//! returns 2x3 affine transformation matrix for the planar rotation.
CV_EXPORTS_W Mat getRotationMatrix2D( Point2f center, double angle, double scale );
//! returns 2x3 affine transformation for the corresponding 3 point pairs.
CV_EXPORTS Mat getAffineTransform( const Point2f src[], const Point2f dst[] );
//! computes 2x3 affine transformation matrix that is inverse to the specified 2x3 affine transformation.
-CV_EXPORTS_W void invertAffineTransform( const Mat& M, CV_OUT Mat& iM );
+CV_EXPORTS_W void invertAffineTransform( const InputArray& M, OutputArray iM );
//! extracts rectangle from the image at sub-pixel location
-CV_EXPORTS_W void getRectSubPix( const Mat& image, Size patchSize,
- Point2f center, CV_OUT Mat& patch, int patchType=-1 );
+CV_EXPORTS_W void getRectSubPix( const InputArray& image, Size patchSize,
+ Point2f center, OutputArray patch, int patchType=-1 );
//! computes the integral image
-CV_EXPORTS_W void integral( const Mat& src, CV_OUT Mat& sum, int sdepth=-1 );
+CV_EXPORTS_W void integral( const InputArray& src, OutputArray sum, int sdepth=-1 );
//! computes the integral image and integral for the squared image
-CV_EXPORTS_AS(integral2) void integral( const Mat& src, CV_OUT Mat& sum, CV_OUT Mat& sqsum, int sdepth=-1 );
+CV_EXPORTS_AS(integral2) void integral( const InputArray& src, OutputArray sum,
+ OutputArray sqsum, int sdepth=-1 );
//! computes the integral image, integral for the squared image and the tilted integral image
-CV_EXPORTS_AS(integral3) void integral( const Mat& src, CV_OUT Mat& sum, CV_OUT Mat& sqsum, CV_OUT Mat& tilted, int sdepth=-1 );
+CV_EXPORTS_AS(integral3) void integral( const InputArray& src, OutputArray sum,
+ OutputArray sqsum, OutputArray tilted,
+ int sdepth=-1 );
//! adds image to the accumulator (dst += src). Unlike cv::add, dst and src can have different types.
-CV_EXPORTS_W void accumulate( const Mat& src, CV_IN_OUT Mat& dst, const Mat& mask=Mat() );
+CV_EXPORTS_W void accumulate( const InputArray& src, CV_IN_OUT InputOutputArray dst,
+ const InputArray& mask=InputArray() );
//! adds squared src image to the accumulator (dst += src*src).
-CV_EXPORTS_W void accumulateSquare( const Mat& src, CV_IN_OUT Mat& dst, const Mat& mask=Mat() );
+CV_EXPORTS_W void accumulateSquare( const InputArray& src, CV_IN_OUT InputOutputArray dst,
+ const InputArray& mask=InputArray() );
//! adds product of the 2 images to the accumulator (dst += src1*src2).
-CV_EXPORTS_W void accumulateProduct( const Mat& src1, const Mat& src2,
- CV_IN_OUT Mat& dst, const Mat& mask=Mat() );
+CV_EXPORTS_W void accumulateProduct( const InputArray& src1, const InputArray& src2,
+ CV_IN_OUT InputOutputArray dst, const InputArray& mask=InputArray() );
//! updates the running average (dst = dst*(1-alpha) + src*alpha)
-CV_EXPORTS_W void accumulateWeighted( const Mat& src, CV_IN_OUT Mat& dst,
- double alpha, const Mat& mask=Mat() );
+CV_EXPORTS_W void accumulateWeighted( const InputArray& src, CV_IN_OUT InputOutputArray dst,
+ double alpha, const InputArray& mask=InputArray() );
//! type of the threshold operation
enum { THRESH_BINARY=CV_THRESH_BINARY, THRESH_BINARY_INV=CV_THRESH_BINARY_INV,
THRESH_OTSU=CV_THRESH_OTSU };
//! applies fixed threshold to the image
-CV_EXPORTS_W double threshold( const Mat& src, CV_OUT Mat& dst, double thresh, double maxval, int type );
+CV_EXPORTS_W double threshold( const InputArray& src, OutputArray dst,
+ double thresh, double maxval, int type );
//! adaptive threshold algorithm
enum { ADAPTIVE_THRESH_MEAN_C=0, ADAPTIVE_THRESH_GAUSSIAN_C=1 };
//! applies variable (adaptive) threshold to the image
-CV_EXPORTS_W void adaptiveThreshold( const Mat& src, CV_OUT Mat& dst, double maxValue,
- int adaptiveMethod, int thresholdType,
- int blockSize, double C );
+CV_EXPORTS_W void adaptiveThreshold( const InputArray& src, OutputArray dst,
+ double maxValue, int adaptiveMethod,
+ int thresholdType, int blockSize, double C );
//! smooths and downsamples the image
-CV_EXPORTS_W void pyrDown( const Mat& src, CV_OUT Mat& dst, const Size& dstsize=Size());
+CV_EXPORTS_W void pyrDown( const InputArray& src, OutputArray dst,
+ const Size& dstsize=Size());
//! upsamples and smoothes the image
-CV_EXPORTS_W void pyrUp( const Mat& src, CV_OUT Mat& dst, const Size& dstsize=Size());
+CV_EXPORTS_W void pyrUp( const InputArray& src, OutputArray dst,
+ const Size& dstsize=Size());
+
//! builds the gaussian pyramid using pyrDown() as a basic operation
-CV_EXPORTS void buildPyramid( const Mat& src, CV_OUT vector<Mat>& 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
{
};
//! 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<Point2f>& 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<CvHistogram>::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
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
};
//! 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
};
//! 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
};
//! 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] );
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
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<vector<Point> >& contours,
- vector<Vec4i>& 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<vector<Point> >& 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<vector<Point> >& contours,
+CV_EXPORTS void drawContours( InputOutputArray image, const InputArrayOfArrays& contours,
int contourIdx, const Scalar& color,
int thickness=1, int lineType=8,
- const vector<Vec4i>& hierarchy=vector<Vec4i>(),
+ 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<Point>& approxCurve,
- double epsilon, bool closed );
-//! approximates contour or a curve using Douglas-Peucker algorithm
-CV_EXPORTS void approxPolyDP( const Mat& curve,
- CV_OUT vector<Point2f>& 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<int>& hull, bool clockwise=false );
-//! computes convex hull for a set of 2D points.
-CV_EXPORTS void convexHull( const Mat& points, CV_OUT vector<Point>& 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<Point2f>& 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 <xavier.delacour@gmail.com>
struct lsh_hash {
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<typename T, typename AT> 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<typename T, typename AT> 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<typename T, typename AT> 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<typename T, typename AT> 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<typename T, typename AT> 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<typename T, typename AT> 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<typename T, typename AT> 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<typename T, typename AT> 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<AT>::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_<uchar, float>;
- else if( src.depth() == CV_8U && dst.depth() == CV_64F )
- func = acc_<uchar, double>;
- else if( src.depth() == CV_32F && dst.depth() == CV_32F )
- func = acc_<float, float>;
- else if( src.depth() == CV_32F && dst.depth() == CV_64F )
- func = acc_<float, double>;
- else if( src.depth() == CV_64F && dst.depth() == CV_64F )
- func = acc_<double, double>;
- 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_<uchar, float>;
- else if( src.type() == CV_8UC3 && dst.type() == CV_32FC3 )
- func = accMask_<Vec3b, Vec3f>;
- else if( src.type() == CV_8UC1 && dst.type() == CV_64FC1 )
- func = accMask_<uchar, double>;
- else if( src.type() == CV_8UC3 && dst.type() == CV_64FC3 )
- func = accMask_<Vec3b, Vec3d>;
- else if( src.type() == CV_32FC1 && dst.type() == CV_32FC1 )
- func = accMask_<float, float>;
- else if( src.type() == CV_32FC3 && dst.type() == CV_32FC3 )
- func = accMask_<Vec3f, Vec3f>;
- else if( src.type() == CV_32FC1 && dst.type() == CV_64FC1 )
- func = accMask_<float, double>;
- else if( src.type() == CV_32FC3 && dst.type() == CV_64FC3 )
- func = accMask_<Vec3f, Vec3d>;
- else if( src.type() == CV_64FC1 && dst.type() == CV_64FC1 )
- func = accMask_<double, double>;
- else if( src.type() == CV_64FC3 && dst.type() == CV_64FC3 )
- func = accMask_<Vec3d, Vec3d>;
- 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_<uchar, float>;
- else if( src.depth() == CV_8U && dst.depth() == CV_64F )
- func = accSqr_<uchar, double>;
- else if( src.depth() == CV_32F && dst.depth() == CV_32F )
- func = accSqr_<float, float>;
- else if( src.depth() == CV_32F && dst.depth() == CV_64F )
- func = accSqr_<float, double>;
- else if( src.depth() == CV_64F && dst.depth() == CV_64F )
- func = accSqr_<double, double>;
- 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_<uchar, float>;
- else if( src.type() == CV_8UC3 && dst.type() == CV_32FC3 )
- func = accSqrMask_<Vec3b, Vec3f>;
- else if( src.type() == CV_8UC1 && dst.type() == CV_64FC1 )
- func = accSqrMask_<uchar, double>;
- else if( src.type() == CV_8UC3 && dst.type() == CV_64FC3 )
- func = accSqrMask_<Vec3b, Vec3d>;
- else if( src.type() == CV_32FC1 && dst.type() == CV_32FC1 )
- func = accSqrMask_<float, float>;
- else if( src.type() == CV_32FC3 && dst.type() == CV_32FC3 )
- func = accSqrMask_<Vec3f, Vec3f>;
- else if( src.type() == CV_32FC1 && dst.type() == CV_64FC1 )
- func = accSqrMask_<float, double>;
- else if( src.type() == CV_32FC3 && dst.type() == CV_64FC3 )
- func = accSqrMask_<Vec3f, Vec3d>;
- else if( src.type() == CV_64FC1 && dst.type() == CV_64FC1 )
- func = accSqrMask_<double, double>;
- else if( src.type() == CV_64FC3 && dst.type() == CV_64FC3 )
- func = accSqrMask_<Vec3d, Vec3d>;
- 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_<uchar, float>;
- else if( src1.depth() == CV_8U && dst.depth() == CV_64F )
- func = accProd_<uchar, double>;
- else if( src1.depth() == CV_32F && dst.depth() == CV_32F )
- func = accProd_<float, float>;
- else if( src1.depth() == CV_32F && dst.depth() == CV_64F )
- func = accProd_<float, double>;
- else if( src1.depth() == CV_64F && dst.depth() == CV_64F )
- func = accProd_<double, double>;
- 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_<uchar, float>;
- else if( src1.type() == CV_8UC3 && dst.type() == CV_32FC3 )
- func = accProdMask_<Vec3b, Vec3f>;
- else if( src1.type() == CV_8UC1 && dst.type() == CV_64FC1 )
- func = accProdMask_<uchar, double>;
- else if( src1.type() == CV_8UC3 && dst.type() == CV_64FC3 )
- func = accProdMask_<Vec3b, Vec3d>;
- else if( src1.type() == CV_32FC1 && dst.type() == CV_32FC1 )
- func = accProdMask_<float, float>;
- else if( src1.type() == CV_32FC3 && dst.type() == CV_32FC3 )
- func = accProdMask_<Vec3f, Vec3f>;
- else if( src1.type() == CV_32FC1 && dst.type() == CV_64FC1 )
- func = accProdMask_<float, double>;
- else if( src1.type() == CV_32FC3 && dst.type() == CV_64FC3 )
- func = accProdMask_<Vec3f, Vec3d>;
- else if( src1.type() == CV_64FC1 && dst.type() == CV_64FC1 )
- func = accProdMask_<double, double>;
- else if( src1.type() == CV_64FC3 && dst.type() == CV_64FC3 )
- func = accProdMask_<Vec3d, Vec3d>;
- 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_<uchar, float>;
- else if( src.depth() == CV_8U && dst.depth() == CV_64F )
- func = accW_<uchar, double>;
- else if( src.depth() == CV_32F && dst.depth() == CV_32F )
- func = accW_<float, float>;
- else if( src.depth() == CV_32F && dst.depth() == CV_64F )
- func = accW_<float, double>;
- else if( src.depth() == CV_64F && dst.depth() == CV_64F )
- func = accW_<double, double>;
- 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_<uchar, float>;
- else if( src.type() == CV_8UC3 && dst.type() == CV_32FC3 )
- func = accWMask_<Vec3b, Vec3f>;
- else if( src.type() == CV_8UC1 && dst.type() == CV_64FC1 )
- func = accWMask_<uchar, double>;
- else if( src.type() == CV_8UC3 && dst.type() == CV_64FC3 )
- func = accWMask_<Vec3b, Vec3d>;
- else if( src.type() == CV_32FC1 && dst.type() == CV_32FC1 )
- func = accWMask_<float, float>;
- else if( src.type() == CV_32FC3 && dst.type() == CV_32FC3 )
- func = accWMask_<Vec3f, Vec3f>;
- else if( src.type() == CV_32FC1 && dst.type() == CV_64FC1 )
- func = accWMask_<float, double>;
- else if( src.type() == CV_32FC3 && dst.type() == CV_64FC3 )
- func = accWMask_<Vec3f, Vec3d>;
- else if( src.type() == CV_64FC1 && dst.type() == CV_64FC1 )
- func = accWMask_<double, double>;
- else if( src.type() == CV_64FC3 && dst.type() == CV_64FC3 )
- func = accWMask_<Vec3d, Vec3d>;
- 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);
}
}
}
-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));
}
}
}
+}
//////////////////////////////////////////////////////////////////////////////////////////
// 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;
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<uchar>(scn, dcn, bidx));
else if( depth == CV_16U )
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 ||
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 ||
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 )
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<uchar>(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;
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<uchar>(scn, bidx, coeffs_i));
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<uchar>(dcn, bidx, coeffs_i));
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<uchar>(scn, bidx, 0));
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<uchar>(dcn, bidx, 0));
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 )
{
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 )
{
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 )
{
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 )
{
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;
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 )
CV_Error( CV_StsBadFlag, "Unknown/unsupported color conversion code" );
}
}
-
-}
CV_IMPL void
cvCvtColor( const CvArr* srcarr, CvArr* dstarr, int code )
return count;
}
-namespace cv
-{
-static void
-_findContours( Mat& image, vector<vector<Point> >& contours,
- vector<Vec4i>* 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<CvSeq*> all_contours(cvTreeToNodeSeq( _contours, sizeof(CvSeq), storage ));
+ Seq<CvSeq*> 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<CvSeq*> it = all_contours.begin();
for( i = 0; i < total; i++, ++it )
{
CvSeq* c = *it;
((CvContour*)c)->color = (int)i;
- Seq<Point>(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<Vec4i>();
+
it = all_contours.begin();
for( i = 0; i < total; i++, ++it )
{
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<vector<Point> >& contours,
- vector<Vec4i>& 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<vector<Point> >& 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<vector<Point> >& contours,
- const vector<Vec4i>& hierarchy,
+static void addChildContour(const InputArrayOfArrays& contours,
+ size_t ncontours,
+ const Vec4i* hierarchy,
int i, vector<CvSeq>& seq,
vector<CvSeqBlock>& block)
{
- size_t count = contours.size();
for( ; i >= 0; i = hierarchy[i][0] )
{
- const vector<Point>& 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<vector<Point> >& contours,
+void cv::drawContours( InputOutputArray _image, const InputArrayOfArrays& _contours,
int contourIdx, const Scalar& color, int thickness,
- int lineType, const vector<Vec4i>& 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<CvSeq> seq;
vector<CvSeqBlock> block;
for( i = first; i < last; i++ )
{
- const vector<Point>& 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 )
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<Vec4i>();
+
+ 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;
}
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<Point>& 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<Point> 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<Point2f>& approxCurve,
- double epsilon, bool closed )
-{
- CV_Assert(curve.checkVector(2, CV_32F) >= 0);
- CvMat _curve = curve;
- MemStorage storage(cvCreateMemStorage());
- Seq<Point2f> 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());
}
-void cv::convexHull( const Mat& points, vector<int>& 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<Point>& 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<Point2f>& 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);
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 );
}
}
-
-}
-
CV_IMPL void
cvCornerMinEigenVal( const CvArr* srcarr, CvArr* dstarr,
int block_size, int aperture_size )
}
}
-void cv::cornerSubPix( const Mat& image, vector<Point2f>& 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. */
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 );
}
-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 )
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" );
}
}
+}
-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 );
}
-Ptr<FilterEngine> createDerivFilter(int srcType, int dstType,
- int dx, int dy, int ksize, int borderType )
+cv::Ptr<cv::FilterEngine> 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 );
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;
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)
{
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()));
}
-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()));
}
-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] =
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<FilterEngine> fx = createSeparableLinearFilter(src.type(),
}
}
-}
-
/////////////////////////////////////////////////////////////////////////////////////////
CV_IMPL void
}
}
-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. */
}
-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. */
bool operator()(const T* a, const T* b) const { return *a > *b; }
};
-void goodFeaturesToTrack( const Mat& image, vector<Point2f>& 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;
}
sort( tmpCorners, greaterThanPtr<float>() );
- corners.clear();
+ vector<Point2f> corners;
size_t i, j, total = tmpCorners.size(), ncorners = 0;
if(minDistance >= 1)
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);
}
*/
}
-
-}
CV_IMPL void
cvGoodFeaturesToTrack( const void* _image, void*, void*,
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 )
;
}
+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;
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;
}
+namespace cv
+{
+
struct RowNoVec
{
RowNoVec() {}
int SHIFT, DELTA;
};
-Ptr<BaseRowFilter> getLinearRowFilter( int srcType, int bufType,
- const Mat& kernel, int anchor,
- int symmetryType )
+}
+
+cv::Ptr<cv::BaseRowFilter> 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) &&
}
-Ptr<BaseColumnFilter> getLinearColumnFilter( int bufType, int dstType,
- const Mat& kernel, int anchor,
+cv::Ptr<cv::BaseColumnFilter> 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) &&
}
-Ptr<FilterEngine> createSeparableLinearFilter(
+cv::Ptr<cv::FilterEngine> 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);
* Non-separable linear filter *
\****************************************************************************************/
+namespace cv
+{
+
void preprocess2DKernel( const Mat& kernel, vector<Point>& coords, vector<uchar>& coeffs )
{
int i, j, k, nz = countNonZero(kernel), ktype = kernel.type();
VecOp vecOp;
};
+}
-Ptr<BaseFilter> getLinearFilter(int srcType, int dstType,
- const Mat& _kernel, Point anchor,
+cv::Ptr<cv::BaseFilter> 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 );
}
-Ptr<FilterEngine> createLinearFilter( int _srcType, int _dstType, const Mat& _kernel,
- Point _anchor, double _delta,
- int _rowBorderType, int _columnBorderType,
- const Scalar& _borderValue )
+cv::Ptr<cv::FilterEngine> 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);
}
-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();
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 )
}
-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<FilterEngine> 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 )
}
-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);
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++ )
}
}
-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 )
namespace cv
{
+template<> void Ptr<CvHistogram>::delete_obj()
+{ cvReleaseHist(&obj); }
+
+
////////////////// Helper functions //////////////////////
static const size_t OUT_OF_RANGE = (size_t)1 << (sizeof(size_t)*8 - 2);
}
}
+}
-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);
ihist.convertTo(hist, CV_32F);
}
-
+namespace cv
+{
+
template<typename T> static void
calcSparseHist_( vector<uchar*>& _ptrs, const vector<int>& _deltas,
Size imsize, SparseMat& hist, int dims, const float** _ranges,
}
}
+}
-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 );
}
/////////////////////////////////////// B A C K P R O J E C T ////////////////////////////////////
+namespace cv
+{
template<typename T, typename BT> static void
calcBackProj_( vector<uchar*>& _ptrs, const vector<int>& _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<uchar*> ptrs;
vector<int> deltas;
vector<double> uniranges;
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;
CV_Error(CV_StsUnsupportedFormat, "");
}
-
+
+namespace cv
+{
+
template<typename T, typename BT> static void
calcSparseBackProj_( vector<uchar*>& _ptrs, const vector<int>& _deltas,
Size imsize, const SparseMat& hist, int dims, const float** _ranges,
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<uchar*> ptrs;
vector<int> deltas;
////////////////// 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 );
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;
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;
}
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;
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);
}
-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();
}
-template<> void Ptr<CvHistogram>::delete_obj()
-{ cvReleaseHist(&obj); }
-
-}
-
-
const int CV_HIST_DEFAULT_TYPE = CV_32F;
/* Creates new histogram */
}
-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 */
const int STORAGE_SIZE = 1 << 12;
-void HoughLines( const Mat& image, vector<Vec2f>& 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<CvMemStorage> 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<Vec2f>(seq).copyTo(lines);
- cvReleaseMemStorage(&storage);
+ seqToMat(seq, _lines);
}
-void HoughLinesP( Mat& image, vector<Vec4i>& 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<CvMemStorage> storage = cvCreateMemStorage(STORAGE_SIZE);
+ CvMat c_image = _image.getMat();
+ CvSeq* seq = cvHoughLines2( &c_image, storage, CV_HOUGH_PROBABILISTIC,
rho, theta, threshold, minLineLength, maxGap );
- Seq<Vec4i>(seq).copyTo(lines);
- cvReleaseMemStorage(&storage);
+ seqToMat(seq, _lines);
}
-void HoughCircles( const Mat& image, vector<Vec3f>& 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<CvMemStorage> storage = cvCreateMemStorage(STORAGE_SIZE);
+ CvMat c_image = _image.getMat();
+ CvSeq* seq = cvHoughCircles( &c_image, storage, method,
dp, min_dist, param1, param2, minRadius, maxRadius );
- Seq<Vec3f>(seq).copyTo(circles);
- cvReleaseMemStorage(&storage);
-}
-
+ seqToMat(seq, _circles);
}
/* End of file. */
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[] =
{
0, resizeArea_<float, float>, resizeArea_<double, double>, 0
};
+ Mat src = _src.getMat();
Size ssize = src.size();
CV_Assert( ssize.area() > 0 );
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;
* General warping (affine, perspective, remap) *
\****************************************************************************************/
+namespace cv
+{
+
template<typename T>
static void remapNearest( const Mat& _src, Mat& _dst, const Mat& _xy,
int borderType, const Scalar& _borderValue )
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[] =
{
remapLanczos4<Cast<float, float>, 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();
}
-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();
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) ||
}
-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;
}
-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;
}
-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;
* 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];
* 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];
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;
CV_Error( CV_StsUnsupportedFormat, "" );
}
-}
-
CV_IMPL void
cvResize( const CvArr* srcarr, CvArr* dstarr, int method )
{
}
}
-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 );
}
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;
}
vector<uchar*> ptrs;
VecOp vecOp;
};
+
+}
/////////////////////////////////// External Interface /////////////////////////////////////
-Ptr<BaseRowFilter> getMorphologyRowFilter(int op, int type, int ksize, int anchor)
+cv::Ptr<cv::BaseRowFilter> cv::getMorphologyRowFilter(int op, int type, int ksize, int anchor)
{
int depth = CV_MAT_DEPTH(type);
if( anchor < 0 )
return Ptr<BaseRowFilter>(0);
}
-Ptr<BaseColumnFilter> getMorphologyColumnFilter(int op, int type, int ksize, int anchor)
+cv::Ptr<cv::BaseColumnFilter> cv::getMorphologyColumnFilter(int op, int type, int ksize, int anchor)
{
int depth = CV_MAT_DEPTH(type);
if( anchor < 0 )
}
-Ptr<BaseFilter> getMorphologyFilter(int op, int type, const Mat& kernel, Point anchor)
+cv::Ptr<cv::BaseFilter> 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 );
}
-Ptr<FilterEngine> createMorphologyFilter( int op, int type, const Mat& kernel,
+cv::Ptr<cv::FilterEngine> 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<BaseRowFilter> rowFilter;
}
-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;
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,
anchor);
iterations = 1;
}
- else
- kernel = _kernel;
Ptr<FilterEngine> f = createMorphologyFilter(op, src.type(),
kernel, anchor, borderType, borderType, borderValue );
for( int i = 1; i < iterations; i++ )
f->apply( dst, dst );
}
+
+template<> void Ptr<IplConvKernel>::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:
}
}
-
-template<> void Ptr<IplConvKernel>::delete_obj()
-{ cvReleaseStructuringElement(&obj); }
-
-
-}
-
CV_IMPL IplConvKernel *
cvCreateStructuringElementEx( int cols, int rows,
int anchorX, int anchorY,
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_<FixPtCast<uchar, 8>, PyrDownVec_32s8u>;
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_<FixPtCast<uchar, 6>, NoVec<int, uchar> >;
else
CV_Error( CV_StsUnsupportedFormat, "" );
- func( _src, _dst );
+ func( src, dst );
}
-void buildPyramid( const Mat& _src, vector<Mat>& _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 )
}
-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. */
}
-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 );
}
}
}
-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 );
}
};
-Ptr<BaseRowFilter> getRowSumFilter(int srcType, int sumType, int ksize, int anchor)
+}
+
+cv::Ptr<cv::BaseRowFilter> 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) );
}
-Ptr<BaseColumnFilter> getColumnSumFilter(int sumType, int dstType, int ksize,
- int anchor, double scale)
+cv::Ptr<cv::BaseColumnFilter> 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) );
}
-Ptr<FilterEngine> createBoxFilter( int srcType, int dstType, Size ksize,
+cv::Ptr<cv::FilterEngine> cv::createBoxFilter( int srcType, int dstType, Size ksize,
Point anchor, bool normalize, int borderType )
{
int sdepth = CV_MAT_DEPTH(srcType);
}
-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 )
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 );
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] =
}
-Ptr<FilterEngine> createGaussianFilter( int type, Size ksize,
+cv::Ptr<cv::FilterEngine> cv::createGaussianFilter( int type, Size ksize,
double sigma1, double sigma2,
int borderType )
{
}
-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 )
Median Filter
\****************************************************************************************/
+namespace cv
+{
+
#if _MSC_VER >= 1200
#pragma warning( disable: 4244 )
#endif
}
}
-
-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);
&& src0.depth() > CV_8U
#endif
);
-
- dst.create( src0.size(), src0.type() );
+
Mat src;
if( useSortNet )
{
Bilateral Filtering
\****************************************************************************************/
+namespace cv
+{
+
static void
bilateralFilter_8u( const Mat& src, Mat& dst, int d,
double sigma_color, double sigma_space,
}
}
+}
-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 )
"Bilateral filtering is only implemented for 8u and 32f images" );
}
-}
-
//////////////////////////////////////////////////////////////////////////////////////////
CV_IMPL void
namespace cv
{
-template<typename QT> inline QT sqr(uchar a) { return a*a; }
-template<typename QT> inline QT sqr(float a) { return a*a; }
-template<typename QT> inline QT sqr(double a) { return a*a; }
-template<> inline double sqr(uchar a) { return CV_8TO32F_SQR(a); }
-
-
template<typename T, typename ST, typename QT>
-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;
{
T it = src[x];
s += it;
- sq += sqr<QT>(it);
+ sq += (QT)it*it;
ST t = sum[x - sumstep] + s;
QT tq = sqsum[x - sqsumstep] + sq;
sum[x] = t;
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<QT>(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<QT>(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 )
ST t1 = buf[x];
buf[x - cn] = t1 + t0;
t0 = it = src[x];
- tq0 = sqr<QT>(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;
}
ST t1 = buf[x];
buf[x - cn] = t1 + t0;
t0 = it = src[x];
- tq0 = sqr<QT>(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_<uchar, int, double>;
+ func = (IntegralFunc)integral_8u32s;
else if( depth == CV_8U && sdepth == CV_32F )
- func = integral_<uchar, float, double>;
+ func = (IntegralFunc)integral_8u32f;
else if( depth == CV_8U && sdepth == CV_64F )
- func = integral_<uchar, double, double>;
+ func = (IntegralFunc)integral_8u64f;
else if( depth == CV_32F && sdepth == CV_32F )
- func = integral_<float, float, double>;
+ func = (IntegralFunc)integral_32f;
else if( depth == CV_32F && sdepth == CV_64F )
- func = integral_<float, double, double>;
+ func = (IntegralFunc)integral_32f64f;
else if( depth == CV_64F && sdepth == CV_64F )
- func = integral_<double, double, double>;
+ 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 );
}
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 );
}
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 );
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;
}
}
-}
-
CV_IMPL void
cvMatchTemplate( const CvArr* _img, const CvArr* _templ, CvArr* _result, int method )
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;
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, "" );
}
-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" );
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;
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 )
{
#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;
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_<double> R = Mat_<double>::eye(3, 3), distCoeffs;
- Mat_<double> A = Mat_<double>(_cameraMatrix), Ar;
+ Mat_<double> R = Mat_<double>::eye(3, 3);
+ Mat_<double> A = Mat_<double>(cameraMatrix), Ar;
- if( _newCameraMatrix.data )
- Ar = Mat_<double>(_newCameraMatrix);
+ if( newCameraMatrix.data )
+ Ar = Mat_<double>(newCameraMatrix);
else
Ar = getDefaultNewCameraMatrix( A, size, true );
if( matR.data )
R = Mat_<double>(matR);
- if( _distCoeffs.data )
- distCoeffs = Mat_<double>(_distCoeffs);
+ if( distCoeffs.data )
+ distCoeffs = Mat_<double>(distCoeffs);
else
{
- distCoeffs.create(8, 1);
+ distCoeffs.create(8, 1, CV_64F);
distCoeffs = 0.;
}
}
-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_<double> A, distCoeffs, Ar, I = Mat_<double>::eye(3,3);
+ Mat_<double> A, Ar, I = Mat_<double>::eye(3,3);
- _cameraMatrix.convertTo(A, CV_64F);
- if( _distCoeffs.data )
- distCoeffs = Mat_<double>(_distCoeffs);
+ cameraMatrix.convertTo(A, CV_64F);
+ if( distCoeffs.data )
+ distCoeffs = Mat_<double>(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);
}
}
-}
-
CV_IMPL void
cvUndistort2( const CvArr* srcarr, CvArr* dstarr, const CvMat* Aarr, const CvMat* dist_coeffs, const CvMat* newAarr )
}
-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<Point2f>& 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)
{
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);
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 */
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(),
top, left, (int)src.elemSize(), (uchar*)buf );
}
}
-
-}
CV_IMPL void
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.);
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++ )
{
__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;
*/
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
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" );
"The distances from the neighbors (if present) must be floating-point matrix of <num_samples> x <k> 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,
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" );
}
// 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" );
RNG rng;
for( int i = 0; i < 0.5f * pointsCount; i++ )
bestLabels.at<int>( 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" );
return false;
vector<uchar> mask;
- matH = findHomography(Mat(fromPt), Mat(toPt), mask, RANSAC, 10);
+ matH = findHomography(fromPt, toPt, RANSAC, 10, mask);
if( matH.data )
{
const Mat_<double>& H = matH;
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 );
{
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);
//! 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);
};
//! 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);
};
-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.
};
}
{
//! 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<Rect>& 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 );
/*!
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<Point2f>& prevPts, CV_OUT vector<Point2f>& nextPts,
- CV_OUT vector<uchar>& status, CV_OUT vector<float>& 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,
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
{
BackgroundSubtractor::~BackgroundSubtractor() {}
-void BackgroundSubtractor::operator()(const Mat&, Mat&, double)
+void BackgroundSubtractor::operator()(const InputArray&, OutputArray, double)
{
}
}
}
-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 );
//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
// 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% */
#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<CvPBGMMGaussian> rGMM;
- std::vector<uchar> 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<nModes;iModes++)
{
- pos=posPixel+iModes;
- 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 weight = m_aGaussians[pos].weight;
- tWeight += weight;
-
- numerator = red * muR + green * muG + blue * muB;
- denominator = muR * muR + muG * muG + muB * muB;
+
+ CvPBGMMGaussian g=pGMM[iModes];
+
+ numerator = 0.0f;
+ denominator = 0.0f;
+ for (int iD=0;iD<nD;iD++)
+ {
+ numerator += data[iD] * g.mean[iD];
+ denominator += g.mean[iD]* g.mean[iD];
+ }
+
// no division by zero allowed
if (denominator == 0)
{
- break;
+ return 0;
};
float a = numerator / denominator;
// if tau < a < 1 then also check the color distortion
- if ((a <= 1) && (a >= 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_fTb*var*a*a)
+ if ((a <= 1) && (a >= m_fTau))
+ {
+
+ float dist2a=0.0f;
+
+ for (int iD=0;iD<nD;iD++)
+ {
+ float dD= a*g.mean[iD] - data[iD];
+ dist2a += (dD*dD);
+ }
+
+ if (dist2a<m_fTb*g.variance*a*a)
{
return 2;
}
};
+
+ tWeight += g.weight;
if (tWeight > 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;iModes<nModes;iModes++)
+ int iMode=0;
+ CvPBGMMGaussian* pGauss=pGMM;
+ for (;iMode<nModes;iMode++,pGauss++)
{
- pos=posPixel+iModes;
- float weight = m_aGaussians[pos].weight;
+ float weight = pGauss->weight;//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 ((totalWeight<m_fTB)&&(dist<m_fTb*var))
+ //calculate difference and distance
+ float dist2=0.0f;
+#if (CV_BGFG_MOG2_NDMAX==1)
+ float dData=pGauss->mean[0]-data[0];
+ dist2=dData*dData;
+#else
+ float dData[CV_BGFG_MOG2_NDMAX];
+
+ for (int iD=0;iD<nD;iD++)
+ {
+ dData[iD]=pGauss->mean[iD]-data[iD];
+ dist2+=dData[iD]*dData[iD];
+ }
+#endif
+ //background? - m_fTb - usually larger than m_fTg
+ if ((totalWeight<m_fTB)&&(dist2<m_fTb*var))
bBackground=1;
+
//check fit
- if (dist<m_fTg*var)
+ if (dist2<m_fTg*var)
{
/////
- //belongs to the mode
+ //belongs to the mode - bFitsPDF becomes 1
bFitsPDF=1;
- //update distribution
- float k = m_fAlphaT/weight;
- weight=m_fOneMinAlpha*weight+m_fPrune;
+ //update distribution
+
+ //update weight
weight+=m_fAlphaT;
- m_aGaussians[pos].muR = muR - k*(dR);
- m_aGaussians[pos].muG = muG - k*(dG);
- m_aGaussians[pos].muB = muB - k*(dB);
-
- //limit update speed for cov matrice
- //not needed
- //k=k>20*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;iD<nD;iD++)
+ {
+ pGauss->mean[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 (;iMode<nModes;iMode++,pGauss++)
+ {
+ float weight = pGauss->weight;//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 ((totalWeight<m_fTB)&&(dist2<m_fTb*var))
+ bBackground=1;
+
+ //check fit
+ if (dist2<m_fTg*var)
+ {
+ /////
+ //belongs to the mode - bFitsPDF becomes 1
+ bFitsPDF=1;
+
+ //update distribution
+
+ //update weight
+ weight+=m_fAlphaT;
+
+ float k = m_fAlphaT/weight;
+
+ //update mean
+ pGauss->mean[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
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;
+ }
}
}
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;iD<nD;iD++) data[iD]=float(sptr[iD]);
+ //update GMM model
+ int result = _icvUpdateGMM(data,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_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
+ for (int iD=0;iD<nD;iD++) data[iD]=float(sptr[iD]);
+ //update GMM model
+ int result = _icvUpdateGMM(data,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_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
+ for (int iD=0;iD<nD;iD++) data[iD]=float(sptr[iD]);
+ //update GMM model
+ int result = _icvUpdateGMM(data,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_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
+ for (int iD=0;iD<nD;iD++) data[iD]=float(sptr[iD]);
+ //update GMM model
+ int result = _icvUpdateGMM(data,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_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(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;iD<nD;iD++) data[iD]=float(sptr[iD]);
+ //update GMM model
+ int result = _icvUpdateGMM(data,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;
+ }
+ }else ///if (nD==3) - a bit faster
+ {
+ 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
+ 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;i<size;i++)
+ CV_FUNCNAME( "icvReleaseGaussianBGModel2" );
+
+ __BEGIN__;
+
+ if( !_bg_model )
+ CV_ERROR( CV_StsNullPtr, "" );
+
+ if( *_bg_model )
+ {
+ CvGaussBGModel2* bg_model = *_bg_model;
+
+ free (bg_model->data.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<vector<Point> > 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<Vec4i>(), 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));
}
}
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. */
#include <float.h>
#include <stdio.h>
-namespace cv
-{
-
-void calcOpticalFlowPyrLK( const Mat& prevImg, const Mat& nextImg,
- const vector<Point2f>& prevPts,
- vector<Point2f>& nextPts,
- vector<uchar>& status, vector<float>& 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;
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<Mat> prevPyr, nextPyr;
int cn = prevImg.channels();
}
}
-}
-
static void
intersect( CvPoint2D32f pt, CvSize win_size, CvSize imgSize,
CvPoint* min_pt, CvPoint* max_pt )
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. */
}
-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<Rect>& 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<CvMemStorage> storage = cvCreateMemStorage();
Seq<CvConnectedComp> comps = cvSegmentMotion(&c_mhi, &c_segmask, storage, timestamp, segThresh);
Seq<CvConnectedComp>::const_iterator it(comps);
}
}
+}
-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++ )
{
}
}
-}
CV_IMPL void cvCalcOpticalFlowFarneback(
const CvArr* _prev, const CvArr* _next,
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 );
}
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 );
}
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 );
}