added hconcat & vconcat functions for joining matrices; moved some inline functions out of the headers; fixed several bugs in documentation; removed MatND from docs

This commit is contained in:
Vadim Pisarevsky 2010-11-23 16:39:20 +00:00
parent dd3c62a4fe
commit f5e5b677c9
10 changed files with 162 additions and 56 deletions

View File

@ -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. Locates a template within an image by using a histogram comparison.
\cvdefC{ \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} \cvdefPy{CalcBackProjectPatch(images,dst,patch\_size,hist,method,factor)-> None}
@ -573,11 +573,10 @@ using namespace cv;
int main( int argc, char** argv ) int main( int argc, char** argv )
{ {
Mat src; Mat src, hsv;
if( argc != 2 || !(src=imread(argv[1], 1)).data ) if( argc != 2 || !(src=imread(argv[1], 1)).data )
return -1; return -1;
Mat hsv;
cvtColor(src, hsv, CV_BGR2HSV); cvtColor(src, hsv, CV_BGR2HSV);
// let's quantize the hue to 30 levels // let's quantize the hue to 30 levels
@ -593,26 +592,26 @@ int main( int argc, char** argv )
MatND hist; MatND hist;
// we compute the histogram from the 0-th and 1-st channels // we compute the histogram from the 0-th and 1-st channels
int channels[] = {0, 1}; int channels[] = {0, 1};
calcHist( &hsv, 1, channels, Mat(), // do not use mask calcHist( &hsv, 1, channels, Mat(), // do not use mask
hist, 2, histSize, ranges, hist, 2, histSize, ranges,
true, // the histogram is uniform true, // the histogram is uniform
false ); false );
double maxVal=0; double maxVal=0;
minMaxLoc(hist, 0, &maxVal, 0, 0); minMaxLoc(hist, 0, &maxVal, 0, 0);
int scale = 10; 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 h = 0; h < hbins; h++ )
for( int s = 0; s < sbins; s++ ) for( int s = 0; s < sbins; s++ )
{ {
float binVal = hist.at<float>(h, s); float binVal = hist.at<float>(h, s);
int intensity = cvRound(binVal*255/maxValue); int intensity = cvRound(binVal*255/maxVal);
cvRectangle( histImg, Point(h*scale, s*scale), rectangle( histImg, Point(h*scale, s*scale),
Point( (h+1)*scale - 1, (s+1)*scale - 1), Point( (h+1)*scale - 1, (s+1)*scale - 1),
Scalar::all(intensity), Scalar::all(intensity),
CV_FILLED ); CV_FILLED );
} }
namedWindow( "Source", 1 ); namedWindow( "Source", 1 );
@ -620,7 +619,6 @@ int main( int argc, char** argv )
namedWindow( "H-S Histogram", 1 ); namedWindow( "H-S Histogram", 1 );
imshow( "H-S Histogram", histImg ); imshow( "H-S Histogram", histImg );
waitKey(); waitKey();
} }
\end{lstlisting} \end{lstlisting}

View File

@ -554,8 +554,8 @@ The function estimates the subsequent stochastic model state by its current stat
\[ \[
\begin{array}{l} \begin{array}{l}
x'_k=A \cdot x_{k-1}+B \cdot u_k\\ x'_k=A x_{k-1} + B u_k\\
P'_k=A \cdot P_{k-1}+A^T + Q P'_k=A P_{k-1} A^T + Q
\end{array} \end{array}
\] \]

View File

