diff --git a/modules/core/src/matrix.cpp b/modules/core/src/matrix.cpp index 9b77a4cf2c..b273c8a7d8 100644 --- a/modules/core/src/matrix.cpp +++ b/modules/core/src/matrix.cpp @@ -4714,8 +4714,8 @@ SparseMat::Hdr::Hdr( int _dims, const int* _sizes, int _type ) refcount = 1; dims = _dims; - valueOffset = (int)alignSize(sizeof(SparseMat::Node) + - sizeof(int)*std::max(dims - CV_MAX_DIM, 0), CV_ELEM_SIZE1(_type)); + valueOffset = (int)alignSize(sizeof(SparseMat::Node) - MAX_DIM*sizeof(int) + + dims*sizeof(int), CV_ELEM_SIZE1(_type)); nodeSize = alignSize(valueOffset + CV_ELEM_SIZE(_type), (int)sizeof(size_t)); @@ -4816,7 +4816,8 @@ void SparseMat::copyTo( SparseMat& m ) const void SparseMat::copyTo( Mat& m ) const { CV_Assert( hdr ); - m.create( dims(), hdr->size, type() ); + int ndims = dims(); + m.create( ndims, hdr->size, type() ); m = Scalar(0); SparseMatConstIterator from = begin(); @@ -4825,7 +4826,7 @@ void SparseMat::copyTo( Mat& m ) const for( i = 0; i < N; i++, ++from ) { const Node* n = from.node(); - copyElem( from.ptr, m.ptr(n->idx), esz); + copyElem( from.ptr, (ndims > 1 ? m.ptr(n->idx) : m.ptr(n->idx[0])), esz); } } @@ -5114,7 +5115,8 @@ uchar* SparseMat::newNode(const int* idx, size_t hashval) if( !hdr->freeList ) { size_t i, nsz = hdr->nodeSize, psize = hdr->pool.size(), - newpsize = std::max(psize*2, 8*nsz); + newpsize = std::max(psize*3/2, 8*nsz); + newpsize = (newpsize/nsz)*nsz; hdr->pool.resize(newpsize); uchar* pool = &hdr->pool[0]; hdr->freeList = std::max(psize, nsz); diff --git a/modules/core/src/stat.cpp b/modules/core/src/stat.cpp index 8a6bd54721..81f9a2484e 100644 --- a/modules/core/src/stat.cpp +++ b/modules/core/src/stat.cpp @@ -504,54 +504,21 @@ static int countNonZero_(const T* src, int len ) return nz; } -#if CV_SSE2 - -static const uchar * initPopcountTable() -{ - static uchar tab[256]; - static volatile bool initialized = false; - if( !initialized ) - { - // we compute inverse popcount table, - // since we pass (img[x] == 0) mask as index in the table. - unsigned int j = 0u; -#if CV_POPCNT - if (checkHardwareSupport(CV_CPU_POPCNT)) - { - for( ; j < 256u; j++ ) - tab[j] = (uchar)(8 - _mm_popcnt_u32(j)); - } -#endif - for( ; j < 256u; j++ ) - { - int val = 0; - for( int mask = 1; mask < 256; mask += mask ) - val += (j & mask) == 0; - tab[j] = (uchar)val; - } - initialized = true; - } - - return tab; -} - -#endif - static int countNonZero8u( const uchar* src, int len ) { int i=0, nz = 0; #if CV_SSE2 if(USE_SSE2)//5x-6x { - __m128i pattern = _mm_setzero_si128 (); - static const uchar * tab = initPopcountTable(); + __m128i v_zero = _mm_setzero_si128(); + __m128i sum = _mm_setzero_si128(); for (; i<=len-16; i+=16) { __m128i r0 = _mm_loadu_si128((const __m128i*)(src+i)); - int val = _mm_movemask_epi8(_mm_cmpeq_epi8(r0, pattern)); - nz += tab[val & 255] + tab[val >> 8]; + sum = _mm_add_epi32(sum, _mm_sad_epu8(_mm_sub_epi8(v_zero, _mm_cmpeq_epi8(r0, v_zero)), v_zero)); } + nz = i - _mm_cvtsi128_si32(_mm_add_epi32(sum, _mm_unpackhi_epi64(sum, sum))); } #elif CV_NEON int len0 = len & -16, blockSize1 = (1 << 8) - 16, blockSize0 = blockSize1 << 6; @@ -598,15 +565,15 @@ static int countNonZero16u( const ushort* src, int len ) if (USE_SSE2) { __m128i v_zero = _mm_setzero_si128 (); - static const uchar * tab = initPopcountTable(); + __m128i sum = _mm_setzero_si128(); for ( ; i <= len - 8; i += 8) { - __m128i v_src = _mm_loadu_si128((const __m128i*)(src + i)); - int val = _mm_movemask_epi8(_mm_packs_epi16(_mm_cmpeq_epi16(v_src, v_zero), v_zero)); - nz += tab[val]; + __m128i r0 = _mm_loadu_si128((const __m128i*)(src + i)); + sum = _mm_add_epi32(sum, _mm_sad_epu8(_mm_sub_epi8(v_zero, _mm_cmpeq_epi16(r0, v_zero)), v_zero)); } + nz = i - (_mm_cvtsi128_si32(_mm_add_epi32(sum, _mm_unpackhi_epi64(sum, sum))) >> 1); src += i; } #elif CV_NEON @@ -649,20 +616,15 @@ static int countNonZero32s( const int* src, int len ) if (USE_SSE2) { __m128i v_zero = _mm_setzero_si128 (); - static const uchar * tab = initPopcountTable(); + __m128i sum = _mm_setzero_si128(); - for ( ; i <= len - 8; i += 8) + for ( ; i <= len - 4; i += 4) { - __m128i v_src = _mm_loadu_si128((const __m128i*)(src + i)); - __m128i v_dst0 = _mm_cmpeq_epi32(v_src, v_zero); - - v_src = _mm_loadu_si128((const __m128i*)(src + i + 4)); - __m128i v_dst1 = _mm_cmpeq_epi32(v_src, v_zero); - - int val = _mm_movemask_epi8(_mm_packs_epi16(_mm_packs_epi32(v_dst0, v_dst1), v_zero)); - nz += tab[val]; + __m128i r0 = _mm_loadu_si128((const __m128i*)(src + i)); + sum = _mm_add_epi32(sum, _mm_sad_epu8(_mm_sub_epi8(v_zero, _mm_cmpeq_epi32(r0, v_zero)), v_zero)); } + nz = i - (_mm_cvtsi128_si32(_mm_add_epi32(sum, _mm_unpackhi_epi64(sum, sum))) >> 2); src += i; } #elif CV_NEON @@ -706,19 +668,17 @@ static int countNonZero32f( const float* src, int len ) #if CV_SSE2 if (USE_SSE2) { - __m128i v_zero_i = _mm_setzero_si128(); __m128 v_zero_f = _mm_setzero_ps(); - static const uchar * tab = initPopcountTable(); + __m128i v_zero = _mm_setzero_si128 (); + __m128i sum = _mm_setzero_si128(); - for ( ; i <= len - 8; i += 8) + for ( ; i <= len - 4; i += 4) { - __m128i v_dst0 = _mm_castps_si128(_mm_cmpeq_ps(_mm_loadu_ps(src + i), v_zero_f)); - __m128i v_dst1 = _mm_castps_si128(_mm_cmpeq_ps(_mm_loadu_ps(src + i + 4), v_zero_f)); - - int val = _mm_movemask_epi8(_mm_packs_epi16(_mm_packs_epi32(v_dst0, v_dst1), v_zero_i)); - nz += tab[val]; + __m128 r0 = _mm_loadu_ps(src + i); + sum = _mm_add_epi32(sum, _mm_sad_epu8(_mm_sub_epi8(v_zero, _mm_castps_si128(_mm_cmpeq_ps(r0, v_zero_f))), v_zero)); } + nz = i - (_mm_cvtsi128_si32(_mm_add_epi32(sum, _mm_unpackhi_epi64(sum, sum))) >> 2); src += i; } #elif CV_NEON @@ -758,32 +718,7 @@ static int countNonZero32f( const float* src, int len ) static int countNonZero64f( const double* src, int len ) { - int i = 0, nz = 0; -#if CV_SSE2 - if (USE_SSE2) - { - __m128i v_zero_i = _mm_setzero_si128(); - __m128d v_zero_d = _mm_setzero_pd(); - static const uchar * tab = initPopcountTable(); - - for ( ; i <= len - 8; i += 8) - { - __m128i v_dst0 = _mm_castpd_si128(_mm_cmpeq_pd(_mm_loadu_pd(src + i), v_zero_d)); - __m128i v_dst1 = _mm_castpd_si128(_mm_cmpeq_pd(_mm_loadu_pd(src + i + 2), v_zero_d)); - __m128i v_dst2 = _mm_castpd_si128(_mm_cmpeq_pd(_mm_loadu_pd(src + i + 4), v_zero_d)); - __m128i v_dst3 = _mm_castpd_si128(_mm_cmpeq_pd(_mm_loadu_pd(src + i + 6), v_zero_d)); - - v_dst0 = _mm_packs_epi32(v_dst0, v_dst1); - v_dst1 = _mm_packs_epi32(v_dst2, v_dst3); - - int val = _mm_movemask_epi8(_mm_packs_epi16(_mm_packs_epi32(v_dst0, v_dst1), v_zero_i)); - nz += tab[val]; - } - - src += i; - } -#endif - return nz + countNonZero_(src, len - i); + return countNonZero_(src, len); } typedef int (*CountNonZeroFunc)(const uchar*, int); diff --git a/modules/core/test/test_mat.cpp b/modules/core/test/test_mat.cpp index 102bd99764..897ac40a43 100644 --- a/modules/core/test/test_mat.cpp +++ b/modules/core/test/test_mat.cpp @@ -1248,3 +1248,27 @@ TEST(Core_SVD, orthogonality) ASSERT_LT(norm(mat_U, Mat::eye(2, 2, type), NORM_INF), 1e-5); } } + + +TEST(Core_SparseMat, footprint) +{ + int n = 1000000; + int sz[] = { n, n }; + SparseMat m(2, sz, CV_64F); + + int nodeSize0 = (int)m.hdr->nodeSize; + double dataSize0 = ((double)m.hdr->pool.size() + (double)m.hdr->hashtab.size()*sizeof(size_t))*1e-6; + printf("before: node size=%d bytes, data size=%.0f Mbytes\n", nodeSize0, dataSize0); + + for (int i = 0; i < n; i++) + { + m.ref(i, i) = 1; + } + + double dataSize1 = ((double)m.hdr->pool.size() + (double)m.hdr->hashtab.size()*sizeof(size_t))*1e-6; + double threshold = (n*nodeSize0*1.6 + n*2.*sizeof(size_t))*1e-6; + printf("after: data size=%.0f Mbytes, threshold=%.0f MBytes\n", dataSize1, threshold); + + ASSERT_LE((int)m.hdr->nodeSize, 32); + ASSERT_LE(dataSize1, threshold); +} diff --git a/modules/hal/src/matrix.cpp b/modules/hal/src/matrix.cpp index 9506aaf478..921b7783f7 100644 --- a/modules/hal/src/matrix.cpp +++ b/modules/hal/src/matrix.cpp @@ -49,7 +49,7 @@ namespace cv { namespace hal { \****************************************************************************************/ template static inline int -LUImpl(_Tp* A, size_t astep, int m, _Tp* b, size_t bstep, int n) +LUImpl(_Tp* A, size_t astep, int m, _Tp* b, size_t bstep, int n, _Tp eps) { int i, j, k, p = 1; astep /= sizeof(A[0]); @@ -63,7 +63,7 @@ LUImpl(_Tp* A, size_t astep, int m, _Tp* b, size_t bstep, int n) if( std::abs(A[j*astep + i]) > std::abs(A[k*astep + i]) ) k = j; - if( std::abs(A[k*astep + i]) < std::numeric_limits<_Tp>::epsilon() ) + if( std::abs(A[k*astep + i]) < eps ) return 0; if( k != i ) @@ -111,13 +111,13 @@ LUImpl(_Tp* A, size_t astep, int m, _Tp* b, size_t bstep, int n) int LU(float* A, size_t astep, int m, float* b, size_t bstep, int n) { - return LUImpl(A, astep, m, b, bstep, n); + return LUImpl(A, astep, m, b, bstep, n, FLT_EPSILON*10); } int LU(double* A, size_t astep, int m, double* b, size_t bstep, int n) { - return LUImpl(A, astep, m, b, bstep, n); + return LUImpl(A, astep, m, b, bstep, n, DBL_EPSILON*100); } diff --git a/modules/imgproc/src/filter.cpp b/modules/imgproc/src/filter.cpp index fb43eee0a1..f0b7ee79e5 100644 --- a/modules/imgproc/src/filter.cpp +++ b/modules/imgproc/src/filter.cpp @@ -3455,7 +3455,7 @@ struct SymmColumnSmallFilter : public SymmColumnFilter bool symmetrical = (this->symmetryType & KERNEL_SYMMETRICAL) != 0; bool is_1_2_1 = ky[0] == 2 && ky[1] == 1; bool is_1_m2_1 = ky[0] == -2 && ky[1] == 1; - bool is_m1_0_1 = ky[1] == 1 || ky[1] == -1; + bool is_m1_0_1 = ky[0] == 0 && (ky[1] == 1 || ky[1] == -1); ST f0 = ky[0], f1 = ky[1]; ST _delta = this->delta; CastOp castOp = this->castOp0; @@ -3486,13 +3486,12 @@ struct SymmColumnSmallFilter : public SymmColumnFilter D[i+2] = castOp(s0); D[i+3] = castOp(s1); } - #else + #endif for( ; i < width; i ++ ) { ST s0 = S0[i] + S1[i]*2 + S2[i] + _delta; D[i] = castOp(s0); } - #endif } else if( is_1_m2_1 ) { @@ -3509,17 +3508,16 @@ struct SymmColumnSmallFilter : public SymmColumnFilter D[i+2] = castOp(s0); D[i+3] = castOp(s1); } - #else + #endif for( ; i < width; i ++ ) { ST s0 = S0[i] - S1[i]*2 + S2[i] + _delta; D[i] = castOp(s0); } - #endif } else { - #if CV_ENABLE_UNROLLED + #if CV_ENABLE_UNROLLED for( ; i <= width - 4; i += 4 ) { ST s0 = (S0[i] + S2[i])*f1 + S1[i]*f0 + _delta; @@ -3532,16 +3530,13 @@ struct SymmColumnSmallFilter : public SymmColumnFilter D[i+2] = castOp(s0); D[i+3] = castOp(s1); } - #else + #endif for( ; i < width; i ++ ) { ST s0 = (S0[i] + S2[i])*f1 + S1[i]*f0 + _delta; D[i] = castOp(s0); } - #endif } - for( ; i < width; i++ ) - D[i] = castOp((S0[i] + S2[i])*f1 + S1[i]*f0 + _delta); } else { @@ -3549,7 +3544,7 @@ struct SymmColumnSmallFilter : public SymmColumnFilter { if( f1 < 0 ) std::swap(S0, S2); - #if CV_ENABLE_UNROLLED + #if CV_ENABLE_UNROLLED for( ; i <= width - 4; i += 4 ) { ST s0 = S2[i] - S0[i] + _delta; @@ -3562,19 +3557,18 @@ struct SymmColumnSmallFilter : public SymmColumnFilter D[i+2] = castOp(s0); D[i+3] = castOp(s1); } - #else + #endif for( ; i < width; i ++ ) { ST s0 = S2[i] - S0[i] + _delta; D[i] = castOp(s0); } - #endif if( f1 < 0 ) std::swap(S0, S2); } else { - #if CV_ENABLE_UNROLLED + #if CV_ENABLE_UNROLLED for( ; i <= width - 4; i += 4 ) { ST s0 = (S2[i] - S0[i])*f1 + _delta; @@ -3588,10 +3582,9 @@ struct SymmColumnSmallFilter : public SymmColumnFilter D[i+3] = castOp(s1); } #endif + for( ; i < width; i++ ) + D[i] = castOp((S2[i] - S0[i])*f1 + _delta); } - - for( ; i < width; i++ ) - D[i] = castOp((S2[i] - S0[i])*f1 + _delta); } } } diff --git a/modules/imgproc/src/imgwarp.cpp b/modules/imgproc/src/imgwarp.cpp index 8a11515389..760f3fb0a2 100644 --- a/modules/imgproc/src/imgwarp.cpp +++ b/modules/imgproc/src/imgwarp.cpp @@ -3805,20 +3805,20 @@ static void remapBilinear( const Mat& _src, Mat& _dst, const Mat& _xy, typedef typename CastOp::rtype T; typedef typename CastOp::type1 WT; Size ssize = _src.size(), dsize = _dst.size(); - int cn = _src.channels(); + int k, cn = _src.channels(); const AT* wtab = (const AT*)_wtab; const T* S0 = _src.ptr(); size_t sstep = _src.step/sizeof(S0[0]); - Scalar_ cval(saturate_cast(_borderValue[0]), - saturate_cast(_borderValue[1]), - saturate_cast(_borderValue[2]), - saturate_cast(_borderValue[3])); + T cval[CV_CN_MAX]; int dx, dy; CastOp castOp; VecOp vecOp; + for( k = 0; k < cn; k++ ) + cval[k] = saturate_cast(_borderValue[k & 3]); + unsigned width1 = std::max(ssize.width-1, 0), height1 = std::max(ssize.height-1, 0); - CV_Assert( cn <= 4 && ssize.area() > 0 ); + CV_Assert( ssize.area() > 0 ); #if CV_SSE2 if( _src.type() == CV_8UC3 ) width1 = std::max(ssize.width-2, 0); @@ -3882,7 +3882,7 @@ static void remapBilinear( const Mat& _src, Mat& _dst, const Mat& _xy, WT t2 = S[2]*w[0] + S[5]*w[1] + S[sstep+2]*w[2] + S[sstep+5]*w[3]; D[0] = castOp(t0); D[1] = castOp(t1); D[2] = castOp(t2); } - else + else if( cn == 4 ) for( ; dx < X1; dx++, D += 4 ) { int sx = XY[dx*2], sy = XY[dx*2+1]; @@ -3895,6 +3895,18 @@ static void remapBilinear( const Mat& _src, Mat& _dst, const Mat& _xy, t1 = S[3]*w[0] + S[7]*w[1] + S[sstep+3]*w[2] + S[sstep+7]*w[3]; D[2] = castOp(t0); D[3] = castOp(t1); } + else + for( ; dx < X1; dx++, D += cn ) + { + int sx = XY[dx*2], sy = XY[dx*2+1]; + const AT* w = wtab + FXY[dx]*4; + const T* S = S0 + sy*sstep + sx*cn; + for( k = 0; k < cn; k++ ) + { + WT t0 = S[k]*w[0] + S[k+cn]*w[1] + S[sstep+k]*w[2] + S[sstep+k+cn]*w[3]; + D[k] = castOp(t0); + } + } } else { @@ -3948,7 +3960,7 @@ static void remapBilinear( const Mat& _src, Mat& _dst, const Mat& _xy, else for( ; dx < X1; dx++, D += cn ) { - int sx = XY[dx*2], sy = XY[dx*2+1], k; + int sx = XY[dx*2], sy = XY[dx*2+1]; if( borderType == BORDER_CONSTANT && (sx >= ssize.width || sx+1 < 0 || sy >= ssize.height || sy+1 < 0) ) diff --git a/modules/imgproc/test/test_contours.cpp b/modules/imgproc/test/test_contours.cpp index b0b8c4fbb5..b94408d3b8 100644 --- a/modules/imgproc/test/test_contours.cpp +++ b/modules/imgproc/test/test_contours.cpp @@ -40,6 +40,7 @@ //M*/ #include "test_precomp.hpp" +#include "opencv2/highgui.hpp" using namespace cv; using namespace std; @@ -429,4 +430,64 @@ TEST(Core_Drawing, polylines) int cnt = countNonZero(img); ASSERT_EQ(cnt, 21); } + +//rotate/flip a quadrant appropriately +static void rot(int n, int *x, int *y, int rx, int ry) +{ + if (ry == 0) { + if (rx == 1) { + *x = n-1 - *x; + *y = n-1 - *y; + } + + //Swap x and y + int t = *x; + *x = *y; + *y = t; + } +} + +static void d2xy(int n, int d, int *x, int *y) +{ + int rx, ry, s, t=d; + *x = *y = 0; + for (s=1; s > contours; + findContours(img, contours, noArray(), RETR_LIST, CHAIN_APPROX_SIMPLE); + printf("ncontours = %d, contour[0].npoints=%d\n", (int)contours.size(), (int)contours[0].size()); + img.setTo(Scalar::all(0)); + + drawContours(img, contours, 0, Scalar::all(255), 1); + //imshow("hilbert", img); + //waitKey(); + ASSERT_EQ(1, (int)contours.size()); + ASSERT_EQ(9832, (int)contours[0].size()); +} + /* End of file. */ diff --git a/modules/imgproc/test/test_filter.cpp b/modules/imgproc/test/test_filter.cpp index a203e60f5c..9253132186 100644 --- a/modules/imgproc/test/test_filter.cpp +++ b/modules/imgproc/test/test_filter.cpp @@ -1918,3 +1918,37 @@ TEST(Imgproc_Blur, borderTypes) EXPECT_EQ(expected_dst.size(), dst.size()); EXPECT_DOUBLE_EQ(0.0, cvtest::norm(expected_dst, dst, NORM_INF)); } + +TEST(Imgproc_Morphology, iterated) +{ + RNG& rng = theRNG(); + for( int iter = 0; iter < 30; iter++ ) + { + int width = rng.uniform(5, 33); + int height = rng.uniform(5, 33); + int cn = rng.uniform(1, 5); + int iterations = rng.uniform(1, 11); + int op = rng.uniform(0, 2); + Mat src(height, width, CV_8UC(cn)), dst0, dst1, dst2; + + randu(src, 0, 256); + if( op == 0 ) + dilate(src, dst0, Mat(), Point(-1,-1), iterations); + else + erode(src, dst0, Mat(), Point(-1,-1), iterations); + + for( int i = 0; i < iterations; i++ ) + if( op == 0 ) + dilate(i == 0 ? src : dst1, dst1, Mat(), Point(-1,-1), 1); + else + erode(i == 0 ? src : dst1, dst1, Mat(), Point(-1,-1), 1); + + Mat kern = getStructuringElement(MORPH_RECT, Size(3,3)); + if( op == 0 ) + dilate(src, dst2, kern, Point(-1,-1), iterations); + else + erode(src, dst2, kern, Point(-1,-1), iterations); + ASSERT_EQ(0.0, norm(dst0, dst1, NORM_INF)); + ASSERT_EQ(0.0, norm(dst0, dst2, NORM_INF)); + } +} diff --git a/modules/imgproc/test/test_imgwarp.cpp b/modules/imgproc/test/test_imgwarp.cpp index 176c9907f3..4ffd50b41a 100644 --- a/modules/imgproc/test/test_imgwarp.cpp +++ b/modules/imgproc/test/test_imgwarp.cpp @@ -1632,4 +1632,64 @@ TEST(Resize, Area_half) } } +TEST(Imgproc_Warp, multichannel) +{ + RNG& rng = theRNG(); + for( int iter = 0; iter < 30; iter++ ) + { + int width = rng.uniform(3, 333); + int height = rng.uniform(3, 333); + int cn = rng.uniform(1, 10); + Mat src(height, width, CV_8UC(cn)), dst; + //randu(src, 0, 256); + src.setTo(0.); + + Mat rot = getRotationMatrix2D(Point2f(0.f, 0.f), 1, 1); + warpAffine(src, dst, rot, src.size()); + ASSERT_EQ(0.0, norm(dst, NORM_INF)); + Mat rot2 = Mat::eye(3, 3, rot.type()); + rot.copyTo(rot2.rowRange(0, 2)); + warpPerspective(src, dst, rot2, src.size()); + ASSERT_EQ(0.0, norm(dst, NORM_INF)); + } +} + +TEST(Imgproc_GetAffineTransform, singularity) +{ + Point2f A_sample[3]; + A_sample[0] = Point2f(8.f, 9.f); + A_sample[1] = Point2f(40.f, 41.f); + A_sample[2] = Point2f(47.f, 48.f); + Point2f B_sample[3]; + B_sample[0] = Point2f(7.37465f, 11.8295f); + B_sample[1] = Point2f(15.0113f, 12.8994f); + B_sample[2] = Point2f(38.9943f, 9.56297f); + Mat trans = getAffineTransform(A_sample, B_sample); + ASSERT_EQ(0.0, norm(trans, NORM_INF)); +} + +TEST(Imgproc_Remap, DISABLED_memleak) +{ + Mat src; + const int N = 400; + src.create(N, N, CV_8U); + randu(src, 0, 256); + Mat map_x, map_y, dst; + dst.create( src.size(), src.type() ); + map_x.create( src.size(), CV_32FC1 ); + map_y.create( src.size(), CV_32FC1 ); + randu(map_x, 0., N+0.); + randu(map_y, 0., N+0.); + + for( int iter = 0; iter < 10000; iter++ ) + { + if(iter % 100 == 0) + { + putchar('.'); + fflush(stdout); + } + remap(src, dst, map_x, map_y, CV_INTER_LINEAR); + } +} + /* End of file. */ diff --git a/modules/photo/src/calibrate.cpp b/modules/photo/src/calibrate.cpp index eda3e1265b..63f1818e47 100644 --- a/modules/photo/src/calibrate.cpp +++ b/modules/photo/src/calibrate.cpp @@ -90,7 +90,9 @@ public: for(int i = 0, x = step_x / 2; i < x_points; i++, x += step_x) { for(int j = 0, y = step_y / 2; j < y_points; j++, y += step_y) { - sample_points.push_back(Point(x, y)); + if( 0 <= x && x < images[0].cols && + 0 <= y && y < images[0].rows ) + sample_points.push_back(Point(x, y)); } } } diff --git a/modules/photo/src/denoising.cpp b/modules/photo/src/denoising.cpp index c68d09b925..93d4b4ebbe 100644 --- a/modules/photo/src/denoising.cpp +++ b/modules/photo/src/denoising.cpp @@ -50,42 +50,50 @@ static void fastNlMeansDenoising_( const Mat& src, Mat& dst, const std::vector( - src, dst, templateWindowSize, searchWindowSize, &h[0])); + src, dst, templateWindowSize, searchWindowSize, &h[0]), + granularity); break; case 2: if (hn == 1) parallel_for_(cv::Range(0, src.rows), FastNlMeansDenoisingInvoker, IT, UIT, D, int>( - src, dst, templateWindowSize, searchWindowSize, &h[0])); + src, dst, templateWindowSize, searchWindowSize, &h[0]), + granularity); else parallel_for_(cv::Range(0, src.rows), FastNlMeansDenoisingInvoker, IT, UIT, D, Vec2i>( - src, dst, templateWindowSize, searchWindowSize, &h[0])); + src, dst, templateWindowSize, searchWindowSize, &h[0]), + granularity); break; case 3: if (hn == 1) parallel_for_(cv::Range(0, src.rows), FastNlMeansDenoisingInvoker, IT, UIT, D, int>( - src, dst, templateWindowSize, searchWindowSize, &h[0])); + src, dst, templateWindowSize, searchWindowSize, &h[0]), + granularity); else parallel_for_(cv::Range(0, src.rows), FastNlMeansDenoisingInvoker, IT, UIT, D, Vec3i>( - src, dst, templateWindowSize, searchWindowSize, &h[0])); + src, dst, templateWindowSize, searchWindowSize, &h[0]), + granularity); break; case 4: if (hn == 1) parallel_for_(cv::Range(0, src.rows), FastNlMeansDenoisingInvoker, IT, UIT, D, int>( - src, dst, templateWindowSize, searchWindowSize, &h[0])); + src, dst, templateWindowSize, searchWindowSize, &h[0]), + granularity); else parallel_for_(cv::Range(0, src.rows), FastNlMeansDenoisingInvoker, IT, UIT, D, Vec4i>( - src, dst, templateWindowSize, searchWindowSize, &h[0])); + src, dst, templateWindowSize, searchWindowSize, &h[0]), + granularity); break; default: CV_Error(Error::StsBadArg, @@ -237,6 +245,7 @@ static void fastNlMeansDenoisingMulti_( const std::vector& srcImgs, Mat& ds int templateWindowSize, int searchWindowSize) { int hn = (int)h.size(); + double granularity = (double)std::max(1., (double)dst.total()/(1 << 16)); switch (srcImgs[0].type()) { @@ -244,43 +253,50 @@ static void fastNlMeansDenoisingMulti_( const std::vector& srcImgs, Mat& ds parallel_for_(cv::Range(0, srcImgs[0].rows), FastNlMeansMultiDenoisingInvoker( srcImgs, imgToDenoiseIndex, temporalWindowSize, - dst, templateWindowSize, searchWindowSize, &h[0])); + dst, templateWindowSize, searchWindowSize, &h[0]), + granularity); break; case CV_8UC2: if (hn == 1) parallel_for_(cv::Range(0, srcImgs[0].rows), FastNlMeansMultiDenoisingInvoker, IT, UIT, D, int>( srcImgs, imgToDenoiseIndex, temporalWindowSize, - dst, templateWindowSize, searchWindowSize, &h[0])); + dst, templateWindowSize, searchWindowSize, &h[0]), + granularity); else parallel_for_(cv::Range(0, srcImgs[0].rows), FastNlMeansMultiDenoisingInvoker, IT, UIT, D, Vec2i>( srcImgs, imgToDenoiseIndex, temporalWindowSize, - dst, templateWindowSize, searchWindowSize, &h[0])); + dst, templateWindowSize, searchWindowSize, &h[0]), + granularity); break; case CV_8UC3: if (hn == 1) parallel_for_(cv::Range(0, srcImgs[0].rows), FastNlMeansMultiDenoisingInvoker, IT, UIT, D, int>( srcImgs, imgToDenoiseIndex, temporalWindowSize, - dst, templateWindowSize, searchWindowSize, &h[0])); + dst, templateWindowSize, searchWindowSize, &h[0]), + granularity); else parallel_for_(cv::Range(0, srcImgs[0].rows), FastNlMeansMultiDenoisingInvoker, IT, UIT, D, Vec3i>( srcImgs, imgToDenoiseIndex, temporalWindowSize, - dst, templateWindowSize, searchWindowSize, &h[0])); + dst, templateWindowSize, searchWindowSize, &h[0]), + granularity); break; case CV_8UC4: if (hn == 1) parallel_for_(cv::Range(0, srcImgs[0].rows), FastNlMeansMultiDenoisingInvoker, IT, UIT, D, int>( srcImgs, imgToDenoiseIndex, temporalWindowSize, - dst, templateWindowSize, searchWindowSize, &h[0])); + dst, templateWindowSize, searchWindowSize, &h[0]), + granularity); else parallel_for_(cv::Range(0, srcImgs[0].rows), FastNlMeansMultiDenoisingInvoker, IT, UIT, D, Vec4i>( srcImgs, imgToDenoiseIndex, temporalWindowSize, - dst, templateWindowSize, searchWindowSize, &h[0])); + dst, templateWindowSize, searchWindowSize, &h[0]), + granularity); break; default: CV_Error(Error::StsBadArg, diff --git a/modules/photo/src/tonemap.cpp b/modules/photo/src/tonemap.cpp index af930abb35..e475482d66 100644 --- a/modules/photo/src/tonemap.cpp +++ b/modules/photo/src/tonemap.cpp @@ -47,6 +47,12 @@ namespace cv { +inline void log_(const Mat& src, Mat& dst) +{ + max(src, Scalar::all(1e-4), dst); + log(dst, dst); +} + class TonemapImpl : public Tonemap { public: @@ -122,7 +128,7 @@ public: Mat gray_img; cvtColor(img, gray_img, COLOR_RGB2GRAY); Mat log_img; - log(gray_img, log_img); + log_(gray_img, log_img); float mean = expf(static_cast(sum(log_img)[0]) / log_img.total()); gray_img /= mean; log_img.release(); @@ -205,7 +211,7 @@ public: Mat gray_img; cvtColor(img, gray_img, COLOR_RGB2GRAY); Mat log_img; - log(gray_img, log_img); + log_(gray_img, log_img); Mat map_img; bilateralFilter(log_img, map_img, -1, sigma_color, sigma_space); @@ -289,7 +295,7 @@ public: Mat gray_img; cvtColor(img, gray_img, COLOR_RGB2GRAY); Mat log_img; - log(gray_img, log_img); + log_(gray_img, log_img); float log_mean = static_cast(sum(log_img)[0] / log_img.total()); double log_min, log_max; @@ -383,7 +389,7 @@ public: Mat gray_img; cvtColor(img, gray_img, COLOR_RGB2GRAY); Mat log_img; - log(gray_img, log_img); + log_(gray_img, log_img); std::vector x_contrast, y_contrast; getContrast(log_img, x_contrast, y_contrast); diff --git a/modules/photo/test/test_denoising.cpp b/modules/photo/test/test_denoising.cpp index 9808e9cddc..c3a69a2f76 100644 --- a/modules/photo/test/test_denoising.cpp +++ b/modules/photo/test/test_denoising.cpp @@ -156,3 +156,14 @@ TEST(Photo_White, issue_2646) ASSERT_EQ(0, nonWhitePixelsCount); } + +TEST(Photo_Denoising, speed) +{ + string imgname = string(cvtest::TS::ptr()->get_data_path()) + "shared/5MP.png"; + Mat src = imread(imgname, 0), dst; + + double t = (double)getTickCount(); + fastNlMeansDenoising(src, dst, 5, 7, 21); + t = (double)getTickCount() - t; + printf("execution time: %gms\n", t*1000./getTickFrequency()); +}