From f5e5b677c9c40e98d318b8658bc68228fde8d04b Mon Sep 17 00:00:00 2001 From: Vadim Pisarevsky Date: Tue, 23 Nov 2010 16:39:20 +0000 Subject: [PATCH] added hconcat & vconcat functions for joining matrices; moved some inline functions out of the headers; fixed several bugs in documentation; removed MatND from docs --- doc/imgproc_histograms.tex | 28 ++++---- doc/video_motion_tracking.tex | 4 +- modules/core/include/opencv2/core/core.hpp | 53 +++++++--------- modules/core/src/convert.cpp | 19 +++++- modules/core/src/copy.cpp | 9 +++ modules/core/src/matmul.cpp | 6 +- modules/core/src/matrix.cpp | 74 ++++++++++++++++++++++ modules/core/src/rand.cpp | 10 +++ .../imgproc/include/opencv2/imgproc/imgproc.hpp | 9 +-- modules/imgproc/src/smooth.cpp | 6 ++ 10 files changed, 162 insertions(+), 56 deletions(-) diff --git a/doc/imgproc_histograms.tex b/doc/imgproc_histograms.tex index 2390d92..672607b 100644 --- a/doc/imgproc_histograms.tex +++ b/doc/imgproc_histograms.tex @@ -56,7 +56,7 @@ That is the approximate algorithm of Camshift color object tracker, except for t Locates a template within an image by using a histogram comparison. \cvdefC{ -void cvCalcBackProjectPatch( \par IplImage** images,\par CvArr* dst,\par CvSize patch\_size,\par CvHistogram* hist,\par int method,\par float factor ); +void cvCalcBackProjectPatch( \par IplImage** images,\par CvArr* dst,\par CvSize patch\_size,\par CvHistogram* hist,\par int method,\par double factor ); } \cvdefPy{CalcBackProjectPatch(images,dst,patch\_size,hist,method,factor)-> None} @@ -573,11 +573,10 @@ using namespace cv; int main( int argc, char** argv ) { - Mat src; + Mat src, hsv; if( argc != 2 || !(src=imread(argv[1], 1)).data ) return -1; - Mat hsv; cvtColor(src, hsv, CV_BGR2HSV); // let's quantize the hue to 30 levels @@ -593,26 +592,26 @@ int main( int argc, char** argv ) MatND hist; // we compute the histogram from the 0-th and 1-st channels int channels[] = {0, 1}; - + calcHist( &hsv, 1, channels, Mat(), // do not use mask - hist, 2, histSize, ranges, - true, // the histogram is uniform - false ); + hist, 2, histSize, ranges, + true, // the histogram is uniform + false ); double maxVal=0; minMaxLoc(hist, 0, &maxVal, 0, 0); - + int scale = 10; - Mat histImg = Mat::zeros(sbins*scale, hbins*10, CV_8UC3); + Mat histImg = Mat::zeros(sbins*scale, hbins*10, CV_8UC3); for( int h = 0; h < hbins; h++ ) for( int s = 0; s < sbins; s++ ) { float binVal = hist.at(h, s); - int intensity = cvRound(binVal*255/maxValue); - cvRectangle( histImg, Point(h*scale, s*scale), - Point( (h+1)*scale - 1, (s+1)*scale - 1), - Scalar::all(intensity), - CV_FILLED ); + int intensity = cvRound(binVal*255/maxVal); + rectangle( histImg, Point(h*scale, s*scale), + Point( (h+1)*scale - 1, (s+1)*scale - 1), + Scalar::all(intensity), + CV_FILLED ); } namedWindow( "Source", 1 ); @@ -620,7 +619,6 @@ int main( int argc, char** argv ) namedWindow( "H-S Histogram", 1 ); imshow( "H-S Histogram", histImg ); - waitKey(); } \end{lstlisting} diff --git a/doc/video_motion_tracking.tex b/doc/video_motion_tracking.tex index bff0df8..5862fe8 100644 --- a/doc/video_motion_tracking.tex +++ b/doc/video_motion_tracking.tex @@ -554,8 +554,8 @@ The function estimates the subsequent stochastic model state by its current stat \[ \begin{array}{l} -x'_k=A \cdot x_{k-1}+B \cdot u_k\\ -P'_k=A \cdot P_{k-1}+A^T + Q +x'_k=A x_{k-1} + B u_k\\ +P'_k=A P_{k-1} A^T + Q \end{array} \] diff --git a/modules/core/include/opencv2/core/core.hpp b/modules/core/include/opencv2/core/core.hpp index dcdd22c..3f39723 100644 --- a/modules/core/include/opencv2/core/core.hpp +++ b/modules/core/include/opencv2/core/core.hpp @@ -1632,7 +1632,7 @@ public: template void push_back(const Mat_<_Tp>& elem); void push_back(const Mat& m); //! removes several hyper-planes from bottom of the matrix - void pop_back(size_t nelems); + void pop_back(size_t nelems=1); //! locates matrix header within a parent matrix. See below void locateROI( Size& wholeSize, Point& ofs ) const; @@ -1756,7 +1756,7 @@ public: - number of channels */ int flags; - //! the matrix dimensionality + //! the matrix dimensionality, >= 2 int dims; //! the number of rows and columns or (-1, -1) when the matrix has more than 2 dimensions int rows, cols; @@ -1955,41 +1955,35 @@ CV_EXPORTS void minMaxIdx(const Mat& src, double* minVal, double* maxVal, CV_EXPORTS_W void reduce(const Mat& src, CV_OUT Mat& 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); +//! makes multi-channel array out of several single-channel arrays +CV_EXPORTS_W void merge(const vector& mv, Mat& dst); + //! copies each plane of a multi-channel array to a dedicated array CV_EXPORTS void split(const Mat& src, Mat* mvbegin); - -CV_WRAP static inline void merge(const vector& mv, Mat& dst) -{ merge(&mv[0], mv.size(), dst); } - -CV_WRAP static inline void split(const Mat& m, vector& mv) -{ - mv.resize(m.channels()); - if(m.channels() > 0) - split(m, &mv[0]); -} +//! copies each plane of a multi-channel array to a dedicated array +CV_EXPORTS_W void split(const Mat& m, vector& mv); //! copies selected channels from the input arrays to the selected channels of the output arrays CV_EXPORTS void mixChannels(const Mat* src, size_t nsrcs, Mat* dst, size_t ndsts, const int* fromTo, size_t npairs); - -static inline void mixChannels(const vector& src, vector& dst, - const int* fromTo, int npairs) -{ - mixChannels(&src[0], (int)src.size(), &dst[0], (int)dst.size(), fromTo, npairs); -} - +CV_EXPORTS void mixChannels(const vector& src, vector& dst, + const int* fromTo, int 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); //! 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); -static inline Mat repeat(const Mat& src, int ny, int nx) -{ - if( nx == 1 && ny == 1 ) return src; - Mat dst; repeat(src, ny, nx, dst); return dst; -} +CV_EXPORTS Mat repeat(const Mat& src, int ny, int nx); + +CV_EXPORTS void hconcat(const Mat* src, size_t nsrc, Mat& dst); +CV_EXPORTS void hconcat(const Mat& src1, const Mat& src2, Mat& dst); +CV_EXPORTS_W void hconcat(const vector& src, CV_OUT Mat& dst); +CV_EXPORTS void vconcat(const Mat* src, size_t nsrc, Mat& dst); +CV_EXPORTS void vconcat(const Mat& src1, const Mat& src2, Mat& dst); +CV_EXPORTS_W void vconcat(const vector& src, CV_OUT Mat& dst); + //! 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()); //! computes bitwise disjunction of the two arrays (dst = src1 | src2) @@ -2228,8 +2222,7 @@ public: //! 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); //! a synonym for Mahalanobis -static inline double Mahalonobis(const Mat& v1, const Mat& v2, const Mat& icovar) -{ return Mahalanobis(v1, v2, icovar); } +CV_EXPORTS double Mahalonobis(const Mat& v1, const Mat& v2, const Mat& 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); @@ -2266,12 +2259,10 @@ CV_EXPORTS RNG& theRNG(); template static inline _Tp randu() { return (_Tp)theRNG(); } //! fills array with uniformly-distributed random numbers from the range [low, high) -CV_WRAP static inline void randu(CV_OUT Mat& dst, const Scalar& low, const Scalar& high) -{ theRNG().fill(dst, RNG::UNIFORM, low, high); } +CV_EXPORTS_W void randu(CV_OUT Mat& dst, const Scalar& low, const Scalar& high); //! fills array with normally-distributed random numbers with the specified mean and the standard deviation -CV_WRAP static inline void randn(CV_OUT Mat& dst, const Scalar& mean, const Scalar& stddev) -{ theRNG().fill(dst, RNG::NORMAL, mean, stddev); } +CV_EXPORTS_W void randn(CV_OUT Mat& dst, const Scalar& mean, const Scalar& stddev); //! shuffles the input array elements CV_EXPORTS void randShuffle(Mat& dst, double iterFactor=1., RNG* rng=0); @@ -2866,7 +2857,7 @@ protected: /*! n-Dimensional Dense Matrix Iterator Class. - The class cv::NAryMatNDIterator is used for iterating over one or more n-dimensional dense arrays (cv::Mat's). + The class cv::NAryMatIterator is used for iterating over one or more n-dimensional dense arrays (cv::Mat's). The iterator is completely different from cv::Mat_ and cv::SparseMat_ iterators. It iterates through the slices (or planes), not the elements, where "slice" is a continuous part of the arrays. diff --git a/modules/core/src/convert.cpp b/modules/core/src/convert.cpp index 8ef1211..5d4d70e 100644 --- a/modules/core/src/convert.cpp +++ b/modules/core/src/convert.cpp @@ -162,6 +162,13 @@ void split(const Mat& src, Mat* mv) mixChannels( &src, 1, mv, cn, &pairs[0], cn ); } } + +void split(const Mat& m, vector& mv) +{ + mv.resize(!m.empty() ? m.channels() : 0); + if(!m.empty()) + split(m, &mv[0]); +} /****************************************************************************************\ * merge * @@ -298,7 +305,10 @@ void merge(const Mat* mv, size_t _n, Mat& dst) } } - +void merge(const vector& mv, Mat& dst) +{ + merge(!mv.empty() ? &mv[0] : 0, mv.size(), dst); +} /****************************************************************************************\ * Generalized split/merge: mixing channels * @@ -437,6 +447,13 @@ void mixChannels( const Mat* src, size_t nsrcs, Mat* dst, size_t ndsts, const in } +void mixChannels(const vector& src, vector& dst, + const int* fromTo, int npairs) +{ + mixChannels(!src.empty() ? &src[0] : 0, src.size(), + !dst.empty() ? &dst[0] : 0, dst.size(), fromTo, npairs); +} + /****************************************************************************************\ * convertScale[Abs] * \****************************************************************************************/ diff --git a/modules/core/src/copy.cpp b/modules/core/src/copy.cpp index 45eec75..e3e5672 100644 --- a/modules/core/src/copy.cpp +++ b/modules/core/src/copy.cpp @@ -480,6 +480,15 @@ void repeat(const Mat& src, int ny, int nx, Mat& dst) memcpy( dst.data + y*dst.step, dst.data + (y - ssize.height)*dst.step, dsize.width ); } +Mat repeat(const Mat& src, int ny, int nx) +{ + if( nx == 1 && ny == 1 ) + return src; + Mat dst; + repeat(src, ny, nx, dst); + return dst; +} + } /* dst = src */ diff --git a/modules/core/src/matmul.cpp b/modules/core/src/matmul.cpp index eb264e1..29b6781 100644 --- a/modules/core/src/matmul.cpp +++ b/modules/core/src/matmul.cpp @@ -2299,7 +2299,11 @@ double Mahalanobis( const Mat& v1, const Mat& v2, const Mat& icovar ) return std::sqrt(result); } - +double Mahalonobis(const Mat& v1, const Mat& v2, const Mat& icovar) +{ + return Mahalanobis(v1, v2, icovar); +} + /****************************************************************************************\ * cvMulTransposed * \****************************************************************************************/ diff --git a/modules/core/src/matrix.cpp b/modules/core/src/matrix.cpp index 17b328d..df7e340 100644 --- a/modules/core/src/matrix.cpp +++ b/modules/core/src/matrix.cpp @@ -845,6 +845,80 @@ void scalarToRawData(const Scalar& s, void* _buf, int type, int unroll_to) Matrix Operations \*************************************************************************************************/ +void hconcat(const Mat* src, size_t nsrc, Mat& dst) +{ + if( nsrc == 0 || !src ) + { + dst.release(); + return; + } + + int totalCols = 0, cols = 0; + size_t i; + for( i = 0; i < nsrc; i++ ) + { + CV_Assert( !src[i].empty() && src[i].dims <= 2 && + src[i].rows == src[0].rows && + src[i].type() == src[0].type()); + totalCols += src[i].cols; + } + dst.create( src[0].rows, totalCols, src[0].type()); + for( i = 0; i < nsrc; i++ ) + { + 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) +{ + Mat src[] = {src1, src2}; + hconcat(src, 2, dst); +} + +void hconcat(const vector& src, CV_OUT Mat& dst) +{ + hconcat(!src.empty() ? &src[0] : 0, src.size(), dst); +} + +void vconcat(const Mat* src, size_t nsrc, Mat& dst) +{ + if( nsrc == 0 || !src ) + { + dst.release(); + return; + } + + int totalRows = 0, rows = 0; + size_t i; + for( i = 0; i < nsrc; i++ ) + { + CV_Assert( !src[i].empty() && src[i].dims <= 2 && + src[i].cols == src[0].cols && + src[i].type() == src[0].type()); + totalRows += src[i].rows; + } + dst.create( totalRows, src[0].cols, src[0].type()); + for( i = 0; i < nsrc; i++ ) + { + Mat dpart(dst, Rect(0, rows, src[i].cols, src[i].rows)); + src[i].copyTo(dpart); + rows += src[i].rows; + } +} + +void vconcat(const Mat& src1, const Mat& src2, Mat& dst) +{ + Mat src[] = {src1, src2}; + vconcat(src, 2, dst); +} + +void vconcat(const vector& src, CV_OUT Mat& dst) +{ + vconcat(!src.empty() ? &src[0] : 0, src.size(), dst); +} + //////////////////////////////////////// set identity //////////////////////////////////////////// void setIdentity( Mat& m, const Scalar& s ) { diff --git a/modules/core/src/rand.cpp b/modules/core/src/rand.cpp index 7feaf11..5a17d05 100644 --- a/modules/core/src/rand.cpp +++ b/modules/core/src/rand.cpp @@ -657,6 +657,16 @@ RNG& theRNG() #endif +void randu(CV_OUT Mat& dst, const Scalar& low, const Scalar& high) +{ + theRNG().fill(dst, RNG::UNIFORM, low, high); +} + +void randn(CV_OUT Mat& dst, const Scalar& mean, const Scalar& stddev) +{ + theRNG().fill(dst, RNG::NORMAL, mean, stddev); +} + template static void randShuffle_( Mat& _arr, RNG& rng, double iterFactor ) { diff --git a/modules/imgproc/include/opencv2/imgproc/imgproc.hpp b/modules/imgproc/include/opencv2/imgproc/imgproc.hpp index f8d10f2..180ba9a 100644 --- a/modules/imgproc/include/opencv2/imgproc/imgproc.hpp +++ b/modules/imgproc/include/opencv2/imgproc/imgproc.hpp @@ -396,12 +396,9 @@ CV_EXPORTS_W void boxFilter( const Mat& src, CV_OUT Mat& dst, int ddepth, bool normalize=true, int borderType=BORDER_DEFAULT ); //! a synonym for normalized box filter -CV_WRAP static inline void blur( const Mat& src, CV_OUT Mat& dst, - Size ksize, Point anchor=Point(-1,-1), - int borderType=BORDER_DEFAULT ) -{ - boxFilter( src, dst, -1, ksize, anchor, true, borderType ); -} +CV_EXPORTS_W void blur( const Mat& src, CV_OUT Mat& 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, diff --git a/modules/imgproc/src/smooth.cpp b/modules/imgproc/src/smooth.cpp index 7839f49..273ccc5 100644 --- a/modules/imgproc/src/smooth.cpp +++ b/modules/imgproc/src/smooth.cpp @@ -312,6 +312,12 @@ void boxFilter( const Mat& src, Mat& dst, int ddepth, f->apply( src, dst ); } +void blur( const Mat& src, CV_OUT Mat& dst, + Size ksize, Point anchor, int borderType ) +{ + boxFilter( src, dst, -1, ksize, anchor, true, borderType ); +} + /****************************************************************************************\ Gaussian Blur \****************************************************************************************/ -- 2.7.4