added hconcat & vconcat functions for joining matrices; moved some inline functions...
authorVadim Pisarevsky <no@email>
Tue, 23 Nov 2010 16:39:20 +0000 (16:39 +0000)
committerVadim Pisarevsky <no@email>
Tue, 23 Nov 2010 16:39:20 +0000 (16:39 +0000)
doc/imgproc_histograms.tex
doc/video_motion_tracking.tex
modules/core/include/opencv2/core/core.hpp
modules/core/src/convert.cpp
modules/core/src/copy.cpp
modules/core/src/matmul.cpp
modules/core/src/matrix.cpp
modules/core/src/rand.cpp
modules/imgproc/include/opencv2/imgproc/imgproc.hpp
modules/imgproc/src/smooth.cpp

index 2390d92..672607b 100644 (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.
 
 \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<float>(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}
index bff0df8..5862fe8 100644 (file)
@@ -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}
 \]
 
index dcdd22c..3f39723 100644 (file)
@@ -1632,7 +1632,7 @@ public:
     template<typename _Tp> 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<Mat>& 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<Mat>& mv, Mat& dst)
-{ 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 each plane of a multi-channel array to a dedicated array
+CV_EXPORTS_W void split(const Mat& m, vector<Mat>& 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<Mat>& src, vector<Mat>& 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<Mat>& src, vector<Mat>& 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<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)
 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<typename _Tp> 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.
index 8ef1211..5d4d70e 100644 (file)
@@ -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<Mat>& 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<Mat>& 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<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]                                       *
 \****************************************************************************************/
index 45eec75..e3e5672 100644 (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 );
 }
 
+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 */
index eb264e1..29b6781 100644 (file)
@@ -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                                 *
 \****************************************************************************************/
index 17b328d..df7e340 100644 (file)
@@ -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<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 ////////////////////////////////////////////
 void setIdentity( Mat& m, const Scalar& s )
 {
index 7feaf11..5a17d05 100644 (file)
@@ -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<typename T> static void
 randShuffle_( Mat& _arr, RNG& rng, double iterFactor )
 {
index f8d10f2..180ba9a 100644 (file)
@@ -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,
index 7839f49..273ccc5 100644 (file)
@@ -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
 \****************************************************************************************/