@ -1632,7 +1632,7 @@ public:
template<typename _Tp> void push_back(const Mat_<_Tp>& elem); template<typename _Tp> void push_back(const Mat_<_Tp>& elem);
void push_back(const Mat& m); void push_back(const Mat& m);
//! removes several hyper-planes from bottom of the matrix //! 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 //! locates matrix header within a parent matrix. See below
void locateROI( Size& wholeSize, Point& ofs ) const; void locateROI( Size& wholeSize, Point& ofs ) const;
@ -1756,7 +1756,7 @@ public:
- number of channels - number of channels
*/ */
int flags; int flags;
//! the matrix dimensionality //! the matrix dimensionality, >= 2
int dims; int dims;
//! the number of rows and columns or (-1, -1) when the matrix has more than 2 dimensions //! the number of rows and columns or (-1, -1) when the matrix has more than 2 dimensions
int rows, cols; 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); 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 //! 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, CV_OUT Mat& dst);
//! makes multi-channel array out of several single-channel arrays
CV_EXPORTS_W void merge(const vector<Mat>& mv, Mat& dst);
//! copies each plane of a multi-channel array to a dedicated array //! copies each plane of a multi-channel array to a dedicated array
CV_EXPORTS void split(const Mat& src, Mat* mvbegin); CV_EXPORTS void split(const Mat& src, Mat* mvbegin);
//! copies each plane of a multi-channel array to a dedicated array
CV_WRAP static inline void merge(const vector<Mat>& mv, Mat& dst) CV_EXPORTS_W void split(const Mat& m, vector<Mat>& mv);
{ merge(&mv[0], mv.size(), dst); }
CV_WRAP static inline void split(const Mat& m, vector<Mat>& mv)
{
mv.resize(m.channels());
if(m.channels() > 0)
split(m, &mv[0]);
}
//! copies selected channels from the input arrays to the selected channels of the output arrays //! 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, CV_EXPORTS void mixChannels(const Mat* src, size_t nsrcs, Mat* dst, size_t ndsts,
const int* fromTo, size_t npairs); const int* fromTo, size_t npairs);
CV_EXPORTS void mixChannels(const vector<Mat>& src, vector<Mat>& dst,
static inline void mixChannels(const vector<Mat>& src, vector<Mat>& dst, const int* fromTo, int npairs);
const int* fromTo, int npairs)
{
mixChannels(&src[0], (int)src.size(), &dst[0], (int)dst.size(), fromTo, npairs);
}
//! reverses the order of the rows, columns or both in a matrix //! 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 Mat& src, CV_OUT Mat& dst, int flipCode);
//! replicates the input matrix the specified number of times in the horizontal and/or vertical direction //! 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 Mat& src, int ny, int nx, CV_OUT Mat& dst);
static inline Mat repeat(const Mat& src, int ny, int nx) CV_EXPORTS Mat repeat(const Mat& src, int ny, int nx);
{
if( nx == 1 && ny == 1 ) return src; CV_EXPORTS void hconcat(const Mat* src, size_t nsrc, Mat& dst);
Mat dst; repeat(src, ny, nx, dst); return 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 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);
//! computes bitwise conjunction of the two arrays (dst = src1 & src2) //! 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 Mat& src1, const Mat& src2, CV_OUT Mat& dst, const Mat& mask=Mat());
//! computes bitwise disjunction of the two arrays (dst = src1 | src2) //! 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 //! 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 Mat& v1, const Mat& v2, const Mat& icovar);
//! a synonym for Mahalanobis //! a synonym for Mahalanobis
static inline double Mahalonobis(const Mat& v1, const Mat& v2, const Mat& icovar) CV_EXPORTS double Mahalonobis(const Mat& v1, const Mat& v2, const Mat& icovar);
{ return Mahalanobis(v1, v2, icovar); }
//! performs forward or inverse 1D or 2D Discrete Fourier Transformation //! 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 Mat& src, CV_OUT Mat& dst, int flags=0, int nonzeroRows=0);
@ -2266,12 +2259,10 @@ CV_EXPORTS RNG& theRNG();
template<typename _Tp> static inline _Tp randu() { return (_Tp)theRNG(); } template<typename _Tp> static inline _Tp randu() { return (_Tp)theRNG(); }
//! fills array with uniformly-distributed random numbers from the range [low, high) //! 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) CV_EXPORTS_W void randu(CV_OUT Mat& dst, const Scalar& low, const Scalar& high);
{ theRNG().fill(dst, RNG::UNIFORM, low, high); }
//! fills array with normally-distributed random numbers with the specified mean and the standard deviation //! 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) CV_EXPORTS_W void randn(CV_OUT Mat& dst, const Scalar& mean, const Scalar& stddev);
{ theRNG().fill(dst, RNG::NORMAL, mean, stddev); }
//! shuffles the input array elements //! shuffles the input array elements
CV_EXPORTS void randShuffle(Mat& dst, double iterFactor=1., RNG* rng=0); CV_EXPORTS void randShuffle(Mat& dst, double iterFactor=1., RNG* rng=0);
@ -2866,7 +2857,7 @@ protected:
/*! /*!
n-Dimensional Dense Matrix Iterator Class. 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. 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. It iterates through the slices (or planes), not the elements, where "slice" is a continuous part of the arrays.

View File

@ -162,6 +162,13 @@ void split(const Mat& src, Mat* mv)
mixChannels( &src, 1, mv, cn, &pairs[0], cn ); mixChannels( &src, 1, mv, cn, &pairs[0], cn );
} }
} }
void split(const Mat& m, vector<Mat>& mv)
{
mv.resize(!m.empty() ? m.channels() : 0);
if(!m.empty())
split(m, &mv[0]);
}
/****************************************************************************************\ /****************************************************************************************\
* merge * * merge *
@ -298,7 +305,10 @@ void merge(const Mat* mv, size_t _n, Mat& dst)
} }
} }
void merge(const vector<Mat>& mv, Mat& dst)
{
merge(!mv.empty() ? &mv[0] : 0, mv.size(), dst);
}
/****************************************************************************************\ /****************************************************************************************\
* Generalized split/merge: mixing channels * * 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<Mat>& src, vector<Mat>& 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] * * convertScale[Abs] *
\****************************************************************************************/ \****************************************************************************************/

