From c9f51d5eed07dbfe803c12a6b97f86bf662f2b21 Mon Sep 17 00:00:00 2001 From: Firat Kalaycilar Date: Fri, 21 Mar 2014 09:44:11 +0200 Subject: [PATCH 01/14] modified BackgroundSubtractorMOG2::getBackgroundImage so that it can now work with gray-level images. --- modules/video/src/bgfg_gaussmix2.cpp | 53 +++++++++++++--------------- 1 file changed, 24 insertions(+), 29 deletions(-) diff --git a/modules/video/src/bgfg_gaussmix2.cpp b/modules/video/src/bgfg_gaussmix2.cpp index b14bc8e1e2..ddc8e64bdd 100644 --- a/modules/video/src/bgfg_gaussmix2.cpp +++ b/modules/video/src/bgfg_gaussmix2.cpp @@ -577,54 +577,49 @@ void BackgroundSubtractorMOG2::operator()(InputArray _image, OutputArray _fgmask void BackgroundSubtractorMOG2::getBackgroundImage(OutputArray backgroundImage) const { int nchannels = CV_MAT_CN(frameType); - CV_Assert( nchannels == 3 ); - Mat meanBackground(frameSize, CV_8UC3, Scalar::all(0)); - + CV_Assert(nchannels == 1 || nchannels == 3); + Mat meanBackground(frameSize, CV_MAKETYPE(CV_8U, nchannels), Scalar::all(0)); int firstGaussianIdx = 0; const GMM* gmm = (GMM*)bgmodel.data; - const Vec3f* mean = reinterpret_cast(gmm + frameSize.width*frameSize.height*nmixtures); + const float* mean = reinterpret_cast(gmm + frameSize.width*frameSize.height*nmixtures); for(int row=0; row(row, col); - Vec3f meanVal; + std::vector meanVal(nchannels, 0.f); float totalWeight = 0.f; for(int gaussianIdx = firstGaussianIdx; gaussianIdx < firstGaussianIdx + nmodes; gaussianIdx++) { GMM gaussian = gmm[gaussianIdx]; - meanVal += gaussian.weight * mean[gaussianIdx]; + size_t meanPosition = gaussianIdx*nchannels; + for(int chn = 0; chn < nchannels; chn++) + { + meanVal[chn] += gaussian.weight * mean[meanPosition + chn]; + } totalWeight += gaussian.weight; if(totalWeight > backgroundRatio) break; } - - meanVal *= (1.f / totalWeight); - meanBackground.at(row, col) = Vec3b(meanVal); + float invWeight = 1.f/totalWeight; + for(int chn = 0; chn < nchannels; chn++) + { + meanVal[chn] *= invWeight; + } + switch(nchannels) + { + case 1: + meanBackground.at(row, col) = (uchar)meanVal[0]; + break; + case 3: + meanBackground.at(row, col) = Vec3b(*reinterpret_cast(&meanVal[0])); + break; + } firstGaussianIdx += nmixtures; } } - - switch(CV_MAT_CN(frameType)) - { - case 1: - { - vector channels; - split(meanBackground, channels); - channels[0].copyTo(backgroundImage); - break; - } - - case 3: - { - meanBackground.copyTo(backgroundImage); - break; - } - - default: - CV_Error(CV_StsUnsupportedFormat, ""); - } + meanBackground.copyTo(backgroundImage); } } From 990295644e4260656787172f959a676bdc0a1066 Mon Sep 17 00:00:00 2001 From: Firat Kalaycilar Date: Tue, 8 Apr 2014 16:10:32 +0300 Subject: [PATCH 02/14] made a performance improvement. changed the way the mean value for each pixel is assigned in the output image. --- modules/video/src/bgfg_gaussmix2.cpp | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/modules/video/src/bgfg_gaussmix2.cpp b/modules/video/src/bgfg_gaussmix2.cpp index ddc8e64bdd..9700dfebd8 100644 --- a/modules/video/src/bgfg_gaussmix2.cpp +++ b/modules/video/src/bgfg_gaussmix2.cpp @@ -582,12 +582,12 @@ void BackgroundSubtractorMOG2::getBackgroundImage(OutputArray backgroundImage) c int firstGaussianIdx = 0; const GMM* gmm = (GMM*)bgmodel.data; const float* mean = reinterpret_cast(gmm + frameSize.width*frameSize.height*nmixtures); + std::vector meanVal(nchannels, 0.f); for(int row=0; row(row, col); - std::vector meanVal(nchannels, 0.f); float totalWeight = 0.f; for(int gaussianIdx = firstGaussianIdx; gaussianIdx < firstGaussianIdx + nmodes; gaussianIdx++) { @@ -603,17 +603,16 @@ void BackgroundSubtractorMOG2::getBackgroundImage(OutputArray backgroundImage) c break; } float invWeight = 1.f/totalWeight; - for(int chn = 0; chn < nchannels; chn++) - { - meanVal[chn] *= invWeight; - } switch(nchannels) { case 1: - meanBackground.at(row, col) = (uchar)meanVal[0]; + meanBackground.at(row, col) = (uchar)(meanVal[0] * invWeight); + meanVal[0] = 0.f; break; case 3: - meanBackground.at(row, col) = Vec3b(*reinterpret_cast(&meanVal[0])); + Vec3f& meanVec = *reinterpret_cast(&meanVal[0]); + meanBackground.at(row, col) = Vec3b(meanVec * invWeight); + meanVec = 0.f; break; } firstGaussianIdx += nmixtures; From 5efd2056f027fdab3b767eb5c1297d2d8271cbff Mon Sep 17 00:00:00 2001 From: Thierry Hoinville Date: Tue, 6 May 2014 15:33:07 +0200 Subject: [PATCH 03/14] Bugfix #3668 in FilterEngine::apply(), use the ROI properly --- modules/imgproc/src/filter.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/modules/imgproc/src/filter.cpp b/modules/imgproc/src/filter.cpp index 1d05d3c2c3..a55c1b0c65 100644 --- a/modules/imgproc/src/filter.cpp +++ b/modules/imgproc/src/filter.cpp @@ -453,8 +453,12 @@ void FilterEngine::apply(const Mat& src, Mat& dst, dstOfs.y + srcRoi.height <= dst.rows ); int y = start(src, srcRoi, isolated); - proceed( src.data + y*src.step, (int)src.step, endY - startY, - dst.data + dstOfs.y*dst.step + dstOfs.x*dst.elemSize(), (int)dst.step ); + proceed( src.data + y*src.step + + srcRoi.x*src.elemSize(),/* Bugfix #3668 use the x-shift of ROI + */ + (int)src.step, endY - startY, + dst.data + dstOfs.y*dst.step + + dstOfs.x*dst.elemSize(), (int)dst.step ); } } From e50ef2dab596935f9ed75389ca4acd2f3dbfc77e Mon Sep 17 00:00:00 2001 From: thoinvil Date: Wed, 7 May 2014 18:27:08 +0200 Subject: [PATCH 04/14] Bugfix #3668 removed the comment --- modules/imgproc/src/filter.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/modules/imgproc/src/filter.cpp b/modules/imgproc/src/filter.cpp index a55c1b0c65..6cdcf3cfbb 100644 --- a/modules/imgproc/src/filter.cpp +++ b/modules/imgproc/src/filter.cpp @@ -454,8 +454,7 @@ void FilterEngine::apply(const Mat& src, Mat& dst, int y = start(src, srcRoi, isolated); proceed( src.data + y*src.step - + srcRoi.x*src.elemSize(),/* Bugfix #3668 use the x-shift of ROI - */ + + srcRoi.x*src.elemSize(), (int)src.step, endY - startY, dst.data + dstOfs.y*dst.step + dstOfs.x*dst.elemSize(), (int)dst.step ); From 006956c32435725e31e9aeb6bfe7035113249f73 Mon Sep 17 00:00:00 2001 From: StevenPuttemans Date: Mon, 12 May 2014 15:39:40 +0200 Subject: [PATCH 05/14] Fixing as suggested in bug 2626, made naming same for both C, C++ and python API --- modules/core/doc/operations_on_arrays.rst | 5 +++-- modules/core/include/opencv2/core/core.hpp | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/modules/core/doc/operations_on_arrays.rst b/modules/core/doc/operations_on_arrays.rst index 8c01a1010b..be91944e72 100644 --- a/modules/core/doc/operations_on_arrays.rst +++ b/modules/core/doc/operations_on_arrays.rst @@ -1252,11 +1252,12 @@ gemm ---- Performs generalized matrix multiplication. -.. ocv:function:: void gemm( InputArray src1, InputArray src2, double alpha, InputArray src3, double gamma, OutputArray dst, int flags=0 ) +.. ocv:function:: void gemm( InputArray src1, InputArray src2, double alpha, InputArray src3, double beta, OutputArray dst, int flags=0 ) -.. ocv:pyfunction:: cv2.gemm(src1, src2, alpha, src3, gamma[, dst[, flags]]) -> dst +.. ocv:pyfunction:: cv2.gemm(src1, src2, alpha, src3, beta[, dst[, flags]]) -> dst .. ocv:cfunction:: void cvGEMM( const CvArr* src1, const CvArr* src2, double alpha, const CvArr* src3, double beta, CvArr* dst, int tABC=0) + .. ocv:pyoldfunction:: cv.GEMM(src1, src2, alpha, src3, beta, dst, tABC=0)-> None :param src1: first multiplied input matrix that should have ``CV_32FC1``, ``CV_64FC1``, ``CV_32FC2``, or ``CV_64FC2`` type. diff --git a/modules/core/include/opencv2/core/core.hpp b/modules/core/include/opencv2/core/core.hpp index 2ecb70c713..5667e9e50f 100644 --- a/modules/core/include/opencv2/core/core.hpp +++ b/modules/core/include/opencv2/core/core.hpp @@ -2319,7 +2319,7 @@ CV_EXPORTS_W void patchNaNs(InputOutputArray a, double val=0); //! implements generalized matrix product algorithm GEMM from BLAS CV_EXPORTS_W void gemm(InputArray src1, InputArray src2, double alpha, - InputArray src3, double gamma, OutputArray dst, int flags=0); + InputArray src3, double beta, OutputArray dst, int flags=0); //! multiplies matrix by its transposition from the left or from the right CV_EXPORTS_W void mulTransposed( InputArray src, OutputArray dst, bool aTa, InputArray delta=noArray(), From 63e508abd2b3f85fe464a0bdbd1f9ce4515e5328 Mon Sep 17 00:00:00 2001 From: Kevin Mitchell Date: Mon, 12 May 2014 14:48:34 -0700 Subject: [PATCH 06/14] doc: update/clarify behaviour of mask in floodFill Clarify how the mask parameter is set on output and how this is affected by the flags parameter. resolves Feature #2942 --- modules/imgproc/doc/miscellaneous_transformations.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/imgproc/doc/miscellaneous_transformations.rst b/modules/imgproc/doc/miscellaneous_transformations.rst index e525f726da..7825a24589 100644 --- a/modules/imgproc/doc/miscellaneous_transformations.rst +++ b/modules/imgproc/doc/miscellaneous_transformations.rst @@ -504,7 +504,7 @@ Fills a connected component with the given color. :param image: Input/output 1- or 3-channel, 8-bit, or floating-point image. It is modified by the function unless the ``FLOODFILL_MASK_ONLY`` flag is set in the second variant of the function. See the details below. - :param mask: (For the second function only) Operation mask that should be a single-channel 8-bit image, 2 pixels wider and 2 pixels taller. The function uses and updates the mask, so you take responsibility of initializing the ``mask`` content. Flood-filling cannot go across non-zero pixels in the mask. For example, an edge detector output can be used as a mask to stop filling at edges. It is possible to use the same mask in multiple calls to the function to make sure the filled area does not overlap. + :param mask: Operation mask that should be a single-channel 8-bit image, 2 pixels wider and 2 pixels taller than ``image``. Since this is both an input and output parameter, you must take responsibility of initializing it. Flood-filling cannot go across non-zero pixels in the input mask. For example, an edge detector output can be used as a mask to stop filling at edges. On output, pixels in the mask corresponding to filled pixels in the image are set to 1 or to the a value specified in ``flags`` as described below. It is therefore possible to use the same mask in multiple calls to the function to make sure the filled areas do not overlap. .. note:: Since the mask is larger than the filled image, a pixel :math:`(x, y)` in ``image`` corresponds to the pixel :math:`(x+1, y+1)` in the ``mask`` . @@ -518,11 +518,11 @@ Fills a connected component with the given color. :param rect: Optional output parameter set by the function to the minimum bounding rectangle of the repainted domain. - :param flags: Operation flags. Lower bits contain a connectivity value, 4 (default) or 8, used within the function. Connectivity determines which neighbors of a pixel are considered. Upper bits can be 0 or a combination of the following flags: + :param flags: Operation flags. The first 8 bits contain a connectivity value. The default value of 4 means that only the four nearest neighbor pixels (those that share an edge) are considered. A connectivity value of 8 means that the eight nearest neighbor pixels (those that share a corner) will be considered. The next 8 bits (8-16) contain a value between 1 and 255 with which to fill the ``mask`` (the default value is 1). For example, ``4 | ( 255 << 8 )`` will consider 4 nearest neighbours and fill the mask with a value of 255. The following additional options occupy higher bits and therefore may be further combined with the connectivity and mask fill values using bit-wise or (``|``): * **FLOODFILL_FIXED_RANGE** If set, the difference between the current pixel and seed pixel is considered. Otherwise, the difference between neighbor pixels is considered (that is, the range is floating). - * **FLOODFILL_MASK_ONLY** If set, the function does not change the image ( ``newVal`` is ignored), but fills the mask. The flag can be used for the second variant only. + * **FLOODFILL_MASK_ONLY** If set, the function does not change the image ( ``newVal`` is ignored), and only fills the mask with the value specified in bits 8-16 of ``flags`` as described above. This option only make sense in function variants that have the ``mask`` parameter. The functions ``floodFill`` fill a connected component starting from the seed point with the specified color. The connectivity is determined by the color/brightness closeness of the neighbor pixels. The pixel at :math:`(x,y)` is considered to belong to the repainted domain if: From 55a714c83bb366b6ad191681802e7ac1675c43dc Mon Sep 17 00:00:00 2001 From: Vladislav Vinogradov Date: Tue, 13 May 2014 17:59:20 +0400 Subject: [PATCH 07/14] fix cv::kmeans function reshape input matrix, since the function works with data as with [N x dims] matrix --- modules/core/src/matrix.cpp | 2 ++ samples/cpp/kmeans.cpp | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/modules/core/src/matrix.cpp b/modules/core/src/matrix.cpp index 517ee9dacb..4b2d91e1dd 100644 --- a/modules/core/src/matrix.cpp +++ b/modules/core/src/matrix.cpp @@ -2701,6 +2701,8 @@ double cv::kmeans( InputArray _data, int K, CV_Assert( data.dims <= 2 && type == CV_32F && K > 0 ); CV_Assert( N >= K ); + data = data.reshape(1, N); + _bestLabels.create(N, 1, CV_32S, -1, true); Mat _labels, best_labels = _bestLabels.getMat(); diff --git a/samples/cpp/kmeans.cpp b/samples/cpp/kmeans.cpp index 19e998379d..d475cf175c 100644 --- a/samples/cpp/kmeans.cpp +++ b/samples/cpp/kmeans.cpp @@ -33,7 +33,7 @@ int main( int /*argc*/, char** /*argv*/ ) { int k, clusterCount = rng.uniform(2, MAX_CLUSTERS+1); int i, sampleCount = rng.uniform(1, 1001); - Mat points(sampleCount, 2, CV_32F), labels; + Mat points(sampleCount, 1, CV_32FC2), labels; clusterCount = MIN(clusterCount, sampleCount); Mat centers; From 6ecd553810c6c443bd92c12c9e2082e93fc9b1e8 Mon Sep 17 00:00:00 2001 From: Yash Vadalia Date: Sun, 11 May 2014 19:09:37 +0530 Subject: [PATCH 08/14] Added doc for LinearPolar Transform --- .../imgproc/doc/geometric_transformations.rst | 51 +++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/modules/imgproc/doc/geometric_transformations.rst b/modules/imgproc/doc/geometric_transformations.rst index b3bb37c796..602610b2ff 100644 --- a/modules/imgproc/doc/geometric_transformations.rst +++ b/modules/imgproc/doc/geometric_transformations.rst @@ -256,6 +256,57 @@ The function computes an inverse affine transformation represented by The result is also a :math:`2 \times 3` matrix of the same type as ``M`` . +LinearPolar +----------- +Remaps an image to polar space. + +.. ocv:cfunction:: void cvLinearPolar( const CvArr* src, CvArr* dst, CvPoint2D32f center, double maxRadius, int flags=CV_INTER_LINEAR+CV_WARP_FILL_OUTLIERS ) + + :param src: Source image + + :param dst: Destination image + + :param center: The transformation center; + + :param maxRadius: Inverse magnitude scale parameter. See below + + :param flags: A combination of interpolation methods and the following optional flags: + + * **CV_WARP_FILL_OUTLIERS** fills all of the destination image pixels. If some of them correspond to outliers in the source image, they are set to zero + + * **CV_WARP_INVERSE_MAP** See below + +The function ``cvLinearPolar`` transforms the source image using the following transformation: + + * + Forward transformation (``CV_WARP_INVERSE_MAP`` is not set): + + .. math:: + + dst( \phi , \rho ) = src(x,y) + + + * + Inverse transformation (``CV_WARP_INVERSE_MAP`` is set): + + .. math:: + + dst(x,y) = src( \phi , \rho ) + + +where + + .. math:: + + \rho = (src.width/maxRadius) \cdot \sqrt{x^2 + y^2} , \phi =atan(y/x) + + +The function can not operate in-place. + +.. note:: + + * An example using the LinearPolar operation can be found at opencv_source_code/samples/c/polar_transforms.c + LogPolar From ea038436e6b115b783212976b57b4f1455c8ac7b Mon Sep 17 00:00:00 2001 From: thoinvil Date: Thu, 15 May 2014 08:40:13 +0200 Subject: [PATCH 09/14] Added condition to 1st test in cv::GaussianBlur Consistent with the test made in cv::boxFilter, it adjusts the kernel size to the source size only if the border is not BORDER_CONSTANT and if BORDER_ISOLATED is set. Otherwise, the source has to be considered possibly in a larger image (i.e. the source being a ROI) in witch the kernel should apply. --- modules/imgproc/src/smooth.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/imgproc/src/smooth.cpp b/modules/imgproc/src/smooth.cpp index ae14ca9e11..c0ea05ea2c 100644 --- a/modules/imgproc/src/smooth.cpp +++ b/modules/imgproc/src/smooth.cpp @@ -837,7 +837,7 @@ void cv::GaussianBlur( InputArray _src, OutputArray _dst, Size ksize, _dst.create( src.size(), src.type() ); Mat dst = _dst.getMat(); - if( borderType != BORDER_CONSTANT ) + if( borderType != BORDER_CONSTANT && (borderType & BORDER_ISOLATED) != 0 ) { if( src.rows == 1 ) ksize.height = 1; From f16503743f98c6a49d9506095d7f4ab143131f25 Mon Sep 17 00:00:00 2001 From: Vladislav Vinogradov Date: Thu, 15 May 2014 12:08:01 +0400 Subject: [PATCH 10/14] use more accurate reshape --- modules/core/src/matrix.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/modules/core/src/matrix.cpp b/modules/core/src/matrix.cpp index 4b2d91e1dd..8e32b0fbee 100644 --- a/modules/core/src/matrix.cpp +++ b/modules/core/src/matrix.cpp @@ -2691,17 +2691,17 @@ double cv::kmeans( InputArray _data, int K, int flags, OutputArray _centers ) { const int SPP_TRIALS = 3; - Mat data = _data.getMat(); - bool isrow = data.rows == 1 && data.channels() > 1; - int N = !isrow ? data.rows : data.cols; - int dims = (!isrow ? data.cols : 1)*data.channels(); - int type = data.depth(); + Mat data0 = _data.getMat(); + bool isrow = data0.rows == 1 && data0.channels() > 1; + int N = !isrow ? data0.rows : data0.cols; + int dims = (!isrow ? data0.cols : 1)*data0.channels(); + int type = data0.depth(); attempts = std::max(attempts, 1); - CV_Assert( data.dims <= 2 && type == CV_32F && K > 0 ); + CV_Assert( data0.dims <= 2 && type == CV_32F && K > 0 ); CV_Assert( N >= K ); - data = data.reshape(1, N); + Mat data(N, dims, CV_32F, data0.data, isrow ? dims * sizeof(float) : static_cast(data0.step)); _bestLabels.create(N, 1, CV_32S, -1, true); From 746185652a3c55e32b74ed9914b9e8c98aa09079 Mon Sep 17 00:00:00 2001 From: Vladislav Vinogradov Date: Thu, 15 May 2014 12:08:38 +0400 Subject: [PATCH 11/14] add additional tests for different input cases --- modules/core/test/test_math.cpp | 91 +++++++++++++++++++++++++++++---- 1 file changed, 81 insertions(+), 10 deletions(-) diff --git a/modules/core/test/test_math.cpp b/modules/core/test/test_math.cpp index a572cd0d92..5dec97e8c1 100644 --- a/modules/core/test/test_math.cpp +++ b/modules/core/test/test_math.cpp @@ -2512,6 +2512,15 @@ TEST(Core_SVD, flt) // TODO: eigenvv, invsqrt, cbrt, fastarctan, (round, floor, ceil(?)), +enum +{ + MAT_N_DIM_C1, + MAT_N_1_CDIM, + MAT_1_N_CDIM, + MAT_N_DIM_C1_NONCONT, + MAT_N_1_CDIM_NONCONT, + VECTOR +}; class CV_KMeansSingularTest : public cvtest::BaseTest { @@ -2519,7 +2528,7 @@ public: CV_KMeansSingularTest() {} ~CV_KMeansSingularTest() {} protected: - void run(int) + void run(int inVariant) { int i, iter = 0, N = 0, N0 = 0, K = 0, dims = 0; Mat labels; @@ -2531,20 +2540,70 @@ protected: for( iter = 0; iter < maxIter; iter++ ) { ts->update_context(this, iter, true); - dims = rng.uniform(1, MAX_DIM+1); + dims = rng.uniform(inVariant == MAT_1_N_CDIM ? 2 : 1, MAX_DIM+1); N = rng.uniform(1, MAX_POINTS+1); N0 = rng.uniform(1, MAX(N/10, 2)); K = rng.uniform(1, N+1); - Mat data0(N0, dims, CV_32F); - rng.fill(data0, RNG::UNIFORM, -1, 1); + if (inVariant == VECTOR) + { + dims = 2; - Mat data(N, dims, CV_32F); - for( i = 0; i < N; i++ ) - data0.row(rng.uniform(0, N0)).copyTo(data.row(i)); + std::vector data0(N0); + rng.fill(data0, RNG::UNIFORM, -1, 1); - kmeans(data, K, labels, TermCriteria(TermCriteria::MAX_ITER+TermCriteria::EPS, 30, 0), - 5, KMEANS_PP_CENTERS); + std::vector data(N); + for( i = 0; i < N; i++ ) + data[i] = data0[rng.uniform(0, N0)]; + + kmeans(data, K, labels, TermCriteria(TermCriteria::MAX_ITER+TermCriteria::EPS, 30, 0), + 5, KMEANS_PP_CENTERS); + } + else + { + Mat data0(N0, dims, CV_32F); + rng.fill(data0, RNG::UNIFORM, -1, 1); + + Mat data; + + switch (inVariant) + { + case MAT_N_DIM_C1: + data.create(N, dims, CV_32F); + for( i = 0; i < N; i++ ) + data0.row(rng.uniform(0, N0)).copyTo(data.row(i)); + break; + + case MAT_N_1_CDIM: + data.create(N, 1, CV_32FC(dims)); + for( i = 0; i < N; i++ ) + memcpy(data.ptr(i), data0.ptr(rng.uniform(0, N0)), dims * sizeof(float)); + break; + + case MAT_1_N_CDIM: + data.create(1, N, CV_32FC(dims)); + for( i = 0; i < N; i++ ) + memcpy(data.data + i * dims * sizeof(float), data0.ptr(rng.uniform(0, N0)), dims * sizeof(float)); + break; + + case MAT_N_DIM_C1_NONCONT: + data.create(N, dims + 5, CV_32F); + data = data(Range(0, N), Range(0, dims)); + for( i = 0; i < N; i++ ) + data0.row(rng.uniform(0, N0)).copyTo(data.row(i)); + break; + + case MAT_N_1_CDIM_NONCONT: + data.create(N, 3, CV_32FC(dims)); + data = data.colRange(0, 1); + for( i = 0; i < N; i++ ) + memcpy(data.ptr(i), data0.ptr(rng.uniform(0, N0)), dims * sizeof(float)); + break; + } + + kmeans(data, K, labels, TermCriteria(TermCriteria::MAX_ITER+TermCriteria::EPS, 30, 0), + 5, KMEANS_PP_CENTERS); + } Mat hist(K, 1, CV_32S, Scalar(0)); for( i = 0; i < N; i++ ) @@ -2568,7 +2627,19 @@ protected: } }; -TEST(Core_KMeans, singular) { CV_KMeansSingularTest test; test.safe_run(); } +TEST(Core_KMeans, singular) { CV_KMeansSingularTest test; test.safe_run(MAT_N_DIM_C1); } + +CV_ENUM(KMeansInputVariant, MAT_N_DIM_C1, MAT_N_1_CDIM, MAT_1_N_CDIM, MAT_N_DIM_C1_NONCONT, MAT_N_1_CDIM_NONCONT, VECTOR) + +typedef testing::TestWithParam Core_KMeans_InputVariants; + +TEST_P(Core_KMeans_InputVariants, singular) +{ + CV_KMeansSingularTest test; + test.safe_run(GetParam()); +} + +INSTANTIATE_TEST_CASE_P(AllVariants, Core_KMeans_InputVariants, KMeansInputVariant::all()); TEST(CovariationMatrixVectorOfMat, accuracy) { From 7fc764f5e5c9470db40eebe2662fa2a84034a1f2 Mon Sep 17 00:00:00 2001 From: StevenPuttemans Date: Mon, 12 May 2014 16:45:42 +0200 Subject: [PATCH 12/14] added documentation for findContours --- .../imgproc/doc/structural_analysis_and_shape_descriptors.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/imgproc/doc/structural_analysis_and_shape_descriptors.rst b/modules/imgproc/doc/structural_analysis_and_shape_descriptors.rst index de4e585d8c..29e8b98571 100644 --- a/modules/imgproc/doc/structural_analysis_and_shape_descriptors.rst +++ b/modules/imgproc/doc/structural_analysis_and_shape_descriptors.rst @@ -133,7 +133,7 @@ Finds contours in a binary image. .. ocv:pyoldfunction:: cv.FindContours(image, storage, mode=CV_RETR_LIST, method=CV_CHAIN_APPROX_SIMPLE, offset=(0, 0)) -> contours - :param image: Source, an 8-bit single-channel image. Non-zero pixels are treated as 1's. Zero pixels remain 0's, so the image is treated as ``binary`` . You can use :ocv:func:`compare` , :ocv:func:`inRange` , :ocv:func:`threshold` , :ocv:func:`adaptiveThreshold` , :ocv:func:`Canny` , and others to create a binary image out of a grayscale or color one. The function modifies the ``image`` while extracting the contours. + :param image: Source, an 8-bit single-channel image. Non-zero pixels are treated as 1's. Zero pixels remain 0's, so the image is treated as ``binary`` . You can use :ocv:func:`compare` , :ocv:func:`inRange` , :ocv:func:`threshold` , :ocv:func:`adaptiveThreshold` , :ocv:func:`Canny` , and others to create a binary image out of a grayscale or color one. The function modifies the ``image`` while extracting the contours. If mode equals to ``CV_RETR_CCOMP`` or ``CV_RETR_FLOODFILL``, the input can also be a 32-bit integer image of labels (``CV_32SC1``). :param contours: Detected contours. Each contour is stored as a vector of points. From 12207ac7630eaf06b357131af0a0350ffa0802aa Mon Sep 17 00:00:00 2001 From: StevenPuttemans Date: Tue, 13 May 2014 11:43:02 +0200 Subject: [PATCH 13/14] fix coordinate problem with large images - bug 1523 --- modules/highgui/src/window_w32.cpp | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/modules/highgui/src/window_w32.cpp b/modules/highgui/src/window_w32.cpp index 48f3aab23e..b5cbc55650 100644 --- a/modules/highgui/src/window_w32.cpp +++ b/modules/highgui/src/window_w32.cpp @@ -1436,8 +1436,6 @@ static LRESULT CALLBACK HighGUIProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM if( window->on_mouse ) { POINT pt; - RECT rect; - SIZE size = {0,0}; int flags = (wParam & MK_LBUTTON ? CV_EVENT_FLAG_LBUTTON : 0)| (wParam & MK_RBUTTON ? CV_EVENT_FLAG_RBUTTON : 0)| @@ -1463,12 +1461,23 @@ static LRESULT CALLBACK HighGUIProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM pt.x = GET_X_LPARAM( lParam ); pt.y = GET_Y_LPARAM( lParam ); - GetClientRect( window->hwnd, &rect ); - icvGetBitmapData( window, &size, 0, 0 ); + if (window->flags & CV_WINDOW_AUTOSIZE) + { + // As user can't change window size, do not scale window coordinates. Underlying windowing system + // may prevent full window from being displayed and in this case coordinates should not be scaled. + window->on_mouse( event, pt.x, pt.y, flags, window->on_mouse_param ); + } else { + // Full window is displayed using different size. Scale coordinates to match underlying positions. + RECT rect; + SIZE size = {0, 0}; - window->on_mouse( event, pt.x*size.cx/MAX(rect.right - rect.left,1), - pt.y*size.cy/MAX(rect.bottom - rect.top,1), flags, - window->on_mouse_param ); + GetClientRect( window->hwnd, &rect ); + icvGetBitmapData( window, &size, 0, 0 ); + + window->on_mouse( event, pt.x*size.cx/MAX(rect.right - rect.left,1), + pt.y*size.cy/MAX(rect.bottom - rect.top,1), flags, + window->on_mouse_param ); + } } break; From bea46c90b5ecf35ced46698c61df0b9ed965e398 Mon Sep 17 00:00:00 2001 From: Roman Donchenko Date: Mon, 19 May 2014 17:38:30 +0400 Subject: [PATCH 14/14] Remove a useless loop that copies an array to itself --- modules/legacy/src/calibfilter.cpp | 6 ------ 1 file changed, 6 deletions(-) diff --git a/modules/legacy/src/calibfilter.cpp b/modules/legacy/src/calibfilter.cpp index 64b9957beb..49ff6e52dc 100644 --- a/modules/legacy/src/calibfilter.cpp +++ b/modules/legacy/src/calibfilter.cpp @@ -333,12 +333,6 @@ void CvCalibFilter::Stop( bool calibrate ) points[0],points[1], buffer, &stereo); - - for( i = 0; i < 9; i++ ) - { - stereo.fundMatr[i] = stereo.fundMatr[i]; - } - } }