From 5a94a95fbfd41e12e694d0527c0e37fb85c8d0dc Mon Sep 17 00:00:00 2001 From: Vadim Pisarevsky Date: Thu, 28 May 2015 19:33:21 +0300 Subject: [PATCH] improvements in Haar CascadeClassifier: 1) use CV_32S instead of CV_32F for the integral of squares (which is more accurate and more efficient); 2) skip the window if its contrast is too low --- modules/imgproc/src/sumpixels.cpp | 3 ++ modules/objdetect/src/cascadedetect.cpp | 33 +++++++++++-------- modules/objdetect/src/opencl/cascadedetect.cl | 2 +- 3 files changed, 23 insertions(+), 15 deletions(-) diff --git a/modules/imgproc/src/sumpixels.cpp b/modules/imgproc/src/sumpixels.cpp index 16c7c7ef26..ce6aa794c6 100755 --- a/modules/imgproc/src/sumpixels.cpp +++ b/modules/imgproc/src/sumpixels.cpp @@ -318,6 +318,7 @@ static void integral_##suffix( T* src, size_t srcstep, ST* sum, size_t sumstep, { integral_(src, srcstep, sum, sumstep, sqsum, sqsumstep, tilted, tiltedstep, size, cn); } DEF_INTEGRAL_FUNC(8u32s, uchar, int, double) +DEF_INTEGRAL_FUNC(8u32s32s, uchar, int, int) DEF_INTEGRAL_FUNC(8u32f64f, uchar, float, double) DEF_INTEGRAL_FUNC(8u64f64f, uchar, double, double) DEF_INTEGRAL_FUNC(16u64f64f, ushort, double, double) @@ -505,6 +506,8 @@ void cv::integral( InputArray _src, OutputArray _sum, OutputArray _sqsum, Output func = (IntegralFunc)GET_OPTIMIZED(integral_8u32s); else if( depth == CV_8U && sdepth == CV_32S && sqdepth == CV_32F ) func = (IntegralFunc)integral_8u32s32f; + else if( depth == CV_8U && sdepth == CV_32S && sqdepth == CV_32S ) + func = (IntegralFunc)integral_8u32s32s; else if( depth == CV_8U && sdepth == CV_32F && sqdepth == CV_64F ) func = (IntegralFunc)integral_8u32f64f; else if( depth == CV_8U && sdepth == CV_32F && sqdepth == CV_32F ) diff --git a/modules/objdetect/src/cascadedetect.cpp b/modules/objdetect/src/cascadedetect.cpp index 5cc861e0f5..056abecc8b 100644 --- a/modules/objdetect/src/cascadedetect.cpp +++ b/modules/objdetect/src/cascadedetect.cpp @@ -627,33 +627,33 @@ void HaarEvaluator::computeChannels(int scaleIdx, InputArray img) int sqy = sy + (sqofs / sbufSize.width); UMat sum(usbuf, Rect(sx, sy, s.szi.width, s.szi.height)); UMat sqsum(usbuf, Rect(sx, sqy, s.szi.width, s.szi.height)); - sqsum.flags = (sqsum.flags & ~UMat::DEPTH_MASK) | CV_32F; + sqsum.flags = (sqsum.flags & ~UMat::DEPTH_MASK) | CV_32S; if (hasTiltedFeatures) { int sty = sy + (tofs / sbufSize.width); UMat tilted(usbuf, Rect(sx, sty, s.szi.width, s.szi.height)); - integral(img, sum, sqsum, tilted, CV_32S, CV_32F); + integral(img, sum, sqsum, tilted, CV_32S, CV_32S); } else { UMatData* u = sqsum.u; - integral(img, sum, sqsum, noArray(), CV_32S, CV_32F); - CV_Assert(sqsum.u == u && sqsum.size() == s.szi && sqsum.type()==CV_32F); + integral(img, sum, sqsum, noArray(), CV_32S, CV_32S); + CV_Assert(sqsum.u == u && sqsum.size() == s.szi && sqsum.type()==CV_32S); } } else { Mat sum(s.szi, CV_32S, sbuf.ptr() + s.layer_ofs, sbuf.step); - Mat sqsum(s.szi, CV_32F, sum.ptr() + sqofs, sbuf.step); + Mat sqsum(s.szi, CV_32S, sum.ptr() + sqofs, sbuf.step); if (hasTiltedFeatures) { Mat tilted(s.szi, CV_32S, sum.ptr() + tofs, sbuf.step); - integral(img, sum, sqsum, tilted, CV_32S, CV_32F); + integral(img, sum, sqsum, tilted, CV_32S, CV_32S); } else - integral(img, sum, sqsum, noArray(), CV_32S, CV_32F); + integral(img, sum, sqsum, noArray(), CV_32S, CV_32S); } } @@ -689,18 +689,23 @@ bool HaarEvaluator::setWindow( Point pt, int scaleIdx ) return false; pwin = &sbuf.at(pt) + s.layer_ofs; - const float* pq = (const float*)(pwin + sqofs); + const int* pq = (const int*)(pwin + sqofs); int valsum = CALC_SUM_OFS(nofs, pwin); - float valsqsum = CALC_SUM_OFS(nofs, pq); + unsigned valsqsum = (unsigned)(CALC_SUM_OFS(nofs, pq)); - double nf = (double)normrect.area() * valsqsum - (double)valsum * valsum; + double area = normrect.area(); + double nf = area * valsqsum - (double)valsum * valsum; if( nf > 0. ) + { nf = std::sqrt(nf); + varianceNormFactor = (float)(1./nf); + return area*varianceNormFactor < 1e-1; + } else - nf = 1.; - varianceNormFactor = (float)(1./nf); - - return true; + { + varianceNormFactor = 1.f; + return false; + } } diff --git a/modules/objdetect/src/opencl/cascadedetect.cl b/modules/objdetect/src/opencl/cascadedetect.cl index 7ab581a282..ccc9c6d688 100644 --- a/modules/objdetect/src/opencl/cascadedetect.cl +++ b/modules/objdetect/src/opencl/cascadedetect.cl @@ -160,7 +160,7 @@ void runHaarClassifier( __global const int* psum = psum1; #endif - __global const float* psqsum = (__global const float*)(psum1 + sqofs); + __global const int* psqsum = (__global const int*)(psum1 + sqofs); float sval = (psum[nofs.x] - psum[nofs.y] - psum[nofs.z] + psum[nofs.w])*invarea; float sqval = (psqsum[nofs0.x] - psqsum[nofs0.y] - psqsum[nofs0.z] + psqsum[nofs0.w])*invarea; float nf = (float)normarea * sqrt(max(sqval - sval * sval, 0.f));