View File

@ -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 ); 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 */ /* dst = src */

View File

@ -2299,7 +2299,11 @@ double Mahalanobis( const Mat& v1, const Mat& v2, const Mat& icovar )
return std::sqrt(result); return std::sqrt(result);
} }
double Mahalonobis(const Mat& v1, const Mat& v2, const Mat& icovar)
{
return Mahalanobis(v1, v2, icovar);
}
/****************************************************************************************\ /****************************************************************************************\
* cvMulTransposed * * cvMulTransposed *
\****************************************************************************************/ \****************************************************************************************/

View File

@ -845,6 +845,80 @@ void scalarToRawData(const Scalar& s, void* _buf, int type, int unroll_to)
Matrix Operations 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<Mat>& 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<Mat>& src, CV_OUT Mat& dst)
{
vconcat(!src.empty() ? &src[0] : 0, src.size(), dst);
}
//////////////////////////////////////// set identity //////////////////////////////////////////// //////////////////////////////////////// set identity ////////////////////////////////////////////
void setIdentity( Mat& m, const Scalar& s ) void setIdentity( Mat& m, const Scalar& s )
{ {

View File

@ -657,6 +657,16 @@ RNG& theRNG()
#endif #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<typename T> static void template<typename T> static void
randShuffle_( Mat& _arr, RNG& rng, double iterFactor ) randShuffle_( Mat& _arr, RNG& rng, double iterFactor )
{ {

View File

@ -396,12 +396,9 @@ CV_EXPORTS_W void boxFilter( const Mat& src, CV_OUT Mat& dst, int ddepth,
bool normalize=true, bool normalize=true,
int borderType=BORDER_DEFAULT ); int borderType=BORDER_DEFAULT );
//! a synonym for normalized box filter //! a synonym for normalized box filter
CV_WRAP static inline void blur( const Mat& src, CV_OUT Mat& dst, CV_EXPORTS_W void blur( const Mat& src, CV_OUT Mat& dst,
Size ksize, Point anchor=Point(-1,-1), Size ksize, Point anchor=Point(-1,-1),
int borderType=BORDER_DEFAULT ) int borderType=BORDER_DEFAULT );
{
boxFilter( src, dst, -1, ksize, anchor, true, borderType );
}
//! applies non-separable 2D linear filter to the image //! applies non-separable 2D linear filter to the image
CV_EXPORTS_W void filter2D( const Mat& src, CV_OUT Mat& dst, int ddepth, CV_EXPORTS_W void filter2D( const Mat& src, CV_OUT Mat& dst, int ddepth,

View File

@ -312,6 +312,12 @@ void boxFilter( const Mat& src, Mat& dst, int ddepth,
f->apply( src, dst ); 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 Gaussian Blur
\****************************************************************************************/ \****************************************************************************************/